From 931b04485d3856f111367b9f0d00c1bb7a62da99 Mon Sep 17 00:00:00 2001 From: Dahlia Trimble Date: Tue, 21 Oct 2008 01:35:05 +0000 Subject: [PATCH] More work in vertex normals and texture UVs. Syncing code with pyov. --- OpenSim/Region/Physics/Meshing/PrimMesher.cs | 346 ++++++++++++++++++- 1 file changed, 328 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs index b36b5a85ec..527bf88e3f 100644 --- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs +++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs @@ -523,6 +523,9 @@ namespace PrimMesher internal List coords; internal List faces; internal List vertexNormals; + internal List us; + internal List faceUVs; + internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f); internal Coord cutNormal1 = new Coord(); internal Coord cutNormal2 = new Coord(); @@ -537,6 +540,8 @@ namespace PrimMesher this.coords = new List(); this.faces = new List(); this.vertexNormals = new List(); + this.us = new List(); + this.faceUVs = new List(); } public Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals) @@ -545,10 +550,13 @@ namespace PrimMesher this.coords = new List(); this.faces = new List(); this.vertexNormals = new List(); + this.us = new List(); + this.faceUVs = new List(); Coord center = new Coord(0.0f, 0.0f, 0.0f); List hollowCoords = new List(); List hollowNormals = new List(); + List hollowUs = new List(); //Quat rot180 = new Quat(new Coord(0.0f, 0.0f, 1.0f), (float)Math.PI); ; bool hasHollow = (hollow > 0.0f); @@ -627,6 +635,7 @@ namespace PrimMesher //hollowNormal *= rot180; //hollowNormals.Add(hollowNormal); hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); + hollowUs.Add(angle.angle); } } } @@ -634,6 +643,8 @@ namespace PrimMesher int index = 0; int numAngles = angles.angles.Count; + //float sideIncrement = 1.0f / (float)sides; + for (int i = 0; i < numAngles; i++) { angle = angles.angles[i]; @@ -642,7 +653,18 @@ namespace PrimMesher newVert.Z = z; this.coords.Add(newVert); if (this.calcVertexNormals) + { this.vertexNormals.Add(new Coord(angle.X, angle.Y, 0.0f)); + if (sides < 5) + { + float u = angle.angle; + //u %= sideIncrement; + //u *= sides; + this.us.Add(u); + } + else + this.us.Add(angle.angle); + } if (hollow > 0.0f) { @@ -658,6 +680,7 @@ namespace PrimMesher //hollowNormal *= rot180; //hollowNormals.Add(hollowNormal); hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); + hollowUs.Add(angle.angle); } } } @@ -677,7 +700,10 @@ namespace PrimMesher { hollowCoords.Reverse(); if (this.calcVertexNormals) + { hollowNormals.Reverse(); + hollowUs.Reverse(); + } if (createFaces) { @@ -759,7 +785,11 @@ namespace PrimMesher this.coords.AddRange(hollowCoords); if (this.calcVertexNormals) + { this.vertexNormals.AddRange(hollowNormals); + this.us.AddRange(hollowUs); + + } } if (simpleFace && createFaces) @@ -797,11 +827,21 @@ namespace PrimMesher this.cutNormal2.Normalize(); } + this.MakeFaceUVs(); + hollowCoords = null; hollowNormals = null; + hollowUs = null; } + public void MakeFaceUVs() + { + this.faceUVs = new List(); + foreach (Coord c in this.coords) + this.faceUVs.Add(new UVCoord(0.5f + c.X, 0.5f - c.Y)); + } + public Profile Clone() { return this.Clone(true); @@ -812,6 +852,8 @@ namespace PrimMesher Profile clone = new Profile(); clone.coords.AddRange(this.coords); + clone.faceUVs.AddRange(this.faceUVs); + if (needFaces) clone.faces.AddRange(this.faces); if ((clone.calcVertexNormals = this.calcVertexNormals) == true) @@ -820,6 +862,7 @@ namespace PrimMesher clone.faceNormal = this.faceNormal; clone.cutNormal1 = this.cutNormal1; clone.cutNormal2 = this.cutNormal2; + clone.us.AddRange(this.us); } clone.numOuterVerts = this.numOuterVerts; clone.numHollowVerts = this.numHollowVerts; @@ -933,6 +976,19 @@ namespace PrimMesher this.faceNormal.X = -this.faceNormal.X; this.faceNormal.Y = -this.faceNormal.Y; this.faceNormal.Z = -this.faceNormal.Z; + + int numUs = this.us.Count; + //for (int i = 0; i < numUs; i++) + // this.us[i] + + int numfaceUVs = this.faceUVs.Count; + for (i = 0; i < numfaceUVs; i++) + { + UVCoord uv = this.faceUVs[i]; + uv.U = 1.0f - uv.U; + //uv.V = 1.0f - uv.V; + this.faceUVs[i] = uv; + } } public void AddValue2FaceVertexIndices(int num) @@ -1162,10 +1218,16 @@ namespace PrimMesher Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals); 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 lastV = 1.0f; bool done = false; while (!done) @@ -1213,6 +1275,10 @@ namespace PrimMesher newViewerFace.n2 = faceNormal; newViewerFace.n3 = faceNormal; + newViewerFace.uv1 = newLayer.faceUVs[face.v1]; + newViewerFace.uv2 = newLayer.faceUVs[face.v2]; + newViewerFace.uv3 = newLayer.faceUVs[face.v3]; + this.viewerFaces.Add(newViewerFace); } @@ -1264,8 +1330,44 @@ namespace PrimMesher if (this.viewerMode) { // add the side faces to the list of viewerFaces here - ViewerFace newViewerFace1 = new ViewerFace(); - ViewerFace newViewerFace2 = new ViewerFace(); + int primFaceNum = 1; + if (whichVert >= sides) + primFaceNum = 2; + ViewerFace newViewerFace1 = new ViewerFace(primFaceNum); + ViewerFace newViewerFace2 = new ViewerFace(primFaceNum); + float u1 = newLayer.us[whichVert]; + float u2 = 1.0f; + if (whichVert < newLayer.us.Count - 1) + u2 = newLayer.us[whichVert + 1]; + if (sides < 5 && whichVert < sides) + { + u1 *= sides; + u2 *= sides; + u1 -= whichVert; + u2 -= whichVert; + if (u2 < 0.1f) + u2 = 1.0f; + //u1 = 0.0f; + //u2 = 1.0f; + + newViewerFace2.primFaceNumber = newViewerFace1.primFaceNumber = whichVert + 1; + } + + newViewerFace1.uv1.U = u1; + newViewerFace1.uv2.U = u1; + newViewerFace1.uv3.U = u2; + + newViewerFace1.uv1.V = 1.0f - percentOfPath; + newViewerFace1.uv2.V = lastV; + newViewerFace1.uv3.V = lastV; + + newViewerFace2.uv1.U = u1; + newViewerFace2.uv2.U = u2; + newViewerFace2.uv3.U = u2; + + newViewerFace2.uv1.V = 1.0f - percentOfPath; + newViewerFace2.uv2.V = lastV; + newViewerFace2.uv3.V = 1.0f - percentOfPath; newViewerFace1.v1 = this.coords[i]; newViewerFace1.v2 = this.coords[i - numVerts]; @@ -1330,9 +1432,18 @@ namespace PrimMesher newViewerFace.v2 = this.coords[coordsLen - numVerts]; // first vert in prior layer newViewerFace.v3 = this.coords[coordsLen]; // first vert in new layer + float u1 = newLayer.us[0]; + float u2 = newLayer.us[newLayer.us.Count - 1]; + newViewerFace.n2 = newViewerFace.n1 = lastCutNormal2; newViewerFace.n3 = newLayer.cutNormal2; + newViewerFace.uv3.U = newViewerFace.uv1.U = u2; + newViewerFace.uv2.U = u1; + + newViewerFace.uv1.V = newViewerFace.uv2.V = lastV; + newViewerFace.uv3.V = 1.0f - percentOfPath; + this.viewerFaces.Add(newViewerFace); newViewerFace.v1 = this.coords[coordsLen + numVerts - 1]; // last vert in new layer @@ -1342,6 +1453,12 @@ namespace PrimMesher newViewerFace.n3 = newViewerFace.n1 = newLayer.cutNormal2; newViewerFace.n2 = lastCutNormal2; + newViewerFace.uv2.U = newViewerFace.uv1.U = u1; + newViewerFace.uv3.U = u2; + + newViewerFace.uv3.V = newViewerFace.uv1.V = 1.0f - percentOfPath; + newViewerFace.uv2.V = lastV; + this.viewerFaces.Add(newViewerFace); } } @@ -1350,6 +1467,7 @@ namespace PrimMesher lastCutNormal1 = newLayer.cutNormal1; lastCutNormal2 = newLayer.cutNormal2; + lastV = 1.0f - percentOfPath; // calc the step for the next iteration of the loop @@ -1381,6 +1499,10 @@ namespace PrimMesher 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]; + this.viewerFaces.Add(newViewerFace); } } @@ -1489,7 +1611,15 @@ namespace PrimMesher Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, needEndFaces, calcVertexNormals); 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 lastV = 1.0f; bool done = false; while (!done) // loop through the length of the path and add the layers @@ -1498,7 +1628,8 @@ namespace PrimMesher if (angle == startAngle || angle >= endAngle) isEndLayer = true; - Profile newLayer = profile.Clone(isEndLayer && needEndFaces); + //Profile newLayer = profile.Clone(isEndLayer && needEndFaces); + Profile newLayer = profile.Clone(); float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX; float yProfileScale = this.holeSizeY; @@ -1547,6 +1678,36 @@ namespace PrimMesher if (angle == startAngle) newLayer.FlipNormals(); + if (angle == startAngle) + { + newLayer.FlipNormals(); + + // add the top faces to the viewerFaces list here + if (this.viewerMode && needEndFaces) + { + Coord faceNormal = newLayer.faceNormal; + ViewerFace newViewerFace = new ViewerFace(); + newViewerFace.primFaceNumber = 0; + foreach (Face face in newLayer.faces) + { + newViewerFace.v1 = newLayer.coords[face.v1]; + newViewerFace.v2 = newLayer.coords[face.v2]; + newViewerFace.v3 = newLayer.coords[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]; + + this.viewerFaces.Add(newViewerFace); + } + + } + } + // append the layer and fill in the sides int coordsLen = this.coords.Count; @@ -1578,6 +1739,8 @@ namespace PrimMesher for (int i = startVert; i < endVert; i++) //for (int i = coordsLen; i < this.coords.Count - 1; i++) { + int whichVert = i - startVert; + newFace.v1 = i; newFace.v2 = i - numVerts; newFace.v3 = i - numVerts + 1; @@ -1587,33 +1750,115 @@ namespace PrimMesher newFace.v3 = i + 1; this.faces.Add(newFace); + //if (this.viewerMode) + //{ + // // add the side faces to the list of viewerFaces here + // ViewerFace newViewerFace = new ViewerFace(); + // newViewerFace.v1 = this.coords[i]; + // newViewerFace.v2 = this.coords[i - numVerts]; + // newViewerFace.v3 = this.coords[i - numVerts + 1]; + + // newViewerFace.n1 = this.normals[i]; + // newViewerFace.n2 = this.normals[i - numVerts]; + // newViewerFace.n3 = this.normals[i - numVerts + 1]; + + // this.viewerFaces.Add(newViewerFace); + + // newViewerFace.v2 = this.coords[i - numVerts + 1]; + // newViewerFace.v3 = this.coords[i + 1]; + + // newViewerFace.n2 = this.normals[i - numVerts + 1]; + // newViewerFace.n3 = this.normals[i + 1]; + + // this.viewerFaces.Add(newViewerFace); + + //} + if (this.viewerMode) { // add the side faces to the list of viewerFaces here - ViewerFace newViewerFace = new ViewerFace(); - newViewerFace.v1 = this.coords[i]; - newViewerFace.v2 = this.coords[i - numVerts]; - newViewerFace.v3 = this.coords[i - numVerts + 1]; + ViewerFace newViewerFace1 = new ViewerFace(); + ViewerFace newViewerFace2 = new ViewerFace(); + float u1 = newLayer.us[whichVert]; + float u2 = 1.0f; + if (whichVert < newLayer.us.Count - 1) + u2 = newLayer.us[whichVert + 1]; - newViewerFace.n1 = this.normals[i]; - newViewerFace.n2 = this.normals[i - numVerts]; - newViewerFace.n3 = this.normals[i - numVerts + 1]; + newViewerFace1.uv1.U = u1; + newViewerFace1.uv2.U = u1; + newViewerFace1.uv3.U = u2; - this.viewerFaces.Add(newViewerFace); + newViewerFace1.uv1.V = 1.0f - percentOfPath; + newViewerFace1.uv2.V = lastV; + newViewerFace1.uv3.V = lastV; - newViewerFace.v2 = this.coords[i - numVerts + 1]; - newViewerFace.v3 = this.coords[i + 1]; + newViewerFace2.uv1.U = u1; + newViewerFace2.uv2.U = u2; + newViewerFace2.uv3.U = u2; - newViewerFace.n2 = this.normals[i - numVerts + 1]; - newViewerFace.n3 = this.normals[i + 1]; + newViewerFace2.uv1.V = 1.0f - percentOfPath; + newViewerFace2.uv2.V = lastV; + newViewerFace2.uv3.V = 1.0f - percentOfPath; - this.viewerFaces.Add(newViewerFace); + newViewerFace1.v1 = this.coords[i]; + newViewerFace1.v2 = this.coords[i - numVerts]; + newViewerFace1.v3 = this.coords[i - numVerts + 1]; + + newViewerFace2.v1 = this.coords[i]; + newViewerFace2.v2 = this.coords[i - numVerts + 1]; + newViewerFace2.v3 = this.coords[i + 1]; + + if (whichVert == newLayer.numOuterVerts - 1 && hasProfileCut) + { // start profile cut faces + + newViewerFace1.n2 = newViewerFace1.n1 = lastCutNormal1; + newViewerFace1.n3 = newLayer.cutNormal1; + + newViewerFace2.n3 = newViewerFace2.n1 = newLayer.cutNormal1; + newViewerFace2.n2 = lastCutNormal1; + } + + else // periphery faces + { + if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts)) + { + newViewerFace1.CalcSurfaceNormal(); + newViewerFace2.CalcSurfaceNormal(); + } + else + { + newViewerFace1.n1 = this.normals[i]; + newViewerFace1.n2 = this.normals[i - numVerts]; + newViewerFace1.n3 = this.normals[i - numVerts + 1]; + + newViewerFace2.n1 = this.normals[i]; + newViewerFace2.n2 = this.normals[i - numVerts + 1]; + newViewerFace2.n3 = this.normals[i + 1]; + } + } + + this.viewerFaces.Add(newViewerFace1); + this.viewerFaces.Add(newViewerFace2); } } + //if (this.hasProfileCut) + //{ + // newFace.v1 = coordsLen - 1; + // newFace.v2 = coordsLen - numVerts; + // newFace.v3 = coordsLen; + // this.faces.Add(newFace); + + // newFace.v1 = coordsLen + numVerts - 1; + // newFace.v2 = coordsLen - 1; + // newFace.v3 = coordsLen; + // this.faces.Add(newFace); + //} + if (this.hasProfileCut) - { + { // add the end cut face to the list of viewerFaces here + // the first cut face was filled in the above loop newFace.v1 = coordsLen - 1; newFace.v2 = coordsLen - numVerts; newFace.v3 = coordsLen; @@ -1623,9 +1868,50 @@ namespace PrimMesher newFace.v2 = coordsLen - 1; newFace.v3 = coordsLen; this.faces.Add(newFace); + + if (this.viewerMode) + { + ViewerFace newViewerFace = new ViewerFace(); + newViewerFace.v1 = this.coords[coordsLen - 1]; // last vert in prior layer + newViewerFace.v2 = this.coords[coordsLen - numVerts]; // first vert in prior layer + newViewerFace.v3 = this.coords[coordsLen]; // first vert in new layer + + float u1 = newLayer.us[0]; + float u2 = newLayer.us[newLayer.us.Count - 1]; + + newViewerFace.n2 = newViewerFace.n1 = lastCutNormal2; + newViewerFace.n3 = newLayer.cutNormal2; + + newViewerFace.uv3.U = newViewerFace.uv1.U = u2; + newViewerFace.uv2.U = u1; + + newViewerFace.uv1.V = newViewerFace.uv2.V = lastV; + newViewerFace.uv3.V = 1.0f - percentOfPath; + + this.viewerFaces.Add(newViewerFace); + + newViewerFace.v1 = this.coords[coordsLen + numVerts - 1]; // last vert in new layer + newViewerFace.v2 = this.coords[coordsLen - 1]; // last vert in prior layer + newViewerFace.v3 = this.coords[coordsLen]; // first vert in new layer + + newViewerFace.n3 = newViewerFace.n1 = newLayer.cutNormal2; + newViewerFace.n2 = lastCutNormal2; + + newViewerFace.uv2.U = newViewerFace.uv1.U = u1; + newViewerFace.uv3.U = u2; + + newViewerFace.uv3.V = newViewerFace.uv1.V = 1.0f - percentOfPath; + newViewerFace.uv2.V = lastV; + + this.viewerFaces.Add(newViewerFace); + } } } + lastCutNormal1 = newLayer.cutNormal1; + lastCutNormal2 = newLayer.cutNormal2; + lastV = 1.0f - percentOfPath; + // calculate terms for next iteration // calculate the angle for the next iteration of the loop @@ -1638,6 +1924,30 @@ namespace PrimMesher if (angle > endAngle) angle = endAngle; } + + if (done && viewerMode && needEndFaces) + { + // add the bottom faces to the viewerFaces list here + Coord faceNormal = newLayer.faceNormal; + ViewerFace newViewerFace = new ViewerFace(); + newViewerFace.primFaceNumber = 0; + foreach (Face face in newLayer.faces) + { + newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen]; + newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen]; + newViewerFace.v3 = newLayer.coords[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]; + + this.viewerFaces.Add(newViewerFace); + } + } } } @@ -1659,7 +1969,7 @@ namespace PrimMesher public Coord SurfaceNormal(int faceIndex) { - //int numFaces = faces.Count; + int numFaces = faces.Count; if (faceIndex < 0 || faceIndex >= faces.Count) throw new Exception("faceIndex out of range");