public static Path spline2Path(AXSpline s) { Path path = new Path(); for (int i = 0; i < s.vertCount; i++) { path.Add(Vec2_2_IntPt(s.verts[i])); } return(path); }
public static AXSpline path2AXSpline(Path path) { AXSpline s = new AXSpline(); for (int i = 0; i < path.Count; i++) { s.Push(IntPt2Vec2(path[i])); } return(s); }
public static AXSpline curve2Spline(List <CurvePoint> curve) { AXSpline s = new AXSpline(); for (int i = 0; i < curve.Count; i++) { s.Push(curve[i].position); } return(s); }
//bool drawingHole = false; public AXTurtle() { updateTrigs(); dir(0); s = new AXSpline(); paths = new Paths(); clips = new Paths(); polytree = new PolyTree(); }
public static void DrawSplineFit(AXParameter p, Vector2 offset, float size, Color splineColor) { AXSpline s = p.spline.clone(); s.rotate(p.Parent.floatValue("Rot_Z")); if (s == null) { return; } // scale the spline to fit in "size" in pixels AXSpline os = s.clone(); os.calcStats(); os.shift(-os.cenX, -os.cenY); float maxdim = (os.width > os.height) ? os.width : os.height; float scale = size / maxdim; os.scale(scale); GUIDrawing.DrawSpline(os, offset, splineColor); }
// GENERATE PLAN_REPEATER public override GameObject generate(bool makeGameObjects, AXParametricObject initiator_po, bool renderToOutputParameter) { if (parametricObject == null || !parametricObject.isActive) { return(null); } //Debug.Log("yo ******* makeGameObjects="+makeGameObjects); // RESULTING MESHES ax_meshes = new List <AXMesh>(); paths_SubsplineIndices = new List <SubsplineIndices[]>(); preGenerate(); planSrc_p = P_Plan.DependsOn; // getUpstreamSourceParameter(P_Plan); planSrc_po = (planSrc_p != null) ? planSrc_p.parametricObject : null; //Debug.Log("planSrc_po = " + planSrc_po.Name+"."+planSrc_p.Name + " ... " + planSrc_p.DependsOn.PType + " ..... " + planSrc_p.getPaths()); P_Plan.polyTree = null; AXShape.thickenAndOffset(ref P_Plan, planSrc_p); if (P_Plan.reverse) { P_Plan.doReverse(); } planPaths = P_Plan.getPaths(); if (planPaths == null || planPaths.Count == 0) { return(null); } // ** CREATE PLAN_SPLINES ** if (planPaths != null && planPaths.Count > 0) { planSplines = new Spline[planPaths.Count]; if (planSplines != null) { for (int i = 0; i < planSplines.Length; i++) { planSplines[i] = new Spline(planPaths[i], (P_Plan.shapeState == ShapeState.Closed) ? true : false); } } } //Debug.Log("controlVertices="+ planSplines[0].controlVertices.Count); // CORNER_MESH GameObject cornerPlugGO = null; if (cornerSrc_p != null) { cornerSrc_po = cornerSrc_p.parametricObject; if (makeGameObjects && !parametricObject.combineMeshes) { cornerPlugGO = cornerSrc_po.generator.generate(true, initiator_po, renderToOutputParameter); } } // NODE_MESH GameObject nodePlugGO = null; if (nodeSrc_p != null) { nodeSrc_po = nodeSrc_p.parametricObject; //Debug.Log("yo makeGameObjects="+makeGameObjects+", parametricObject.combineMeshes="+parametricObject.combineMeshes); if (makeGameObjects && !parametricObject.combineMeshes) { nodePlugGO = nodeSrc_po.generator.generate(true, initiator_po, renderToOutputParameter); } } // CELL_MESH GameObject cellPlugGO = null; if (cellSrc_p != null) { cellSrc_po = cellSrc_p.parametricObject; if (makeGameObjects && !parametricObject.combineMeshes) { cellPlugGO = cellSrc_po.generator.generate(true, initiator_po, renderToOutputParameter); } } // Plan // This is the main spline used for the iteration //AXParameter plan_p = ip.DependsOn; // The section spline is used to provide the connective tissue around corners // SECTION // The plan may have multiple paths. Each may generate a separate GO. sectionSrc_p = P_Section.DependsOn; //getUpstreamSourceParameter(P_Section); sectionSrc_po = (sectionSrc_p != null) ? sectionSrc_p.parametricObject : null; if (sectionSrc_po != null) { P_Section.polyTree = null; AXShape.thickenAndOffset(ref P_Section, sectionSrc_p); if (P_Section.reverse) { P_Section.doReverse(); } } float bay_U = parametricObject.floatValue("bay_U"); float bay_V = parametricObject.floatValue("bay_V"); if (bay_U == 0) { bay_U = .1f; } if (bay_V == 0) { bay_V = 10f; } float margin_U = parametricObject.floatValue("margin_U"); Vector2 prevV = new Vector2(); //Vector3 scaler1 = Vector3.one; //float margin = 2.5f; Vector2 firstPM = new Vector2(); Vector2 prevVM = new Vector2(); AXSpline secSpline = null; AXSplineExtrudeGenerator tmpEXSP = null; if (sectionSrc_p != null && sectionSrc_p.spline != null && sectionSrc_p.spline.vertCount > 0) { secSpline = sectionSrc_p.spline; } tmpEXSP = new AXSplineExtrudeGenerator(); Material tmp_mat = parametricObject.axMat.mat; if (parametricObject.axTex != null) { tmpEXSP.uScale = parametricObject.axTex.scale.x; tmpEXSP.vScale = parametricObject.axTex.scale.y; tmpEXSP.uShift = -parametricObject.axTex.shift.x; tmpEXSP.vShift = parametricObject.axTex.shift.y; } float runningU = 0; //ip.spline.getAnglesArray(); //Spline sectionSpline = null; // = new Spline(sectionPath, sectionIsClosed, sec_p.breakGeom, sec_p.breakNorm); GameObject go = null; GameObject planGO = null; if (makeGameObjects && !parametricObject.combineMeshes) { go = ArchimatixUtils.createAXGameObject(parametricObject.Name, parametricObject); } // BOUNDING List <AXMesh> boundingMeshes = new List <AXMesh>(); // FOR EACH PATH for (int path_i = 0; path_i < planPaths.Count; path_i++) { if (makeGameObjects && !parametricObject.combineMeshes) { planGO = ArchimatixUtils.createAXGameObject(parametricObject.Name + "_" + path_i, parametricObject); } // **** PREPARE EACH SPLINE *** // Spline planSpline = planSplines[path_i]; planSpline.breakAngleCorners = cornerBreakAngle; planSpline.shapeState = P_Plan.shapeState; // Create subsplines between each break point planSpline.getSmoothSubsplineIndicies(0, maxSegmentLength); // ....... DEBUG //Pather.printPaths(planPaths); planSpline.groupNearBreakAngleVertices(inset * 2); if (planSpline.groupedCornerNodes == null || planSpline.groupedCornerNodes.Count == 0) { inset = 0; } // **** PREPARE EACH SPLINE *** // Matrix4x4 localPlacement_mx = Matrix4x4.identity; // INSET PLANSWEEPS GameObject plansweepGO = null; if (sectionSrc_p != null && inset > 0 && planSpline.insetSplines != null) { // convert planSpline.insetSplines to Paths Paths insetPaths = AXGeometryTools.Utilities.Splines2Paths(planSpline.insetSplines); AXParameter tmpPlanP = new AXParameter(); tmpPlanP.parametricObject = parametricObject; tmpPlanP.paths = insetPaths; tmpPlanP.Type = AXParameter.DataType.Shape; tmpPlanP.shapeState = ShapeState.Open; tmpPlanP.breakGeom = 0; if (planSpline.insetSplines.Count == 1) { tmpPlanP.shapeState = planSpline.insetSplines[0].shapeState; } topCap = false; botCap = false; plansweepGO = generateFirstPass(initiator_po, makeGameObjects, tmpPlanP, P_Section, Matrix4x4.identity, renderToOutputParameter, false); if (makeGameObjects && !parametricObject.combineMeshes && plansweepGO != null) { plansweepGO.transform.parent = go.transform; } } AXMesh tmpMesh = null; if (planSpline.insetSpanSplines != null && planSpline.insetSpanSplines.Count > 0) { //Debug.Log(".....????>> spanSpline.subsplines.Count="+ planSpline.insetSpanSplines.Count + " --- " + planSpline.subsplines.Count ); for (int si = 0; si < planSpline.insetSpanSplines.Count; si++) { planSpline.insetSpanSplines[si].setRepeaterTransforms(si, inset, bay); } // SPAN NODES - MESHES ALONG SUBSPLINES if (nodeSrc_p != null && nodeSrc_p.meshes != null) { //int endCount = (P_Plan != null && P_Plan.shapeState == ShapeState.Open) ? planSpline.subsplines.Count-1 : planSpline.subsplines.Count; int endCount = (P_Plan != null && P_Plan.shapeState == ShapeState.Open) ? planSpline.insetSpanSplines.Count - 1 : planSpline.insetSpanSplines.Count; for (int i = 0; i < endCount; i++) { //SubsplineIndices rsi = planSpline.subsplines[i]; Spline spanSpline = planSpline.insetSpanSplines[i]; //Debug.Log(i + "||||||||||> " + spanSpline.toString()); List <Matrix4x4> nodeMatrices = spanSpline.repeaterNodeTransforms; // on each of these nodes, place a nodePlug instance. bool spanNodesAtBreakCorners = true; int starter = (inset > 0 || spanNodesAtBreakCorners) ? 0 : 1; //Debug.Log("starter="+starter); int ender = (inset > 0 || spanSpline.shapeState == ShapeState.Open || planSpline.subsplines.Count == 1) ? nodeMatrices.Count : nodeMatrices.Count - 1; //Debug.Log("starter="+starter +", ender="+ender + ", nodeMatrices.Count=" + nodeMatrices.Count); //Debug.Log("(inset > 0 && spanNodesAtBreakCorners)="+(inset > 0 && spanNodesAtBreakCorners)+", nodeMatrices.Length="+nodeMatrices.Length+", starter="+starter+", ender="+ender); string this_address = ""; if (nodeMatrices != null) { for (int ii = starter; ii < ender; ii++) { this_address = "node_" + path_i + "_" + i + "_" + ii; //Debug.Log("this_address="+this_address); // LOCAL_PLACEMENT localPlacement_mx = localMatrixFromAddress(RepeaterItem.Node, path_i, i, ii); // AX_MESHES for (int mi = 0; mi < nodeSrc_p.meshes.Count; mi++) { AXMesh dep_amesh = nodeSrc_p.meshes [mi]; tmpMesh = dep_amesh.Clone(localPlacement_mx * dep_amesh.transMatrix); tmpMesh.subItemAddress = this_address; ax_meshes.Add(tmpMesh); } // BOUNDING boundingMeshes.Add(new AXMesh(nodeSrc_po.boundsMesh, localPlacement_mx * nodeSrc_po.generator.localMatrix)); //Debug.Log("boundingMeshes: " + boundingMeshes.Count); // GAME_OBJECTS if (nodePlugGO != null && makeGameObjects && !parametricObject.combineMeshes) { Matrix4x4 mx = localPlacement_mx * nodeSrc_po.generator.localMatrixWithAxisRotationAndAlignment; GameObject copyGO = (GameObject)GameObject.Instantiate(nodePlugGO, AXUtilities.GetPosition(mx), AXUtilities.QuaternionFromMatrix(mx)); Vector3 newJitterScale = jitterScale + Vector3.one; copyGO.transform.localScale = new Vector3(copyGO.transform.localScale.x * newJitterScale.x, copyGO.transform.localScale.y * newJitterScale.y, copyGO.transform.localScale.z * newJitterScale.z); copyGO.transform.localScale += jitterScale; AXGameObject axgo = copyGO.GetComponent <AXGameObject>(); if (axgo != null) { axgo.consumerAddress = this_address; //Debug.Log("ADD ADDRESS: " + this_address); } copyGO.name = copyGO.name + "_" + this_address; //Debug.Log("copyGO.name = "+copyGO.name); copyGO.transform.parent = planGO.transform; } } } } } // \NODE MESHES // CELL NODES - MESHES ALONG SUBSPLINES if (cellSrc_p != null && cellSrc_p.meshes != null) { //int endCount = (P_Plan != null && P_Plan.shapeState == ShapeState.Open) ? planSpline.subsplines.Count-1 : planSpline.subsplines.Count; int endCount = (P_Plan != null && P_Plan.shapeState == ShapeState.Open) ? planSpline.insetSpanSplines.Count - 1 : planSpline.insetSpanSplines.Count; for (int i = 0; i < endCount; i++) { //SubsplineIndices rsi = planSpline.subsplines[i]; Spline spanSpline = planSpline.insetSpanSplines[i]; spanSpline.setRepeaterTransforms(i, inset, bay); List <Matrix4x4> cellMatrices = spanSpline.repeaterCellTransforms; // on each of these cell, place a nodePlug instance. //bool spanNodesAtBreakCorners = true; int starter = 0; //spanNodesAtBreakCorners ? 0 : 1; //int ender = (inset > 0 || spanNodesAtBreakCorners) ? cellMatrices.Count : cellMatrices.Count-1; int ender = cellMatrices.Count; //Debug.Log("(inset > 0 && spanNodesAtBreakCorners)="+(inset > 0 && spanNodesAtBreakCorners)+", nodeMatrices.Length="+nodeMatrices.Length+", starter="+starter+", ender="+ender); string this_address = ""; if (cellMatrices != null) { for (int ii = starter; ii < ender; ii++) { // ADDRESS this_address = "cell_" + path_i + "_" + i + "_" + ii; // LOCAL_PLACEMENT localPlacement_mx = localMatrixFromAddress(RepeaterItem.Cell, path_i, i, ii); // AX_MESHES for (int mi = 0; mi < cellSrc_p.meshes.Count; mi++) { AXMesh dep_amesh = cellSrc_p.meshes [mi]; tmpMesh = dep_amesh.Clone(localPlacement_mx * dep_amesh.transMatrix); tmpMesh.subItemAddress = this_address; ax_meshes.Add(tmpMesh); } // BOUNDING boundingMeshes.Add(new AXMesh(cellSrc_po.boundsMesh, localPlacement_mx * cellSrc_po.generator.localMatrix)); // GAME_OBJECTS if (cellPlugGO != null && makeGameObjects && !parametricObject.combineMeshes) { Matrix4x4 mx = localPlacement_mx * cellSrc_po.generator.localMatrixWithAxisRotationAndAlignment; GameObject copyGO = (GameObject)GameObject.Instantiate(cellPlugGO, AXUtilities.GetPosition(mx), AXUtilities.QuaternionFromMatrix(mx)); Vector3 newJitterScale = jitterScale + Vector3.one; copyGO.transform.localScale = new Vector3(copyGO.transform.localScale.x * newJitterScale.x, copyGO.transform.localScale.y * newJitterScale.y, copyGO.transform.localScale.z * newJitterScale.z); copyGO.transform.localScale += jitterScale; AXGameObject axgo = copyGO.GetComponent <AXGameObject>(); if (axgo != null) { axgo.consumerAddress = this_address; //Debug.Log("ADD ADDRESS: " + this_address); } copyGO.name = copyGO.name + "_"; // + this_address; //Debug.Log("copyGO.name = "+copyGO.name); copyGO.transform.parent = planGO.transform; } } } } } // \CELL MESHES } // \each spanSpline // BREAK CORNER MESHES if (cornerSrc_p != null && cornerSrc_p.meshes != null) { for (int bi = 0; bi < planSpline.breakIndices.Count; bi++) { // ADDRESS string this_address = "corner_" + path_i + "_" + planSpline.breakIndices[bi]; // LOCAL_PLACEMENT localPlacement_mx = localMatrixFromAddress(RepeaterItem.Corner, path_i, planSpline.breakIndices[bi]); // AX_MESHES for (int mi = 0; mi < cornerSrc_p.meshes.Count; mi++) { AXMesh dep_amesh = cornerSrc_p.meshes [mi]; tmpMesh = dep_amesh.Clone(localPlacement_mx * dep_amesh.transMatrix); tmpMesh.subItemAddress = this_address; ax_meshes.Add(tmpMesh); } // BOUNDING boundingMeshes.Add(new AXMesh(cornerSrc_po.boundsMesh, localPlacement_mx * cornerSrc_po.generator.localMatrix)); // GAME_OBJECTS if (cornerPlugGO != null && makeGameObjects && !parametricObject.combineMeshes) { Matrix4x4 mx = localPlacement_mx * cornerSrc_po.generator.localMatrixWithAxisRotationAndAlignment; GameObject copyGO = (GameObject)GameObject.Instantiate(cornerPlugGO, AXUtilities.GetPosition(mx), AXUtilities.QuaternionFromMatrix(mx)); Vector3 newJitterScale = jitterScale + Vector3.one; copyGO.transform.localScale = new Vector3(copyGO.transform.localScale.x * newJitterScale.x, copyGO.transform.localScale.y * newJitterScale.y, copyGO.transform.localScale.z * newJitterScale.z); copyGO.transform.localScale += jitterScale; AXGameObject axgo = copyGO.GetComponent <AXGameObject>(); if (axgo != null) { axgo.consumerAddress = this_address; } copyGO.name = copyGO.name + "_" + this_address; copyGO.transform.parent = planGO.transform; } } } /* * int cells = Mathf.CeilToInt( md/bay_U ); * int nby = Mathf.CeilToInt( height/bay_V ); * * //Debug.Log ("d="+d+", md="+md); * * float actual_bayx = md/cells; * float actual_bayy = height/nby; * * // CREATE VERSIONS OF INPUT BAY_CENTER MESH(ES) USING BOUNDING BOX * // ****************************************************************************** * // someting similar shoud be added to griditerator, stepiterator, and where else? * * // instead of prev, would be better to create a dictionary of bounds and AXMeshes? * if (bay_span_p != null && (prevActuralBayx != actual_bayx || prevActuralBayx != actual_bayy)) * { * // regnerate the input meshes using actual_bayx * bay_span_p.Parent.setParameterValueByName("uScale", parametricObject.floatValue("uScale")); * bay_span_p.Parent.setParameterValueByName("vScale", parametricObject.floatValue("vScale")); * bay_span_p.Parent.setParameterValueByName("uShift", parametricObject.floatValue("uShift")); * bay_span_p.Parent.setParameterValueByName("vShift", parametricObject.floatValue("vShift")); * * //bay_span_p.Parent.generateOutputNow (makeGameObjects, parametricObject, true);//, new Vector3(actual_bayx, actual_bayy, margin_th)); * * } * // ****************************************************************************** * * * // CREATE VERSIONS OF INPUT BAY_CENTER MESH(ES) USING BOUNDING BOX * // ****************************************************************************** * // someting similar shoud be added to griditerator, stepiterator, and where else? * * // instead of prev, would be better to create a dictionary of bounds and AXMeshes? * if (node_p != null && (prevActuralBayx != actual_bayx || prevActuralBayx != actual_bayy)) * { * // regnerate the input meshes using actual_bayx * node_p.Parent.setParameterValueByName("uScale", parametricObject.floatValue("uScale")); * node_p.Parent.setParameterValueByName("vScale", parametricObject.floatValue("vScale")); * node_p.Parent.setParameterValueByName("uShift", parametricObject.floatValue("uShift")); * node_p.Parent.setParameterValueByName("vShift", parametricObject.floatValue("vShift")); * * //node_p.Parent.generateOutputNow (makeGameObjects, parametricObject, true);//, new Vector3(actual_bayx, actual_bayy, margin_th)); * * } * // ****************************************************************************** */ //margin_U = .5f; if (margin_U > 0 && planSpline.isClosed) { AXSpline connSpline2 = new AXSpline(); connSpline2.Push(prevVM); connSpline2.Push(prevV); connSpline2.Push(firstPM); connSpline2.isClosed = false; tmpEXSP.uShift = parametricObject.floatValue("uShift") + (runningU) / tmpEXSP.uScale; Mesh mesh = tmpEXSP.generate(connSpline2, secSpline); ax_meshes.Add(new AXMesh(mesh, Matrix4x4.identity, tmp_mat)); } if (makeGameObjects && !parametricObject.combineMeshes) { planGO.transform.parent = go.transform; } } // end paths //GameObject.DestroyImmediate(bay_spanPlugGO); GameObject.DestroyImmediate(cornerPlugGO); GameObject.DestroyImmediate(nodePlugGO); GameObject.DestroyImmediate(cellPlugGO); // FINISH AX_MESHES //Debug.Log("finish " + ax_meshes.Count); parametricObject.finishMultiAXMeshAndOutput(ax_meshes, renderToOutputParameter); // FINISH BOUNDS CombineInstance[] boundsCombinator = new CombineInstance[boundingMeshes.Count]; for (int bb = 0; bb < boundsCombinator.Length; bb++) { boundsCombinator[bb].mesh = boundingMeshes[bb].mesh; boundsCombinator[bb].transform = boundingMeshes[bb].transMatrix; } setBoundsWithCombinator(boundsCombinator); // FINISH GAME_OBJECTS if (makeGameObjects) { if (parametricObject.combineMeshes) { go = parametricObject.makeGameObjectsFromAXMeshes(ax_meshes, true); } Matrix4x4 tmx = parametricObject.getLocalMatrix(); go.transform.rotation = AXUtilities.QuaternionFromMatrix(tmx); go.transform.position = AXUtilities.GetPosition(tmx); go.transform.localScale = parametricObject.getLocalScaleAxisRotated(); //AXUtilities.GetScale(tmx); if (P_Plan.reverse) { P_Plan.doReverse(); } if (P_Section != null && P_Section.reverse) { P_Section.doReverse(); } return(go); } else { // Submit AXMeshes for realtime rendering //parametricObject.finishMultiAXMeshAndOutput(ax_meshes, renderToOutputParameter); //setBoundaryFromMeshes(ax_meshes); } if (P_Plan.reverse) { P_Plan.doReverse(); } if (P_Section != null && P_Section.reverse) { P_Section.doReverse(); } return(null); }
public static void DrawSpline(AXSpline _spline, Vector2 offset, Color splineColor) { Handles.BeginGUI(); Handles.color = splineColor; if (_spline != null) { List <AXSpline> subs = _spline.getSubsplines(); if (subs != null && subs.Count > 0) { foreach (AXSpline sub in subs) { if (sub.verts == null || sub.vertCount == 0) { continue; } List <AXSpline> parts = sub.getSolidAndHoles(); AXSpline contour = parts[0]; Color closeColor = splineColor; closeColor.a = splineColor.a / 3; // origin Handles.color = new Color(0, 1, 0, .5f); GUIDrawing.drawSquare(new Vector2(contour.verts[0].x + offset.x, -contour.verts[0].y + offset.y), 2); for (int i = 1; i < contour.vertCount; i++) { Handles.color = splineColor; Handles.DrawLine(new Vector3(contour.verts[i - 1].x + offset.x, -contour.verts[i - 1].y + offset.y, 0), new Vector3(contour.verts[i].x + offset.x, -contour.verts[i].y + offset.y, 0)); } Handles.color = closeColor; if (contour.isClosed) { Handles.DrawLine(new Vector3(contour.verts[contour.vertCount - 1].x + offset.x, -contour.verts[contour.vertCount - 1].y + offset.y, 0), new Vector3(contour.verts[0].x + offset.x, -contour.verts[0].y + offset.y, 0)); } Handles.color = Color.magenta; for (int pc = 1; pc < parts.Count; pc++) { // origin Handles.color = new Color(0, 1, 0, .5f); GUIDrawing.drawSquare(new Vector2(parts[pc].verts[0].x + offset.x, -parts[pc].verts[0].y + offset.y), 2); Handles.color = Color.cyan; for (int i = 1; i < parts[pc].vertCount; i++) { Handles.DrawLine(new Vector3(parts[pc].verts[i - 1].x + offset.x, -parts[pc].verts[i - 1].y + offset.y, 0), new Vector3(parts[pc].verts[i].x + offset.x, -parts[pc].verts[i].y + offset.y, 0)); } Handles.DrawLine(new Vector3(parts[pc].verts[parts[pc].vertCount - 1].x + offset.x, -parts[pc].verts[parts[pc].vertCount - 1].y + offset.y, 0), new Vector3(parts[pc].verts[0].x + offset.x, -parts[pc].verts[0].y + offset.y, 0)); } //Debug.Log ("close= "+(contour.vertCount-1)); } } } Handles.EndGUI(); }
public static Mesh triangulate(AXSpline poly, float height, AXTexCoords tex) { // poly has verts that are delimeted by 8888888 for holes //Debug.Log ("F"); // 1. transpose points to poly2tri structures // 2. create mesh Polygon _polygon = null; List <AXSpline> parts = poly.getSolidAndHoles(); if (parts == null || parts.Count == 0) { return(null); } // CONTOUR AXSpline contour = parts[0]; List <PolygonPoint> _points = new List <PolygonPoint>(); for (int ii = 0; ii < contour.vertCount; ii++) { _points.Add(new PolygonPoint((double)contour.verts[ii].x, (double)contour.verts[ii].y)); } // POLYGON if (_points.Count >= 3) { _polygon = new Polygon(_points); // HOLES? if (parts.Count > 1) { for (int i = 1; i < parts.Count; i++) { List <PolygonPoint> _holepoints = new List <PolygonPoint>(); for (int ii = 0; ii < parts[i].vertCount; ii++) { _holepoints.Add(new PolygonPoint((double)parts[i].verts[ii].x, (double)parts[i].verts[ii].y)); } if (_holepoints.Count >= 3) { Polygon _hole = new Polygon(_holepoints); _polygon.AddHole(_hole); } } } } // populate the polygon triangles if (_polygon != null) { P2T.Triangulate(_polygon); return(polygon2mesh(_polygon, tex)); } return(null); }
/* * public void setElev(Vector3 a, Vector3 b, Vector3 c) * { * _elev = new Plane(a, b, c); * } * public void setBase(Vector3 a, Vector3 b, Vector3 c) * { * _base = new Plane(a, b, c); * } */ public Mesh generate(AXSpline spline, float _height) { // If a GameObject is passed, just replace its mesh. Debug.Log("--- Extrude: " + spline.toString()); height = _height; float[] angles = spline.getAnglesArray(); int edgeLoopVertCt = spline.getAllocateVertsCt(); if (spline.isClosed && !spline.closeJointIsAcute()) // add a close rib { edgeLoopVertCt++; } int totalVertCount = 0; int totalTriangCount = 0; int vcount = spline.vertCount; if (!spline.isClosed) { vcount--; } totalVertCount += ((segs + 1) * edgeLoopVertCt); totalTriangCount += 3 * (segs * (2 * vcount)); //Debug.Log ("totalVertCount="+totalVertCount); spline.getAnglesArray(); spline.getUValues(); Vector3[] vertices = new Vector3[totalVertCount]; Vector2[] uv = new Vector2[totalVertCount]; int[] triangles = new int[totalTriangCount * 2]; int index = 0; int vertCount = 0; int segThis = 0; // Create the Geometry // Run around the outline float x = 0; float y = 0; float z = 0; float u = 0; float v = 0; int i; float segHgt; int reps = spline.vertCount - 1; if (spline.isClosed) { reps++; } //Debug.Log ("reps="+reps); // SIDE VERTICES for (int seg = 0; seg <= segs; seg++) { // each vert on spline for (i = 0; i <= reps; i++) { segHgt = getHeight(spline.verts[i].x, spline.verts[i].y, seg); if (i == spline.vertCount) { x = spline.verts[0].x; y = segHgt; z = spline.verts[0].y; } else { x = spline.verts[i].x; y = segHgt; z = spline.verts[i].y; } if (rotSidesTex && axis != Axis.Y) { //Debug.Log ("use height of extrude for u, heigth of vert for v"); u = height * (seg / segs); v = z; } else { // Y-Axis, use length along spline if (i == 0) { u = 0; } else if (i == spline.vertCount) { u = spline.getLength(); } else { u = spline.curve_distances[i]; } v = height * (seg / segs); } u /= uScale; v /= vScale; u += uShift; v += vShift; vertices[vertCount] = new Vector3(x, y, z); // bottom uv[vertCount] = new Vector2(u, v); vertCount++; if (spline.jointIsAcute(i)) { vertices[vertCount] = new Vector3(x, y, z); uv[vertCount] = new Vector2(u, v); vertCount++; } } // end edge loop // if first vertex is acute, close loop by addeding vert0 /* * if (angles[0] > spline.breakAngle) { * u = 1; * * vertices[vertCount] = vert0; * uv[vertCount] = new Vector2(u,v); * vertCount++; * } */ // Added bottom, now jump to next horizontal.... if (seg == 0) { continue; } // skin between this edgeLoop and the previous segThis = seg; // TRIANGLES ///////////////////////////////////////////////////////////////////////////////////////// // now make triangles var segPrev = segThis - 1; int this_L; int this_U; int next_L = -1; int next_U = -1; var edgeloop_cursor = 0; for (i = 0; i < reps; i++) { if (angles[i] > spline.breakAngle && i > 0) { edgeloop_cursor++; } this_L = segPrev * edgeLoopVertCt + edgeloop_cursor; next_L = segPrev * edgeLoopVertCt + ((edgeloop_cursor + 1) % edgeLoopVertCt); this_U = segThis * edgeLoopVertCt + edgeloop_cursor; next_U = segThis * edgeLoopVertCt + ((edgeloop_cursor + 1) % edgeLoopVertCt); triangles[index++] = next_L; triangles[index++] = this_L; triangles[index++] = this_U; triangles[index++] = next_U; triangles[index++] = next_L; triangles[index++] = this_U; edgeloop_cursor++; } } // end segs Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.uv = uv; mesh.triangles = triangles; mesh.RecalculateNormals(); /* * // adjust normals for first and last vert * if (! spline.closeJointIsAcute()) * { * Vector3[] norms = mesh.normals; * Quaternion rotation; * * // first rib * rotation = Quaternion.Euler(0, spline.angles[0], 0); * norms[0] = rotation * norms[0]; * norms[edgeLoopVertCt] = rotation * norms[edgeLoopVertCt]; * * // last rib * rotation = Quaternion.Euler(0, -spline.angles[0], 0); * norms[spline.vertCount-1] = rotation * norms[spline.vertCount-1]; * norms[spline.vertCount-1+edgeLoopVertCt] = rotation * norms[spline.vertCount-1+edgeLoopVertCt]; * * mesh.normals = norms; * } */ return(mesh); }
public Mesh generate(AXSpline _planSpline, AXSpline _sectionSpline, float uShiftNow, float vShiftNow) { _planSpline.removeLastVertIfIdenticalToFirst(); //Debug.Log ("topCap="+topCap+", planSpline.isClosed="+_planSpline.isClosed + " : sectionSpline.isClosed=" + _sectionSpline.isClosed); if (uShiftNow != 0) { uShift = uShiftNow; } if (vShiftNow != 0) { vShift = vShiftNow; } if (_planSpline == null || _planSpline.vertCount == 0 || _sectionSpline == null || _sectionSpline.vertCount == 0) { return(null); } // plan spline AXSpline planSpline = _planSpline; // LATER: calc this on whether vert 0 and n are the same. planSpline.isClosed = false; planSpline.calcStats(); planSpline.getUValues(); // section spline AXSpline sectionSpline; sectionSpline = _sectionSpline.turnRight(); sectionSpline.isClosed = true; //_sectionSpline.isClosed; sectionSpline.breakAngle = _sectionSpline.breakAngle; int index = 0; if (!planSpline.isClosed && !sectionSpline.isClosed) { begCap = false; endCap = false; } // ALLOCATE ARRAYS //////////////////////////////////////////////////////////// // SECTION ALLOCATION int sec_AdjustedVertsCount = sectionSpline.getAllocateVertsCt(); //if (sectionSpline.isClosed && ! sectionSpline.closeJointIsAcute()) // add a close rib // sec_AdjustedVertsCount++; // PLAN ALLOCATION int plan_AdjustedVertsCount = planSpline.getAllocateVertsCt(); if (planSpline.isClosed && !planSpline.closeJointIsAcute()) // add a close rib { plan_AdjustedVertsCount++; } int fabricVertCount = plan_AdjustedVertsCount * sec_AdjustedVertsCount + 2; //Debug.Log // use the count of sides to determine the quads count in the extrusion int planSides = planSpline.vertCount; if (!planSpline.isClosed) { planSides--; } int sectionSides = sectionSpline.vertCount; if (!sectionSpline.isClosed) { sectionSides--; } int quadCount = planSides * sectionSides; int totalVertCount = fabricVertCount; int totalTriangCount = 3 * 2 * quadCount; Vector3[] vertices = new Vector3[totalVertCount]; Vector2[] uv = new Vector2[totalVertCount]; int[] triangles = new int[totalTriangCount]; //Debug.Log("plan_AdjustedVertsCount="+plan_AdjustedVertsCount+", sec_AdjustedVertsCount="+sec_AdjustedVertsCount+", fabricVertCount = "+ fabricVertCount); // 1. CREATE VERTICES ////////////////////////////////////////////////////////// // i is current vert: // // (i-1) // | // | // | edgeAfter // | // | // (i) // / // / // / edgeBefore // / // / // (i-1) int ribCount = 0; int planRib_VertCursor = 0; int vertCursor0 = 0; Vector2 edgeBefore = Vector2.zero; Vector2 edgeBeforePerp = Vector2.zero; Vector2 edgeBeforePerpN = Vector2.zero; Vector2 edgeAfter = Vector2.zero; Vector2 edgeAfterPerp = Vector2.zero; Vector2 edgeAfterPerpN = Vector2.zero; float uScalerAfter = 1f; float plan_u = 0f; // FOR EACH PLAN VERT for (int i = 0; i < planSpline.vertCount; i++) { //Debug.Log ("New PLAN POINT: " + i + " :: ribCount=" + ribCount + ", sec_AdjustedVertsCount="+sec_AdjustedVertsCount); planRib_VertCursor = ribCount * sec_AdjustedVertsCount; Debug.Log("planRib_VertCursor[" + i + "] = " + planRib_VertCursor); plan_u = planSpline.curve_distances[i] / uScale; //Debug.Log (planSpline.angles[i]); // EACH Plan node // ASSUME: If spline is open then the first and last are perpendicular to the end segments. // For each plan point, find the transformation matrix withwhich to transform the section as a "rib" // Then traverse the section verts and mutiply them by the plan point matrix. Matrix4x4 transMatrix = Matrix4x4.identity; Vector3 translation = new Vector3(planSpline.verts[i].x, 0.0f, planSpline.verts[i].y); Quaternion rotation = Quaternion.identity; Vector3 scaler = Vector3.one; if (!planSpline.isClosed && (i == 0 || i == planSpline.vertCount - 1)) { // open plan has special treatment of first and last verts if (i == 0) { edgeAfter = planSpline.verts[i + 1] - planSpline.verts[i]; edgeAfterPerp = new Vector2(edgeAfter.y, -edgeAfter.x); edgeAfterPerpN = edgeAfterPerp.normalized; rotation = Quaternion.FromToRotation(Vector3.right, new Vector3(edgeAfterPerp.x, 0, edgeAfterPerp.y)); } else { edgeBefore = planSpline.verts[i] - planSpline.verts[i - 1]; edgeBeforePerp = new Vector2(edgeAfter.y, -edgeAfter.x); edgeBeforePerpN = edgeBeforePerp.normalized; rotation = Quaternion.FromToRotation(Vector3.right, new Vector3(edgeBeforePerp.x, 0, edgeBeforePerp.y)); } // scaler remains one } else { if (i == 0) { edgeBefore = planSpline.verts[i] - planSpline.verts[planSpline.vertCount - 1]; } else { edgeBefore = planSpline.verts[i] - planSpline.verts[i - 1]; } edgeBeforePerp = new Vector2(edgeBefore.y, -edgeBefore.x); edgeBeforePerpN = edgeBeforePerp.normalized; if (i == planSpline.vertCount - 1) { edgeAfter = planSpline.verts[0] - planSpline.verts[i]; } else { edgeAfter = planSpline.verts[i + 1] - planSpline.verts[i]; } edgeAfterPerp = new Vector2(edgeAfter.y, -edgeAfter.x); edgeAfterPerpN = edgeAfterPerp.normalized; // the addition of the normalized perpendicular vectors leads to a bisector Vector2 bisector = edgeAfterPerpN + edgeBeforePerpN; rotation = Quaternion.FromToRotation(Vector3.right, new Vector3(bisector.x, 0, bisector.y)); float biAngle = Vector2.Angle(bisector, edgeAfter); // we can get the scaler from the dot product float scalerVal = 1 / Vector2.Dot(edgeBeforePerpN, bisector.normalized); scaler = new Vector3(scalerVal, 1, 1); uScalerAfter = scalerVal * Mathf.Cos(Mathf.Deg2Rad * biAngle); //Debug.Log ("biAngle="+biAngle + " :: " + Mathf.Cos (Mathf.Deg2Rad*biAngle) + ", scalerVal="+scalerVal + " -- " + scalerVal*Mathf.Cos (Mathf.Deg2Rad*biAngle)); } //Debug.Log("["+i+"] " + translation + " :: " + rotation + " :: " + scaler); transMatrix.SetTRS(translation, rotation, scaler); // ADD RIB ----------------------------------------------------------------------------- // FOR EACH POINT IN SECTION SPLINE (sectionSpline) int section_VertCursor = 0; Vector3 vert = Vector3.zero; int j; float u = 0; float nu = 0; float v = 0; int ribEnd_vertIndex = 0; int ribBeg_vertIndex = 0; // ** A RIB ** // ** each spline vert // ** - transform by plan location, rotation and scale for (j = 0; j <= sectionSpline.vertCount; j++) { if (!sectionSpline.isClosed && j == sectionSpline.vertCount) { break; } /* **** VERT IS CREATED *** */ if (j == sectionSpline.vertCount) // return to first vert { vert = transMatrix.MultiplyPoint(new Vector3(-sectionSpline.verts[0].y, sectionSpline.verts[0].x, 0)); } else { vert = transMatrix.MultiplyPoint(new Vector3(-sectionSpline.verts[j].y, sectionSpline.verts[j].x, 0)); } // THIS IS THE MAIN SECTION OF CODE // // Determine UV coordinates // THIS_U if (i == 0 && !planSpline.closeJointIsAcute()) { u = uShift + plan_u; } else { u = uShift + plan_u - (uScalerAfter * sectionSpline.verts[j].y / uScale); } // NEXT_U (AFTER BREAK BUT AT SAME LOCATION) if (planSpline.jointIsAcute(i) || (i == 0 && planSpline.closeJointIsAcute())) { if (i == 0 && planSpline.isClosed) { nu = uShift + (planSpline.getLength() / uScale) + (uScalerAfter * sectionSpline.verts[j].y / uScale); } else { nu = uShift + plan_u + (uScalerAfter * sectionSpline.verts[j].y / uScale); } } else { if (i == 0 && planSpline.isClosed) { nu = uShift + (planSpline.getLength() / uScale); } else { nu = uShift + plan_u; } } // THIS_V if (j == sectionSpline.vertCount) { v = vShift + sectionSpline.getLength() / vScale; } else { v = vShift + sectionSpline.curve_distances[j] / vScale; } // determine vertices address if (i == 0 && planSpline.isClosed) { ribEnd_vertIndex = (fabricVertCount - sec_AdjustedVertsCount) + section_VertCursor; ribBeg_vertIndex = planRib_VertCursor + section_VertCursor; } else { ribEnd_vertIndex = planRib_VertCursor + section_VertCursor; ribBeg_vertIndex = planRib_VertCursor + section_VertCursor + sec_AdjustedVertsCount; } // ** ADD THIS VERT TO MESH VERTICES ** vertices[ribEnd_vertIndex] = vert; uv[ribEnd_vertIndex] = new Vector2(nu, v); //Debug.Log ("Add ribEnd_vertIndex="+ribEnd_vertIndex + " -- "+vertices[ribEnd_vertIndex]); if ((i > 0 && planSpline.jointIsAcute(i)) || (i == 0 && planSpline.isClosed)) { // add an additional vert in the next rib (in same location vertices[ribBeg_vertIndex] = vert; uv[ribBeg_vertIndex] = new Vector2(u, v); //Debug.Log ("Add ribBeg_vertIndex="+ribBeg_vertIndex + " -- "+vertices[ribBeg_vertIndex]); } section_VertCursor++; // SECTION BREAK? if (j < sectionSpline.vertCount && sectionSpline.jointIsAcute(j)) { // ** ADD THIS VERT TO MESH VERTICES (AGAIN) ** (and restart the u?) // add an additional section point in the same location if (i == 0 && planSpline.isClosed) { ribEnd_vertIndex = (fabricVertCount - sec_AdjustedVertsCount) + section_VertCursor; ribBeg_vertIndex = planRib_VertCursor + section_VertCursor; } else { ribEnd_vertIndex = planRib_VertCursor + section_VertCursor; ribBeg_vertIndex = planRib_VertCursor + section_VertCursor + sec_AdjustedVertsCount; } //Debug.Log ("ribEnd_vertIndex="+ribEnd_vertIndex+", ribBeg_vertIndex="+ribBeg_vertIndex + " -- "+vertices[ribBeg_vertIndex]); vertices[ribEnd_vertIndex] = vert; uv[ribEnd_vertIndex] = new Vector2(nu, v); //Debug.Log ("Add ribEnd_vertIndex="+ribEnd_vertIndex + " -- "+vertices[ribEnd_vertIndex]); if ((i > 0 && planSpline.jointIsAcute(i)) || (i == 0 && planSpline.isClosed)) { // add an additional vert in the next rib (in same location vertices[ribBeg_vertIndex] = vert; uv[ribBeg_vertIndex] = new Vector2(u, v); //Debug.Log ("Add ribBeg_vertIndex="+ribBeg_vertIndex + " -- "+vertices[ribBeg_vertIndex]); } section_VertCursor++; } } ribCount++; // COUNT THIS RIB, ie, RIB if (planSpline.jointIsAcute(i)) { ribCount++; // ADD ADDITIONAL RIB COUNT } } // 2. CREATE TRIANGLES ////////////////////////////////////////////////////////// int LRib_L; int RRib_L; int LRib_U; int RRib_U; int leftRib = 0; // FOREACH PLAN NODE....... for (int i = 1; i <= planSpline.vertCount; i++) { if (i == planSpline.vertCount && !planSpline.isClosed) { break; } // from left to right planRib_VertCursor = leftRib * sec_AdjustedVertsCount; vertCursor0 = planRib_VertCursor; // FOREACH SEC NODE....... for (int j = 1; j <= sectionSpline.vertCount; j++) { if (j == sectionSpline.vertCount && !sectionSpline.isClosed) { break; } LRib_L = planRib_VertCursor; if (j == sectionSpline.vertCount && sectionSpline.isClosed && !sectionSpline.closeJointIsAcute()) { //Debug.Log ("GOING BACK TO SEC ORIGN..."); LRib_U = vertCursor0; } else { LRib_U = LRib_L + 1; } // use next rib's points ( Never loop back to use rib0) RRib_L = LRib_L + sec_AdjustedVertsCount; RRib_U = LRib_U + sec_AdjustedVertsCount; triangles[index++] = LRib_L; triangles[index++] = RRib_U; triangles[index++] = RRib_L; triangles[index++] = LRib_L; triangles[index++] = LRib_U; triangles[index++] = RRib_U; planRib_VertCursor++; if (j < sectionSpline.vertCount && sectionSpline.jointIsAcute(j)) { planRib_VertCursor++; } } // GO TO NEXT SEGMENT leftRib++; if (i < planSpline.vertCount && planSpline.jointIsAcute(i)) { leftRib++; } } Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.uv = uv; mesh.triangles = triangles; // Auto-calculate vertex normals from the mesh mesh.RecalculateNormals(); return(mesh); }
// Constructors public Mesh generate(AXSpline _planSpline, AXSpline _sectionSpline) { return(generate(_planSpline, _sectionSpline, 0f, 0f)); }
public Mesh generate(AXSpline _sectionSpline, float radius, int segs, float begAng, float endAng) { if (_sectionSpline == null || _sectionSpline.verts == null || _sectionSpline.verts.Length == 0 || float.IsNaN(_sectionSpline.verts[0].x)) { return(new Mesh()); } if (radius <= 0) { radius = .01f; } //Debug.Log (float.IsNaN(_sectionSpline.verts[0].x)); //return new Mesh(); if (segs < 3) { segs = 3; } // section spline AXSpline sectionSpline; sectionSpline = _sectionSpline.turnRight(); sectionSpline.isClosed = _sectionSpline.isClosed; sectionSpline.breakAngle = _sectionSpline.breakAngle; // Cap Splines AXSpline3 planSplineBegCap = new AXSpline3(); AXSpline3 planSplineEndCap = new AXSpline3(); AXSpline3 secSplineBegCap = new AXSpline3(); AXSpline3 secSplineEndCap = new AXSpline3(); int index = 0; float arcDegs = endAng - begAng; float deltaAng = arcDegs / segs; Vector3 scaler = new Vector3((1 / Mathf.Cos(Mathf.Deg2Rad * deltaAng / 2)), 1, 1); bool circleIsClosed = false; int circleAdjustedVertCount = segs + 1; if (arcDegs == 360) { circleIsClosed = true; } bool circleIsAccute = false; if (deltaAng > breakAngle) { circleIsAccute = true; circleAdjustedVertCount += (circleAdjustedVertCount - 2); } float segLength = 2 * radius * Mathf.Sin(Mathf.Deg2Rad * deltaAng / 2); //Debug.Log ("segLength = " + segLength); // ALLOCATE ARRAYS //////////////////////////////////////////////////////////// //float[] sec_Angles = sectionSpline.getAnglesArray(); int sec_AdjustedVertsCount = sectionSpline.getAllocateVertsCt(); int fabricVertCount = circleAdjustedVertCount * sec_AdjustedVertsCount; //Debug.Log ("fabricVertCount="+fabricVertCount); int begCapVertCount = 0; int endCapVertCount = 0; if (begCap) { if (circleIsClosed) { //if(circleIsAccute) fabricVertCount += circleAdjustedVertCount; begCapVertCount = segs; } else if (sectionSpline.isClosed) { //if(sectionSpline.closeJointIsAcute()) fabricVertCount += sec_AdjustedVertsCount; begCapVertCount = sectionSpline.vertCount; } } if (endCap) { if (circleIsClosed) { //if(circleIsAccute) fabricVertCount += circleAdjustedVertCount; endCapVertCount = segs; } else if (sectionSpline.isClosed) { //if(sectionSpline.closeJointIsAcute()) fabricVertCount += sec_AdjustedVertsCount; endCapVertCount = sectionSpline.vertCount; } } int totalVertCount = fabricVertCount + begCapVertCount + endCapVertCount; int faceCount = segs * (sectionSpline.vertCount - 1); int facesTriangleCount = 3 * 2 * faceCount; int begTriangleCount = (begCap) ? (3 * (begCapVertCount - 2)) : 0; int endTriangleCount = (endCap) ? (3 * (endCapVertCount - 2)) : 0; int totalTriangCount = facesTriangleCount + begTriangleCount + endTriangleCount; Vector3[] vertices = new Vector3[totalVertCount]; Vector2[] uv = new Vector2[totalVertCount]; int[] triangles = new int[totalTriangCount]; float u = 0.0f; float v = 0.0f; // 1. CREATE VERTICES ////////////////////////////////////////////////////////// // i is current vert: // // (i-1) // | // | // | edgeAfter // | // | // (i) // / // / // / edgeBefore // / // / // (i-1) int ribCounter = 0; int vertCursor = 0; int vertCursor0 = 0; if (arcDegs == 360) { //endAng = 360-deltaAng; } // FOR EACH VERT IN ARC // For arc vert, find the transformation matrix withwhich to transform the section as a "rib" // Then traverse the section verts and mutiply them by the matrix. // If arc is open (less than 360 degs), then the first and last ribs make the caps. float theta_i = 0; for (int i = 0; i <= segs; i++) { theta_i = i * deltaAng + begAng; u = uShift + i * segLength / uScale; vertCursor = ribCounter * sec_AdjustedVertsCount; Vector2 arc_vert = new Vector2(radius * Mathf.Cos(Mathf.Deg2Rad * theta_i), radius * Mathf.Sin(Mathf.Deg2Rad * theta_i)); Matrix4x4 transMatrix = Matrix4x4.identity; Vector3 translation = new Vector3(arc_vert.x, 0, arc_vert.y); Quaternion rotation = Quaternion.Euler(new Vector3(0, -theta_i, 0));; transMatrix.SetTRS(translation, rotation, scaler); // ADD RIB ----------------------------------------------------------------------------- // FOR EACH POINT IN SECTION SPLINE (sectionSpline) int thisRibVertCursor = 0; Vector3 vert0 = Vector3.zero; Vector3 vert = Vector3.zero; //u = 0.0f; v = 0.0f; int j; // ** A RIB ** // ** each spline vert // ** - transform by plan location, rotation and scale for (j = 0; j < sectionSpline.vertCount; j++) { /* **** VERT IS CREATED *** */ vert = transMatrix.MultiplyPoint(new Vector3(-sectionSpline.verts[j].y, sectionSpline.verts[j].x, 0)); if (j == 0) { vert0 = vert; } //if (j>0) v = vShift + sectionSpline.curve_distances[j] / vScale; // BUILDUP CAP POLYGON VERTS everytime you start and finish a sec rib. Vector3 thisVert = new Vector3(vert.x, vert.y, vert.z); if (circleIsClosed) { // circle is closed if (begCap && j == 0) { planSplineBegCap.Push(thisVert); } if (endCap && j == (sectionSpline.vertCount - 1)) { planSplineEndCap.Push(thisVert); } } else if (sectionSpline.isClosed) { // circle is open -- end caps if (begCap && theta_i == begAng) { secSplineBegCap.Push(thisVert); } if (endCap && theta_i == endAng) { secSplineEndCap.Push(thisVert); } } // ** ADD THIS VERT TO MESH VERTICES ** vertices[vertCursor + thisRibVertCursor] = vert; uv[vertCursor + thisRibVertCursor] = new Vector2(u, v); thisRibVertCursor++; if (sectionSpline.jointIsAcute(j)) { // ** ADD THIS VERT TO MESH VERTICES (AGAIN) ** (and restart the u?) vertices[vertCursor + thisRibVertCursor] = vert; uv[vertCursor + thisRibVertCursor] = new Vector2(u, v); thisRibVertCursor++; } } if (sectionSpline.isClosed) { if (sectionSpline.closeJointIsAcute()) { //float d = Vector3.Distance(preVert, vert0); //Debug.Log (d); //u += d/100.0f; //Debug.Log ("u="+u); vertices[vertCursor + thisRibVertCursor] = vert0; uv[vertCursor + thisRibVertCursor] = new Vector2(u, v); } } // GET READY FOR NEXT PLAN VERT, ie, RIB ribCounter++; if (i > 0 && i < segs && circleIsAccute) { // ADD RIB ----------------------------------------------------------------------------- for (var n = 0; n < sec_AdjustedVertsCount; n++) { vertices[vertCursor + n + sec_AdjustedVertsCount] = vertices[vertCursor + n]; uv[vertCursor + n + sec_AdjustedVertsCount] = uv[vertCursor + n]; } u = 0.0f; ribCounter++; } } vertCursor = ribCounter * sec_AdjustedVertsCount; //int tmp = vertCursor-1; /* * if (i == segs && circleIsClosed && circleIsAccute) { * // ADD RIB ------------------------------------- DUPLICATE FIRST RIB -------------------- * for(int n=0; n<sec_AdjustedVertsCount; n++) { * vertices[vertCursor+n] = vertices[n]; * uv[vertCursor+n] = new Vector2(uScale, uv[n].y); * } * * } */ // 2. CREATE TRIANGLES ////////////////////////////////////////////////////////// int LRib_L; int RRib_L; int LRib_U; int RRib_U; int leftRib = 0; // FOREACH PLAN NODE....... for (int i = 0; i < segs; i++) { vertCursor = leftRib * sec_AdjustedVertsCount; vertCursor0 = vertCursor; // FOREACH SEC NODE....... for (int j = 1; j < sectionSpline.vertCount; j++) { //if (j == sectionSpline.vertCount-1 && ! sectionSpline.isClosed) // break; LRib_L = vertCursor; if (j == sectionSpline.vertCount && sectionSpline.isClosed && !sectionSpline.closeJointIsAcute()) { Debug.Log("GOING BACK TO SEC ORIGN..."); LRib_U = vertCursor0; } else { LRib_U = LRib_L + 1; } if (circleIsClosed && i == segs && !circleIsAccute) { // use rib0 RRib_L = LRib_L - fabricVertCount + sec_AdjustedVertsCount; RRib_U = LRib_U - fabricVertCount + sec_AdjustedVertsCount;; } else { // use next rib's points RRib_L = LRib_L + sec_AdjustedVertsCount; RRib_U = LRib_U + sec_AdjustedVertsCount; } triangles[index++] = LRib_L; triangles[index++] = RRib_U; triangles[index++] = RRib_L; triangles[index++] = LRib_L; triangles[index++] = LRib_U; triangles[index++] = RRib_U; vertCursor++; if (j < sectionSpline.vertCount && sectionSpline.jointIsAcute(j)) { vertCursor++; } } // GO TO NEXT SEGMENT leftRib++; if (i < (segs + 1) && circleIsAccute) { leftRib++; } } //for (int l = 0; l<vertices.Length; l++) // Debug.Log (l+": " + vertices[l]); // CAPS //////////////////////// if (isCapped) { //int vertCount = fabricVertCount; //int[] indices; //Vector2[] vertices2D; if ((botCap || topCap) && circleIsClosed && !sectionSpline.isClosed) { // planSpline CAPS // BOT_CAP /* * if (botCap) { * // BOT_CAP VERTS * * for (int i=0; i<planSplineBegCap.vertCount; i++) { * vertices[vertCount+i] = new Vector3(planSplineBegCap.verts[i].x, planSplineBegCap.verts[i].y, planSplineBegCap.verts[i].z); * uv [vertCount+i] = new Vector2 (uShift+planSplineBegCap.verts[i].x/uScale, vShift+planSplineBegCap.verts[i].z/vScale); * } * * // INDICES * * AXSpline begCapSlpine = new AXSpline(planSplineBegCap.getVertsAsVector2s()); * * * vertices2D = begCapSlpine.getVertsAsVector2s(); * * * tr = new Triangulator(vertices2D); * indices = tr.Triangulate(); * * // flip * int[] indicesFlipped = new int[indices.Length]; * int c = 0; * for(int i=(indices.Length-1); i >= 0; i--) * indicesFlipped[c++] = indices[i]; * * * for(int i=0; i<indicesFlipped.Length; i++) * triangles[index++] = indicesFlipped[i] + vertCount; * * * vertCount += planSplineBegCap.vertCount; * * } * * * * // TOP CAP * * if (topCap) { * // TOP CAP VERTS * * for (int i=0; i<planSplineEndCap.vertCount; i++) { * vertices[vertCount+i] = new Vector3(planSplineEndCap.verts[i].x, planSplineEndCap.verts[i].y, planSplineEndCap.verts[i].z); * uv [vertCount+i] = new Vector2 (planSplineEndCap.verts[i].x/uScale, planSplineEndCap.verts[i].z/vScale); * } * * // INDICES * AXSpline endCapSlpine = new AXSpline(planSplineEndCap.getVertsAsVector2s()); * vertices2D = endCapSlpine.getVertsAsVector2s(); * * tr = new Triangulator(vertices2D); * indices = tr.Triangulate(); * for(int i=0; i<indices.Length; i++) * { * triangles[index++] = indices[i] + vertCount; * } * vertCount += planSplineEndCap.vertCount; * } * * * * */ } else if (!circleIsClosed && sectionSpline.isClosed) { // SS CAPS // SEC BEG CAP VERTS // The indices are independent of where the sec points are in space //vertices2D = sectionSpline.getVertsAsVector2s(); /* * tr = new Triangulator(vertices2D); * indices = tr.Triangulate(); * * * * // SEC BEG CAP * if (begCap) * { * for (int i=0; i<secSplineBegCap.vertCount; i++) { * vertices[vertCount+i] = new Vector3(secSplineBegCap.verts[i].x, secSplineBegCap.verts[i].y, secSplineBegCap.verts[i].z); * uv [vertCount+i] = new Vector2 (secSplineBegCap.verts[i].x/uScale, secSplineBegCap.verts[i].y/vScale); * } * for(int i=0; i<indices.Length; i++) * triangles[index++] = indices[i] + vertCount; * * vertCount += secSplineBegCap.vertCount; * } * * * // SEC END CAP * if (endCap) * { * for (int i=0; i<secSplineEndCap.vertCount; i++) { * vertices[vertCount+i] = new Vector3(secSplineEndCap.verts[i].x, secSplineEndCap.verts[i].y, secSplineEndCap.verts[i].z); * uv [vertCount+i] = new Vector2 (secSplineEndCap.verts[i].x/uScale, secSplineEndCap.verts[i].y/vScale); * } * for(int i=indices.Length-1; i>=0; i--) * triangles[index++] = indices[i] + vertCount; * * vertCount += secSplineBegCap.vertCount; * } * */ } } Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.uv = uv; mesh.triangles = triangles; // Auto-calculate vertex normals from the mesh mesh.RecalculateNormals(); // adjust normals for first and last vert if (!circleIsAccute) { //Debug.Log ("adjust normals"); Vector3[] norms = mesh.normals; Quaternion rotation0 = Quaternion.Euler(0, deltaAng / 2, 0); Quaternion rotationN = Quaternion.Euler(0, -deltaAng / 2, 0); int lastRibV0 = (circleAdjustedVertCount - 1) * sec_AdjustedVertsCount; for (int jj = 0; jj < sec_AdjustedVertsCount; jj++) { // first rib norms[jj] = rotation0 * norms[jj]; // last rib norms[lastRibV0 + jj] = rotationN * norms[lastRibV0 + jj]; } mesh.normals = norms; } return(mesh); }
// Constructors public Mesh generate(AXSpline _sectionSpline, float radius, int segs) { return(generate(_sectionSpline, radius, segs, 0, 360)); }