aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitMeshing
diff options
context:
space:
mode:
authorUbitUmarov2013-05-29 02:08:14 +0100
committerUbitUmarov2013-05-29 02:08:14 +0100
commit4e72cf9ee21dd8833af860fa5af4fc91e11018cb (patch)
treedc3992d2d9383172524eeacf939d9a3bca165ad2 /OpenSim/Region/Physics/UbitMeshing
parentAllow Linden trees to preserve their type when taken into inventory and rezze... (diff)
downloadopensim-SC_OLD-4e72cf9ee21dd8833af860fa5af4fc91e11018cb.zip
opensim-SC_OLD-4e72cf9ee21dd8833af860fa5af4fc91e11018cb.tar.gz
opensim-SC_OLD-4e72cf9ee21dd8833af860fa5af4fc91e11018cb.tar.bz2
opensim-SC_OLD-4e72cf9ee21dd8833af860fa5af4fc91e11018cb.tar.xz
*** DANGER TESTING **** changed prims mesh generation hopefully removing
spurius faces. CHanged several aspects. Fixed prims inertia that was too low, still using box as model. Increased number of quickstep SOR iterations to 15. Keep it 15 even on heavy load ( will only jump simulation time).
Diffstat (limited to 'OpenSim/Region/Physics/UbitMeshing')
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/HelperTypes.cs4
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Mesh.cs33
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs64
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/PrimMesher.cs1230
4 files changed, 358 insertions, 973 deletions
diff --git a/OpenSim/Region/Physics/UbitMeshing/HelperTypes.cs b/OpenSim/Region/Physics/UbitMeshing/HelperTypes.cs
index 2938257..5dc1e78 100644
--- a/OpenSim/Region/Physics/UbitMeshing/HelperTypes.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/HelperTypes.cs
@@ -256,9 +256,9 @@ public class Vertex : IComparable<Vertex>
256 // settings your machine works with. Unusable for a machine readable file format :-( 256 // settings your machine works with. Unusable for a machine readable file format :-(
257 NumberFormatInfo nfi = new NumberFormatInfo(); 257 NumberFormatInfo nfi = new NumberFormatInfo();
258 nfi.NumberDecimalSeparator = "."; 258 nfi.NumberDecimalSeparator = ".";
259 nfi.NumberDecimalDigits = 3; 259 nfi.NumberDecimalDigits = 6;
260 260
261 String s1 = X.ToString("N2", nfi) + " " + Y.ToString("N2", nfi) + " " + Z.ToString("N2", nfi); 261 String s1 = X.ToString(nfi) + " " + Y.ToString(nfi) + " " + Z.ToString(nfi);
262 262
263 return s1; 263 return s1;
264 } 264 }
diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
index fa06926..0418893 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
@@ -205,34 +205,21 @@ namespace OpenSim.Region.Physics.Meshing
205 205
206 } 206 }
207 207
208 private float fRound(float f)
209 {
210 int i;
211 if (f == 0f)
212 return f;
213 else if (f > 0f)
214 i = (int)(1e5f * f + 0.5f);
215 else
216 i = (int)(1e5f * f - 0.5f);
217
218 return ((float)i * 1e-5f);
219 }
220
221 public void Add(Triangle triangle) 208 public void Add(Triangle triangle)
222 { 209 {
223 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) 210 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
224 throw new NotSupportedException("Attempt to Add to a pinned Mesh"); 211 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
225 212
226 // round down 213
227 triangle.v1.X = fRound(triangle.v1.X); 214 triangle.v1.X = (float)Math.Round(triangle.v1.X, 6);
228 triangle.v1.Y = fRound(triangle.v1.Y); 215 triangle.v1.Y = (float)Math.Round(triangle.v1.Y, 6);
229 triangle.v1.Z = fRound(triangle.v1.Z); 216 triangle.v1.Z = (float)Math.Round(triangle.v1.Z, 6);
230 triangle.v2.X = fRound(triangle.v2.X); 217 triangle.v2.X = (float)Math.Round(triangle.v2.X, 6);
231 triangle.v2.Y = fRound(triangle.v2.Y); 218 triangle.v2.Y = (float)Math.Round(triangle.v2.Y, 6);
232 triangle.v2.Z = fRound(triangle.v2.Z); 219 triangle.v2.Z = (float)Math.Round(triangle.v2.Z, 6);
233 triangle.v3.X = fRound(triangle.v3.X); 220 triangle.v3.X = (float)Math.Round(triangle.v3.X, 6);
234 triangle.v3.Y = fRound(triangle.v3.Y); 221 triangle.v3.Y = (float)Math.Round(triangle.v3.Y, 6);
235 triangle.v3.Z = fRound(triangle.v3.Z); 222 triangle.v3.Z = (float)Math.Round(triangle.v3.Z, 6);
236 223
237 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z) 224 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
238 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z) 225 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
index 00cbfbd..c131c6f 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs
@@ -816,15 +816,31 @@ namespace OpenSim.Region.Physics.Meshing
816 816
817 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f; 817 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
818 float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f; 818 float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f;
819
820 if (profileBegin < 0.0f)
821 profileBegin = 0.0f;
822
823 if (profileEnd < 0.02f)
824 profileEnd = 0.02f;
825 else if (profileEnd > 1.0f)
826 profileEnd = 1.0f;
827
828 if (profileBegin >= profileEnd)
829 profileBegin = profileEnd - 0.02f;
830
819 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f; 831 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f;
820 if (profileHollow > 0.95f) 832 if (profileHollow > 0.95f)
821 profileHollow = 0.95f; 833 profileHollow = 0.95f;
822 834
823 int sides = 4; 835 int sides = 4;
824 LevelOfDetail iLOD = (LevelOfDetail)lod; 836 LevelOfDetail iLOD = (LevelOfDetail)lod;
825 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) 837 byte profshape = (byte)(primShape.ProfileCurve & 0x07);
838
839 if (profshape == (byte)ProfileShape.EquilateralTriangle
840 || profshape == (byte)ProfileShape.IsometricTriangle
841 || profshape == (byte)ProfileShape.RightTriangle)
826 sides = 3; 842 sides = 3;
827 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) 843 else if (profshape == (byte)ProfileShape.Circle)
828 { 844 {
829 switch (iLOD) 845 switch (iLOD)
830 { 846 {
@@ -835,7 +851,7 @@ namespace OpenSim.Region.Physics.Meshing
835 default: sides = 24; break; 851 default: sides = 24; break;
836 } 852 }
837 } 853 }
838 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) 854 else if (profshape == (byte)ProfileShape.HalfCircle)
839 { // half circle, prim is a sphere 855 { // half circle, prim is a sphere
840 switch (iLOD) 856 switch (iLOD)
841 { 857 {
@@ -865,10 +881,15 @@ namespace OpenSim.Region.Physics.Meshing
865 else if (primShape.HollowShape == HollowShape.Square) 881 else if (primShape.HollowShape == HollowShape.Square)
866 hollowSides = 4; 882 hollowSides = 4;
867 else if (primShape.HollowShape == HollowShape.Triangle) 883 else if (primShape.HollowShape == HollowShape.Triangle)
868 hollowSides = 3; 884 {
885 if (profshape == (byte)ProfileShape.HalfCircle)
886 hollowSides = 6;
887 else
888 hollowSides = 3;
889 }
869 890
870 primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides); 891 primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides);
871 892
872 if (primMesh.errorMessage != null) 893 if (primMesh.errorMessage != null)
873 if (primMesh.errorMessage.Length > 0) 894 if (primMesh.errorMessage.Length > 0)
874 m_log.Error("[ERROR] " + primMesh.errorMessage); 895 m_log.Error("[ERROR] " + primMesh.errorMessage);
@@ -880,17 +901,11 @@ namespace OpenSim.Region.Physics.Meshing
880 901
881 if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible) 902 if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible)
882 { 903 {
883 primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10; 904 primMesh.twistBegin = (primShape.PathTwistBegin * 18) / 10;
884 primMesh.twistEnd = primShape.PathTwist * 18 / 10; 905 primMesh.twistEnd = (primShape.PathTwist * 18) / 10;
885 primMesh.taperX = pathScaleX; 906 primMesh.taperX = pathScaleX;
886 primMesh.taperY = pathScaleY; 907 primMesh.taperY = pathScaleY;
887 908
888 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
889 {
890 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh);
891 if (profileBegin < 0.0f) profileBegin = 0.0f;
892 if (profileEnd > 1.0f) profileEnd = 1.0f;
893 }
894#if SPAM 909#if SPAM
895 m_log.Debug("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString()); 910 m_log.Debug("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString());
896#endif 911#endif
@@ -911,17 +926,11 @@ namespace OpenSim.Region.Physics.Meshing
911 primMesh.radius = 0.01f * primShape.PathRadiusOffset; 926 primMesh.radius = 0.01f * primShape.PathRadiusOffset;
912 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions; 927 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions;
913 primMesh.skew = 0.01f * primShape.PathSkew; 928 primMesh.skew = 0.01f * primShape.PathSkew;
914 primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10; 929 primMesh.twistBegin = (primShape.PathTwistBegin * 36) / 10;
915 primMesh.twistEnd = primShape.PathTwist * 36 / 10; 930 primMesh.twistEnd = (primShape.PathTwist * 36) / 10;
916 primMesh.taperX = primShape.PathTaperX * 0.01f; 931 primMesh.taperX = primShape.PathTaperX * 0.01f;
917 primMesh.taperY = primShape.PathTaperY * 0.01f; 932 primMesh.taperY = primShape.PathTaperY * 0.01f;
918 933
919 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
920 {
921 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh);
922 if (profileBegin < 0.0f) profileBegin = 0.0f;
923 if (profileEnd > 1.0f) profileEnd = 1.0f;
924 }
925#if SPAM 934#if SPAM
926 m_log.Debug("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString()); 935 m_log.Debug("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString());
927#endif 936#endif
@@ -1031,14 +1040,19 @@ namespace OpenSim.Region.Physics.Meshing
1031 1040
1032 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 1041 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
1033 { 1042 {
1034 return CreateMesh(primName, primShape, size, lod, false,false,false,false); 1043 return CreateMesh(primName, primShape, size, lod, false,false,false);
1035 } 1044 }
1036 1045
1037 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 1046 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
1038 { 1047 {
1039 return CreateMesh(primName, primShape, size, lod, false,false,false,false); 1048 return CreateMesh(primName, primShape, size, lod, false,false,false);
1040 } 1049 }
1041 1050
1051 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde)
1052 {
1053 return CreateMesh(primName, primShape, size, lod, false, false, false);
1054 }
1055
1042 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) 1056 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
1043 { 1057 {
1044 Mesh mesh = null; 1058 Mesh mesh = null;
@@ -1080,7 +1094,7 @@ namespace OpenSim.Region.Physics.Meshing
1080 1094
1081 private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f); 1095 private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f);
1082 1096
1083 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde) 1097 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
1084 { 1098 {
1085#if SPAM 1099#if SPAM
1086 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); 1100 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
diff --git a/OpenSim/Region/Physics/UbitMeshing/PrimMesher.cs b/OpenSim/Region/Physics/UbitMeshing/PrimMesher.cs
index 4049ee1..8eb136b 100644
--- a/OpenSim/Region/Physics/UbitMeshing/PrimMesher.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/PrimMesher.cs
@@ -225,26 +225,6 @@ namespace PrimMesher
225 } 225 }
226 } 226 }
227 227
228 public struct UVCoord
229 {
230 public float U;
231 public float V;
232
233
234 public UVCoord(float u, float v)
235 {
236 this.U = u;
237 this.V = v;
238 }
239
240 public UVCoord Flip()
241 {
242 this.U = 1.0f - this.U;
243 this.V = 1.0f - this.V;
244 return this;
245 }
246 }
247
248 public struct Face 228 public struct Face
249 { 229 {
250 public int primFace; 230 public int primFace;
@@ -254,16 +234,6 @@ namespace PrimMesher
254 public int v2; 234 public int v2;
255 public int v3; 235 public int v3;
256 236
257 //normals
258 public int n1;
259 public int n2;
260 public int n3;
261
262 // uvs
263 public int uv1;
264 public int uv2;
265 public int uv3;
266
267 public Face(int v1, int v2, int v3) 237 public Face(int v1, int v2, int v3)
268 { 238 {
269 primFace = 0; 239 primFace = 0;
@@ -272,31 +242,6 @@ namespace PrimMesher
272 this.v2 = v2; 242 this.v2 = v2;
273 this.v3 = v3; 243 this.v3 = v3;
274 244
275 this.n1 = 0;
276 this.n2 = 0;
277 this.n3 = 0;
278
279 this.uv1 = 0;
280 this.uv2 = 0;
281 this.uv3 = 0;
282
283 }
284
285 public Face(int v1, int v2, int v3, int n1, int n2, int n3)
286 {
287 primFace = 0;
288
289 this.v1 = v1;
290 this.v2 = v2;
291 this.v3 = v3;
292
293 this.n1 = n1;
294 this.n2 = n2;
295 this.n3 = n3;
296
297 this.uv1 = 0;
298 this.uv2 = 0;
299 this.uv3 = 0;
300 } 245 }
301 246
302 public Coord SurfaceNormal(List<Coord> coordList) 247 public Coord SurfaceNormal(List<Coord> coordList)
@@ -312,96 +257,6 @@ namespace PrimMesher
312 } 257 }
313 } 258 }
314 259
315 public struct ViewerFace
316 {
317 public int primFaceNumber;
318
319 public Coord v1;
320 public Coord v2;
321 public Coord v3;
322
323 public int coordIndex1;
324 public int coordIndex2;
325 public int coordIndex3;
326
327 public Coord n1;
328 public Coord n2;
329 public Coord n3;
330
331 public UVCoord uv1;
332 public UVCoord uv2;
333 public UVCoord uv3;
334
335 public ViewerFace(int primFaceNumber)
336 {
337 this.primFaceNumber = primFaceNumber;
338
339 this.v1 = new Coord();
340 this.v2 = new Coord();
341 this.v3 = new Coord();
342
343 this.coordIndex1 = this.coordIndex2 = this.coordIndex3 = -1; // -1 means not assigned yet
344
345 this.n1 = new Coord();
346 this.n2 = new Coord();
347 this.n3 = new Coord();
348
349 this.uv1 = new UVCoord();
350 this.uv2 = new UVCoord();
351 this.uv3 = new UVCoord();
352 }
353
354 public void Scale(float x, float y, float z)
355 {
356 this.v1.X *= x;
357 this.v1.Y *= y;
358 this.v1.Z *= z;
359
360 this.v2.X *= x;
361 this.v2.Y *= y;
362 this.v2.Z *= z;
363
364 this.v3.X *= x;
365 this.v3.Y *= y;
366 this.v3.Z *= z;
367 }
368
369 public void AddPos(float x, float y, float z)
370 {
371 this.v1.X += x;
372 this.v2.X += x;
373 this.v3.X += x;
374
375 this.v1.Y += y;
376 this.v2.Y += y;
377 this.v3.Y += y;
378
379 this.v1.Z += z;
380 this.v2.Z += z;
381 this.v3.Z += z;
382 }
383
384 public void AddRot(Quat q)
385 {
386 this.v1 *= q;
387 this.v2 *= q;
388 this.v3 *= q;
389
390 this.n1 *= q;
391 this.n2 *= q;
392 this.n3 *= q;
393 }
394
395 public void CalcSurfaceNormal()
396 {
397
398 Coord edge1 = new Coord(this.v2.X - this.v1.X, this.v2.Y - this.v1.Y, this.v2.Z - this.v1.Z);
399 Coord edge2 = new Coord(this.v3.X - this.v1.X, this.v3.Y - this.v1.Y, this.v3.Z - this.v1.Z);
400
401 this.n1 = this.n2 = this.n3 = Coord.Cross(edge1, edge2).Normalize();
402 }
403 }
404
405 internal struct Angle 260 internal struct Angle
406 { 261 {
407 internal float angle; 262 internal float angle;
@@ -428,14 +283,6 @@ namespace PrimMesher
428 new Angle(1.0f, 1.0f, 0.0f) 283 new Angle(1.0f, 1.0f, 0.0f)
429 }; 284 };
430 285
431 private static Coord[] normals3 =
432 {
433 new Coord(0.25f, 0.4330127019f, 0.0f).Normalize(),
434 new Coord(-0.5f, 0.0f, 0.0f).Normalize(),
435 new Coord(0.25f, -0.4330127019f, 0.0f).Normalize(),
436 new Coord(0.25f, 0.4330127019f, 0.0f).Normalize()
437 };
438
439 private static Angle[] angles4 = 286 private static Angle[] angles4 =
440 { 287 {
441 new Angle(0.0f, 1.0f, 0.0f), 288 new Angle(0.0f, 1.0f, 0.0f),
@@ -445,13 +292,32 @@ namespace PrimMesher
445 new Angle(1.0f, 1.0f, 0.0f) 292 new Angle(1.0f, 1.0f, 0.0f)
446 }; 293 };
447 294
448 private static Coord[] normals4 = 295 private static Angle[] angles6 =
449 { 296 {
450 new Coord(0.5f, 0.5f, 0.0f).Normalize(), 297 new Angle(0.0f, 1.0f, 0.0f),
451 new Coord(-0.5f, 0.5f, 0.0f).Normalize(), 298 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
452 new Coord(-0.5f, -0.5f, 0.0f).Normalize(), 299 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
453 new Coord(0.5f, -0.5f, 0.0f).Normalize(), 300 new Angle(0.5f, -1.0f, 0.0f),
454 new Coord(0.5f, 0.5f, 0.0f).Normalize() 301 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
302 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
303 new Angle(1.0f, 1.0f, 0.0f)
304 };
305
306 private static Angle[] angles12 =
307 {
308 new Angle(0.0f, 1.0f, 0.0f),
309 new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
310 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
311 new Angle(0.25f, 0.0f, 1.0f),
312 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
313 new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
314 new Angle(0.5f, -1.0f, 0.0f),
315 new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
316 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
317 new Angle(0.75f, 0.0f, -1.0f),
318 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
319 new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
320 new Angle(1.0f, 1.0f, 0.0f)
455 }; 321 };
456 322
457 private static Angle[] angles24 = 323 private static Angle[] angles24 =
@@ -503,56 +369,72 @@ namespace PrimMesher
503 } 369 }
504 370
505 internal List<Angle> angles; 371 internal List<Angle> angles;
506 internal List<Coord> normals;
507 372
508 internal void makeAngles(int sides, float startAngle, float stopAngle) 373 internal void makeAngles(int sides, float startAngle, float stopAngle, bool hasCut)
509 { 374 {
510 angles = new List<Angle>(); 375 angles = new List<Angle>();
511 normals = new List<Coord>();
512 376
513 double twoPi = System.Math.PI * 2.0; 377 const double twoPi = System.Math.PI * 2.0;
514 float twoPiInv = 1.0f / (float)twoPi; 378 const float twoPiInv = (float)(1.0d / twoPi);
515 379
516 if (sides < 1) 380 if (sides < 1)
517 throw new Exception("number of sides not greater than zero"); 381 throw new Exception("number of sides not greater than zero");
518 if (stopAngle <= startAngle) 382 if (stopAngle <= startAngle)
519 throw new Exception("stopAngle not greater than startAngle"); 383 throw new Exception("stopAngle not greater than startAngle");
520 384
521 if ((sides == 3 || sides == 4 || sides == 24)) 385 if ((sides == 3 || sides == 4 || sides == 6 || sides == 12 || sides == 24))
522 { 386 {
523 startAngle *= twoPiInv; 387 startAngle *= twoPiInv;
524 stopAngle *= twoPiInv; 388 stopAngle *= twoPiInv;
525 389
526 Angle[] sourceAngles; 390 Angle[] sourceAngles;
527 if (sides == 3) 391 switch (sides)
528 sourceAngles = angles3; 392 {
529 else if (sides == 4) 393 case 3:
530 sourceAngles = angles4; 394 sourceAngles = angles3;
531 else sourceAngles = angles24; 395 break;
396 case 4:
397 sourceAngles = angles4;
398 break;
399 case 6:
400 sourceAngles = angles6;
401 break;
402 case 12:
403 sourceAngles = angles12;
404 break;
405 default:
406 sourceAngles = angles24;
407 break;
408 }
532 409
533 int startAngleIndex = (int)(startAngle * sides); 410 int startAngleIndex = (int)(startAngle * sides);
534 int endAngleIndex = sourceAngles.Length - 1; 411 int endAngleIndex = sourceAngles.Length - 1;
535 if (stopAngle < 1.0f)
536 endAngleIndex = (int)(stopAngle * sides) + 1;
537 if (endAngleIndex == startAngleIndex)
538 endAngleIndex++;
539 412
540 for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++) 413 if (hasCut)
541 { 414 {
542 angles.Add(sourceAngles[angleIndex]); 415 if (stopAngle < 1.0f)
543 if (sides == 3) 416 endAngleIndex = (int)(stopAngle * sides) + 1;
544 normals.Add(normals3[angleIndex]); 417 if (endAngleIndex == startAngleIndex)
545 else if (sides == 4) 418 endAngleIndex++;
546 normals.Add(normals4[angleIndex]); 419
547 } 420 for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++)
421 {
422 angles.Add(sourceAngles[angleIndex]);
423 }
548 424
549 if (startAngle > 0.0f) 425 if (startAngle > 0.0f)
550 angles[0] = interpolatePoints(startAngle, angles[0], angles[1]); 426 angles[0] = interpolatePoints(startAngle, angles[0], angles[1]);
551 427
552 if (stopAngle < 1.0f) 428 if (stopAngle < 1.0f)
429 {
430 int lastAngleIndex = angles.Count - 1;
431 angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]);
432 }
433 }
434 else
553 { 435 {
554 int lastAngleIndex = angles.Count - 1; 436 for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex; angleIndex++)
555 angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]); 437 angles.Add(sourceAngles[angleIndex]);
556 } 438 }
557 } 439 }
558 else 440 else
@@ -618,20 +500,10 @@ namespace PrimMesher
618 500
619 public List<Coord> coords; 501 public List<Coord> coords;
620 public List<Face> faces; 502 public List<Face> faces;
621 public List<Coord> vertexNormals;
622 public List<float> us;
623 public List<UVCoord> faceUVs;
624 public List<int> faceNumbers;
625 503
626 // use these for making individual meshes for each prim face 504 // use these for making individual meshes for each prim face
627 public List<int> outerCoordIndices = null; 505 public List<int> outerCoordIndices = null;
628 public List<int> hollowCoordIndices = null; 506 public List<int> hollowCoordIndices = null;
629 public List<int> cut1CoordIndices = null;
630 public List<int> cut2CoordIndices = null;
631
632 public Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f);
633 public Coord cutNormal1 = new Coord();
634 public Coord cutNormal2 = new Coord();
635 507
636 public int numOuterVerts = 0; 508 public int numOuterVerts = 0;
637 public int numHollowVerts = 0; 509 public int numHollowVerts = 0;
@@ -639,7 +511,6 @@ namespace PrimMesher
639 public int outerFaceNumber = -1; 511 public int outerFaceNumber = -1;
640 public int hollowFaceNumber = -1; 512 public int hollowFaceNumber = -1;
641 513
642 public bool calcVertexNormals = false;
643 public int bottomFaceNumber = 0; 514 public int bottomFaceNumber = 0;
644 public int numPrimFaces = 0; 515 public int numPrimFaces = 0;
645 516
@@ -647,40 +518,19 @@ namespace PrimMesher
647 { 518 {
648 this.coords = new List<Coord>(); 519 this.coords = new List<Coord>();
649 this.faces = new List<Face>(); 520 this.faces = new List<Face>();
650 this.vertexNormals = new List<Coord>();
651 this.us = new List<float>();
652 this.faceUVs = new List<UVCoord>();
653 this.faceNumbers = new List<int>();
654 } 521 }
655 522
656 public Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals) 523 public Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool hasProfileCut, bool createFaces)
657 { 524 {
658 this.calcVertexNormals = calcVertexNormals; 525 const float halfSqr2 = 0.7071067811866f;
526
659 this.coords = new List<Coord>(); 527 this.coords = new List<Coord>();
660 this.faces = new List<Face>(); 528 this.faces = new List<Face>();
661 this.vertexNormals = new List<Coord>();
662 this.us = new List<float>();
663 this.faceUVs = new List<UVCoord>();
664 this.faceNumbers = new List<int>();
665
666 Coord center = new Coord(0.0f, 0.0f, 0.0f);
667 529
668 List<Coord> hollowCoords = new List<Coord>(); 530 List<Coord> hollowCoords = new List<Coord>();
669 List<Coord> hollowNormals = new List<Coord>();
670 List<float> hollowUs = new List<float>();
671
672 if (calcVertexNormals)
673 {
674 this.outerCoordIndices = new List<int>();
675 this.hollowCoordIndices = new List<int>();
676 this.cut1CoordIndices = new List<int>();
677 this.cut2CoordIndices = new List<int>();
678 }
679 531
680 bool hasHollow = (hollow > 0.0f); 532 bool hasHollow = (hollow > 0.0f);
681 533
682 bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f);
683
684 AngleList angles = new AngleList(); 534 AngleList angles = new AngleList();
685 AngleList hollowAngles = new AngleList(); 535 AngleList hollowAngles = new AngleList();
686 536
@@ -688,14 +538,14 @@ namespace PrimMesher
688 float yScale = 0.5f; 538 float yScale = 0.5f;
689 if (sides == 4) // corners of a square are sqrt(2) from center 539 if (sides == 4) // corners of a square are sqrt(2) from center
690 { 540 {
691 xScale = 0.707107f; 541 xScale = halfSqr2;
692 yScale = 0.707107f; 542 yScale = halfSqr2;
693 } 543 }
694 544
695 float startAngle = profileStart * twoPi; 545 float startAngle = profileStart * twoPi;
696 float stopAngle = profileEnd * twoPi; 546 float stopAngle = profileEnd * twoPi;
697 547
698 try { angles.makeAngles(sides, startAngle, stopAngle); } 548 try { angles.makeAngles(sides, startAngle, stopAngle,hasProfileCut); }
699 catch (Exception ex) 549 catch (Exception ex)
700 { 550 {
701 551
@@ -707,6 +557,9 @@ namespace PrimMesher
707 557
708 this.numOuterVerts = angles.angles.Count; 558 this.numOuterVerts = angles.angles.Count;
709 559
560 Angle angle;
561 Coord newVert = new Coord();
562
710 // flag to create as few triangles as possible for 3 or 4 side profile 563 // flag to create as few triangles as possible for 3 or 4 side profile
711 bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut); 564 bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut);
712 565
@@ -716,7 +569,7 @@ namespace PrimMesher
716 hollowAngles = angles; 569 hollowAngles = angles;
717 else 570 else
718 { 571 {
719 try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle); } 572 try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle, hasProfileCut); }
720 catch (Exception ex) 573 catch (Exception ex)
721 { 574 {
722 errorMessage = "makeAngles failed: Exception: " + ex.ToString() 575 errorMessage = "makeAngles failed: Exception: " + ex.ToString()
@@ -724,116 +577,48 @@ namespace PrimMesher
724 577
725 return; 578 return;
726 } 579 }
580
581 int numHollowAngles = hollowAngles.angles.Count;
582 for (int i = 0; i < numHollowAngles; i++)
583 {
584 angle = hollowAngles.angles[i];
585 newVert.X = hollow * xScale * angle.X;
586 newVert.Y = hollow * yScale * angle.Y;
587 newVert.Z = 0.0f;
588
589 hollowCoords.Add(newVert);
590 }
727 } 591 }
728 this.numHollowVerts = hollowAngles.angles.Count; 592 this.numHollowVerts = hollowAngles.angles.Count;
729 } 593 }
730 else if (!simpleFace) 594 else if (!simpleFace)
731 { 595 {
596 Coord center = new Coord(0.0f, 0.0f, 0.0f);
732 this.coords.Add(center); 597 this.coords.Add(center);
733 if (this.calcVertexNormals)
734 this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f));
735 this.us.Add(0.0f);
736 }
737
738 float z = 0.0f;
739
740 Angle angle;
741 Coord newVert = new Coord();
742 if (hasHollow && hollowSides != sides)
743 {
744 int numHollowAngles = hollowAngles.angles.Count;
745 for (int i = 0; i < numHollowAngles; i++)
746 {
747 angle = hollowAngles.angles[i];
748 newVert.X = hollow * xScale * angle.X;
749 newVert.Y = hollow * yScale * angle.Y;
750 newVert.Z = z;
751
752 hollowCoords.Add(newVert);
753 if (this.calcVertexNormals)
754 {
755 if (hollowSides < 5)
756 hollowNormals.Add(hollowAngles.normals[i].Invert());
757 else
758 hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f));
759
760 if (hollowSides == 4)
761 hollowUs.Add(angle.angle * hollow * 0.707107f);
762 else
763 hollowUs.Add(angle.angle * hollow);
764 }
765 }
766 } 598 }
767 599
768 int index = 0;
769 int numAngles = angles.angles.Count; 600 int numAngles = angles.angles.Count;
601 bool hollowsame = (hasHollow && hollowSides == sides);
770 602
771 for (int i = 0; i < numAngles; i++) 603 for (int i = 0; i < numAngles; i++)
772 { 604 {
773 angle = angles.angles[i]; 605 angle = angles.angles[i];
774 newVert.X = angle.X * xScale; 606 newVert.X = angle.X * xScale;
775 newVert.Y = angle.Y * yScale; 607 newVert.Y = angle.Y * yScale;
776 newVert.Z = z; 608 newVert.Z = 0.0f;
777 this.coords.Add(newVert); 609 this.coords.Add(newVert);
778 if (this.calcVertexNormals) 610 if (hollowsame)
779 { 611 {
780 this.outerCoordIndices.Add(this.coords.Count - 1); 612 newVert.X *= hollow;
781 613 newVert.Y *= hollow;
782 if (sides < 5) 614 hollowCoords.Add(newVert);
783 {
784 this.vertexNormals.Add(angles.normals[i]);
785 float u = angle.angle;
786 this.us.Add(u);
787 }
788 else
789 {
790 this.vertexNormals.Add(new Coord(angle.X, angle.Y, 0.0f));
791 this.us.Add(angle.angle);
792 }
793 }
794
795 if (hasHollow)
796 {
797 if (hollowSides == sides)
798 {
799 newVert.X *= hollow;
800 newVert.Y *= hollow;
801 newVert.Z = z;
802 hollowCoords.Add(newVert);
803 if (this.calcVertexNormals)
804 {
805 if (sides < 5)
806 {
807 hollowNormals.Add(angles.normals[i].Invert());
808 }
809
810 else
811 hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f));
812
813 hollowUs.Add(angle.angle * hollow);
814 }
815 }
816 }
817 else if (!simpleFace && createFaces && angle.angle > 0.0001f)
818 {
819 Face newFace = new Face();
820 newFace.v1 = 0;
821 newFace.v2 = index;
822 newFace.v3 = index + 1;
823
824 this.faces.Add(newFace);
825 } 615 }
826 index += 1;
827 } 616 }
828 617
829 if (hasHollow) 618 if (hasHollow)
830 { 619 {
831 hollowCoords.Reverse(); 620 hollowCoords.Reverse();
832 if (this.calcVertexNormals) 621 this.coords.AddRange(hollowCoords);
833 {
834 hollowNormals.Reverse();
835 hollowUs.Reverse();
836 }
837 622
838 if (createFaces) 623 if (createFaces)
839 { 624 {
@@ -855,187 +640,176 @@ namespace PrimMesher
855 newFace.v3 = numTotalVerts - coordIndex - 1; 640 newFace.v3 = numTotalVerts - coordIndex - 1;
856 this.faces.Add(newFace); 641 this.faces.Add(newFace);
857 } 642 }
643 if (!hasProfileCut)
644 {
645 newFace.v1 = this.numOuterVerts - 1;
646 newFace.v2 = 0;
647 newFace.v3 = this.numOuterVerts;
648 this.faces.Add(newFace);
649
650 newFace.v1 = 0;
651 newFace.v2 = numTotalVerts - 1;
652 newFace.v3 = this.numOuterVerts;
653 this.faces.Add(newFace);
654 }
858 } 655 }
859 else 656 else if (this.numOuterVerts < this.numHollowVerts)
860 { 657 {
861 if (this.numOuterVerts < this.numHollowVerts) 658 Face newFace = new Face();
659 int j = 0; // j is the index for outer vertices
660 int i;
661 int maxJ = this.numOuterVerts - 1;
662 float curHollowAngle = 0;
663 for (i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices
862 { 664 {
863 Face newFace = new Face(); 665 curHollowAngle = hollowAngles.angles[i].angle;
864 int j = 0; // j is the index for outer vertices 666 if (j < maxJ)
865 int maxJ = this.numOuterVerts - 1;
866 for (int i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices
867 { 667 {
868 if (j < maxJ) 668 if (angles.angles[j + 1].angle - curHollowAngle < curHollowAngle - angles.angles[j].angle + 0.000001f)
869 if (angles.angles[j + 1].angle - hollowAngles.angles[i].angle < hollowAngles.angles[i].angle - angles.angles[j].angle + 0.000001f) 669 {
870 { 670 newFace.v1 = numTotalVerts - i - 1;
871 newFace.v1 = numTotalVerts - i - 1; 671 newFace.v2 = j;
872 newFace.v2 = j; 672 newFace.v3 = j + 1;
873 newFace.v3 = j + 1; 673 this.faces.Add(newFace);
674 j++;
675 }
676 }
677 else
678 {
679 if (1.0f - curHollowAngle < curHollowAngle - angles.angles[j].angle + 0.000001f)
680 break;
681 }
682
683 newFace.v1 = j;
684 newFace.v2 = numTotalVerts - i - 2;
685 newFace.v3 = numTotalVerts - i - 1;
874 686
875 this.faces.Add(newFace); 687 this.faces.Add(newFace);
876 j += 1; 688 }
877 }
878 689
879 newFace.v1 = j; 690 if (!hasProfileCut)
880 newFace.v2 = numTotalVerts - i - 2; 691 {
881 newFace.v3 = numTotalVerts - i - 1; 692 if (i == this.numHollowVerts)
693 {
694 newFace.v1 = numTotalVerts - this.numHollowVerts;
695 newFace.v2 = maxJ;
696 newFace.v3 = 0;
882 697
883 this.faces.Add(newFace); 698 this.faces.Add(newFace);
884 } 699 }
885 } 700 else
886 else // numHollowVerts < numOuterVerts
887 {
888 Face newFace = new Face();
889 int j = 0; // j is the index for inner vertices
890 int maxJ = this.numHollowVerts - 1;
891 for (int i = 0; i < this.numOuterVerts; i++)
892 { 701 {
893 if (j < maxJ) 702 if (1.0f - curHollowAngle < curHollowAngle - angles.angles[maxJ].angle + 0.000001f)
894 if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f) 703 {
895 { 704 newFace.v1 = numTotalVerts - i - 1;
896 newFace.v1 = i; 705 newFace.v2 = maxJ;
897 newFace.v2 = numTotalVerts - j - 2; 706 newFace.v3 = 0;
898 newFace.v3 = numTotalVerts - j - 1;
899 707
900 this.faces.Add(newFace); 708 this.faces.Add(newFace);
901 j += 1; 709 }
902 }
903 710
904 newFace.v1 = numTotalVerts - j - 1; 711 for (; i < this.numHollowVerts - 1; i++)
905 newFace.v2 = i; 712 {
906 newFace.v3 = i + 1; 713 newFace.v1 = 0;
714 newFace.v2 = numTotalVerts - i - 2;
715 newFace.v3 = numTotalVerts - i - 1;
907 716
908 this.faces.Add(newFace); 717 this.faces.Add(newFace);
718 }
909 } 719 }
720
721 newFace.v1 = 0;
722 newFace.v2 = numTotalVerts - this.numHollowVerts;
723 newFace.v3 = numTotalVerts - 1;
724 this.faces.Add(newFace);
910 } 725 }
911 } 726 }
912 } 727 else // numHollowVerts < numOuterVerts
913
914 if (calcVertexNormals)
915 {
916 foreach (Coord hc in hollowCoords)
917 { 728 {
918 this.coords.Add(hc); 729 Face newFace = new Face();
919 hollowCoordIndices.Add(this.coords.Count - 1); 730 int j = 0; // j is the index for inner vertices
920 } 731 int maxJ = this.numHollowVerts - 1;
921 } 732 for (int i = 0; i < this.numOuterVerts; i++)
922 else 733 {
923 this.coords.AddRange(hollowCoords); 734 if (j < maxJ)
735 if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f)
736 {
737 newFace.v1 = i;
738 newFace.v2 = numTotalVerts - j - 2;
739 newFace.v3 = numTotalVerts - j - 1;
924 740
925 if (this.calcVertexNormals) 741 this.faces.Add(newFace);
926 { 742 j += 1;
927 this.vertexNormals.AddRange(hollowNormals); 743 }
928 this.us.AddRange(hollowUs);
929 744
930 } 745 newFace.v1 = numTotalVerts - j - 1;
931 } 746 newFace.v2 = i;
747 newFace.v3 = i + 1;
932 748
933 if (simpleFace && createFaces) 749 this.faces.Add(newFace);
934 { 750 }
935 if (sides == 3)
936 this.faces.Add(new Face(0, 1, 2));
937 else if (sides == 4)
938 {
939 this.faces.Add(new Face(0, 1, 2));
940 this.faces.Add(new Face(0, 2, 3));
941 }
942 }
943 751
944 if (calcVertexNormals && hasProfileCut) 752 if (!hasProfileCut)
945 { 753 {
946 int lastOuterVertIndex = this.numOuterVerts - 1; 754 int i = this.numOuterVerts - 1;
947 755
948 if (hasHollow) 756 if (hollowAngles.angles[0].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[maxJ].angle + 0.000001f)
949 { 757 {
950 this.cut1CoordIndices.Add(0); 758 newFace.v1 = 0;
951 this.cut1CoordIndices.Add(this.coords.Count - 1); 759 newFace.v2 = numTotalVerts - maxJ - 1;
760 newFace.v3 = numTotalVerts - 1;
952 761
953 this.cut2CoordIndices.Add(lastOuterVertIndex + 1); 762 this.faces.Add(newFace);
954 this.cut2CoordIndices.Add(lastOuterVertIndex); 763 }
955 764
956 this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y; 765 newFace.v1 = numTotalVerts - maxJ - 1;
957 this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X); 766 newFace.v2 = i;
767 newFace.v3 = 0;
958 768
959 this.cutNormal2.X = this.coords[lastOuterVertIndex + 1].Y - this.coords[lastOuterVertIndex].Y; 769 this.faces.Add(newFace);
960 this.cutNormal2.Y = -(this.coords[lastOuterVertIndex + 1].X - this.coords[lastOuterVertIndex].X); 770 }
771 }
961 } 772 }
773
774 }
962 775
776 else if (createFaces)
777 {
778 if (simpleFace)
779 {
780 if (sides == 3)
781 this.faces.Add(new Face(0, 1, 2));
782 else if (sides == 4)
783 {
784 this.faces.Add(new Face(0, 1, 2));
785 this.faces.Add(new Face(0, 2, 3));
786 }
787 }
963 else 788 else
964 { 789 {
965 this.cut1CoordIndices.Add(0); 790 for (int i = 1; i < numAngles ; i++)
966 this.cut1CoordIndices.Add(1); 791 {
967 792 Face newFace = new Face();
968 this.cut2CoordIndices.Add(lastOuterVertIndex); 793 newFace.v1 = 0;
969 this.cut2CoordIndices.Add(0); 794 newFace.v2 = i;
970 795 newFace.v3 = i + 1;
971 this.cutNormal1.X = this.vertexNormals[1].Y; 796 this.faces.Add(newFace);
972 this.cutNormal1.Y = -this.vertexNormals[1].X; 797 }
973 798 if (!hasProfileCut)
974 this.cutNormal2.X = -this.vertexNormals[this.vertexNormals.Count - 2].Y; 799 {
975 this.cutNormal2.Y = this.vertexNormals[this.vertexNormals.Count - 2].X; 800 Face newFace = new Face();
976 801 newFace.v1 = 0;
802 newFace.v2 = numAngles;
803 newFace.v3 = 1;
804 this.faces.Add(newFace);
805 }
977 } 806 }
978 this.cutNormal1.Normalize();
979 this.cutNormal2.Normalize();
980 } 807 }
981 808
982 this.MakeFaceUVs();
983 809
984 hollowCoords = null; 810 hollowCoords = null;
985 hollowNormals = null;
986 hollowUs = null;
987
988 if (calcVertexNormals)
989 { // calculate prim face numbers
990
991 // face number order is top, outer, hollow, bottom, start cut, end cut
992 // I know it's ugly but so is the whole concept of prim face numbers
993
994 int faceNum = 1; // start with outer faces
995 this.outerFaceNumber = faceNum;
996
997 int startVert = hasProfileCut && !hasHollow ? 1 : 0;
998 if (startVert > 0)
999 this.faceNumbers.Add(-1);
1000 for (int i = 0; i < this.numOuterVerts - 1; i++)
1001 this.faceNumbers.Add(sides < 5 && i <= sides ? faceNum++ : faceNum);
1002
1003 this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++);
1004
1005 if (sides > 4 && (hasHollow || hasProfileCut))
1006 faceNum++;
1007
1008 if (sides < 5 && (hasHollow || hasProfileCut) && this.numOuterVerts < sides)
1009 faceNum++;
1010
1011 if (hasHollow)
1012 {
1013 for (int i = 0; i < this.numHollowVerts; i++)
1014 this.faceNumbers.Add(faceNum);
1015
1016 this.hollowFaceNumber = faceNum++;
1017 }
1018
1019 this.bottomFaceNumber = faceNum++;
1020
1021 if (hasHollow && hasProfileCut)
1022 this.faceNumbers.Add(faceNum++);
1023
1024 for (int i = 0; i < this.faceNumbers.Count; i++)
1025 if (this.faceNumbers[i] == -1)
1026 this.faceNumbers[i] = faceNum++;
1027
1028 this.numPrimFaces = faceNum;
1029 }
1030
1031 } 811 }
1032 812
1033 public void MakeFaceUVs()
1034 {
1035 this.faceUVs = new List<UVCoord>();
1036 foreach (Coord c in this.coords)
1037 this.faceUVs.Add(new UVCoord(1.0f - (0.5f + c.X), 1.0f - (0.5f - c.Y)));
1038 }
1039 813
1040 public Profile Copy() 814 public Profile Copy()
1041 { 815 {
@@ -1047,24 +821,10 @@ namespace PrimMesher
1047 Profile copy = new Profile(); 821 Profile copy = new Profile();
1048 822
1049 copy.coords.AddRange(this.coords); 823 copy.coords.AddRange(this.coords);
1050 copy.faceUVs.AddRange(this.faceUVs);
1051 824
1052 if (needFaces) 825 if (needFaces)
1053 copy.faces.AddRange(this.faces); 826 copy.faces.AddRange(this.faces);
1054 if ((copy.calcVertexNormals = this.calcVertexNormals) == true) 827
1055 {
1056 copy.vertexNormals.AddRange(this.vertexNormals);
1057 copy.faceNormal = this.faceNormal;
1058 copy.cutNormal1 = this.cutNormal1;
1059 copy.cutNormal2 = this.cutNormal2;
1060 copy.us.AddRange(this.us);
1061 copy.faceNumbers.AddRange(this.faceNumbers);
1062
1063 copy.cut1CoordIndices = new List<int>(this.cut1CoordIndices);
1064 copy.cut2CoordIndices = new List<int>(this.cut2CoordIndices);
1065 copy.hollowCoordIndices = new List<int>(this.hollowCoordIndices);
1066 copy.outerCoordIndices = new List<int>(this.outerCoordIndices);
1067 }
1068 copy.numOuterVerts = this.numOuterVerts; 828 copy.numOuterVerts = this.numOuterVerts;
1069 copy.numHollowVerts = this.numHollowVerts; 829 copy.numHollowVerts = this.numHollowVerts;
1070 830
@@ -1099,18 +859,6 @@ namespace PrimMesher
1099 859
1100 for (i = 0; i < numVerts; i++) 860 for (i = 0; i < numVerts; i++)
1101 this.coords[i] *= q; 861 this.coords[i] *= q;
1102
1103 if (this.calcVertexNormals)
1104 {
1105 int numNormals = this.vertexNormals.Count;
1106 for (i = 0; i < numNormals; i++)
1107 this.vertexNormals[i] *= q;
1108
1109 this.faceNormal *= q;
1110 this.cutNormal1 *= q;
1111 this.cutNormal2 *= q;
1112
1113 }
1114 } 862 }
1115 863
1116 public void Scale(float x, float y) 864 public void Scale(float x, float y)
@@ -1146,29 +894,6 @@ namespace PrimMesher
1146 tmpFace.v1 = tmp; 894 tmpFace.v1 = tmp;
1147 this.faces[i] = tmpFace; 895 this.faces[i] = tmpFace;
1148 } 896 }
1149
1150 if (this.calcVertexNormals)
1151 {
1152 int normalCount = this.vertexNormals.Count;
1153 if (normalCount > 0)
1154 {
1155 Coord n = this.vertexNormals[normalCount - 1];
1156 n.Z = -n.Z;
1157 this.vertexNormals[normalCount - 1] = n;
1158 }
1159 }
1160
1161 this.faceNormal.X = -this.faceNormal.X;
1162 this.faceNormal.Y = -this.faceNormal.Y;
1163 this.faceNormal.Z = -this.faceNormal.Z;
1164
1165 int numfaceUVs = this.faceUVs.Count;
1166 for (i = 0; i < numfaceUVs; i++)
1167 {
1168 UVCoord uv = this.faceUVs[i];
1169 uv.V = 1.0f - uv.V;
1170 this.faceUVs[i] = uv;
1171 }
1172 } 897 }
1173 898
1174 public void AddValue2FaceVertexIndices(int num) 899 public void AddValue2FaceVertexIndices(int num)
@@ -1186,25 +911,7 @@ namespace PrimMesher
1186 } 911 }
1187 } 912 }
1188 913
1189 public void AddValue2FaceNormalIndices(int num) 914 public void DumpRaw(String path, String name, String title)
1190 {
1191 if (this.calcVertexNormals)
1192 {
1193 int numFaces = this.faces.Count;
1194 Face tmpFace;
1195 for (int i = 0; i < numFaces; i++)
1196 {
1197 tmpFace = this.faces[i];
1198 tmpFace.n1 += num;
1199 tmpFace.n2 += num;
1200 tmpFace.n3 += num;
1201
1202 this.faces[i] = tmpFace;
1203 }
1204 }
1205 }
1206
1207 public void DumpRaw(String path, String name, String title)
1208 { 915 {
1209 if (path == null) 916 if (path == null)
1210 return; 917 return;
@@ -1451,11 +1158,9 @@ namespace PrimMesher
1451 private const float twoPi = 2.0f * (float)Math.PI; 1158 private const float twoPi = 2.0f * (float)Math.PI;
1452 1159
1453 public List<Coord> coords; 1160 public List<Coord> coords;
1454 public List<Coord> normals; 1161// public List<Coord> normals;
1455 public List<Face> faces; 1162 public List<Face> faces;
1456 1163
1457 public List<ViewerFace> viewerFaces;
1458
1459 private int sides = 4; 1164 private int sides = 4;
1460 private int hollowSides = 4; 1165 private int hollowSides = 4;
1461 private float profileStart = 0.0f; 1166 private float profileStart = 0.0f;
@@ -1478,15 +1183,8 @@ namespace PrimMesher
1478 public float revolutions = 1.0f; 1183 public float revolutions = 1.0f;
1479 public int stepsPerRevolution = 24; 1184 public int stepsPerRevolution = 24;
1480 1185
1481 private int profileOuterFaceNumber = -1;
1482 private int profileHollowFaceNumber = -1;
1483
1484 private bool hasProfileCut = false; 1186 private bool hasProfileCut = false;
1485 private bool hasHollow = false; 1187 private bool hasHollow = false;
1486 public bool calcVertexNormals = false;
1487 private bool normalsProcessed = false;
1488 public bool viewerMode = false;
1489 public bool sphereMode = false;
1490 1188
1491 public int numPrimFaces = 0; 1189 public int numPrimFaces = 0;
1492 1190
@@ -1518,27 +1216,16 @@ namespace PrimMesher
1518 s += "\nradius...............: " + this.radius.ToString(); 1216 s += "\nradius...............: " + this.radius.ToString();
1519 s += "\nrevolutions..........: " + this.revolutions.ToString(); 1217 s += "\nrevolutions..........: " + this.revolutions.ToString();
1520 s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString(); 1218 s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString();
1521 s += "\nsphereMode...........: " + this.sphereMode.ToString();
1522 s += "\nhasProfileCut........: " + this.hasProfileCut.ToString(); 1219 s += "\nhasProfileCut........: " + this.hasProfileCut.ToString();
1523 s += "\nhasHollow............: " + this.hasHollow.ToString(); 1220 s += "\nhasHollow............: " + this.hasHollow.ToString();
1524 s += "\nviewerMode...........: " + this.viewerMode.ToString();
1525 1221
1526 return s; 1222 return s;
1527 } 1223 }
1528 1224
1529 public int ProfileOuterFaceNumber
1530 {
1531 get { return profileOuterFaceNumber; }
1532 }
1533
1534 public int ProfileHollowFaceNumber
1535 {
1536 get { return profileHollowFaceNumber; }
1537 }
1538
1539 public bool HasProfileCut 1225 public bool HasProfileCut
1540 { 1226 {
1541 get { return hasProfileCut; } 1227 get { return hasProfileCut; }
1228 set { hasProfileCut = value; }
1542 } 1229 }
1543 1230
1544 public bool HasHollow 1231 public bool HasHollow
@@ -1555,6 +1242,7 @@ namespace PrimMesher
1555 /// <param name="profileEnd"></param> 1242 /// <param name="profileEnd"></param>
1556 /// <param name="hollow"></param> 1243 /// <param name="hollow"></param>
1557 /// <param name="hollowSides"></param> 1244 /// <param name="hollowSides"></param>
1245 /// <param name="sphereMode"></param>
1558 public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides) 1246 public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides)
1559 { 1247 {
1560 this.coords = new List<Coord>(); 1248 this.coords = new List<Coord>();
@@ -1594,32 +1282,12 @@ namespace PrimMesher
1594 this.coords = new List<Coord>(); 1282 this.coords = new List<Coord>();
1595 this.faces = new List<Face>(); 1283 this.faces = new List<Face>();
1596 1284
1597 if (this.viewerMode)
1598 {
1599 this.viewerFaces = new List<ViewerFace>();
1600 this.calcVertexNormals = true;
1601 }
1602
1603 if (this.calcVertexNormals)
1604 this.normals = new List<Coord>();
1605
1606 int steps = 1; 1285 int steps = 1;
1607 1286
1608 float length = this.pathCutEnd - this.pathCutBegin; 1287 float length = this.pathCutEnd - this.pathCutBegin;
1609 normalsProcessed = false;
1610 1288
1611 if (this.viewerMode && this.sides == 3) 1289 this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1612 {
1613 // prisms don't taper well so add some vertical resolution
1614 // other prims may benefit from this but just do prisms for now
1615 if (Math.Abs(this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01)
1616 steps = (int)(steps * 4.5 * length);
1617 }
1618 1290
1619 if (this.sphereMode)
1620 this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f;
1621 else
1622 this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1623 this.hasHollow = (this.hollow > 0.001f); 1291 this.hasHollow = (this.hollow > 0.001f);
1624 1292
1625 float twistBegin = this.twistBegin / 360.0f * twoPi; 1293 float twistBegin = this.twistBegin / 360.0f * twoPi;
@@ -1701,47 +1369,16 @@ namespace PrimMesher
1701 hollow *= 1.414f; 1369 hollow *= 1.414f;
1702 } 1370 }
1703 1371
1704 Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals); 1372 Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, this.hasProfileCut,true);
1705 this.errorMessage = profile.errorMessage; 1373 this.errorMessage = profile.errorMessage;
1706 1374
1707 this.numPrimFaces = profile.numPrimFaces; 1375 this.numPrimFaces = profile.numPrimFaces;
1708 1376
1709 int cut1FaceNumber = profile.bottomFaceNumber + 1;
1710 int cut2FaceNumber = cut1FaceNumber + 1;
1711 if (!needEndFaces)
1712 {
1713 cut1FaceNumber -= 2;
1714 cut2FaceNumber -= 2;
1715 }
1716
1717 profileOuterFaceNumber = profile.outerFaceNumber;
1718 if (!needEndFaces)
1719 profileOuterFaceNumber--;
1720
1721 if (hasHollow)
1722 {
1723 profileHollowFaceNumber = profile.hollowFaceNumber;
1724 if (!needEndFaces)
1725 profileHollowFaceNumber--;
1726 }
1727
1728 int cut1Vert = -1;
1729 int cut2Vert = -1;
1730 if (hasProfileCut)
1731 {
1732 cut1Vert = hasHollow ? profile.coords.Count - 1 : 0;
1733 cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts;
1734 }
1735
1736 if (initialProfileRot != 0.0f) 1377 if (initialProfileRot != 0.0f)
1737 { 1378 {
1738 profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot)); 1379 profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
1739 if (viewerMode)
1740 profile.MakeFaceUVs();
1741 } 1380 }
1742 1381
1743 Coord lastCutNormal1 = new Coord();
1744 Coord lastCutNormal2 = new Coord();
1745 float thisV = 0.0f; 1382 float thisV = 0.0f;
1746 float lastV = 0.0f; 1383 float lastV = 0.0f;
1747 1384
@@ -1764,57 +1401,21 @@ namespace PrimMesher
1764 path.stepsPerRevolution = stepsPerRevolution; 1401 path.stepsPerRevolution = stepsPerRevolution;
1765 1402
1766 path.Create(pathType, steps); 1403 path.Create(pathType, steps);
1404
1405 int lastNode = path.pathNodes.Count -1;
1767 1406
1768 for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) 1407 for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1769 { 1408 {
1770 PathNode node = path.pathNodes[nodeIndex]; 1409 PathNode node = path.pathNodes[nodeIndex];
1771 Profile newLayer = profile.Copy(); 1410 Profile newLayer = profile.Copy();
1772 newLayer.Scale(node.xScale, node.yScale);
1773 1411
1412 newLayer.Scale(node.xScale, node.yScale);
1774 newLayer.AddRot(node.rotation); 1413 newLayer.AddRot(node.rotation);
1775 newLayer.AddPos(node.position); 1414 newLayer.AddPos(node.position);
1776 1415
1777 if (needEndFaces && nodeIndex == 0) 1416 if (needEndFaces && nodeIndex == 0)
1778 { 1417 {
1779 newLayer.FlipNormals(); 1418 newLayer.FlipNormals();
1780
1781 // add the bottom faces to the viewerFaces list
1782 if (this.viewerMode)
1783 {
1784 Coord faceNormal = newLayer.faceNormal;
1785 ViewerFace newViewerFace = new ViewerFace(profile.bottomFaceNumber);
1786 int numFaces = newLayer.faces.Count;
1787 List<Face> faces = newLayer.faces;
1788
1789 for (int i = 0; i < numFaces; i++)
1790 {
1791 Face face = faces[i];
1792 newViewerFace.v1 = newLayer.coords[face.v1];
1793 newViewerFace.v2 = newLayer.coords[face.v2];
1794 newViewerFace.v3 = newLayer.coords[face.v3];
1795
1796 newViewerFace.coordIndex1 = face.v1;
1797 newViewerFace.coordIndex2 = face.v2;
1798 newViewerFace.coordIndex3 = face.v3;
1799
1800 newViewerFace.n1 = faceNormal;
1801 newViewerFace.n2 = faceNormal;
1802 newViewerFace.n3 = faceNormal;
1803
1804 newViewerFace.uv1 = newLayer.faceUVs[face.v1];
1805 newViewerFace.uv2 = newLayer.faceUVs[face.v2];
1806 newViewerFace.uv3 = newLayer.faceUVs[face.v3];
1807
1808 if (pathType == PathType.Linear)
1809 {
1810 newViewerFace.uv1.Flip();
1811 newViewerFace.uv2.Flip();
1812 newViewerFace.uv3.Flip();
1813 }
1814
1815 this.viewerFaces.Add(newViewerFace);
1816 }
1817 }
1818 } // if (nodeIndex == 0) 1419 } // if (nodeIndex == 0)
1819 1420
1820 // append this layer 1421 // append this layer
@@ -1824,15 +1425,17 @@ namespace PrimMesher
1824 1425
1825 this.coords.AddRange(newLayer.coords); 1426 this.coords.AddRange(newLayer.coords);
1826 1427
1827 if (this.calcVertexNormals) 1428 if (needEndFaces)
1828 { 1429 {
1829 newLayer.AddValue2FaceNormalIndices(this.normals.Count); 1430 if (nodeIndex == 0)
1830 this.normals.AddRange(newLayer.vertexNormals); 1431 this.faces.AddRange(newLayer.faces);
1432 else if (nodeIndex == lastNode)
1433 {
1434 if (node.xScale > 1e-6 && node.yScale > 1e-6)
1435 this.faces.AddRange(newLayer.faces);
1436 }
1831 } 1437 }
1832 1438
1833 if (node.percentOfPath < this.pathCutBegin + 0.01f || node.percentOfPath > this.pathCutEnd - 0.01f)
1834 this.faces.AddRange(newLayer.faces);
1835
1836 // fill faces between layers 1439 // fill faces between layers
1837 1440
1838 int numVerts = newLayer.coords.Count; 1441 int numVerts = newLayer.coords.Count;
@@ -1843,219 +1446,88 @@ namespace PrimMesher
1843 1446
1844 if (nodeIndex > 0) 1447 if (nodeIndex > 0)
1845 { 1448 {
1846 int startVert = coordsLen + 1; 1449 int startVert = coordsLen;
1847 int endVert = this.coords.Count; 1450 int endVert = this.coords.Count;
1848 1451 if (!this.hasProfileCut)
1849 if (sides < 5 || this.hasProfileCut || this.hasHollow)
1850 startVert--;
1851
1852 for (int i = startVert; i < endVert; i++)
1853 { 1452 {
1854 int iNext = i + 1; 1453 int i = startVert;
1855 if (i == endVert - 1) 1454 for (int l = 0; l < profile.numOuterVerts - 1; l++)
1856 iNext = startVert; 1455 {
1857 1456 newFace1.v1 = i;
1858 int whichVert = i - startVert; 1457 newFace1.v2 = i - numVerts;
1458 newFace1.v3 = i + 1;
1459 this.faces.Add(newFace1);
1460
1461 newFace2.v1 = i + 1;
1462 newFace2.v2 = i - numVerts;
1463 newFace2.v3 = i + 1 - numVerts;
1464 this.faces.Add(newFace2);
1465 i++;
1466 }
1859 1467
1860 newFace1.v1 = i; 1468 newFace1.v1 = i;
1861 newFace1.v2 = i - numVerts; 1469 newFace1.v2 = i - numVerts;
1862 newFace1.v3 = iNext; 1470 newFace1.v3 = startVert;
1863
1864 newFace1.n1 = newFace1.v1;
1865 newFace1.n2 = newFace1.v2;
1866 newFace1.n3 = newFace1.v3;
1867 this.faces.Add(newFace1); 1471 this.faces.Add(newFace1);
1868 1472
1869 newFace2.v1 = iNext; 1473 newFace2.v1 = startVert;
1870 newFace2.v2 = i - numVerts; 1474 newFace2.v2 = i - numVerts;
1871 newFace2.v3 = iNext - numVerts; 1475 newFace2.v3 = startVert - numVerts;
1872
1873 newFace2.n1 = newFace2.v1;
1874 newFace2.n2 = newFace2.v2;
1875 newFace2.n3 = newFace2.v3;
1876 this.faces.Add(newFace2); 1476 this.faces.Add(newFace2);
1877 1477
1878 if (this.viewerMode) 1478 if (this.hasHollow)
1879 { 1479 {
1880 // add the side faces to the list of viewerFaces here 1480 startVert = ++i;
1881 1481 for (int l = 0; l < profile.numHollowVerts - 1; l++)
1882 int primFaceNum = profile.faceNumbers[whichVert];
1883 if (!needEndFaces)
1884 primFaceNum -= 1;
1885
1886 ViewerFace newViewerFace1 = new ViewerFace(primFaceNum);
1887 ViewerFace newViewerFace2 = new ViewerFace(primFaceNum);
1888
1889 int uIndex = whichVert;
1890 if (!hasHollow && sides > 4 && uIndex < newLayer.us.Count - 1)
1891 {
1892 uIndex++;
1893 }
1894
1895 float u1 = newLayer.us[uIndex];
1896 float u2 = 1.0f;
1897 if (uIndex < (int)newLayer.us.Count - 1)
1898 u2 = newLayer.us[uIndex + 1];
1899
1900 if (whichVert == cut1Vert || whichVert == cut2Vert)
1901 {
1902 u1 = 0.0f;
1903 u2 = 1.0f;
1904 }
1905 else if (sides < 5)
1906 {
1907 if (whichVert < profile.numOuterVerts)
1908 { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled
1909 // to reflect the entire texture width
1910 u1 *= sides;
1911 u2 *= sides;
1912 u2 -= (int)u1;
1913 u1 -= (int)u1;
1914 if (u2 < 0.1f)
1915 u2 = 1.0f;
1916 }
1917 }
1918
1919 if (this.sphereMode)
1920 { 1482 {
1921 if (whichVert != cut1Vert && whichVert != cut2Vert) 1483 newFace1.v1 = i;
1922 { 1484 newFace1.v2 = i - numVerts;
1923 u1 = u1 * 2.0f - 1.0f; 1485 newFace1.v3 = i + 1;
1924 u2 = u2 * 2.0f - 1.0f; 1486 this.faces.Add(newFace1);
1925 1487
1926 if (whichVert >= newLayer.numOuterVerts) 1488 newFace2.v1 = i + 1;
1927 { 1489 newFace2.v2 = i - numVerts;
1928 u1 -= hollow; 1490 newFace2.v3 = i + 1 - numVerts;
1929 u2 -= hollow; 1491 this.faces.Add(newFace2);
1930 } 1492 i++;
1931
1932 }
1933 }
1934
1935 newViewerFace1.uv1.U = u1;
1936 newViewerFace1.uv2.U = u1;
1937 newViewerFace1.uv3.U = u2;
1938
1939 newViewerFace1.uv1.V = thisV;
1940 newViewerFace1.uv2.V = lastV;
1941 newViewerFace1.uv3.V = thisV;
1942
1943 newViewerFace2.uv1.U = u2;
1944 newViewerFace2.uv2.U = u1;
1945 newViewerFace2.uv3.U = u2;
1946
1947 newViewerFace2.uv1.V = thisV;
1948 newViewerFace2.uv2.V = lastV;
1949 newViewerFace2.uv3.V = lastV;
1950
1951 newViewerFace1.v1 = this.coords[newFace1.v1];
1952 newViewerFace1.v2 = this.coords[newFace1.v2];
1953 newViewerFace1.v3 = this.coords[newFace1.v3];
1954
1955 newViewerFace2.v1 = this.coords[newFace2.v1];
1956 newViewerFace2.v2 = this.coords[newFace2.v2];
1957 newViewerFace2.v3 = this.coords[newFace2.v3];
1958
1959 newViewerFace1.coordIndex1 = newFace1.v1;
1960 newViewerFace1.coordIndex2 = newFace1.v2;
1961 newViewerFace1.coordIndex3 = newFace1.v3;
1962
1963 newViewerFace2.coordIndex1 = newFace2.v1;
1964 newViewerFace2.coordIndex2 = newFace2.v2;
1965 newViewerFace2.coordIndex3 = newFace2.v3;
1966
1967 // profile cut faces
1968 if (whichVert == cut1Vert)
1969 {
1970 newViewerFace1.primFaceNumber = cut1FaceNumber;
1971 newViewerFace2.primFaceNumber = cut1FaceNumber;
1972 newViewerFace1.n1 = newLayer.cutNormal1;
1973 newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1;
1974
1975 newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1;
1976 newViewerFace2.n2 = lastCutNormal1;
1977 }
1978 else if (whichVert == cut2Vert)
1979 {
1980 newViewerFace1.primFaceNumber = cut2FaceNumber;
1981 newViewerFace2.primFaceNumber = cut2FaceNumber;
1982 newViewerFace1.n1 = newLayer.cutNormal2;
1983 newViewerFace1.n2 = lastCutNormal2;
1984 newViewerFace1.n3 = lastCutNormal2;
1985
1986 newViewerFace2.n1 = newLayer.cutNormal2;
1987 newViewerFace2.n3 = newLayer.cutNormal2;
1988 newViewerFace2.n2 = lastCutNormal2;
1989 }
1990
1991 else // outer and hollow faces
1992 {
1993 if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts))
1994 { // looks terrible when path is twisted... need vertex normals here
1995 newViewerFace1.CalcSurfaceNormal();
1996 newViewerFace2.CalcSurfaceNormal();
1997 }
1998 else
1999 {
2000 newViewerFace1.n1 = this.normals[newFace1.n1];
2001 newViewerFace1.n2 = this.normals[newFace1.n2];
2002 newViewerFace1.n3 = this.normals[newFace1.n3];
2003
2004 newViewerFace2.n1 = this.normals[newFace2.n1];
2005 newViewerFace2.n2 = this.normals[newFace2.n2];
2006 newViewerFace2.n3 = this.normals[newFace2.n3];
2007 }
2008 } 1493 }
2009 1494
2010 this.viewerFaces.Add(newViewerFace1); 1495 newFace1.v1 = i;
2011 this.viewerFaces.Add(newViewerFace2); 1496 newFace1.v2 = i - numVerts;
1497 newFace1.v3 = startVert;
1498 this.faces.Add(newFace1);
2012 1499
1500 newFace2.v1 = startVert;
1501 newFace2.v2 = i - numVerts;
1502 newFace2.v3 = startVert - numVerts;
1503 this.faces.Add(newFace2);
2013 } 1504 }
2014 }
2015 }
2016 1505
2017 lastCutNormal1 = newLayer.cutNormal1;
2018 lastCutNormal2 = newLayer.cutNormal2;
2019 lastV = thisV;
2020 1506
2021 if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode) 1507 }
2022 { 1508 else
2023 // add the top faces to the viewerFaces list here
2024 Coord faceNormal = newLayer.faceNormal;
2025 ViewerFace newViewerFace = new ViewerFace(0);
2026 int numFaces = newLayer.faces.Count;
2027 List<Face> faces = newLayer.faces;
2028
2029 for (int i = 0; i < numFaces; i++)
2030 { 1509 {
2031 Face face = faces[i]; 1510 for (int i = startVert; i < endVert; i++)
2032 newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen]; 1511 {
2033 newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen]; 1512 int iNext = i + 1;
2034 newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen]; 1513 if (i == endVert - 1)
2035 1514 iNext = startVert;
2036 newViewerFace.coordIndex1 = face.v1 - coordsLen;
2037 newViewerFace.coordIndex2 = face.v2 - coordsLen;
2038 newViewerFace.coordIndex3 = face.v3 - coordsLen;
2039 1515
2040 newViewerFace.n1 = faceNormal; 1516 newFace1.v1 = i;
2041 newViewerFace.n2 = faceNormal; 1517 newFace1.v2 = i - numVerts;
2042 newViewerFace.n3 = faceNormal; 1518 newFace1.v3 = iNext;
1519 this.faces.Add(newFace1);
2043 1520
2044 newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen]; 1521 newFace2.v1 = iNext;
2045 newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen]; 1522 newFace2.v2 = i - numVerts;
2046 newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen]; 1523 newFace2.v3 = iNext - numVerts;
1524 this.faces.Add(newFace2);
2047 1525
2048 if (pathType == PathType.Linear)
2049 {
2050 newViewerFace.uv1.Flip();
2051 newViewerFace.uv2.Flip();
2052 newViewerFace.uv3.Flip();
2053 } 1526 }
2054
2055 this.viewerFaces.Add(newViewerFace);
2056 } 1527 }
2057 } 1528 }
2058 1529
1530 lastV = thisV;
2059 1531
2060 } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) 1532 } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
2061 1533
@@ -2138,51 +1610,17 @@ namespace PrimMesher
2138 copy.radius = this.radius; 1610 copy.radius = this.radius;
2139 copy.revolutions = this.revolutions; 1611 copy.revolutions = this.revolutions;
2140 copy.stepsPerRevolution = this.stepsPerRevolution; 1612 copy.stepsPerRevolution = this.stepsPerRevolution;
2141 copy.calcVertexNormals = this.calcVertexNormals; 1613
2142 copy.normalsProcessed = this.normalsProcessed;
2143 copy.viewerMode = this.viewerMode;
2144 copy.numPrimFaces = this.numPrimFaces; 1614 copy.numPrimFaces = this.numPrimFaces;
2145 copy.errorMessage = this.errorMessage; 1615 copy.errorMessage = this.errorMessage;
2146 1616
2147 copy.coords = new List<Coord>(this.coords); 1617 copy.coords = new List<Coord>(this.coords);
2148 copy.faces = new List<Face>(this.faces); 1618 copy.faces = new List<Face>(this.faces);
2149 copy.viewerFaces = new List<ViewerFace>(this.viewerFaces);
2150 copy.normals = new List<Coord>(this.normals);
2151 1619
2152 return copy; 1620 return copy;
2153 } 1621 }
2154 1622
2155 /// <summary> 1623 /// <summary>
2156 /// Calculate surface normals for all of the faces in the list of faces in this mesh
2157 /// </summary>
2158 public void CalcNormals()
2159 {
2160 if (normalsProcessed)
2161 return;
2162
2163 normalsProcessed = true;
2164
2165 int numFaces = faces.Count;
2166
2167 if (!this.calcVertexNormals)
2168 this.normals = new List<Coord>();
2169
2170 for (int i = 0; i < numFaces; i++)
2171 {
2172 Face face = faces[i];
2173
2174 this.normals.Add(SurfaceNormal(i).Normalize());
2175
2176 int normIndex = normals.Count - 1;
2177 face.n1 = normIndex;
2178 face.n2 = normIndex;
2179 face.n3 = normIndex;
2180
2181 this.faces[i] = face;
2182 }
2183 }
2184
2185 /// <summary>
2186 /// Adds a value to each XYZ vertex coordinate in the mesh 1624 /// Adds a value to each XYZ vertex coordinate in the mesh
2187 /// </summary> 1625 /// </summary>
2188 /// <param name="x"></param> 1626 /// <param name="x"></param>
@@ -2202,18 +1640,6 @@ namespace PrimMesher
2202 vert.Z += z; 1640 vert.Z += z;
2203 this.coords[i] = vert; 1641 this.coords[i] = vert;
2204 } 1642 }
2205
2206 if (this.viewerFaces != null)
2207 {
2208 int numViewerFaces = this.viewerFaces.Count;
2209
2210 for (i = 0; i < numViewerFaces; i++)
2211 {
2212 ViewerFace v = this.viewerFaces[i];
2213 v.AddPos(x, y, z);
2214 this.viewerFaces[i] = v;
2215 }
2216 }
2217 } 1643 }
2218 1644
2219 /// <summary> 1645 /// <summary>
@@ -2227,38 +1653,11 @@ namespace PrimMesher
2227 1653
2228 for (i = 0; i < numVerts; i++) 1654 for (i = 0; i < numVerts; i++)
2229 this.coords[i] *= q; 1655 this.coords[i] *= q;
2230
2231 if (this.normals != null)
2232 {
2233 int numNormals = this.normals.Count;
2234 for (i = 0; i < numNormals; i++)
2235 this.normals[i] *= q;
2236 }
2237
2238 if (this.viewerFaces != null)
2239 {
2240 int numViewerFaces = this.viewerFaces.Count;
2241
2242 for (i = 0; i < numViewerFaces; i++)
2243 {
2244 ViewerFace v = this.viewerFaces[i];
2245 v.v1 *= q;
2246 v.v2 *= q;
2247 v.v3 *= q;
2248
2249 v.n1 *= q;
2250 v.n2 *= q;
2251 v.n3 *= q;
2252 this.viewerFaces[i] = v;
2253 }
2254 }
2255 } 1656 }
2256 1657
2257#if VERTEX_INDEXER 1658#if VERTEX_INDEXER
2258 public VertexIndexer GetVertexIndexer() 1659 public VertexIndexer GetVertexIndexer()
2259 { 1660 {
2260 if (this.viewerMode && this.viewerFaces.Count > 0)
2261 return new VertexIndexer(this);
2262 return null; 1661 return null;
2263 } 1662 }
2264#endif 1663#endif
@@ -2278,21 +1677,6 @@ namespace PrimMesher
2278 Coord m = new Coord(x, y, z); 1677 Coord m = new Coord(x, y, z);
2279 for (i = 0; i < numVerts; i++) 1678 for (i = 0; i < numVerts; i++)
2280 this.coords[i] *= m; 1679 this.coords[i] *= m;
2281
2282 if (this.viewerFaces != null)
2283 {
2284 int numViewerFaces = this.viewerFaces.Count;
2285 for (i = 0; i < numViewerFaces; i++)
2286 {
2287 ViewerFace v = this.viewerFaces[i];
2288 v.v1 *= m;
2289 v.v2 *= m;
2290 v.v3 *= m;
2291 this.viewerFaces[i] = v;
2292 }
2293
2294 }
2295
2296 } 1680 }
2297 1681
2298 /// <summary> 1682 /// <summary>