/* * 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); }