/** * Updates a strip vertex with vertices shaping a rounded beginning. This method is called when * the polygon is open (not {@link #isClosedPolygon()}). * * @param inside whether this is a <b>inside</b> triangle strip, as opposed to an outside triangle * strip. */ private void updateVertexBeginning(boolean inside) { // if polygon is not closed the endings must be fixed int index = 0; BoundingBox box = boundingBoxes.items[0]; box.needsCullingUpdate = true; StripVertex stripVertex = vertexDataArray.items[index]; AuxVertexFinder auxVertexFinder = this.auxVertexFinder; Array<Float> vertexData = inside ? stripVertex.insideVertexData : stripVertex.outsideVertexData; vertexData.clear(); auxVertexFinder.setInsideStrip(inside); Vector2 currentVertex = vertices.items[index]; Vector2 currentAux = auxVertexFinder.getAuxBeginning(vertices, index, MathUtils.PI * 0.5f); add(currentVertex, VERTEX_TYPE_USER, vertexData); add(currentAux, VERTEX_TYPE_AUX, vertexData); currentAux = auxVertexFinder.getAuxBeginning(vertices, index, MathUtils.PI * 0.25f); add(currentVertex, VERTEX_TYPE_USER, vertexData); add(currentAux, VERTEX_TYPE_AUX, vertexData); currentAux = auxVertexFinder.getAuxBeginning(vertices, index, 0); add(currentVertex, VERTEX_TYPE_USER, vertexData); add(currentAux, VERTEX_TYPE_AUX, vertexData); }
/** * @param halfWidth half the width of the edges. * @return this for chaining. */ public OutlinePolygon setHalfWidth(float halfWidth) { this.halfWidth = halfWidth; auxVertexFinder.setHalfWidth(this.halfWidth); for (int i = 0; i < needsUpdate.size; i++) { needsUpdate.items[i] = true; } changesToStripOrCulling = true; return this; }
/** * The aux vertex finder needs to know if the polygon is a clockwise one. Instead of figuring out * whether the polygon is clockwise each time it needs to know this method is called at most once * during {@link #updateStripAndCulling()}, and only if the vertices has been changed. */ private void updateAuxVertexFinderClockwise() { boolean clockwisePolygon = Util.clockwisePolygon(vertices); auxVertexFinder.setClockwise(clockwisePolygon); }
// TODO Comment private void updateVertexDefault(int index, boolean inside) { BoundingBox box = boundingBoxes.items[index / verticesPerBox]; box.needsCullingUpdate = true; int k = index % vertices.size; StripVertex stripVertex = vertexDataArray.items[k]; AuxVertexFinder auxVertexFinder = this.auxVertexFinder; Array<Float> vertexData = inside ? stripVertex.insideVertexData : stripVertex.outsideVertexData; vertexData.clear(); auxVertexFinder.setInsideStrip(inside); Vector2 currentVertex = vertices.items[k]; Vector2 defaultAux = auxVertexFinder.getAux(vertices, k); boolean roundCorner = false; { // within these brackets i figure out if i should round the corner. // i hope to rewrite this code to something i can understand one day after writing it Vector2 previous = tmp.set(vertices.items[(k - 1 + vertices.size) % vertices.size]); Vector2 copyOfDefaultAux = tmp1.set(defaultAux); previous.sub(currentVertex); copyOfDefaultAux.sub(currentVertex); float angle = previous.angleRad() - copyOfDefaultAux.angleRad(); angle = ((angle + MathUtils.PI2) % MathUtils.PI) * 2f; boolean angleMoreThanPI; if (inside) { angleMoreThanPI = angle > MathUtils.PI * 1.1f; } else { angleMoreThanPI = angle < MathUtils.PI * 0.9f; } if (auxVertexFinder.clockWisePolygon) angleMoreThanPI = !angleMoreThanPI; if (angleMoreThanPI) { boolean sharpCorner = Math.abs(MathUtils.PI - angle) > Math.PI * 0.4f; roundCorner = roundSharpCorners && sharpCorner; } } if (roundCorner) { Vector2 beginningAux = auxVertexFinder.getAuxEnding(vertices, k, 0); Vector2 endingAux = auxVertexFinder.getAuxBeginning(vertices, k, 0); Vector2 middleAux = tmp.set(defaultAux).sub(currentVertex).nor().scl(halfWidth).add(currentVertex); add(currentVertex, VERTEX_TYPE_USER, vertexData); add(beginningAux, VERTEX_TYPE_AUX, vertexData); add(currentVertex, VERTEX_TYPE_USER, vertexData); add(middleAux, VERTEX_TYPE_AUX, vertexData); add(currentVertex, VERTEX_TYPE_USER, vertexData); add(endingAux, VERTEX_TYPE_AUX, vertexData); } else { add(currentVertex, VERTEX_TYPE_USER, vertexData); add(defaultAux, VERTEX_TYPE_AUX, vertexData); } }
/** Draws anti aliased polygon edges. */ public OutlinePolygon(OutlinePolygonDef outlinePolygonDef) { debugRenderer = new DebugRenderer(this) { @Override public void draw(ShapeRenderer shapeRenderer) { if (drawCullingRectangles) drawCullingRectangles(shapeRenderer, Color.GREEN); if (drawLineFromFirstToLast) drawLineFromFirstToLast(shapeRenderer, Color.BLUE); if (drawTriangleStrips) drawTriangleStrips(shapeRenderer, Color.RED, Color.ORANGE); } @Override void update() { super.update(); boolean enabled = drawLineFromFirstToLast; enabled |= drawCullingRectangles; enabled |= drawTriangleStrips; enabled &= myParents.size == 0; boolean change = this.enabled != enabled; if (!change) return; this.enabled = enabled; debugColors.clear(); if (drawCullingRectangles) { debugColors.add(new DebugColor(Color.GREEN, "Bounding box")); } if (drawLineFromFirstToLast) { debugColors.add( new DebugColor(Color.BLUE, "Line from first to last vertex in bounding box")); } if (drawTriangleStrips) { debugColors.add(new DebugColor(Color.RED, "Triangle strip visualization")); debugColors.add(new DebugColor(Color.ORANGE, "Triangle strip visualization")); } } }; auxVertexFinder.setHalfWidth(this.halfWidth); if (outlinePolygonDef != null) { setDrawOutside(outlinePolygonDef.drawOutside); setDrawInside(outlinePolygonDef.drawInside); setColor(outlinePolygonDef.color); setClosedPolygon(outlinePolygonDef.closedPolygon); setHalfWidth(outlinePolygonDef.halfWidth); setWeight(outlinePolygonDef.weight); setRoundSharpCorners(outlinePolygonDef.roundSharpCorners); setDrawLineFromFirstToLast(outlinePolygonDef.drawLineFromFirstToLast); setDrawCullingRectangles(outlinePolygonDef.drawBoundingBoxes); setDrawTriangleStrips(outlinePolygonDef.drawTriangleStrips); setVisible(outlinePolygonDef.visible); setVertices(outlinePolygonDef.vertices); setScale(outlinePolygonDef.scale); setAngle(outlinePolygonDef.angle); setPosition(outlinePolygonDef.position); setOpacity(outlinePolygonDef.opacity); } }