internal Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals) { this.calcVertexNormals = calcVertexNormals; coords = new List<Coord> (); faces = new List<Face> (); vertexNormals = new List<Coord> (); us = new List<float> (); faceUVs = new List<UVCoord> (); faceNumbers = new List<int> (); Coord center = new Coord (0.0f, 0.0f, 0.0f); List<Coord> hollowCoords = new List<Coord> (); List<Coord> hollowNormals = new List<Coord> (); List<float> hollowUs = new List<float> (); if (calcVertexNormals) { outerCoordIndices = new List<int> (); hollowCoordIndices = new List<int> (); cut1CoordIndices = new List<int> (); cut2CoordIndices = new List<int> (); } bool hasHollow = (hollow > 0.0f); bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f); AngleList angles = new AngleList (); AngleList hollowAngles = new AngleList (); float xScale = 0.5f; float yScale = 0.5f; if (sides == 4) // corners of a square are sqrt(2) from center { xScale = 0.707107f; yScale = 0.707107f; } float startAngle = profileStart * twoPi; float stopAngle = profileEnd * twoPi; try { angles.makeAngles (sides, startAngle, stopAngle); } catch (Exception ex) { errorMessage = "makeAngles failed: Exception: " + ex + "\nsides: " + sides + " startAngle: " + startAngle + " stopAngle: " + stopAngle; return; } numOuterVerts = angles.angles.Count; // flag to create as few triangles as possible for 3 or 4 side profile bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut); if (hasHollow) { if (sides == hollowSides) hollowAngles = angles; else { try { hollowAngles.makeAngles (hollowSides, startAngle, stopAngle); } catch (Exception ex) { errorMessage = "makeAngles failed: Exception: " + ex + "\nsides: " + sides + " startAngle: " + startAngle + " stopAngle: " + stopAngle; return; } } numHollowVerts = hollowAngles.angles.Count; } else if (!simpleFace) { coords.Add (center); if (this.calcVertexNormals) vertexNormals.Add (new Coord (0.0f, 0.0f, 1.0f)); us.Add (0.0f); } const float z = 0.0f; Angle angle; Coord newVert = new Coord (); if (hasHollow && hollowSides != sides) { int numHollowAngles = hollowAngles.angles.Count; for (int i = 0; i < numHollowAngles; i++) { angle = hollowAngles.angles [i]; newVert.X = hollow * xScale * angle.X; newVert.Y = hollow * yScale * angle.Y; newVert.Z = z; hollowCoords.Add (newVert); if (this.calcVertexNormals) { hollowNormals.Add (hollowSides < 5 ? hollowAngles.normals [i].Invert () : new Coord (-angle.X, -angle.Y, 0.0f)); if (hollowSides == 4) hollowUs.Add(angle.angle * hollow * 0.707107f); else hollowUs.Add(angle.angle * hollow); } } } int index = 0; int numAngles = angles.angles.Count; for (int i = 0; i < numAngles; i++) { angle = angles.angles [i]; newVert.X = angle.X * xScale; newVert.Y = angle.Y * yScale; newVert.Z = z; coords.Add (newVert); if (this.calcVertexNormals) { outerCoordIndices.Add (coords.Count - 1); if (sides < 5) { vertexNormals.Add (angles.normals [i]); float u = angle.angle; us.Add (u); } else { vertexNormals.Add (new Coord (angle.X, angle.Y, 0.0f)); us.Add (angle.angle); } } if (hasHollow) { if (hollowSides == sides) { newVert.X *= hollow; newVert.Y *= hollow; newVert.Z = z; hollowCoords.Add (newVert); if (this.calcVertexNormals) { hollowNormals.Add (sides < 5 ? angles.normals [i].Invert () : new Coord (-angle.X, -angle.Y, 0.0f)); hollowUs.Add (angle.angle * hollow); //20151106 - not used here?? } } } else if (!simpleFace && createFaces && angle.angle > 0.0001f) { Face newFace = new Face { v1 = 0, v2 = index, v3 = index + 1 }; faces.Add (newFace); } index += 1; } if (hasHollow) { hollowCoords.Reverse (); if (this.calcVertexNormals) { hollowNormals.Reverse (); hollowUs.Reverse (); } if (createFaces) { int numTotalVerts = numOuterVerts + numHollowVerts; if (numOuterVerts == numHollowVerts) { Face newFace = new Face (); for (int coordIndex = 0; coordIndex < numOuterVerts - 1; coordIndex++) { newFace.v1 = coordIndex; newFace.v2 = coordIndex + 1; newFace.v3 = numTotalVerts - coordIndex - 1; faces.Add (newFace); newFace.v1 = coordIndex + 1; newFace.v2 = numTotalVerts - coordIndex - 2; newFace.v3 = numTotalVerts - coordIndex - 1; faces.Add (newFace); } } else { if (numOuterVerts < numHollowVerts) { Face newFace = new Face (); int j = 0; // j is the index for outer vertices int maxJ = numOuterVerts - 1; for (int i = 0; i < numHollowVerts; i++) // i is the index for inner vertices { if (j < maxJ) if (angles.angles [j + 1].angle - hollowAngles.angles [i].angle < hollowAngles.angles [i].angle - angles.angles [j].angle + 0.000001f) { newFace.v1 = numTotalVerts - i - 1; newFace.v2 = j; newFace.v3 = j + 1; faces.Add (newFace); j += 1; } newFace.v1 = j; newFace.v2 = numTotalVerts - i - 2; newFace.v3 = numTotalVerts - i - 1; faces.Add (newFace); } } else // numHollowVerts < numOuterVerts { Face newFace = new Face (); int j = 0; // j is the index for inner vertices int maxJ = numHollowVerts - 1; for (int i = 0; i < numOuterVerts; i++) { if (j < maxJ) if (hollowAngles.angles [j + 1].angle - angles.angles [i].angle < angles.angles [i].angle - hollowAngles.angles [j].angle + 0.000001f) { newFace.v1 = i; newFace.v2 = numTotalVerts - j - 2; newFace.v3 = numTotalVerts - j - 1; faces.Add (newFace); j += 1; } newFace.v1 = numTotalVerts - j - 1; newFace.v2 = i; newFace.v3 = i + 1; faces.Add (newFace); } } } } if (calcVertexNormals) { foreach (Coord hc in hollowCoords) { coords.Add (hc); hollowCoordIndices.Add (coords.Count - 1); } } else coords.AddRange (hollowCoords); if (this.calcVertexNormals) { vertexNormals.AddRange (hollowNormals); us.AddRange (hollowUs); } } if (simpleFace && createFaces) { if (sides == 3) faces.Add (new Face (0, 1, 2)); else if (sides == 4) { faces.Add (new Face (0, 1, 2)); faces.Add (new Face (0, 2, 3)); } } if (calcVertexNormals && hasProfileCut) { int lastOuterVertIndex = numOuterVerts - 1; if (hasHollow) { cut1CoordIndices.Add (0); cut1CoordIndices.Add (coords.Count - 1); cut2CoordIndices.Add (lastOuterVertIndex + 1); cut2CoordIndices.Add (lastOuterVertIndex); cutNormal1.X = coords [0].Y - coords [coords.Count - 1].Y; cutNormal1.Y = -(coords [0].X - coords [coords.Count - 1].X); cutNormal2.X = coords [lastOuterVertIndex + 1].Y - coords [lastOuterVertIndex].Y; cutNormal2.Y = -(coords [lastOuterVertIndex + 1].X - coords [lastOuterVertIndex].X); } else { cut1CoordIndices.Add (0); cut1CoordIndices.Add (1); cut2CoordIndices.Add (lastOuterVertIndex); cut2CoordIndices.Add (0); cutNormal1.X = vertexNormals [1].Y; cutNormal1.Y = -vertexNormals [1].X; cutNormal2.X = -vertexNormals [vertexNormals.Count - 2].Y; cutNormal2.Y = vertexNormals [vertexNormals.Count - 2].X; } cutNormal1.Normalize (); cutNormal2.Normalize (); } MakeFaceUVs (); hollowCoords = null; hollowNormals = null; hollowUs = null; if (calcVertexNormals) { // calculate prim face numbers // face number order is top, outer, hollow, bottom, start cut, end cut // I know it's ugly but so is the whole concept of prim face numbers int faceNum = 1; // start with outer faces outerFaceNumber = faceNum; int startVert = hasProfileCut && !hasHollow ? 1 : 0; if (startVert > 0) faceNumbers.Add (-1); for (int i = 0; i < numOuterVerts - 1; i++) faceNumbers.Add (sides < 5 && i <= sides ? faceNum++ : faceNum); //if (!hasHollow && !hasProfileCut) // this.bottomFaceNumber = faceNum++; faceNumbers.Add (hasProfileCut ? -1 : faceNum++); if (sides > 4 && (hasHollow || hasProfileCut)) faceNum++; if (sides < 5 && (hasHollow || hasProfileCut) && numOuterVerts < sides) faceNum++; if (hasHollow) { for (int i = 0; i < numHollowVerts; i++) faceNumbers.Add (faceNum); hollowFaceNumber = faceNum++; } //if (hasProfileCut || hasHollow) // this.bottomFaceNumber = faceNum++; bottomFaceNumber = faceNum++; if (hasHollow && hasProfileCut) faceNumbers.Add (faceNum++); for (int i = 0; i < faceNumbers.Count; i++) if (faceNumbers [i] == -1) faceNumbers [i] = faceNum++; numPrimFaces = faceNum; } }
Coord SurfaceNormal(Face face) { return SurfaceNormal (coords [face.v1], coords [face.v2], coords [face.v3]); }
/// <summary> /// ** Experimental ** May disappear from future versions ** not recommended for use in applications /// Construct a sculpt mesh from a 2D array of floats /// </summary> /// <param name="zMap"></param> /// <param name="xBegin"></param> /// <param name="xEnd"></param> /// <param name="yBegin"></param> /// <param name="yEnd"></param> /// <param name="viewerMode"></param> public SculptMesh (float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode) { float xStep, yStep; float uStep, vStep; int numYElements = zMap.GetLength (0); int numXElements = zMap.GetLength (1); try { xStep = (xEnd - xBegin) / (numXElements - 1); yStep = (yEnd - yBegin) / (numYElements - 1); uStep = 1.0f / (numXElements - 1); vStep = 1.0f / (numYElements - 1); } catch (DivideByZeroException) { return; } coords = new List<Coord> (); faces = new List<Face> (); normals = new List<Coord> (); uvs = new List<UVCoord> (); viewerFaces = new List<ViewerFace> (); int p1, p2, p3, p4; int x, y; int xStart = 0, yStart = 0; for (y = yStart; y < numYElements; y++) { int rowOffset = y * numXElements; for (x = xStart; x < numXElements; x++) { /* * p1-----p2 * | \ f2 | * | \ | * | f1 \| * p3-----p4 */ p4 = rowOffset + x; p3 = p4 - 1; p2 = p4 - numXElements; p1 = p3 - numXElements; Coord c = new Coord (xBegin + x * xStep, yBegin + y * yStep, zMap [y, x]); this.coords.Add (c); if (viewerMode) { this.normals.Add (new Coord ()); this.uvs.Add (new UVCoord (uStep * x, 1.0f - vStep * y)); } if (y > 0 && x > 0) { Face f1, f2; if (viewerMode) { f1 = new Face (p1, p4, p3, p1, p4, p3) { uv1 = p1, uv2 = p4, uv3 = p3 }; f2 = new Face (p1, p2, p4, p1, p2, p4) { uv1 = p1, uv2 = p2, uv3 = p4 }; } else { f1 = new Face (p1, p4, p3); f2 = new Face (p1, p2, p4); } this.faces.Add (f1); this.faces.Add (f2); } } } if (viewerMode) calcVertexNormals (SculptType.plane, numXElements, numYElements); }
/// <summary> /// Extrudes a profile along a path. /// </summary> public void Extrude(PathType pathType) { bool needEndFaces = false; coords = new List<Coord> (); faces = new List<Face> (); if (viewerMode) { viewerFaces = new List<ViewerFace> (); calcVertexNormals = true; } if (calcVertexNormals) normals = new List<Coord> (); int steps = 1; float length = pathCutEnd - pathCutBegin; normalsProcessed = false; if (viewerMode && sides == 3) { // prisms don't taper well so add some vertical resolution // other prims may benefit from this but just do prisms for now if (Math.Abs (taperX) > 0.01 || Math.Abs (taperY) > 0.01) steps = (int)(steps * 4.5 * length); } if (sphereMode) hasProfileCut = profileEnd - profileStart < 0.4999f; else hasProfileCut = profileEnd - profileStart < 0.9999f; hasHollow = (hollow > 0.001f); float twistBegin2 = twistBegin / 360.0f * twoPi; float twistEnd2 = twistEnd / 360.0f * twoPi; float twistTotal = twistEnd2 - twistBegin2; float twistTotalAbs = Math.Abs (twistTotal); if (twistTotalAbs > 0.01f) steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number float hollow2 = hollow; // sanity checks float initialProfileRot = 0.0f; if (pathType == PathType.Circular) { if (sides == 3) { initialProfileRot = (float)Math.PI; if (hollowSides == 4) { if (hollow2 > 0.7f) hollow2 = 0.7f; hollow2 *= 0.707f; } else hollow2 *= 0.5f; } else if (sides == 4) { initialProfileRot = 0.25f * (float)Math.PI; if (hollowSides != 4) hollow2 *= 0.707f; } else if (sides > 4) { initialProfileRot = (float)Math.PI; if (hollowSides == 4) { if (hollow2 > 0.7f) hollow2 = 0.7f; hollow2 /= 0.7f; } } } else { if (sides == 3) { if (hollowSides == 4) { if (hollow2 > 0.7f) hollow2 = 0.7f; hollow2 *= 0.707f; } else hollow2 *= 0.5f; } else if (sides == 4) { initialProfileRot = 1.25f * (float)Math.PI; if (hollowSides != 4) hollow2 *= 0.707f; } else if (sides == 24 && hollowSides == 5) hollow2 *= 1.414f; } Profile profile = new Profile (sides, profileStart, profileEnd, hollow2, hollowSides, true, calcVertexNormals); errorMessage = profile.errorMessage; numPrimFaces = profile.numPrimFaces; int cut1FaceNumber = profile.bottomFaceNumber + 1; int cut2FaceNumber = cut1FaceNumber + 1; if (!needEndFaces) { cut1FaceNumber -= 2; cut2FaceNumber -= 2; } profileOuterFaceNumber = profile.outerFaceNumber; if (pathType == PathType.Circular) { needEndFaces = false; if (pathCutBegin != 0.0f || pathCutEnd != 1.0f) needEndFaces = true; else if (taperX != 0.0f || taperY != 0.0f) needEndFaces = true; else if (skew != 0.0f) needEndFaces = true; else if (twistTotal != 0.0f) needEndFaces = true; else if (radius != 0.0f) needEndFaces = true; } else needEndFaces = true; if (!needEndFaces) profileOuterFaceNumber--; if (hasHollow) { profileHollowFaceNumber = profile.hollowFaceNumber; if (!needEndFaces) profileHollowFaceNumber--; } int cut1Vert = -1; int cut2Vert = -1; if (hasProfileCut) { cut1Vert = hasHollow ? profile.coords.Count - 1 : 0; cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts; } if (initialProfileRot != 0.0f) { profile.AddRot (new Quat (new Coord (0.0f, 0.0f, 1.0f), initialProfileRot)); if (viewerMode) profile.MakeFaceUVs (); } Coord lastCutNormal1 = new Coord (); Coord lastCutNormal2 = new Coord (); float thisV = 0.0f; float lastV = 0.0f; Path path = new Path { twistBegin = twistBegin2, //20151106 - original was twistBegin twistEnd = twistEnd2, // ditto for twistEnd topShearX = topShearX, topShearY = topShearY, pathCutBegin = pathCutBegin, pathCutEnd = pathCutEnd, dimpleBegin = dimpleBegin, dimpleEnd = dimpleEnd, skew = skew, holeSizeX = holeSizeX, holeSizeY = holeSizeY, taperX = taperX, taperY = taperY, radius = radius, revolutions = revolutions, stepsPerRevolution = stepsPerRevolution }; path.Create (pathType, steps); for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) { PathNode node = path.pathNodes [nodeIndex]; Profile newLayer = profile.Copy (); newLayer.Scale (node.xScale, node.yScale); newLayer.AddRot (node.rotation); newLayer.AddPos (node.position); if (needEndFaces && nodeIndex == 0) { newLayer.FlipNormals (); // add the top faces to the viewerFaces list here if (viewerMode) { Coord faceNormal = newLayer.faceNormal; ViewerFace newViewerFace = new ViewerFace (profile.bottomFaceNumber); int numFaces = newLayer.faces.Count; List<Face> faces2 = newLayer.faces; for (int i = 0; i < numFaces; i++) { Face face = faces2 [i]; newViewerFace.v1 = newLayer.coords [face.v1]; newViewerFace.v2 = newLayer.coords [face.v2]; newViewerFace.v3 = newLayer.coords [face.v3]; newViewerFace.coordIndex1 = face.v1; newViewerFace.coordIndex2 = face.v2; newViewerFace.coordIndex3 = face.v3; newViewerFace.n1 = faceNormal; newViewerFace.n2 = faceNormal; newViewerFace.n3 = faceNormal; newViewerFace.uv1 = newLayer.faceUVs [face.v1]; newViewerFace.uv2 = newLayer.faceUVs [face.v2]; newViewerFace.uv3 = newLayer.faceUVs [face.v3]; if (pathType == PathType.Linear) { newViewerFace.uv1.Flip(); newViewerFace.uv2.Flip(); newViewerFace.uv3.Flip(); } viewerFaces.Add (newViewerFace); } } } // if (nodeIndex == 0) // append this layer int coordsLen = coords.Count; newLayer.AddValue2FaceVertexIndices (coordsLen); coords.AddRange (newLayer.coords); if (calcVertexNormals) { newLayer.AddValue2FaceNormalIndices (normals.Count); normals.AddRange (newLayer.vertexNormals); } if (node.percentOfPath < pathCutBegin + 0.01f || node.percentOfPath > pathCutEnd - 0.01f) faces.AddRange (newLayer.faces); // fill faces between layers int numVerts = newLayer.coords.Count; thisV = 1.0f - node.percentOfPath; if (nodeIndex > 0) { Face newFace1 = new Face (); Face newFace2 = new Face (); int startVert = coordsLen + 1; int endVert = coords.Count; if (sides < 5 || hasProfileCut || hasHollow) startVert--; for (int i = startVert; i < endVert; i++) { int iNext = i + 1; if (i == endVert - 1) iNext = startVert; int whichVert = i - startVert; newFace1.v1 = i; newFace1.v2 = i - numVerts; newFace1.v3 = iNext; newFace1.n1 = newFace1.v1; newFace1.n2 = newFace1.v2; newFace1.n3 = newFace1.v3; faces.Add(newFace1); newFace2.v1 = iNext; newFace2.v2 = i - numVerts; newFace2.v3 = iNext - numVerts; newFace2.n1 = newFace2.v1; newFace2.n2 = newFace2.v2; newFace2.n3 = newFace2.v3; faces.Add(newFace2); if (viewerMode) { // add the side faces to the list of viewerFaces here int primFaceNum = profile.faceNumbers [whichVert]; if (!needEndFaces) primFaceNum -= 1; ViewerFace newViewerFace1 = new ViewerFace (primFaceNum); ViewerFace newViewerFace2 = new ViewerFace (primFaceNum); int uIndex = whichVert; if (!hasHollow && sides > 4 && uIndex < newLayer.us.Count - 1) { uIndex++; } float u1 = newLayer.us[uIndex]; float u2 = 1.0f; if (uIndex < (int)newLayer.us.Count - 1) u2 = newLayer.us[uIndex + 1]; if (whichVert == cut1Vert || whichVert == cut2Vert) { u1 = 0.0f; u2 = 1.0f; if (uIndex < (int) newLayer.us.Count - 1) u2 = newLayer.us[uIndex + 1]; if (whichVert == cut1Vert || whichVert == cut2Vert) { u1 = 0.0f; u2 = 1.0f; } } else if (sides < 5) { if (whichVert < profile.numOuterVerts) { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled // to reflect the entire texture width u1 *= sides; u2 *= sides; u2 -= u1; u1 -= u1; if (u2 < 0.1f) u2 = 1.0f; } else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1) { u1 *= 2.0f; u2 *= 2.0f; //profileHollowFaceNumber = primFaceNum; } } if (sphereMode) { if (whichVert != cut1Vert && whichVert != cut2Vert) { u1 = u1 * 2.0f - 1.0f; u2 = u2 * 2.0f - 1.0f; if (whichVert >= newLayer.numOuterVerts) { u1 -= hollow; u2 -= hollow; } } } newViewerFace1.uv1.U = u1; newViewerFace1.uv2.U = u1; newViewerFace1.uv3.U = u2; newViewerFace1.uv1.V = thisV; newViewerFace1.uv2.V = lastV; newViewerFace1.uv3.V = thisV; newViewerFace2.uv1.U = u2; newViewerFace2.uv2.U = u1; newViewerFace2.uv3.U = u2; newViewerFace2.uv1.V = thisV; newViewerFace2.uv2.V = lastV; newViewerFace2.uv3.V = lastV; newViewerFace1.v1 = coords[newFace1.v1]; newViewerFace1.v2 = coords[newFace1.v2]; newViewerFace1.v3 = coords[newFace1.v3]; newViewerFace2.v1 = coords[newFace2.v1]; newViewerFace2.v2 = coords[newFace2.v2]; newViewerFace2.v3 = coords[newFace2.v3]; newViewerFace1.coordIndex1 = newFace1.v1; newViewerFace1.coordIndex2 = newFace1.v2; newViewerFace1.coordIndex3 = newFace1.v3; newViewerFace2.coordIndex1 = newFace2.v1; newViewerFace2.coordIndex2 = newFace2.v2; newViewerFace2.coordIndex3 = newFace2.v3; // profile cut faces if (whichVert == cut1Vert) { newViewerFace1.primFaceNumber = cut1FaceNumber; newViewerFace2.primFaceNumber = cut1FaceNumber; newViewerFace1.n1 = newLayer.cutNormal1; newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1; newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1; newViewerFace2.n2 = lastCutNormal1; } else if (whichVert == cut2Vert) { newViewerFace1.primFaceNumber = cut2FaceNumber; newViewerFace2.primFaceNumber = cut2FaceNumber; newViewerFace1.n1 = newLayer.cutNormal2; newViewerFace1.n2 = lastCutNormal2; newViewerFace1.n3 = lastCutNormal2; newViewerFace2.n1 = newLayer.cutNormal2; newViewerFace2.n3 = newLayer.cutNormal2; newViewerFace2.n2 = lastCutNormal2; } else // outer and hollow faces { if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts)) { // looks terrible when path is twisted... need vertex normals here newViewerFace1.CalcSurfaceNormal (); newViewerFace2.CalcSurfaceNormal (); } else { newViewerFace1.n1 = normals[newFace1.n1]; newViewerFace1.n2 = normals[newFace1.n2]; newViewerFace1.n3 = normals[newFace1.n3]; newViewerFace2.n1 = normals[newFace2.n1]; newViewerFace2.n2 = normals[newFace2.n2]; newViewerFace2.n3 = normals[newFace2.n3]; } } viewerFaces.Add (newViewerFace1); viewerFaces.Add (newViewerFace2); } } } lastCutNormal1 = newLayer.cutNormal1; lastCutNormal2 = newLayer.cutNormal2; lastV = 1.0f - node.percentOfPath; if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode) { // add the top faces to the viewerFaces list here Coord faceNormal = newLayer.faceNormal; ViewerFace newViewerFace = new ViewerFace { primFaceNumber = 0 }; int numFaces = newLayer.faces.Count; List<Face> faces2 = newLayer.faces; for (int i = 0; i < numFaces; i++) { Face face = faces2 [i]; newViewerFace.v1 = newLayer.coords [face.v1 - coordsLen]; newViewerFace.v2 = newLayer.coords [face.v2 - coordsLen]; newViewerFace.v3 = newLayer.coords [face.v3 - coordsLen]; newViewerFace.coordIndex1 = face.v1 - coordsLen; newViewerFace.coordIndex2 = face.v2 - coordsLen; newViewerFace.coordIndex3 = face.v3 - coordsLen; newViewerFace.n1 = faceNormal; newViewerFace.n2 = faceNormal; newViewerFace.n3 = faceNormal; newViewerFace.uv1 = newLayer.faceUVs [face.v1 - coordsLen]; newViewerFace.uv2 = newLayer.faceUVs [face.v2 - coordsLen]; newViewerFace.uv3 = newLayer.faceUVs [face.v3 - coordsLen]; if (pathType == PathType.Linear) { newViewerFace.uv1.Flip(); newViewerFace.uv2.Flip(); newViewerFace.uv3.Flip(); } viewerFaces.Add (newViewerFace); } } } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) }
void _SculptMesh (List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) { coords = new List<Coord> (); faces = new List<Face> (); normals = new List<Coord> (); uvs = new List<UVCoord> (); sculptType = (SculptType)(((int)sculptType) & 0x07); if (mirror) invert = !invert; viewerFaces = new List<ViewerFace> (); int width = rows [0].Count; int p1, p2, p3, p4; int imageX, imageY; if (sculptType != SculptType.plane) { if (rows.Count % 2 == 0) { foreach (List<Coord> t in rows) t.Add (t [0]); } else { int lastIndex = rows [0].Count - 1; foreach (List<Coord> t in rows) t [0] = t [lastIndex]; } } Coord topPole = rows [0] [width / 2]; Coord bottomPole = rows [rows.Count - 1] [width / 2]; if (sculptType == SculptType.sphere) { if (rows.Count % 2 == 0) { int count = rows [0].Count; List<Coord> topPoleRow = new List<Coord> (count); List<Coord> bottomPoleRow = new List<Coord> (count); for (int i = 0; i < count; i++) { topPoleRow.Add (topPole); bottomPoleRow.Add (bottomPole); } rows.Insert (0, topPoleRow); rows.Add (bottomPoleRow); } else { int count = rows [0].Count; List<Coord> topPoleRow = rows [0]; List<Coord> bottomPoleRow = rows [rows.Count - 1]; for (int i = 0; i < count; i++) { topPoleRow [i] = topPole; bottomPoleRow [i] = bottomPole; } } } if (sculptType == SculptType.torus) rows.Add (rows [0]); int coordsDown = rows.Count; int coordsAcross = rows [0].Count; float widthUnit = 1.0f / (coordsAcross - 1); float heightUnit = 1.0f / (coordsDown - 1); for (imageY = 0; imageY < coordsDown; imageY++) { int rowOffset = imageY * coordsAcross; for (imageX = 0; imageX < coordsAcross; imageX++) { /* * p1-----p2 * | \ f2 | * | \ | * | f1 \| * p3-----p4 */ p4 = rowOffset + imageX; p3 = p4 - 1; p2 = p4 - coordsAcross; p1 = p3 - coordsAcross; coords.Add (rows [imageY] [imageX]); if (viewerMode) { normals.Add (new Coord ()); uvs.Add (new UVCoord (widthUnit * imageX, heightUnit * imageY)); } if (imageY > 0 && imageX > 0) { Face f1, f2; if (viewerMode) { if (invert) { f1 = new Face (p1, p4, p3, p1, p4, p3) { uv1 = p1, uv2 = p4, uv3 = p3 }; f2 = new Face (p1, p2, p4, p1, p2, p4) { uv1 = p1, uv2 = p2, uv3 = p4 }; } else { f1 = new Face (p1, p3, p4, p1, p3, p4) { uv1 = p1, uv2 = p3, uv3 = p4 }; f2 = new Face (p1, p4, p2, p1, p4, p2) { uv1 = p1, uv2 = p4, uv3 = p2 }; } } else { if (invert) { f1 = new Face (p1, p4, p3); f2 = new Face (p1, p2, p4); } else { f1 = new Face (p1, p3, p4); f2 = new Face (p1, p4, p2); } } faces.Add (f1); faces.Add (f2); } } } if (viewerMode) calcVertexNormals (sculptType, coordsAcross, coordsDown); }