diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 1761 |
1 files changed, 131 insertions, 1630 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 6955aa0..a65d0f4 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -31,6 +31,9 @@ using System.Collections.Generic; | |||
31 | using OpenSim.Framework; | 31 | using OpenSim.Framework; |
32 | using OpenSim.Region.Physics.Manager; | 32 | using OpenSim.Region.Physics.Manager; |
33 | using OpenMetaverse; | 33 | using OpenMetaverse; |
34 | using OpenMetaverse.Imaging; | ||
35 | using System.Drawing; | ||
36 | using System.Drawing.Imaging; | ||
34 | using PrimMesher; | 37 | using PrimMesher; |
35 | 38 | ||
36 | namespace OpenSim.Region.Physics.Meshing | 39 | namespace OpenSim.Region.Physics.Meshing |
@@ -54,8 +57,6 @@ namespace OpenSim.Region.Physics.Meshing | |||
54 | 57 | ||
55 | public class Meshmerizer : IMesher | 58 | public class Meshmerizer : IMesher |
56 | { | 59 | { |
57 | private bool usePrimMesher = true; | ||
58 | |||
59 | //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 60 | //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
60 | 61 | ||
61 | // Setting baseDir to a path will enable the dumping of raw files | 62 | // Setting baseDir to a path will enable the dumping of raw files |
@@ -65,277 +66,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
65 | #else | 66 | #else |
66 | private const string baseDir = null; //"rawFiles"; | 67 | private const string baseDir = null; //"rawFiles"; |
67 | #endif | 68 | #endif |
68 | private const float DEG_TO_RAD = 0.01745329238f; | ||
69 | 69 | ||
70 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh | 70 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh |
71 | 71 | ||
72 | // private static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, | ||
73 | // PhysicsVector r2, ref float lambda, ref float mu) | ||
74 | // { | ||
75 | // p1, p2, points on the straight | ||
76 | // r1, r2, directional vectors of the straight. Not necessarily of length 1! | ||
77 | // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points, | ||
78 | // thus allowing to decide whether an intersection is between two points | ||
79 | |||
80 | // float r1x = r1.X; | ||
81 | // float r1y = r1.Y; | ||
82 | // float r2x = r2.X; | ||
83 | // float r2y = r2.Y; | ||
84 | // | ||
85 | // float denom = r1y * r2x - r1x * r2y; | ||
86 | // | ||
87 | // if (denom == 0.0) | ||
88 | // { | ||
89 | // lambda = Single.NaN; | ||
90 | // mu = Single.NaN; | ||
91 | // return; | ||
92 | // } | ||
93 | // | ||
94 | // float p1x = p1.X; | ||
95 | // float p1y = p1.Y; | ||
96 | // float p2x = p2.X; | ||
97 | // float p2y = p2.Y; | ||
98 | // lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom; | ||
99 | // mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom; | ||
100 | // } | ||
101 | |||
102 | private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v) | ||
103 | { | ||
104 | List<Triangle> influenced = new List<Triangle>(); | ||
105 | foreach (Triangle t in triangles) | ||
106 | { | ||
107 | if (t.isInCircle(v.X, v.Y)) | ||
108 | { | ||
109 | influenced.Add(t); | ||
110 | } | ||
111 | } | ||
112 | return influenced; | ||
113 | } | ||
114 | |||
115 | private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles) | ||
116 | { | ||
117 | // This is a variant of the delaunay algorithm | ||
118 | // each time a new vertex is inserted, all triangles that are influenced by it are deleted | ||
119 | // and replaced by new ones including the new vertex | ||
120 | // It is not very time efficient but easy to implement. | ||
121 | |||
122 | int iCurrentVertex; | ||
123 | int iMaxVertex = vertices.Count; | ||
124 | for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++) | ||
125 | { | ||
126 | // Background: A triangle mesh fulfills the delaunay condition if (iff!) | ||
127 | // each circumlocutory circle (i.e. the circle that touches all three corners) | ||
128 | // of each triangle is empty of other vertices. | ||
129 | // Obviously a single (seeding) triangle fulfills this condition. | ||
130 | // If we now add one vertex, we need to reconstruct all triangles, that | ||
131 | // do not fulfill this condition with respect to the new triangle | ||
132 | |||
133 | // Find the triangles that are influenced by the new vertex | ||
134 | Vertex v = vertices[iCurrentVertex]; | ||
135 | if (v == null) | ||
136 | continue; // Null is polygon stop marker. Ignore it | ||
137 | List<Triangle> influencedTriangles = FindInfluencedTriangles(triangles, v); | ||
138 | |||
139 | List<Simplex> simplices = new List<Simplex>(); | ||
140 | |||
141 | // Reconstruction phase. First step, dissolve each triangle into it's simplices, | ||
142 | // i.e. it's "border lines" | ||
143 | // Goal is to find "inner" borders and delete them, while the hull gets conserved. | ||
144 | // Inner borders are special in the way that they always come twice, which is how we detect them | ||
145 | foreach (Triangle t in influencedTriangles) | ||
146 | { | ||
147 | List<Simplex> newSimplices = t.GetSimplices(); | ||
148 | simplices.AddRange(newSimplices); | ||
149 | triangles.Remove(t); | ||
150 | } | ||
151 | // Now sort the simplices. That will make identical ones reside side by side in the list | ||
152 | simplices.Sort(); | ||
153 | |||
154 | // Look for duplicate simplices here. | ||
155 | // Remember, they are directly side by side in the list right now, | ||
156 | // So we only check directly neighbours | ||
157 | int iSimplex; | ||
158 | List<Simplex> innerSimplices = new List<Simplex>(); | ||
159 | for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards | ||
160 | { | ||
161 | if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0) | ||
162 | { | ||
163 | innerSimplices.Add(simplices[iSimplex - 1]); | ||
164 | innerSimplices.Add(simplices[iSimplex]); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | foreach (Simplex s in innerSimplices) | ||
169 | { | ||
170 | simplices.Remove(s); | ||
171 | } | ||
172 | |||
173 | // each simplex still in the list belongs to the hull of the region in question | ||
174 | // The new vertex (yes, we still deal with verices here :-)) forms a triangle | ||
175 | // with each of these simplices. Build the new triangles and add them to the list | ||
176 | foreach (Simplex s in simplices) | ||
177 | { | ||
178 | Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]); | ||
179 | if (!t.isDegraded()) | ||
180 | { | ||
181 | triangles.Add(t); | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | private static SimpleHull BuildHoleHull(PrimitiveBaseShape pbs, ProfileShape pshape, HollowShape hshape, UInt16 hollowFactor) | ||
188 | { | ||
189 | // Tackle HollowShape.Same | ||
190 | float fhollowFactor = (float)hollowFactor; | ||
191 | |||
192 | switch (pshape) | ||
193 | { | ||
194 | case ProfileShape.Square: | ||
195 | if (hshape == HollowShape.Same) | ||
196 | hshape= HollowShape.Square; | ||
197 | break; | ||
198 | case ProfileShape.EquilateralTriangle: | ||
199 | fhollowFactor = ((float)hollowFactor / 1.9f); | ||
200 | if (hshape == HollowShape.Same) | ||
201 | { | ||
202 | hshape = HollowShape.Triangle; | ||
203 | } | ||
204 | |||
205 | break; | ||
206 | |||
207 | case ProfileShape.HalfCircle: | ||
208 | case ProfileShape.Circle: | ||
209 | if (pbs.PathCurve == (byte)Extrusion.Straight) | ||
210 | { | ||
211 | if (hshape == HollowShape.Same) | ||
212 | { | ||
213 | hshape = HollowShape.Circle; | ||
214 | } | ||
215 | } | ||
216 | break; | ||
217 | |||
218 | |||
219 | default: | ||
220 | if (hshape == HollowShape.Same) | ||
221 | hshape= HollowShape.Square; | ||
222 | break; | ||
223 | } | ||
224 | |||
225 | |||
226 | SimpleHull holeHull = null; | ||
227 | |||
228 | if (hshape == HollowShape.Square) | ||
229 | { | ||
230 | float hollowFactorF = (float)fhollowFactor / (float)50000; | ||
231 | Vertex IMM; | ||
232 | Vertex IPM; | ||
233 | Vertex IPP; | ||
234 | Vertex IMP; | ||
235 | |||
236 | if (pshape == ProfileShape.Circle) | ||
237 | { // square cutout in cylinder is 45 degress rotated | ||
238 | IMM = new Vertex(0.0f, -0.707f * hollowFactorF, 0.0f); | ||
239 | IPM = new Vertex(0.707f * hollowFactorF, 0.0f, 0.0f); | ||
240 | IPP = new Vertex(0.0f, 0.707f * hollowFactorF, 0.0f); | ||
241 | IMP = new Vertex(-0.707f * hollowFactorF, 0.0f, 0.0f); | ||
242 | } | ||
243 | else if (pshape == ProfileShape.EquilateralTriangle) | ||
244 | { | ||
245 | IMM = new Vertex(0.0f, -0.667f * hollowFactorF, 0.0f); | ||
246 | IPM = new Vertex(0.667f * hollowFactorF, 0.0f, 0.0f); | ||
247 | IPP = new Vertex(0.0f, 0.667f * hollowFactorF, 0.0f); | ||
248 | IMP = new Vertex(-0.667f * hollowFactorF, 0.0f, 0.0f); | ||
249 | } | ||
250 | else | ||
251 | { | ||
252 | IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); | ||
253 | IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f); | ||
254 | IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); | ||
255 | IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f); | ||
256 | } | ||
257 | |||
258 | holeHull = new SimpleHull(); | ||
259 | |||
260 | holeHull.AddVertex(IMM); | ||
261 | holeHull.AddVertex(IMP); | ||
262 | holeHull.AddVertex(IPP); | ||
263 | holeHull.AddVertex(IPM); | ||
264 | } | ||
265 | //if (hshape == HollowShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) | ||
266 | if (hshape == HollowShape.Circle) | ||
267 | { | ||
268 | float hollowFactorF = (float)fhollowFactor / (float)50000; | ||
269 | |||
270 | //Counter clockwise around the quadrants | ||
271 | holeHull = new SimpleHull(); | ||
272 | |||
273 | holeHull.AddVertex(new Vertex(0.353553f * hollowFactorF, 0.353553f * hollowFactorF, 0.0f)); // 45 degrees | ||
274 | holeHull.AddVertex(new Vertex(0.433013f * hollowFactorF, 0.250000f * hollowFactorF, 0.0f)); // 30 degrees | ||
275 | holeHull.AddVertex(new Vertex(0.482963f * hollowFactorF, 0.129410f * hollowFactorF, 0.0f)); // 15 degrees | ||
276 | holeHull.AddVertex(new Vertex(0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 0 degrees | ||
277 | holeHull.AddVertex(new Vertex(0.482963f * hollowFactorF, -0.129410f * hollowFactorF, 0.0f)); // 345 degrees | ||
278 | holeHull.AddVertex(new Vertex(0.433013f * hollowFactorF, -0.250000f * hollowFactorF, 0.0f)); // 330 degrees | ||
279 | holeHull.AddVertex(new Vertex(0.353553f * hollowFactorF, -0.353553f * hollowFactorF, 0.0f)); // 315 degrees | ||
280 | holeHull.AddVertex(new Vertex(0.250000f * hollowFactorF, -0.433013f * hollowFactorF, 0.0f)); // 300 degrees | ||
281 | holeHull.AddVertex(new Vertex(0.129410f * hollowFactorF, -0.482963f * hollowFactorF, 0.0f)); // 285 degrees | ||
282 | holeHull.AddVertex(new Vertex(0.000000f * hollowFactorF, -0.500000f * hollowFactorF, 0.0f)); // 270 degrees | ||
283 | holeHull.AddVertex(new Vertex(-0.129410f * hollowFactorF, -0.482963f * hollowFactorF, 0.0f)); // 255 degrees | ||
284 | holeHull.AddVertex(new Vertex(-0.250000f * hollowFactorF, -0.433013f * hollowFactorF, 0.0f)); // 240 degrees | ||
285 | holeHull.AddVertex(new Vertex(-0.353553f * hollowFactorF, -0.353553f * hollowFactorF, 0.0f)); // 225 degrees | ||
286 | holeHull.AddVertex(new Vertex(-0.433013f * hollowFactorF, -0.250000f * hollowFactorF, 0.0f)); // 210 degrees | ||
287 | holeHull.AddVertex(new Vertex(-0.482963f * hollowFactorF, -0.129410f * hollowFactorF, 0.0f)); // 195 degrees | ||
288 | holeHull.AddVertex(new Vertex(-0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 180 degrees | ||
289 | holeHull.AddVertex(new Vertex(-0.482963f * hollowFactorF, 0.129410f * hollowFactorF, 0.0f)); // 165 degrees | ||
290 | holeHull.AddVertex(new Vertex(-0.433013f * hollowFactorF, 0.250000f * hollowFactorF, 0.0f)); // 150 degrees | ||
291 | holeHull.AddVertex(new Vertex(-0.353553f * hollowFactorF, 0.353553f * hollowFactorF, 0.0f)); // 135 degrees | ||
292 | holeHull.AddVertex(new Vertex(-0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 120 degrees | ||
293 | holeHull.AddVertex(new Vertex(-0.129410f * hollowFactorF, 0.482963f * hollowFactorF, 0.0f)); // 105 degrees | ||
294 | holeHull.AddVertex(new Vertex(0.000000f * hollowFactorF, 0.500000f * hollowFactorF, 0.0f)); // 90 degrees | ||
295 | holeHull.AddVertex(new Vertex(0.129410f * hollowFactorF, 0.482963f * hollowFactorF, 0.0f)); // 75 degrees | ||
296 | holeHull.AddVertex(new Vertex(0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 60 degrees | ||
297 | holeHull.AddVertex(new Vertex(0.353553f * hollowFactorF, 0.353553f * hollowFactorF, 0.0f)); // 45 degrees | ||
298 | |||
299 | } | ||
300 | if (hshape == HollowShape.Triangle) | ||
301 | { | ||
302 | float hollowFactorF = (float)fhollowFactor / (float)50000; | ||
303 | Vertex IMM; | ||
304 | Vertex IPM; | ||
305 | Vertex IPP; | ||
306 | |||
307 | if (pshape == ProfileShape.Square) | ||
308 | { | ||
309 | // corner points are at 345, 105, and 225 degrees for the triangle within a box | ||
310 | |||
311 | //IMM = new Vertex(((float)Math.Cos(345.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, ((float)Math.Sin(345.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, 0.0f); | ||
312 | //IPM = new Vertex(((float)Math.Cos(105.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, ((float)Math.Sin(105.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, 0.0f); | ||
313 | //IPP = new Vertex(((float)Math.Cos(225.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, ((float)Math.Sin(225.0 * DEG_TO_RAD) * 0.5f) * hollowFactorF, 0.0f); | ||
314 | |||
315 | // hard coded here for speed, the equations are in the commented out lines above | ||
316 | IMM = new Vertex(0.48296f * hollowFactorF, -0.12941f * hollowFactorF, 0.0f); | ||
317 | IPM = new Vertex(-0.12941f * hollowFactorF, 0.48296f * hollowFactorF, 0.0f); | ||
318 | IPP = new Vertex(-0.35355f * hollowFactorF, -0.35355f * hollowFactorF, 0.0f); | ||
319 | } | ||
320 | else | ||
321 | { | ||
322 | IMM = new Vertex(-0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f); | ||
323 | IPM = new Vertex(+0.5f * hollowFactorF, +0f * hollowFactorF, 0.0f); | ||
324 | IPP = new Vertex(-0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f); | ||
325 | } | ||
326 | |||
327 | holeHull = new SimpleHull(); | ||
328 | |||
329 | holeHull.AddVertex(IMM); | ||
330 | holeHull.AddVertex(IPP); | ||
331 | holeHull.AddVertex(IPM); | ||
332 | |||
333 | } | ||
334 | |||
335 | return holeHull; | ||
336 | |||
337 | |||
338 | } | ||
339 | 72 | ||
340 | /// <summary> | 73 | /// <summary> |
341 | /// creates a simple box mesh of the specified size | 74 | /// creates a simple box mesh of the specified size |
@@ -420,1364 +153,197 @@ namespace OpenSim.Region.Physics.Meshing | |||
420 | return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ); | 153 | return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ); |
421 | } | 154 | } |
422 | 155 | ||
423 | 156 | private void ReportPrimError(string message, string primName, PrimMesh primMesh) | |
424 | private static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | ||
425 | // Builds the z (+ and -) surfaces of a box shaped prim | ||
426 | { | ||
427 | UInt16 hollowFactor = primShape.ProfileHollow; | ||
428 | UInt16 profileBegin = primShape.ProfileBegin; | ||
429 | UInt16 profileEnd = primShape.ProfileEnd; | ||
430 | UInt16 taperX = primShape.PathScaleX; | ||
431 | UInt16 taperY = primShape.PathScaleY; | ||
432 | UInt16 pathShearX = primShape.PathShearX; | ||
433 | UInt16 pathShearY = primShape.PathShearY; | ||
434 | |||
435 | #if SPAM | ||
436 | reportPrimParams("[BOX] " + primName, primShape); | ||
437 | #endif | ||
438 | |||
439 | // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface | ||
440 | // of a block are basically the same | ||
441 | // They may be warped differently but the shape is identical | ||
442 | // So we only create one surface as a model and derive both plus and minus surface of the block from it | ||
443 | // This is done in a model space where the block spans from -.5 to +.5 in X and Y | ||
444 | // The mapping to Scene space is done later during the "extrusion" phase | ||
445 | |||
446 | // Base | ||
447 | Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f); | ||
448 | Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f); | ||
449 | Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f); | ||
450 | Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f); | ||
451 | |||
452 | SimpleHull outerHull = new SimpleHull(); | ||
453 | |||
454 | outerHull.AddVertex(PP); | ||
455 | outerHull.AddVertex(MP); | ||
456 | outerHull.AddVertex(MM); | ||
457 | outerHull.AddVertex(PM); | ||
458 | |||
459 | // Deal with cuts now | ||
460 | if ((profileBegin != 0) || (profileEnd != 0)) | ||
461 | { | ||
462 | double fProfileBeginAngle = profileBegin / 50000.0*360.0; | ||
463 | // In degree, for easier debugging and understanding | ||
464 | fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y | ||
465 | double fProfileEndAngle = 360.0 - profileEnd / 50000.0*360.0; // Pathend comes as complement to 1.0 | ||
466 | fProfileEndAngle -= (90.0 + 45.0); | ||
467 | |||
468 | // avoid some problem angles until the hull subtraction routine is fixed | ||
469 | if ((fProfileBeginAngle + 45.0f) % 90.0f == 0.0f) | ||
470 | fProfileBeginAngle += 5.0f; | ||
471 | if ((fProfileEndAngle + 45.0f) % 90.0f == 0.0f) | ||
472 | fProfileEndAngle -= 5.0f; | ||
473 | if (fProfileBeginAngle % 90.0f == 0.0f) | ||
474 | fProfileBeginAngle += 1.0f; | ||
475 | if (fProfileEndAngle % 90.0f == 0.0f) | ||
476 | fProfileEndAngle -= 1.0f; | ||
477 | |||
478 | if (fProfileBeginAngle < fProfileEndAngle) | ||
479 | fProfileEndAngle -= 360.0; | ||
480 | |||
481 | #if SPAM | ||
482 | Console.WriteLine("Meshmerizer: fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString()); | ||
483 | #endif | ||
484 | |||
485 | // Note, that we don't want to cut out a triangle, even if this is a | ||
486 | // good approximation for small cuts. Indeed we want to cut out an arc | ||
487 | // and we approximate this arc by a polygon chain | ||
488 | // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space | ||
489 | // So it can easily be subtracted from the outer hull | ||
490 | int iSteps = (int) (((fProfileBeginAngle - fProfileEndAngle)/45.0) + .5); | ||
491 | // how many steps do we need with approximately 45 degree | ||
492 | double dStepWidth = (fProfileBeginAngle - fProfileEndAngle)/iSteps; | ||
493 | |||
494 | Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); | ||
495 | |||
496 | // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull | ||
497 | SimpleHull cutHull = new SimpleHull(); | ||
498 | cutHull.AddVertex(origin); | ||
499 | for (int i = 0; i < iSteps; i++) | ||
500 | { | ||
501 | double angle = fProfileBeginAngle - i*dStepWidth; // we count against the angle orientation!!!! | ||
502 | Vertex v = Vertex.FromAngle(angle*Math.PI/180.0); | ||
503 | cutHull.AddVertex(v); | ||
504 | } | ||
505 | Vertex legEnd = Vertex.FromAngle(fProfileEndAngle*Math.PI/180.0); | ||
506 | // Calculated separately to avoid errors | ||
507 | cutHull.AddVertex(legEnd); | ||
508 | |||
509 | //m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName); | ||
510 | SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); | ||
511 | |||
512 | outerHull = cuttedHull; | ||
513 | } | ||
514 | |||
515 | // Deal with the hole here | ||
516 | if (hollowFactor > 0) | ||
517 | { | ||
518 | if (hollowFactor < 1000) | ||
519 | hollowFactor = 1000; // some sane minimum for our beloved SimpleHull routines | ||
520 | |||
521 | SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor); | ||
522 | if (holeHull != null) | ||
523 | { | ||
524 | SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); | ||
525 | |||
526 | outerHull = hollowedHull; | ||
527 | } | ||
528 | } | ||
529 | |||
530 | Mesh m = new Mesh(); | ||
531 | |||
532 | Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); | ||
533 | Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); | ||
534 | Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); | ||
535 | |||
536 | m.Add(Seed1); | ||
537 | m.Add(Seed2); | ||
538 | m.Add(Seed3); | ||
539 | |||
540 | m.Add(new Triangle(Seed1, Seed2, Seed3)); | ||
541 | m.Add(outerHull.getVertices()); | ||
542 | |||
543 | InsertVertices(m.vertices, 3, m.triangles); | ||
544 | m.DumpRaw(baseDir, primName, "Proto first Mesh"); | ||
545 | |||
546 | m.Remove(Seed1); | ||
547 | m.Remove(Seed2); | ||
548 | m.Remove(Seed3); | ||
549 | m.DumpRaw(baseDir, primName, "Proto seeds removed"); | ||
550 | |||
551 | m.RemoveTrianglesOutside(outerHull); | ||
552 | m.DumpRaw(baseDir, primName, "Proto outsides removed"); | ||
553 | |||
554 | foreach (Triangle t in m.triangles) | ||
555 | { | ||
556 | PhysicsVector n = t.getNormal(); | ||
557 | if (n.Z < 0.0) | ||
558 | t.invertNormal(); | ||
559 | } | ||
560 | |||
561 | Extruder extr = new Extruder(); | ||
562 | |||
563 | extr.size = size; | ||
564 | |||
565 | if (taperX != 100) | ||
566 | { | ||
567 | if (taperX > 100) | ||
568 | { | ||
569 | extr.taperTopFactorX = 1.0f - ((float)(taperX - 100) / 100); | ||
570 | } | ||
571 | else | ||
572 | { | ||
573 | extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100); | ||
574 | } | ||
575 | |||
576 | } | ||
577 | |||
578 | if (taperY != 100) | ||
579 | { | ||
580 | if (taperY > 100) | ||
581 | { | ||
582 | extr.taperTopFactorY = 1.0f - ((float)(taperY - 100) / 100); | ||
583 | } | ||
584 | else | ||
585 | { | ||
586 | extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | if (pathShearX != 0) | ||
591 | { | ||
592 | if (pathShearX > 50) | ||
593 | { | ||
594 | // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 | ||
595 | extr.pushX = (((float)(256 - pathShearX) / 100) * -1f); | ||
596 | } | ||
597 | else | ||
598 | { | ||
599 | extr.pushX = (float)pathShearX / 100; | ||
600 | } | ||
601 | } | ||
602 | |||
603 | if (pathShearY != 0) | ||
604 | { | ||
605 | if (pathShearY > 50) | ||
606 | { | ||
607 | // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 | ||
608 | extr.pushY = (((float)(256 - pathShearY) / 100) * -1f); | ||
609 | } | ||
610 | else | ||
611 | { | ||
612 | extr.pushY = (float)pathShearY / 100; | ||
613 | } | ||
614 | } | ||
615 | |||
616 | extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.01f; | ||
617 | extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.01f; | ||
618 | extr.pathBegin = primShape.PathBegin; | ||
619 | extr.pathEnd = primShape.PathEnd; | ||
620 | |||
621 | Mesh result = extr.ExtrudeLinearPath(m); | ||
622 | result.DumpRaw(baseDir, primName, "Z extruded"); | ||
623 | #if SPAM | ||
624 | int vCount = 0; | ||
625 | |||
626 | foreach (Vertex v in result.vertices) | ||
627 | if (v != null) | ||
628 | vCount++; | ||
629 | System.Console.WriteLine("Mesh vertex count: " + vCount.ToString()); | ||
630 | #endif | ||
631 | return result; | ||
632 | } | ||
633 | |||
634 | private static Mesh CreateCylinderMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | ||
635 | // Builds the z (+ and -) surfaces of a box shaped prim | ||
636 | { | 157 | { |
158 | Console.WriteLine(message); | ||
159 | Console.WriteLine("\nPrim Name: " + primName); | ||
160 | Console.WriteLine("****** PrimMesh Parameters ******\n" + primMesh.ParamsToDisplayString()); | ||
637 | 161 | ||
638 | UInt16 hollowFactor = primShape.ProfileHollow; | ||
639 | UInt16 profileBegin = primShape.ProfileBegin; | ||
640 | UInt16 profileEnd = primShape.ProfileEnd; | ||
641 | UInt16 taperX = primShape.PathScaleX; | ||
642 | UInt16 taperY = primShape.PathScaleY; | ||
643 | UInt16 pathShearX = primShape.PathShearX; | ||
644 | UInt16 pathShearY = primShape.PathShearY; | ||
645 | |||
646 | #if SPAM | ||
647 | reportPrimParams("[CYLINDER] " + primName, primShape); | ||
648 | #endif | ||
649 | |||
650 | |||
651 | // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface | ||
652 | // of a block are basically the same | ||
653 | // They may be warped differently but the shape is identical | ||
654 | // So we only create one surface as a model and derive both plus and minus surface of the block from it | ||
655 | // This is done in a model space where the block spans from -.5 to +.5 in X and Y | ||
656 | // The mapping to Scene space is done later during the "extrusion" phase | ||
657 | |||
658 | // Base | ||
659 | |||
660 | SimpleHull outerHull = new SimpleHull(); | ||
661 | |||
662 | // counter-clockwise around the quadrants, start at 45 degrees | ||
663 | |||
664 | outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees | ||
665 | outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees | ||
666 | outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees | ||
667 | outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees | ||
668 | outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees | ||
669 | outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees | ||
670 | outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees | ||
671 | outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees | ||
672 | outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees | ||
673 | outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees | ||
674 | outerHull.AddVertex(new Vertex(-0.482963f, -0.129410f, 0.0f)); // 195 degrees | ||
675 | outerHull.AddVertex(new Vertex(-0.433013f, -0.250000f, 0.0f)); // 210 degrees | ||
676 | outerHull.AddVertex(new Vertex(-0.353553f, -0.353553f, 0.0f)); // 225 degrees | ||
677 | outerHull.AddVertex(new Vertex(-0.250000f, -0.433013f, 0.0f)); // 240 degrees | ||
678 | outerHull.AddVertex(new Vertex(-0.129410f, -0.482963f, 0.0f)); // 255 degrees | ||
679 | outerHull.AddVertex(new Vertex(0.000000f, -0.500000f, 0.0f)); // 270 degrees | ||
680 | outerHull.AddVertex(new Vertex(0.129410f, -0.482963f, 0.0f)); // 285 degrees | ||
681 | outerHull.AddVertex(new Vertex(0.250000f, -0.433013f, 0.0f)); // 300 degrees | ||
682 | outerHull.AddVertex(new Vertex(0.353553f, -0.353553f, 0.0f)); // 315 degrees | ||
683 | outerHull.AddVertex(new Vertex(0.433013f, -0.250000f, 0.0f)); // 330 degrees | ||
684 | outerHull.AddVertex(new Vertex(0.482963f, -0.129410f, 0.0f)); // 345 degrees | ||
685 | outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees | ||
686 | outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees | ||
687 | outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees | ||
688 | |||
689 | |||
690 | |||
691 | // Deal with cuts now | ||
692 | if ((profileBegin != 0) || (profileEnd != 0)) | ||
693 | { | ||
694 | double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; | ||
695 | // In degree, for easier debugging and understanding | ||
696 | double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 | ||
697 | |||
698 | #if SPAM | ||
699 | Console.WriteLine("Extruder: Cylinder fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString()); | ||
700 | #endif | ||
701 | if (fProfileBeginAngle > 270.0f && fProfileBeginAngle < 271.8f) // a problem angle for the hull subtract routine :( | ||
702 | fProfileBeginAngle = 271.8f; // workaround - use the smaller slice | ||
703 | |||
704 | if (fProfileBeginAngle < fProfileEndAngle) | ||
705 | fProfileEndAngle -= 360.0; | ||
706 | #if SPAM | ||
707 | Console.WriteLine("Extruder: Cylinder fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString()); | ||
708 | #endif | ||
709 | |||
710 | // Note, that we don't want to cut out a triangle, even if this is a | ||
711 | // good approximation for small cuts. Indeed we want to cut out an arc | ||
712 | // and we approximate this arc by a polygon chain | ||
713 | // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space | ||
714 | // So it can easily be subtracted from the outer hull | ||
715 | int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); | ||
716 | // how many steps do we need with approximately 45 degree | ||
717 | double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps; | ||
718 | |||
719 | Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); | ||
720 | |||
721 | // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull | ||
722 | SimpleHull cutHull = new SimpleHull(); | ||
723 | cutHull.AddVertex(origin); | ||
724 | for (int i = 0; i < iSteps; i++) | ||
725 | { | ||
726 | double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!! | ||
727 | Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0); | ||
728 | cutHull.AddVertex(v); | ||
729 | } | ||
730 | Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); | ||
731 | // Calculated separately to avoid errors | ||
732 | cutHull.AddVertex(legEnd); | ||
733 | |||
734 | SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); | ||
735 | |||
736 | outerHull = cuttedHull; | ||
737 | } | ||
738 | |||
739 | // Deal with the hole here | ||
740 | if (hollowFactor > 0) | ||
741 | { | ||
742 | if (hollowFactor < 1000) | ||
743 | hollowFactor = 1000; // some sane minimum for our beloved SimpleHull routines | ||
744 | |||
745 | SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor); | ||
746 | if (holeHull != null) | ||
747 | { | ||
748 | SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); | ||
749 | |||
750 | outerHull = hollowedHull; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | Mesh m = new Mesh(); | ||
755 | |||
756 | Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); | ||
757 | Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); | ||
758 | Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); | ||
759 | |||
760 | m.Add(Seed1); | ||
761 | m.Add(Seed2); | ||
762 | m.Add(Seed3); | ||
763 | |||
764 | m.Add(new Triangle(Seed1, Seed2, Seed3)); | ||
765 | m.Add(outerHull.getVertices()); | ||
766 | |||
767 | InsertVertices(m.vertices, 3, m.triangles); | ||
768 | m.DumpRaw(baseDir, primName, "Proto first Mesh"); | ||
769 | |||
770 | m.Remove(Seed1); | ||
771 | m.Remove(Seed2); | ||
772 | m.Remove(Seed3); | ||
773 | m.DumpRaw(baseDir, primName, "Proto seeds removed"); | ||
774 | |||
775 | m.RemoveTrianglesOutside(outerHull); | ||
776 | m.DumpRaw(baseDir, primName, "Proto outsides removed"); | ||
777 | |||
778 | foreach (Triangle t in m.triangles) | ||
779 | { | ||
780 | PhysicsVector n = t.getNormal(); | ||
781 | if (n.Z < 0.0) | ||
782 | t.invertNormal(); | ||
783 | } | ||
784 | |||
785 | Extruder extr = new Extruder(); | ||
786 | |||
787 | extr.size = size; | ||
788 | |||
789 | if (taperX != 100) | ||
790 | { | ||
791 | if (taperX > 100) | ||
792 | { | ||
793 | extr.taperTopFactorX = 1.0f - ((float)(taperX - 100) / 100); } | ||
794 | else | ||
795 | { | ||
796 | extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100); | ||
797 | } | ||
798 | |||
799 | } | ||
800 | |||
801 | if (taperY != 100) | ||
802 | { | ||
803 | if (taperY > 100) | ||
804 | { | ||
805 | extr.taperTopFactorY = 1.0f - ((float)(taperY - 100) / 100); | ||
806 | } | ||
807 | else | ||
808 | { | ||
809 | extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100); | ||
810 | } | ||
811 | } | ||
812 | |||
813 | if (pathShearX != 0) | ||
814 | { | ||
815 | if (pathShearX > 50) | ||
816 | { | ||
817 | // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 | ||
818 | extr.pushX = (((float)(256 - pathShearX) / 100) * -1f); | ||
819 | } | ||
820 | else | ||
821 | { | ||
822 | extr.pushX = (float)pathShearX / 100; | ||
823 | } | ||
824 | } | ||
825 | |||
826 | if (pathShearY != 0) | ||
827 | { | ||
828 | if (pathShearY > 50) | ||
829 | { | ||
830 | // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 | ||
831 | extr.pushY = (((float)(256 - pathShearY) / 100) * -1f); | ||
832 | } | ||
833 | else | ||
834 | { | ||
835 | extr.pushY = (float)pathShearY / 100; | ||
836 | } | ||
837 | |||
838 | } | ||
839 | |||
840 | extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.01f; | ||
841 | extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.01f; | ||
842 | extr.pathBegin = primShape.PathBegin; | ||
843 | extr.pathEnd = primShape.PathEnd; | ||
844 | |||
845 | Mesh result = extr.ExtrudeLinearPath(m); | ||
846 | result.DumpRaw(baseDir, primName, "Z extruded"); | ||
847 | #if SPAM | ||
848 | int vCount = 0; | ||
849 | |||
850 | foreach (Vertex v in result.vertices) | ||
851 | if (v != null) | ||
852 | vCount++; | ||
853 | System.Console.WriteLine("Mesh vertex count: " + vCount.ToString()); | ||
854 | #endif | ||
855 | return result; | ||
856 | } | 162 | } |
857 | 163 | ||
858 | private static Mesh CreatePrismMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | 164 | public Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod) |
859 | // Builds the z (+ and -) surfaces of a box shaped prim | ||
860 | { | 165 | { |
861 | UInt16 hollowFactor = primShape.ProfileHollow; | 166 | Mesh mesh = new Mesh(); |
862 | UInt16 profileBegin = primShape.ProfileBegin; | 167 | PrimMesh primMesh; |
863 | UInt16 profileEnd = primShape.ProfileEnd; | 168 | PrimMesher.SculptMesh sculptMesh; |
864 | UInt16 taperX = primShape.PathScaleX; | ||
865 | UInt16 taperY = primShape.PathScaleY; | ||
866 | UInt16 pathShearX = primShape.PathShearX; | ||
867 | UInt16 pathShearY = primShape.PathShearY; | ||
868 | |||
869 | |||
870 | #if SPAM | ||
871 | reportPrimParams("[PRISM] " + primName, primShape); | ||
872 | #endif | ||
873 | // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface | ||
874 | // of a block are basically the same | ||
875 | // They may be warped differently but the shape is identical | ||
876 | // So we only create one surface as a model and derive both plus and minus surface of the block from it | ||
877 | // This is done in a model space where the block spans from -.5 to +.5 in X and Y | ||
878 | // The mapping to Scene space is done later during the "extrusion" phase | ||
879 | |||
880 | // Base | ||
881 | Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f); | ||
882 | Vertex PM = new Vertex(+0.5f, 0f, 0.0f); | ||
883 | Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f); | ||
884 | |||
885 | |||
886 | SimpleHull outerHull = new SimpleHull(); | ||
887 | |||
888 | outerHull.AddVertex(PP); | ||
889 | outerHull.AddVertex(MM); | ||
890 | outerHull.AddVertex(PM); | ||
891 | |||
892 | // Deal with cuts now | ||
893 | if ((profileBegin != 0) || (profileEnd != 0)) | ||
894 | { | ||
895 | double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; | ||
896 | // In degree, for easier debugging and understanding | ||
897 | double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 | ||
898 | |||
899 | if (fProfileBeginAngle < fProfileEndAngle) | ||
900 | fProfileEndAngle -= 360.0; | ||
901 | |||
902 | // Note, that we don't want to cut out a triangle, even if this is a | ||
903 | // good approximation for small cuts. Indeed we want to cut out an arc | ||
904 | // and we approximate this arc by a polygon chain | ||
905 | // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space | ||
906 | // So it can easily be subtracted from the outer hull | ||
907 | int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); | ||
908 | // how many steps do we need with approximately 45 degree | ||
909 | double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps; | ||
910 | |||
911 | Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); | ||
912 | |||
913 | // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull | ||
914 | SimpleHull cutHull = new SimpleHull(); | ||
915 | cutHull.AddVertex(origin); | ||
916 | for (int i = 0; i < iSteps; i++) | ||
917 | { | ||
918 | double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!! | ||
919 | Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0); | ||
920 | cutHull.AddVertex(v); | ||
921 | } | ||
922 | Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); | ||
923 | // Calculated separately to avoid errors | ||
924 | cutHull.AddVertex(legEnd); | ||
925 | |||
926 | SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); | ||
927 | |||
928 | outerHull = cuttedHull; | ||
929 | } | ||
930 | |||
931 | // Deal with the hole here | ||
932 | if (hollowFactor > 0) | ||
933 | { | ||
934 | if (hollowFactor < 1000) | ||
935 | hollowFactor = 1000; // some sane minimum for our beloved SimpleHull routines | ||
936 | |||
937 | SimpleHull holeHull = BuildHoleHull(primShape, primShape.ProfileShape, primShape.HollowShape, hollowFactor); | ||
938 | if (holeHull != null) | ||
939 | { | ||
940 | SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); | ||
941 | |||
942 | outerHull = hollowedHull; | ||
943 | } | ||
944 | } | ||
945 | |||
946 | Mesh m = new Mesh(); | ||
947 | |||
948 | Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); | ||
949 | Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); | ||
950 | Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); | ||
951 | |||
952 | m.Add(Seed1); | ||
953 | m.Add(Seed2); | ||
954 | m.Add(Seed3); | ||
955 | |||
956 | m.Add(new Triangle(Seed1, Seed2, Seed3)); | ||
957 | m.Add(outerHull.getVertices()); | ||
958 | |||
959 | InsertVertices(m.vertices, 3, m.triangles); | ||
960 | m.DumpRaw(baseDir, primName, "Proto first Mesh"); | ||
961 | |||
962 | m.Remove(Seed1); | ||
963 | m.Remove(Seed2); | ||
964 | m.Remove(Seed3); | ||
965 | m.DumpRaw(baseDir, primName, "Proto seeds removed"); | ||
966 | |||
967 | m.RemoveTrianglesOutside(outerHull); | ||
968 | m.DumpRaw(baseDir, primName, "Proto outsides removed"); | ||
969 | |||
970 | foreach (Triangle t in m.triangles) | ||
971 | { | ||
972 | PhysicsVector n = t.getNormal(); | ||
973 | if (n.Z < 0.0) | ||
974 | t.invertNormal(); | ||
975 | } | ||
976 | 169 | ||
977 | Extruder extr = new Extruder(); | 170 | List<Coord> coords; |
171 | List<Face> faces; | ||
978 | 172 | ||
979 | extr.size = size; | 173 | Image idata = null; |
980 | 174 | ||
981 | if (taperX != 100) | 175 | if (primShape.SculptEntry) |
982 | { | 176 | { |
983 | if (taperX > 100) | 177 | if (primShape.SculptData.Length == 0) |
984 | { | 178 | return null; |
985 | extr.taperTopFactorX = 1.0f - ((float)(taperX - 100) / 100); | ||
986 | } | ||
987 | else | ||
988 | { | ||
989 | extr.taperBotFactorX = 1.0f - ((100 - (float)taperX) / 100); | ||
990 | } | ||
991 | |||
992 | } | ||
993 | 179 | ||
994 | if (taperY != 100) | 180 | try |
995 | { | ||
996 | if (taperY > 100) | ||
997 | { | 181 | { |
998 | extr.taperTopFactorY = 1.0f - ((float)(taperY - 100) / 100); | 182 | ManagedImage managedImage; // we never use this |
183 | OpenJPEG.DecodeToImage(primShape.SculptData, out managedImage, out idata); | ||
999 | } | 184 | } |
1000 | else | 185 | catch (Exception) |
1001 | { | 186 | { |
1002 | extr.taperBotFactorY = 1.0f - ((100 - (float)taperY) / 100); | 187 | System.Console.WriteLine("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed!"); |
188 | return null; | ||
1003 | } | 189 | } |
1004 | } | ||
1005 | 190 | ||
1006 | if (pathShearX != 0) | ||
1007 | { | ||
1008 | if (pathShearX > 50) | ||
1009 | { | ||
1010 | // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 | ||
1011 | extr.pushX = (((float)(256 - pathShearX) / 100) * -1f); | ||
1012 | } | ||
1013 | else | ||
1014 | { | ||
1015 | extr.pushX = (float)pathShearX / 100; | ||
1016 | } | ||
1017 | } | ||
1018 | 191 | ||
1019 | if (pathShearY != 0) | 192 | PrimMesher.SculptMesh.SculptType sculptType; |
1020 | { | 193 | switch ((OpenMetaverse.SculptType)primShape.SculptType) |
1021 | if (pathShearY > 50) | ||
1022 | { | ||
1023 | // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 | ||
1024 | extr.pushY = (((float)(256 - pathShearY) / 100) * -1f); | ||
1025 | } | ||
1026 | else | ||
1027 | { | 194 | { |
1028 | extr.pushY = (float)pathShearY / 100; | 195 | case OpenMetaverse.SculptType.Cylinder: |
196 | sculptType = PrimMesher.SculptMesh.SculptType.cylinder; | ||
197 | break; | ||
198 | case OpenMetaverse.SculptType.Plane: | ||
199 | sculptType = PrimMesher.SculptMesh.SculptType.plane; | ||
200 | break; | ||
201 | case OpenMetaverse.SculptType.Torus: | ||
202 | sculptType = PrimMesher.SculptMesh.SculptType.torus; | ||
203 | break; | ||
204 | case OpenMetaverse.SculptType.Sphere: | ||
205 | default: | ||
206 | sculptType = PrimMesher.SculptMesh.SculptType.sphere; | ||
207 | break; | ||
1029 | } | 208 | } |
1030 | } | 209 | sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false); |
1031 | |||
1032 | extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.01f; | ||
1033 | extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.01f; | ||
1034 | extr.pathBegin = primShape.PathBegin; | ||
1035 | extr.pathEnd = primShape.PathEnd; | ||
1036 | |||
1037 | Mesh result = extr.ExtrudeLinearPath(m); | ||
1038 | result.DumpRaw(baseDir, primName, "Z extruded"); | ||
1039 | #if SPAM | ||
1040 | int vCount = 0; | ||
1041 | |||
1042 | foreach (Vertex v in result.vertices) | ||
1043 | if (v != null) | ||
1044 | vCount++; | ||
1045 | System.Console.WriteLine("Mesh vertex count: " + vCount.ToString()); | ||
1046 | #endif | ||
1047 | return result; | ||
1048 | } | ||
1049 | |||
1050 | /// <summary> | ||
1051 | /// builds an icosahedral geodesic sphere - used as default in place of problem meshes | ||
1052 | /// </summary> | ||
1053 | /// <param name="primName"></param> | ||
1054 | /// <param name="primShape"></param> | ||
1055 | /// <param name="size"></param> | ||
1056 | /// <returns></returns> | ||
1057 | private static Mesh CreateSphereMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | ||
1058 | { | ||
1059 | // Builds an icosahedral geodesic sphere | ||
1060 | // based on an article by Paul Bourke | ||
1061 | // http://local.wasp.uwa.edu.au/~pbourke/ | ||
1062 | // articles: | ||
1063 | // http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonmesh/ | ||
1064 | // and | ||
1065 | // http://local.wasp.uwa.edu.au/~pbourke/geometry/polyhedra/index.html | ||
1066 | |||
1067 | // Still have more to do here. | ||
1068 | |||
1069 | Mesh m = new Mesh(); | ||
1070 | |||
1071 | #if SPAM | ||
1072 | reportPrimParams("[SPHERE] " + primName, primShape); | ||
1073 | #endif | ||
1074 | |||
1075 | float LOD = 0.2f; | ||
1076 | float diameter = 0.5f;// Our object will result in -0.5 to 0.5 | ||
1077 | float sq5 = (float) Math.Sqrt(5.0); | ||
1078 | float phi = (1 + sq5) * 0.5f; | ||
1079 | float rat = (float) Math.Sqrt(10f + (2f * sq5)) / (4f * phi); | ||
1080 | float a = (diameter / rat) * 0.5f; | ||
1081 | float b = (diameter / rat) / (2.0f * phi); | ||
1082 | |||
1083 | |||
1084 | // 12 Icosahedron vertexes | ||
1085 | Vertex v1 = new Vertex(0f, b, -a); | ||
1086 | Vertex v2 = new Vertex(b, a, 0f); | ||
1087 | Vertex v3 = new Vertex(-b, a, 0f); | ||
1088 | Vertex v4 = new Vertex(0f, b, a); | ||
1089 | Vertex v5 = new Vertex(0f, -b, a); | ||
1090 | Vertex v6 = new Vertex(-a, 0f, b); | ||
1091 | Vertex v7 = new Vertex(0f, -b, -a); | ||
1092 | Vertex v8 = new Vertex(a, 0f, -b); | ||
1093 | Vertex v9 = new Vertex(a, 0f, b); | ||
1094 | Vertex v10 = new Vertex(-a, 0f, -b); | ||
1095 | Vertex v11 = new Vertex(b, -a, 0); | ||
1096 | Vertex v12 = new Vertex(-b, -a, 0); | ||
1097 | |||
1098 | |||
1099 | |||
1100 | // Base Faces of the Icosahedron (20) | ||
1101 | SphereLODTriangle(v1, v2, v3, diameter, LOD, m); | ||
1102 | SphereLODTriangle(v4, v3, v2, diameter, LOD, m); | ||
1103 | SphereLODTriangle(v4, v5, v6, diameter, LOD, m); | ||
1104 | SphereLODTriangle(v4, v9, v5, diameter, LOD, m); | ||
1105 | SphereLODTriangle(v1, v7, v8, diameter, LOD, m); | ||
1106 | SphereLODTriangle(v1, v10, v7, diameter, LOD, m); | ||
1107 | SphereLODTriangle(v5, v11, v12, diameter, LOD, m); | ||
1108 | SphereLODTriangle(v7, v12, v11, diameter, LOD, m); | ||
1109 | SphereLODTriangle(v3, v6, v10, diameter, LOD, m); | ||
1110 | SphereLODTriangle(v12, v10, v6, diameter, LOD, m); | ||
1111 | SphereLODTriangle(v2, v8, v9, diameter, LOD, m); | ||
1112 | SphereLODTriangle(v11, v9, v8, diameter, LOD, m); | ||
1113 | SphereLODTriangle(v4, v6, v3, diameter, LOD, m); | ||
1114 | SphereLODTriangle(v4, v2, v9, diameter, LOD, m); | ||
1115 | SphereLODTriangle(v1, v3, v10, diameter, LOD, m); | ||
1116 | SphereLODTriangle(v1, v8, v2, diameter, LOD, m); | ||
1117 | SphereLODTriangle(v7, v10, v12, diameter, LOD, m); | ||
1118 | SphereLODTriangle(v7, v11, v8, diameter, LOD, m); | ||
1119 | SphereLODTriangle(v5, v12, v6, diameter, LOD, m); | ||
1120 | SphereLODTriangle(v5, v9, v11, diameter, LOD, m); | ||
1121 | |||
1122 | // Scale the mesh based on our prim scale | ||
1123 | foreach (Vertex v in m.vertices) | ||
1124 | { | ||
1125 | v.X *= size.X; | ||
1126 | v.Y *= size.Y; | ||
1127 | v.Z *= size.Z; | ||
1128 | } | ||
1129 | |||
1130 | // This was built with the normals pointing inside.. | ||
1131 | // therefore we have to invert the normals | ||
1132 | foreach (Triangle t in m.triangles) | ||
1133 | { | ||
1134 | t.invertNormal(); | ||
1135 | } | ||
1136 | // Dump the faces for visualization in blender. | ||
1137 | m.DumpRaw(baseDir, primName, "Icosahedron"); | ||
1138 | #if SPAM | ||
1139 | int vCount = 0; | ||
1140 | |||
1141 | foreach (Vertex v in m.vertices) | ||
1142 | if (v != null) | ||
1143 | vCount++; | ||
1144 | System.Console.WriteLine("Mesh vertex count: " + vCount.ToString()); | ||
1145 | #endif | ||
1146 | |||
1147 | return m; | ||
1148 | } | ||
1149 | private SculptMesh CreateSculptMesh(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod) | ||
1150 | { | ||
1151 | |||
1152 | #if SPAM | ||
1153 | reportPrimParams("[SCULPT] " + primName, primShape); | ||
1154 | #endif | ||
1155 | |||
1156 | SculptMesh sm = new SculptMesh(primShape.SculptData, lod); | ||
1157 | // Scale the mesh based on our prim scale | ||
1158 | foreach (Vertex v in sm.vertices) | ||
1159 | { | ||
1160 | v.X *= 0.5f; | ||
1161 | v.Y *= 0.5f; | ||
1162 | v.Z *= 0.5f; | ||
1163 | v.X *= size.X; | ||
1164 | v.Y *= size.Y; | ||
1165 | v.Z *= size.Z; | ||
1166 | } | ||
1167 | // This was built with the normals pointing inside.. | ||
1168 | // therefore we have to invert the normals | ||
1169 | foreach (Triangle t in sm.triangles) | ||
1170 | { | ||
1171 | t.invertNormal(); | ||
1172 | } | ||
1173 | sm.DumpRaw(baseDir, primName, "Sculpt"); | ||
1174 | return sm; | ||
1175 | |||
1176 | } | ||
1177 | |||
1178 | /// <summary> | ||
1179 | /// Creates a mesh for prim types torus, ring, tube, and sphere | ||
1180 | /// </summary> | ||
1181 | /// <param name="primName"></param> | ||
1182 | /// <param name="primShape"></param> | ||
1183 | /// <param name="size"></param> | ||
1184 | /// <returns></returns> | ||
1185 | private static Mesh CreateCircularPathMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size) | ||
1186 | { | ||
1187 | |||
1188 | UInt16 hollowFactor = primShape.ProfileHollow; | ||
1189 | UInt16 profileBegin = primShape.ProfileBegin; | ||
1190 | UInt16 profileEnd = primShape.ProfileEnd; | ||
1191 | UInt16 pathShearX = primShape.PathShearX; | ||
1192 | UInt16 pathShearY = primShape.PathShearY; | ||
1193 | HollowShape hollowShape = primShape.HollowShape; | ||
1194 | |||
1195 | #if SPAM | ||
1196 | reportPrimParams("[CIRCULAR PATH PRIM] " + primName, primShape); | ||
1197 | Console.WriteLine("pathTwist: " + primShape.PathTwist.ToString() + " pathTwistBegin: " + primShape.PathTwistBegin.ToString()); | ||
1198 | Console.WriteLine("primShape.ProfileCurve & 0x07: " + Convert.ToString(primShape.ProfileCurve & 0x07)); | ||
1199 | |||
1200 | #endif | ||
1201 | |||
1202 | SimpleHull outerHull = new SimpleHull(); | ||
1203 | |||
1204 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
1205 | { | ||
1206 | #if SPAM | ||
1207 | Console.WriteLine("Meshmerizer thinks " + primName + " is a TORUS"); | ||
1208 | #endif | ||
1209 | if (hollowShape == HollowShape.Same) | ||
1210 | hollowShape = HollowShape.Circle; | ||
1211 | |||
1212 | // build the profile shape | ||
1213 | // counter-clockwise around the quadrants, start at 45 degrees | ||
1214 | |||
1215 | outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees | ||
1216 | outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees | ||
1217 | outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees | ||
1218 | outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees | ||
1219 | outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees | ||
1220 | outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees | ||
1221 | outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees | ||
1222 | outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees | ||
1223 | outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees | ||
1224 | outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees | ||
1225 | outerHull.AddVertex(new Vertex(-0.482963f, -0.129410f, 0.0f)); // 195 degrees | ||
1226 | outerHull.AddVertex(new Vertex(-0.433013f, -0.250000f, 0.0f)); // 210 degrees | ||
1227 | outerHull.AddVertex(new Vertex(-0.353553f, -0.353553f, 0.0f)); // 225 degrees | ||
1228 | outerHull.AddVertex(new Vertex(-0.250000f, -0.433013f, 0.0f)); // 240 degrees | ||
1229 | outerHull.AddVertex(new Vertex(-0.129410f, -0.482963f, 0.0f)); // 255 degrees | ||
1230 | outerHull.AddVertex(new Vertex(0.000000f, -0.500000f, 0.0f)); // 270 degrees | ||
1231 | outerHull.AddVertex(new Vertex(0.129410f, -0.482963f, 0.0f)); // 285 degrees | ||
1232 | outerHull.AddVertex(new Vertex(0.250000f, -0.433013f, 0.0f)); // 300 degrees | ||
1233 | outerHull.AddVertex(new Vertex(0.353553f, -0.353553f, 0.0f)); // 315 degrees | ||
1234 | outerHull.AddVertex(new Vertex(0.433013f, -0.250000f, 0.0f)); // 330 degrees | ||
1235 | outerHull.AddVertex(new Vertex(0.482963f, -0.129410f, 0.0f)); // 345 degrees | ||
1236 | outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees | ||
1237 | outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees | ||
1238 | outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees | ||
1239 | } | ||
1240 | |||
1241 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) // a ring | ||
1242 | { | ||
1243 | #if SPAM | ||
1244 | Console.WriteLine("Meshmerizer thinks " + primName + " is a TUBE"); | ||
1245 | #endif | ||
1246 | if (hollowShape == HollowShape.Same) | ||
1247 | hollowShape = HollowShape.Square; | ||
1248 | 210 | ||
1249 | outerHull.AddVertex(new Vertex(+0.5f, +0.5f, 0.0f)); | 211 | idata.Dispose(); |
1250 | outerHull.AddVertex(new Vertex(-0.5f, +0.5f, 0.0f)); | ||
1251 | outerHull.AddVertex(new Vertex(-0.5f, -0.5f, 0.0f)); | ||
1252 | outerHull.AddVertex(new Vertex(+0.5f, -0.5f, 0.0f)); | ||
1253 | } | ||
1254 | 212 | ||
1255 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | 213 | sculptMesh.DumpRaw(baseDir, primName, "primMesh"); |
1256 | { | ||
1257 | #if SPAM | ||
1258 | Console.WriteLine("Meshmerizer thinks " + primName + " is a RING"); | ||
1259 | #endif | ||
1260 | if (hollowShape == HollowShape.Same) | ||
1261 | hollowShape = HollowShape.Triangle; | ||
1262 | 214 | ||
1263 | outerHull.AddVertex(new Vertex(+0.255f, -0.375f, 0.0f)); | 215 | sculptMesh.Scale(size.X, size.Y, size.Z); |
1264 | outerHull.AddVertex(new Vertex(+0.25f, +0.375f, 0.0f)); | ||
1265 | outerHull.AddVertex(new Vertex(-0.5f, +0.0f, 0.0f)); | ||
1266 | 216 | ||
217 | coords = sculptMesh.coords; | ||
218 | faces = sculptMesh.faces; | ||
1267 | } | 219 | } |
1268 | 220 | ||
1269 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | 221 | else |
1270 | { | 222 | { |
1271 | #if SPAM | 223 | float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f; |
1272 | Console.WriteLine("Meshmerizer thinks " + primName + " is a SPHERE"); | 224 | float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f; |
1273 | #endif | 225 | float pathBegin = (float)primShape.PathBegin * 2.0e-5f; |
1274 | 226 | float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f; | |
1275 | // sanity check here... some spheres have inverted normals which can trap avatars | 227 | float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f; |
1276 | // so for now if the shape parameters are such that this may happen, revert to the | 228 | float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f; |
1277 | // geodesic sphere mesh.. the threshold is arbitrary as it seems any twist on a sphere | ||
1278 | // will create some inverted normals | ||
1279 | if ( | ||
1280 | (System.Math.Abs(primShape.PathTwist - primShape.PathTwistBegin) > 65) | ||
1281 | || (primShape.PathBegin == 0 | ||
1282 | && primShape.PathEnd == 0 | ||
1283 | && primShape.PathTwist == 0 | ||
1284 | && primShape.PathTwistBegin == 0 | ||
1285 | && primShape.ProfileBegin == 0 | ||
1286 | && primShape.ProfileEnd == 0 | ||
1287 | && hollowFactor == 0 | ||
1288 | ) // simple sphere, revert to geodesic shape | ||
1289 | |||
1290 | ) | ||
1291 | { | ||
1292 | #if SPAM | ||
1293 | System.Console.WriteLine("reverting to geodesic sphere for prim: " + primName); | ||
1294 | #endif | ||
1295 | return CreateSphereMesh(primName, primShape, size); | ||
1296 | } | ||
1297 | 229 | ||
1298 | if (hollowFactor == 0) | 230 | float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f; |
1299 | { | 231 | float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f; |
1300 | // the hull triangulator is happier with a minimal hollow | 232 | float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f; |
1301 | hollowFactor = 2000; | ||
1302 | } | ||
1303 | 233 | ||
1304 | if (hollowShape == HollowShape.Same) | 234 | int sides = 4; |
1305 | hollowShape = HollowShape.Circle; | 235 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) |
1306 | 236 | sides = 3; | |
1307 | outerHull.AddVertex(new Vertex(0.250000f, 0.433013f, 0.0f)); // 60 degrees | 237 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) |
1308 | outerHull.AddVertex(new Vertex(0.129410f, 0.482963f, 0.0f)); // 75 degrees | 238 | sides = 24; |
1309 | outerHull.AddVertex(new Vertex(0.000000f, 0.500000f, 0.0f)); // 90 degrees | 239 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) |
1310 | outerHull.AddVertex(new Vertex(-0.129410f, 0.482963f, 0.0f)); // 105 degrees | 240 | { // half circle, prim is a sphere |
1311 | outerHull.AddVertex(new Vertex(-0.250000f, 0.433013f, 0.0f)); // 120 degrees | 241 | sides = 24; |
1312 | outerHull.AddVertex(new Vertex(-0.353553f, 0.353553f, 0.0f)); // 135 degrees | ||
1313 | outerHull.AddVertex(new Vertex(-0.433013f, 0.250000f, 0.0f)); // 150 degrees | ||
1314 | outerHull.AddVertex(new Vertex(-0.482963f, 0.129410f, 0.0f)); // 165 degrees | ||
1315 | outerHull.AddVertex(new Vertex(-0.500000f, 0.000000f, 0.0f)); // 180 degrees | ||
1316 | |||
1317 | outerHull.AddVertex(new Vertex(0.500000f, 0.000000f, 0.0f)); // 0 degrees | ||
1318 | outerHull.AddVertex(new Vertex(0.482963f, 0.129410f, 0.0f)); // 15 degrees | ||
1319 | outerHull.AddVertex(new Vertex(0.433013f, 0.250000f, 0.0f)); // 30 degrees | ||
1320 | outerHull.AddVertex(new Vertex(0.353553f, 0.353553f, 0.0f)); // 45 degrees | ||
1321 | } | ||
1322 | 242 | ||
1323 | // Deal with cuts now | 243 | profileBegin = 0.5f * profileBegin + 0.5f; |
1324 | if ((profileBegin != 0) || (profileEnd != 0)) | 244 | profileEnd = 0.5f * profileEnd + 0.5f; |
1325 | { | ||
1326 | double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; | ||
1327 | // In degree, for easier debugging and understanding | ||
1328 | double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0 | ||
1329 | |||
1330 | if (fProfileBeginAngle < fProfileEndAngle) | ||
1331 | fProfileEndAngle -= 360.0; | ||
1332 | |||
1333 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
1334 | { // dimpled sphere uses profile cut but since it's a half circle the angles are smaller | ||
1335 | fProfileBeginAngle = 0.0036f * (float)primShape.ProfileBegin; | ||
1336 | fProfileEndAngle = 180.0f - 0.0036f * (float)primShape.ProfileEnd; | ||
1337 | if (fProfileBeginAngle < fProfileEndAngle) | ||
1338 | fProfileEndAngle -= 360.0f; | ||
1339 | // a cut starting at 0 degrees with a hollow causes an infinite loop so move the start angle | ||
1340 | // past it into the empty part of the circle to avoid this condition | ||
1341 | if (fProfileBeginAngle == 0.0f) fProfileBeginAngle = -10.0f; | ||
1342 | 245 | ||
1343 | #if SPAM | ||
1344 | Console.WriteLine("Sphere dimple: fProfileBeginAngle: " + fProfileBeginAngle.ToString() + " fProfileEndAngle: " + fProfileEndAngle.ToString()); | ||
1345 | #endif | ||
1346 | } | ||
1347 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) | ||
1348 | { // tube profile cut is offset 45 degrees from other prim types | ||
1349 | fProfileBeginAngle += 45.0f; | ||
1350 | fProfileEndAngle += 45.0f; | ||
1351 | if (fProfileBeginAngle < fProfileEndAngle) | ||
1352 | fProfileEndAngle -= 360.0; | ||
1353 | } | ||
1354 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
1355 | { // ring profile cut is offset 180 degrees from other prim types | ||
1356 | fProfileBeginAngle += 180.0f; | ||
1357 | fProfileEndAngle += 180.0f; | ||
1358 | if (fProfileBeginAngle < fProfileEndAngle) | ||
1359 | fProfileEndAngle -= 360.0; | ||
1360 | } | 246 | } |
1361 | 247 | ||
1362 | // Note, that we don't want to cut out a triangle, even if this is a | 248 | int hollowSides = sides; |
1363 | // good approximation for small cuts. Indeed we want to cut out an arc | 249 | if (primShape.HollowShape == HollowShape.Circle) |
1364 | // and we approximate this arc by a polygon chain | 250 | hollowSides = 24; |
1365 | // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space | 251 | else if (primShape.HollowShape == HollowShape.Square) |
1366 | // So it can easily be subtracted from the outer hull | 252 | hollowSides = 4; |
1367 | int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); | 253 | else if (primShape.HollowShape == HollowShape.Triangle) |
1368 | // how many steps do we need with approximately 45 degree | 254 | hollowSides = 3; |
1369 | double dStepWidth = (fProfileBeginAngle - fProfileEndAngle) / iSteps; | ||
1370 | |||
1371 | Vertex origin = new Vertex(0.0f, 0.0f, 0.0f); | ||
1372 | |||
1373 | // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull | ||
1374 | SimpleHull cutHull = new SimpleHull(); | ||
1375 | cutHull.AddVertex(origin); | ||
1376 | for (int i = 0; i < iSteps; i++) | ||
1377 | { | ||
1378 | double angle = fProfileBeginAngle - i * dStepWidth; // we count against the angle orientation!!!! | ||
1379 | Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0); | ||
1380 | cutHull.AddVertex(v); | ||
1381 | } | ||
1382 | Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); | ||
1383 | // Calculated separately to avoid errors | ||
1384 | cutHull.AddVertex(legEnd); | ||
1385 | 255 | ||
1386 | // m_log.DebugFormat("Starting cutting of the hollow shape from the prim {1}", 0, primName); | 256 | primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides); |
1387 | SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull); | ||
1388 | 257 | ||
1389 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | 258 | primMesh.topShearX = pathShearX; |
1390 | { | 259 | primMesh.topShearY = pathShearY; |
1391 | Quaternion zFlip = Quaternion.CreateFromAxisAngle(new Vector3(0.0f, 0.0f, 1.0f), (float)Math.PI); | 260 | primMesh.pathCutBegin = pathBegin; |
1392 | Vertex vTmp = new Vertex(0.0f, 0.0f, 0.0f); | 261 | primMesh.pathCutEnd = pathEnd; |
1393 | foreach (Vertex v in cuttedHull.getVertices()) | ||
1394 | if (v != null) | ||
1395 | { | ||
1396 | vTmp = v * zFlip; | ||
1397 | v.X = vTmp.X; | ||
1398 | v.Y = vTmp.Y; | ||
1399 | v.Z = vTmp.Z; | ||
1400 | } | ||
1401 | } | ||
1402 | |||
1403 | outerHull = cuttedHull; | ||
1404 | } | ||
1405 | 262 | ||
1406 | // Deal with the hole here | 263 | if (primShape.PathCurve == (byte)Extrusion.Straight) |
1407 | if (hollowFactor > 0) | ||
1408 | { | ||
1409 | SimpleHull holeHull; | ||
1410 | |||
1411 | if (hollowShape == HollowShape.Triangle) | ||
1412 | { | 264 | { |
1413 | holeHull = new SimpleHull(); | 265 | primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10; |
266 | primMesh.twistEnd = primShape.PathTwist * 18 / 10; | ||
267 | primMesh.taperX = pathScaleX; | ||
268 | primMesh.taperY = pathScaleY; | ||
1414 | 269 | ||
1415 | float hollowFactorF = (float)hollowFactor * 2.0e-5f; | 270 | if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f) |
1416 | |||
1417 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
1418 | { | 271 | { |
1419 | holeHull.AddVertex(new Vertex(+0.125f * hollowFactorF, -0.1875f * hollowFactorF, 0.0f)); | 272 | ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh); |
1420 | holeHull.AddVertex(new Vertex(-0.25f * hollowFactorF, -0f * hollowFactorF, 0.0f)); | 273 | if (profileBegin < 0.0f) profileBegin = 0.0f; |
1421 | holeHull.AddVertex(new Vertex(+0.125f * hollowFactorF, +0.1875f * hollowFactorF, 0.0f)); | 274 | if (profileEnd > 1.0f) profileEnd = 1.0f; |
1422 | } | 275 | } |
1423 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | 276 | #if SPAM |
277 | Console.WriteLine("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString()); | ||
278 | #endif | ||
279 | try | ||
1424 | { | 280 | { |
1425 | holeHull.AddVertex(new Vertex(-0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 180 degrees | 281 | primMesh.ExtrudeLinear(); |
1426 | holeHull.AddVertex(new Vertex(-0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 120 degrees | ||
1427 | holeHull.AddVertex(new Vertex(0.250000f * hollowFactorF, 0.433013f * hollowFactorF, 0.0f)); // 60 degrees | ||
1428 | holeHull.AddVertex(new Vertex(0.500000f * hollowFactorF, 0.000000f * hollowFactorF, 0.0f)); // 0 degrees | ||
1429 | } | 282 | } |
1430 | else | 283 | catch (Exception ex) |
1431 | { | 284 | { |
1432 | holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, -0.45f * hollowFactorF, 0.0f)); | 285 | ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh); |
1433 | holeHull.AddVertex(new Vertex(-0.5f * hollowFactorF, -0f * hollowFactorF, 0.0f)); | 286 | return null; |
1434 | holeHull.AddVertex(new Vertex(+0.25f * hollowFactorF, +0.45f * hollowFactorF, 0.0f)); | ||
1435 | } | 287 | } |
1436 | } | 288 | } |
1437 | else if (hollowShape == HollowShape.Square && (primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
1438 | { | ||
1439 | holeHull = new SimpleHull(); | ||
1440 | |||
1441 | float hollowFactorF = (float)hollowFactor * 2.0e-5f; | ||
1442 | |||
1443 | holeHull.AddVertex(new Vertex(-0.707f * hollowFactorF, 0.0f, 0.0f)); // 180 degrees | ||
1444 | holeHull.AddVertex(new Vertex(0.0f, 0.707f * hollowFactorF, 0.0f)); // 120 degrees | ||
1445 | holeHull.AddVertex(new Vertex(0.707f * hollowFactorF, 0.0f, 0.0f)); // 60 degrees | ||
1446 | } | ||
1447 | else | 289 | else |
1448 | { | 290 | { |
1449 | holeHull = BuildHoleHull(primShape, primShape.ProfileShape, hollowShape, hollowFactor); | 291 | primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f; |
1450 | } | 292 | primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f; |
1451 | 293 | primMesh.radius = 0.01f * primShape.PathRadiusOffset; | |
1452 | if (holeHull != null) | 294 | primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions; |
1453 | { | 295 | primMesh.skew = 0.01f * primShape.PathSkew; |
1454 | SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull); | 296 | primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10; |
1455 | 297 | primMesh.twistEnd = primShape.PathTwist * 36 / 10; | |
1456 | outerHull = hollowedHull; | 298 | primMesh.taperX = primShape.PathTaperX * 0.01f; |
1457 | } | 299 | primMesh.taperY = primShape.PathTaperY * 0.01f; |
1458 | } | 300 | |
1459 | 301 | if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f) | |
1460 | Mesh m = new Mesh(); | 302 | { |
1461 | 303 | ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh); | |
1462 | Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f); | 304 | if (profileBegin < 0.0f) profileBegin = 0.0f; |
1463 | Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f); | 305 | if (profileEnd > 1.0f) profileEnd = 1.0f; |
1464 | Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f); | 306 | } |
1465 | |||
1466 | m.Add(Seed1); | ||
1467 | m.Add(Seed2); | ||
1468 | m.Add(Seed3); | ||
1469 | |||
1470 | m.Add(new Triangle(Seed1, Seed2, Seed3)); | ||
1471 | m.Add(outerHull.getVertices()); | ||
1472 | |||
1473 | InsertVertices(m.vertices, 3, m.triangles); | ||
1474 | m.DumpRaw(baseDir, primName, "Proto first Mesh"); | ||
1475 | |||
1476 | m.Remove(Seed1); | ||
1477 | m.Remove(Seed2); | ||
1478 | m.Remove(Seed3); | ||
1479 | m.DumpRaw(baseDir, primName, "Proto seeds removed"); | ||
1480 | |||
1481 | m.RemoveTrianglesOutside(outerHull); | ||
1482 | m.DumpRaw(baseDir, primName, "Proto outsides removed"); | ||
1483 | |||
1484 | foreach (Triangle t in m.triangles) | ||
1485 | t.invertNormal(); | ||
1486 | |||
1487 | |||
1488 | float skew = primShape.PathSkew * 0.01f; | ||
1489 | float pathScaleX = (float)(200 - primShape.PathScaleX) * 0.01f; | ||
1490 | float pathScaleY = (float)(200 - primShape.PathScaleY) * 0.01f; | ||
1491 | float profileXComp = pathScaleX * (1.0f - Math.Abs(skew)); | ||
1492 | |||
1493 | #if SPAM | ||
1494 | //Console.WriteLine("primShape.PathScaleX: " + primShape.PathScaleX.ToString() + " primShape.PathScaleY: " + primShape.PathScaleY.ToString()); | ||
1495 | //Console.WriteLine("primShape.PathSkew: " + primShape.PathSkew.ToString() + " primShape.PathRadiusOffset: " + primShape.PathRadiusOffset.ToString() + " primShape.pathRevolutions: " + primShape.PathRevolutions.ToString()); | ||
1496 | Console.WriteLine("PathScaleX: " + pathScaleX.ToString() + " pathScaleY: " + pathScaleY.ToString()); | ||
1497 | Console.WriteLine("skew: " + skew.ToString() + " profileXComp: " + profileXComp.ToString()); | ||
1498 | #endif | ||
1499 | |||
1500 | foreach (Vertex v in m.vertices) | ||
1501 | if (v != null) | ||
1502 | { | ||
1503 | v.X *= profileXComp; | ||
1504 | v.Y *= pathScaleY; | ||
1505 | } | ||
1506 | |||
1507 | Extruder extr = new Extruder(); | ||
1508 | |||
1509 | extr.size = size; | ||
1510 | extr.pathScaleX = pathScaleX; | ||
1511 | extr.pathScaleY = pathScaleY; | ||
1512 | extr.pathCutBegin = 0.00002f * primShape.PathBegin; | ||
1513 | extr.pathCutEnd = 0.00002f * (50000 - primShape.PathEnd); | ||
1514 | extr.pathBegin = primShape.PathBegin; | ||
1515 | extr.pathEnd = primShape.PathEnd; | ||
1516 | extr.skew = skew; | ||
1517 | extr.revolutions = 1.0f + (float)primShape.PathRevolutions * 3.0f / 200.0f; | ||
1518 | extr.pathTaperX = 0.01f * (float)primShape.PathTaperX; | ||
1519 | extr.pathTaperY = 0.01f * (float)primShape.PathTaperY; | ||
1520 | |||
1521 | extr.radius = 0.01f * (float)primShape.PathRadiusOffset; | ||
1522 | |||
1523 | #if SPAM | 307 | #if SPAM |
1524 | //System.Console.WriteLine("primShape.PathBegin: " + primShape.PathBegin.ToString() + " primShape.PathEnd: " + primShape.PathEnd.ToString()); | 308 | Console.WriteLine("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString()); |
1525 | System.Console.WriteLine("extr.pathCutBegin: " + extr.pathCutBegin.ToString() + " extr.pathCutEnd: " + extr.pathCutEnd.ToString()); | ||
1526 | System.Console.WriteLine("extr.revolutions: " + extr.revolutions.ToString()); | ||
1527 | |||
1528 | //System.Console.WriteLine("primShape.PathTaperX: " + primShape.PathTaperX.ToString()); | ||
1529 | //System.Console.WriteLine("primShape.PathTaperY: " + primShape.PathTaperY.ToString()); | ||
1530 | |||
1531 | |||
1532 | //System.Console.WriteLine("primShape.PathRadiusOffset: " + primShape.PathRadiusOffset.ToString()); | ||
1533 | #endif | 309 | #endif |
1534 | 310 | try | |
1535 | 311 | { | |
1536 | 312 | primMesh.ExtrudeCircular(); | |
1537 | 313 | } | |
1538 | if (pathShearX != 0) | 314 | catch (Exception ex) |
1539 | { | 315 | { |
1540 | if (pathShearX > 50) | 316 | ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh); |
1541 | { | 317 | return null; |
1542 | // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 | 318 | } |
1543 | extr.pushX = (((float)(256 - pathShearX) / 100) * -1f); | ||
1544 | } | ||
1545 | else | ||
1546 | { | ||
1547 | extr.pushX = (float)pathShearX / 100; | ||
1548 | } | ||
1549 | } | ||
1550 | |||
1551 | if (pathShearY != 0) | ||
1552 | { | ||
1553 | if (pathShearY > 50) | ||
1554 | { | ||
1555 | // Complimentary byte. Negative values wrap around the byte. Positive values go up to 50 | ||
1556 | extr.pushY = (((float)(256 - pathShearY) / 100) * -1f); | ||
1557 | } | ||
1558 | else | ||
1559 | { | ||
1560 | extr.pushY = (float)pathShearY / 100; | ||
1561 | } | 319 | } |
1562 | 320 | ||
1563 | } | 321 | primMesh.DumpRaw(baseDir, primName, "primMesh"); |
1564 | |||
1565 | extr.twistTop = (float)primShape.PathTwist * (float)Math.PI * 0.02f; | ||
1566 | extr.twistBot = (float)primShape.PathTwistBegin * (float)Math.PI * 0.02f; | ||
1567 | |||
1568 | Mesh result = extr.ExtrudeCircularPath(m); | ||
1569 | result.DumpRaw(baseDir, primName, "Z extruded"); | ||
1570 | |||
1571 | #if SPAM | ||
1572 | int vCount = 0; | ||
1573 | |||
1574 | foreach (Vertex v in result.vertices) | ||
1575 | { | ||
1576 | if (v != null) | ||
1577 | vCount++; | ||
1578 | } | ||
1579 | |||
1580 | System.Console.WriteLine("Mesh vertex count: " + vCount.ToString()); | ||
1581 | #endif | ||
1582 | |||
1583 | return result; | ||
1584 | } | ||
1585 | |||
1586 | public static Vertex midUnitRadialPoint(Vertex a, Vertex b, float radius) | ||
1587 | { | ||
1588 | Vertex midpoint = new Vertex(a + b) * 0.5f; | ||
1589 | return (midpoint.normalize() * radius); | ||
1590 | } | ||
1591 | |||
1592 | public static void SphereLODTriangle(Vertex a, Vertex b, Vertex c, float diameter, float LOD, Mesh m) | ||
1593 | { | ||
1594 | Vertex aa = a - b; | ||
1595 | Vertex ba = b - c; | ||
1596 | Vertex da = c - a; | ||
1597 | |||
1598 | if (((aa.length() < LOD) && (ba.length() < LOD) && (da.length() < LOD))) | ||
1599 | { | ||
1600 | // We don't want duplicate verticies. Duplicates cause the scale algorithm to produce a spikeball | ||
1601 | // spikes are novel, but we want ellipsoids. | ||
1602 | |||
1603 | if (!m.vertices.Contains(a)) | ||
1604 | m.Add(a); | ||
1605 | if (!m.vertices.Contains(b)) | ||
1606 | m.Add(b); | ||
1607 | if (!m.vertices.Contains(c)) | ||
1608 | m.Add(c); | ||
1609 | |||
1610 | // Add the triangle to the mesh | ||
1611 | Triangle t = new Triangle(a, b, c); | ||
1612 | m.Add(t); | ||
1613 | } | ||
1614 | else | ||
1615 | { | ||
1616 | Vertex ab = midUnitRadialPoint(a, b, diameter); | ||
1617 | Vertex bc = midUnitRadialPoint(b, c, diameter); | ||
1618 | Vertex ca = midUnitRadialPoint(c, a, diameter); | ||
1619 | |||
1620 | // Recursive! Splits the triangle up into 4 smaller triangles | ||
1621 | SphereLODTriangle(a, ab, ca, diameter, LOD, m); | ||
1622 | SphereLODTriangle(ab, b, bc, diameter, LOD, m); | ||
1623 | SphereLODTriangle(ca, bc, c, diameter, LOD, m); | ||
1624 | SphereLODTriangle(ab, bc, ca, diameter, LOD, m); | ||
1625 | |||
1626 | } | ||
1627 | } | ||
1628 | |||
1629 | private void ReportPrimError(string message, string primName, PrimMesh primMesh) | ||
1630 | { | ||
1631 | Console.WriteLine(message); | ||
1632 | Console.WriteLine("\nPrim Name: " + primName); | ||
1633 | Console.WriteLine("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString()); | ||
1634 | |||
1635 | } | ||
1636 | |||
1637 | public Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod) | ||
1638 | { | ||
1639 | Mesh mesh = new Mesh(); | ||
1640 | |||
1641 | float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f; | ||
1642 | float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f; | ||
1643 | float pathBegin = (float)primShape.PathBegin * 2.0e-5f; | ||
1644 | float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f; | ||
1645 | float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f; | ||
1646 | float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f; | ||
1647 | |||
1648 | float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f; | ||
1649 | float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f; | ||
1650 | float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f; | ||
1651 | |||
1652 | int sides = 4; | ||
1653 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
1654 | sides = 3; | ||
1655 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
1656 | sides = 24; | ||
1657 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
1658 | { // half circle, prim is a sphere | ||
1659 | sides = 24; | ||
1660 | |||
1661 | profileBegin = 0.5f * profileBegin + 0.5f; | ||
1662 | profileEnd = 0.5f * profileEnd + 0.5f; | ||
1663 | |||
1664 | } | ||
1665 | |||
1666 | int hollowSides = sides; | ||
1667 | if (primShape.HollowShape == HollowShape.Circle) | ||
1668 | hollowSides = 24; | ||
1669 | else if (primShape.HollowShape == HollowShape.Square) | ||
1670 | hollowSides = 4; | ||
1671 | else if (primShape.HollowShape == HollowShape.Triangle) | ||
1672 | hollowSides = 3; | ||
1673 | 322 | ||
1674 | PrimMesh primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides); | 323 | primMesh.Scale(size.X, size.Y, size.Z); |
1675 | 324 | ||
1676 | primMesh.topShearX = pathShearX; | 325 | coords = primMesh.coords; |
1677 | primMesh.topShearY = pathShearY; | 326 | faces = primMesh.faces; |
1678 | primMesh.pathCutBegin = pathBegin; | ||
1679 | primMesh.pathCutEnd = pathEnd; | ||
1680 | 327 | ||
1681 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
1682 | { | ||
1683 | primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10; | ||
1684 | primMesh.twistEnd = primShape.PathTwist * 18 / 10; | ||
1685 | primMesh.taperX = pathScaleX; | ||
1686 | primMesh.taperY = pathScaleY; | ||
1687 | |||
1688 | if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f) | ||
1689 | { | ||
1690 | ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh); | ||
1691 | if (profileBegin < 0.0f) profileBegin = 0.0f; | ||
1692 | if (profileEnd > 1.0f) profileEnd = 1.0f; | ||
1693 | } | ||
1694 | #if SPAM | ||
1695 | Console.WriteLine("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString()); | ||
1696 | #endif | ||
1697 | try | ||
1698 | { | ||
1699 | primMesh.ExtrudeLinear(); | ||
1700 | } | ||
1701 | catch (Exception ex) | ||
1702 | { | ||
1703 | ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh); | ||
1704 | return null; | ||
1705 | } | ||
1706 | } | 328 | } |
1707 | else | ||
1708 | { | ||
1709 | primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f; | ||
1710 | primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f; | ||
1711 | primMesh.radius = 0.01f * primShape.PathRadiusOffset; | ||
1712 | primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions; | ||
1713 | primMesh.skew = 0.01f * primShape.PathSkew; | ||
1714 | primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10; | ||
1715 | primMesh.twistEnd = primShape.PathTwist * 36 / 10; | ||
1716 | primMesh.taperX = primShape.PathTaperX * 0.01f; | ||
1717 | primMesh.taperY = primShape.PathTaperY * 0.01f; | ||
1718 | |||
1719 | if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f) | ||
1720 | { | ||
1721 | ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh); | ||
1722 | if (profileBegin < 0.0f) profileBegin = 0.0f; | ||
1723 | if (profileEnd > 1.0f) profileEnd = 1.0f; | ||
1724 | } | ||
1725 | #if SPAM | ||
1726 | Console.WriteLine("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString()); | ||
1727 | #endif | ||
1728 | try | ||
1729 | { | ||
1730 | primMesh.ExtrudeCircular(); | ||
1731 | } | ||
1732 | catch (Exception ex) | ||
1733 | { | ||
1734 | ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh); | ||
1735 | return null; | ||
1736 | } | ||
1737 | } | ||
1738 | |||
1739 | primMesh.DumpRaw(baseDir, primName, "primMesh"); | ||
1740 | 329 | ||
1741 | primMesh.Scale(size.X, size.Y, size.Z); | ||
1742 | 330 | ||
1743 | int numCoords = primMesh.coords.Count; | 331 | int numCoords = coords.Count; |
1744 | int numFaces = primMesh.faces.Count; | 332 | int numFaces = faces.Count; |
1745 | 333 | ||
1746 | List<Coord> coords = primMesh.coords; | ||
1747 | for (int i = 0; i < numCoords; i++) | 334 | for (int i = 0; i < numCoords; i++) |
1748 | { | 335 | { |
1749 | Coord c = coords[i]; | 336 | Coord c = coords[i]; |
1750 | mesh.vertices.Add(new Vertex(c.X, c.Y, c.Z)); | 337 | mesh.vertices.Add(new Vertex(c.X, c.Y, c.Z)); |
1751 | } | 338 | } |
1752 | 339 | ||
1753 | List<Face> faces = primMesh.faces; | ||
1754 | List<Vertex> vertices = mesh.vertices; | 340 | List<Vertex> vertices = mesh.vertices; |
1755 | |||
1756 | for (int i = 0; i < numFaces; i++) | 341 | for (int i = 0; i < numFaces; i++) |
1757 | { | 342 | { |
1758 | Face f = faces[i]; | 343 | Face f = faces[i]; |
1759 | mesh.triangles.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3])); | 344 | mesh.triangles.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3])); |
1760 | } | 345 | } |
1761 | 346 | ||
1762 | //for (int i = 0; i < numFaces; i++) | ||
1763 | //{ | ||
1764 | // Face f = primMesh.faces[i]; | ||
1765 | // Coord vert = primMesh.coords[f.v1]; | ||
1766 | // Vertex v1 = new Vertex(vert.X, vert.Y, vert.Z); | ||
1767 | // mesh.vertices.Add(v1); | ||
1768 | // vert = primMesh.coords[f.v2]; | ||
1769 | // Vertex v2 = new Vertex(vert.X, vert.Y, vert.Z); | ||
1770 | // mesh.vertices.Add(v2); | ||
1771 | // vert = primMesh.coords[f.v3]; | ||
1772 | // Vertex v3 = new Vertex(vert.X, vert.Y, vert.Z); | ||
1773 | // mesh.vertices.Add(v3); | ||
1774 | // mesh.triangles.Add(new Triangle(v1, v2, v3)); | ||
1775 | //} | ||
1776 | |||
1777 | //mesh.DumpRaw(baseDir, primName, "Mesh"); | ||
1778 | |||
1779 | //mesh.primMesh = primMesh; | ||
1780 | |||
1781 | return mesh; | 347 | return mesh; |
1782 | } | 348 | } |
1783 | 349 | ||
@@ -1794,83 +360,16 @@ namespace OpenSim.Region.Physics.Meshing | |||
1794 | if (size.Y < 0.01f) size.Y = 0.01f; | 360 | if (size.Y < 0.01f) size.Y = 0.01f; |
1795 | if (size.Z < 0.01f) size.Z = 0.01f; | 361 | if (size.Z < 0.01f) size.Z = 0.01f; |
1796 | 362 | ||
1797 | #if SPAM | 363 | mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod); |
1798 | reportPrimParams(primName, primShape); | ||
1799 | #endif | ||
1800 | |||
1801 | if (primShape.SculptEntry && primShape.SculptType != (byte)0 && primShape.SculptData.Length > 0) | ||
1802 | { | ||
1803 | SculptMesh smesh = CreateSculptMesh(primName, primShape, size, lod); | ||
1804 | mesh = (Mesh)smesh; | ||
1805 | } | ||
1806 | |||
1807 | else if (usePrimMesher) | ||
1808 | { | ||
1809 | mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod); | ||
1810 | } | ||
1811 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) | ||
1812 | { | ||
1813 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
1814 | { // its a box | ||
1815 | mesh = CreateBoxMesh(primName, primShape, size); | ||
1816 | //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod); | ||
1817 | } | ||
1818 | else if (primShape.PathCurve == (byte)Extrusion.Curve1) | ||
1819 | { // tube | ||
1820 | // do a cylinder for now | ||
1821 | mesh = CreateCylinderMesh(primName, primShape, size); | ||
1822 | //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod); | ||
1823 | } | ||
1824 | } | ||
1825 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
1826 | { | ||
1827 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
1828 | { | ||
1829 | mesh = CreateCylinderMesh(primName, primShape, size); | ||
1830 | //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod); | ||
1831 | } | ||
1832 | |||
1833 | // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits | ||
1834 | else if (primShape.PathCurve == (byte) Extrusion.Curve1) | ||
1835 | { // dahlia's favorite, a torus :) | ||
1836 | mesh = CreateCircularPathMesh(primName, primShape, size); | ||
1837 | //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod);\ | ||
1838 | } | ||
1839 | } | ||
1840 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
1841 | { | ||
1842 | if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte) Extrusion.Curve2) | ||
1843 | { | ||
1844 | //mesh = CreateSphereMesh(primName, primShape, size); | ||
1845 | mesh = CreateCircularPathMesh(primName, primShape, size); | ||
1846 | //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod); | ||
1847 | } | ||
1848 | } | ||
1849 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
1850 | { | ||
1851 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
1852 | { | ||
1853 | mesh = CreatePrismMesh(primName, primShape, size); | ||
1854 | //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod); | ||
1855 | } | ||
1856 | else if (primShape.PathCurve == (byte) Extrusion.Curve1) | ||
1857 | { // a ring - do a cylinder for now | ||
1858 | //mesh = CreateCylinderMesh(primName, primShape, size); | ||
1859 | mesh = CreateCircularPathMesh(primName, primShape, size); | ||
1860 | //mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod); | ||
1861 | } | ||
1862 | } | ||
1863 | else // just do a box | ||
1864 | { | ||
1865 | mesh = CreateBoxMesh(primName, primShape, size); | ||
1866 | } | ||
1867 | 364 | ||
1868 | if (mesh != null) | 365 | if (mesh != null) |
1869 | { | 366 | { |
1870 | if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh) | 367 | if ((!isPhysical) && size.X < minSizeForComplexMesh && size.Y < minSizeForComplexMesh && size.Z < minSizeForComplexMesh) |
1871 | { | 368 | { |
1872 | #if SPAM | 369 | #if SPAM |
1873 | Console.WriteLine("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " + minSizeForComplexMesh.ToString() + " - creating simple bounding box" ); | 370 | Console.WriteLine("Meshmerizer: prim " + primName + " has a size of " + size.ToString() + " which is below threshold of " + |
371 | |||
372 | minSizeForComplexMesh.ToString() + " - creating simple bounding box" ); | ||
1874 | #endif | 373 | #endif |
1875 | mesh = CreateBoundingBoxMesh(mesh); | 374 | mesh = CreateBoundingBoxMesh(mesh); |
1876 | mesh.DumpRaw(baseDir, primName, "Z extruded"); | 375 | mesh.DumpRaw(baseDir, primName, "Z extruded"); |
@@ -1884,6 +383,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
1884 | return mesh; | 383 | return mesh; |
1885 | } | 384 | } |
1886 | 385 | ||
386 | |||
387 | |||
1887 | #if SPAM | 388 | #if SPAM |
1888 | // please dont comment this out until I'm done with this module - dahlia | 389 | // please dont comment this out until I'm done with this module - dahlia |
1889 | private static void reportPrimParams(string name, PrimitiveBaseShape primShape) | 390 | private static void reportPrimParams(string name, PrimitiveBaseShape primShape) |