diff options
author | Dahlia Trimble | 2008-11-29 11:02:14 +0000 |
---|---|---|
committer | Dahlia Trimble | 2008-11-29 11:02:14 +0000 |
commit | fdd238833163eb947986bfcdd09da82f6949a5f2 (patch) | |
tree | 6b90177758405f6106f4f5d4d75e3b98bf08053c /OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |
parent | Comment the ScriptSponsor and restore the indefinite lifetime for (diff) | |
download | opensim-SC_OLD-fdd238833163eb947986bfcdd09da82f6949a5f2.zip opensim-SC_OLD-fdd238833163eb947986bfcdd09da82f6949a5f2.tar.gz opensim-SC_OLD-fdd238833163eb947986bfcdd09da82f6949a5f2.tar.bz2 opensim-SC_OLD-fdd238833163eb947986bfcdd09da82f6949a5f2.tar.xz |
Update meshing code to sync with current PrimMesher.cs on forge.
Migrate sculpt meshing code to primMesher version. This should result in more accurate physical sculpted prim proxies.
Remove much obsolete code from Region/Physics/Meshing
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/Meshmerizer.cs')
-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) |