aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs375
1 files changed, 0 insertions, 375 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs
deleted file mode 100644
index 37fbb8a..0000000
--- a/OpenSim/Region/Physics/OdePlugin/Meshing/Meshmerizer.cs
+++ /dev/null
@@ -1,375 +0,0 @@
1/*
2* Copyright (c) Contributors, http://opensimulator.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*
27*/
28
29using System;
30using System.IO;
31using System.Globalization;
32using System.Diagnostics;
33using System.Collections.Generic;
34using System.Runtime.InteropServices;
35using OpenSim.Framework;
36using OpenSim.Framework.Console;
37using OpenSim.Region.Physics.Manager;
38
39namespace OpenSim.Region.Physics.OdePlugin.Meshing
40{
41
42 public class Meshmerizer
43 {
44 // Setting baseDir to a path will enable the dumping of raw files
45 // raw files can be imported by blender so a visual inspection of the results can be done
46 // const string baseDir = "rawFiles";
47 const string baseDir = null;
48
49 static void IntersectionParameterPD(PhysicsVector p1, PhysicsVector r1, PhysicsVector p2, PhysicsVector r2, ref float lambda, ref float mu)
50 {
51 // p1, p2, points on the straight
52 // r1, r2, directional vectors of the straight. Not necessarily of length 1!
53 // note, that l, m can be scaled such, that the range 0..1 is mapped to the area between two points,
54 // thus allowing to decide whether an intersection is between two points
55
56 float r1x = r1.X;
57 float r1y = r1.Y;
58 float r2x = r2.X;
59 float r2y = r2.Y;
60
61 float denom = r1y*r2x - r1x*r2y;
62
63 if (denom == 0.0)
64 {
65 lambda = Single.NaN;
66 mu = Single.NaN;
67 return;
68 }
69
70 float p1x = p1.X;
71 float p1y = p1.Y;
72 float p2x = p2.X;
73 float p2y = p2.Y;
74 lambda = (-p2x * r2y + p1x * r2y + (p2y - p1y) * r2x) / denom;
75 mu = (-p2x * r1y + p1x * r1y + (p2y - p1y) * r1x) / denom;
76
77 }
78
79 private static List<Triangle> FindInfluencedTriangles(List<Triangle> triangles, Vertex v)
80 {
81 List<Triangle> influenced = new List<Triangle>();
82 foreach (Triangle t in triangles)
83 {
84 if (t.isInCircle(v.X, v.Y))
85 {
86 influenced.Add(t);
87 }
88 }
89 return influenced;
90 }
91
92
93 private static void InsertVertices(List<Vertex> vertices, int usedForSeed, List<Triangle> triangles)
94 {
95 // This is a variant of the delaunay algorithm
96 // each time a new vertex is inserted, all triangles that are influenced by it are deleted
97 // and replaced by new ones including the new vertex
98 // It is not very time efficient but easy to implement.
99
100 int iCurrentVertex;
101 int iMaxVertex = vertices.Count;
102 for (iCurrentVertex = usedForSeed; iCurrentVertex < iMaxVertex; iCurrentVertex++)
103 {
104 // Background: A triangle mesh fulfills the delaunay condition if (iff!)
105 // each circumlocutory circle (i.e. the circle that touches all three corners)
106 // of each triangle is empty of other vertices.
107 // Obviously a single (seeding) triangle fulfills this condition.
108 // If we now add one vertex, we need to reconstruct all triangles, that
109 // do not fulfill this condition with respect to the new triangle
110
111 // Find the triangles that are influenced by the new vertex
112 Vertex v=vertices[iCurrentVertex];
113 if (v == null)
114 continue; // Null is polygon stop marker. Ignore it
115 List<Triangle> influencedTriangles=FindInfluencedTriangles(triangles, v);
116
117 List<Simplex> simplices = new List<Simplex>();
118
119 // Reconstruction phase. First step, dissolve each triangle into it's simplices,
120 // i.e. it's "border lines"
121 // Goal is to find "inner" borders and delete them, while the hull gets conserved.
122 // Inner borders are special in the way that they always come twice, which is how we detect them
123 foreach (Triangle t in influencedTriangles)
124 {
125 List<Simplex> newSimplices = t.GetSimplices();
126 simplices.AddRange(newSimplices);
127 triangles.Remove(t);
128 }
129 // Now sort the simplices. That will make identical ones reside side by side in the list
130 simplices.Sort();
131
132 // Look for duplicate simplices here.
133 // Remember, they are directly side by side in the list right now,
134 // So we only check directly neighbours
135 int iSimplex;
136 List<Simplex> innerSimplices = new List<Simplex>();
137 for (iSimplex = 1; iSimplex < simplices.Count; iSimplex++) // Startindex=1, so we can refer backwards
138 {
139 if (simplices[iSimplex - 1].CompareTo(simplices[iSimplex]) == 0)
140 {
141 innerSimplices.Add(simplices[iSimplex - 1]);
142 innerSimplices.Add(simplices[iSimplex]);
143 }
144 }
145
146 foreach (Simplex s in innerSimplices)
147 {
148 simplices.Remove(s);
149 }
150
151 // each simplex still in the list belongs to the hull of the region in question
152 // The new vertex (yes, we still deal with verices here :-) ) forms a triangle
153 // with each of these simplices. Build the new triangles and add them to the list
154 foreach (Simplex s in simplices)
155 {
156 Triangle t = new Triangle(s.v1, s.v2, vertices[iCurrentVertex]);
157 if (!t.isDegraded())
158 {
159 triangles.Add(t);
160 }
161 }
162 }
163
164 }
165
166
167 static Mesh CreateBoxMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
168 // Builds the z (+ and -) surfaces of a box shaped prim
169 {
170 UInt16 hollowFactor = primShape.ProfileHollow;
171 UInt16 profileBegin = primShape.ProfileBegin;
172 UInt16 profileEnd = primShape.ProfileEnd;
173
174 // Procedure: This is based on the fact that the upper (plus) and lower (minus) Z-surface
175 // of a block are basically the same
176 // They may be warped differently but the shape is identical
177 // So we only create one surface as a model and derive both plus and minus surface of the block from it
178 // This is done in a model space where the block spans from -.5 to +.5 in X and Y
179 // The mapping to Scene space is done later during the "extrusion" phase
180
181 // Base
182 Vertex MM = new Vertex(-0.5f, -0.5f, 0.0f);
183 Vertex PM = new Vertex(+0.5f, -0.5f, 0.0f);
184 Vertex MP = new Vertex(-0.5f, +0.5f, 0.0f);
185 Vertex PP = new Vertex(+0.5f, +0.5f, 0.0f);
186
187 Meshing.SimpleHull outerHull = new SimpleHull();
188 outerHull.AddVertex(MM);
189 outerHull.AddVertex(PM);
190 outerHull.AddVertex(PP);
191 outerHull.AddVertex(MP);
192
193 // Deal with cuts now
194 if ((profileBegin != 0) || (profileEnd != 0))
195 {
196 double fProfileBeginAngle = profileBegin / 50000.0 * 360.0; // In degree, for easier debugging and understanding
197 fProfileBeginAngle -= (90.0 + 45.0); // for some reasons, the SL client counts from the corner -X/-Y
198 double fProfileEndAngle = 360.0 - profileEnd / 50000.0 * 360.0; // Pathend comes as complement to 1.0
199 fProfileEndAngle -= (90.0 + 45.0);
200 if (fProfileBeginAngle < fProfileEndAngle)
201 fProfileEndAngle -= 360.0;
202
203 // Note, that we don't want to cut out a triangle, even if this is a
204 // good approximation for small cuts. Indeed we want to cut out an arc
205 // and we approximate this arc by a polygon chain
206 // Also note, that these vectors are of length 1.0 and thus their endpoints lay outside the model space
207 // So it can easily be subtracted from the outer hull
208 int iSteps = (int)(((fProfileBeginAngle - fProfileEndAngle) / 45.0) + .5); // how many steps do we need with approximately 45 degree
209 double dStepWidth=(fProfileBeginAngle-fProfileEndAngle)/iSteps;
210
211 Vertex origin = new Vertex(0.0f, 0.0f, 0.0f);
212
213 // Note the sequence of vertices here. It's important to have the other rotational sense than in outerHull
214 SimpleHull cutHull = new SimpleHull();
215 cutHull.AddVertex(origin);
216 for (int i=0; i<iSteps; i++) {
217 double angle=fProfileBeginAngle-i*dStepWidth; // we count against the angle orientation!!!!
218 Vertex v = Vertex.FromAngle(angle * Math.PI / 180.0);
219 cutHull.AddVertex(v);
220 }
221 Vertex legEnd = Vertex.FromAngle(fProfileEndAngle * Math.PI / 180.0); // Calculated separately to avoid errors
222 cutHull.AddVertex(legEnd);
223
224 MainLog.Instance.Debug("Starting cutting of the hollow shape from the prim {1}", 0, primName);
225 SimpleHull cuttedHull = SimpleHull.SubtractHull(outerHull, cutHull);
226
227 outerHull = cuttedHull;
228 }
229
230 // Deal with the hole here
231 if (hollowFactor > 0)
232 {
233 float hollowFactorF = (float) hollowFactor/(float) 50000;
234 Vertex IMM = new Vertex(-0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
235 Vertex IPM = new Vertex(+0.5f * hollowFactorF, -0.5f * hollowFactorF, 0.0f);
236 Vertex IMP = new Vertex(-0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
237 Vertex IPP = new Vertex(+0.5f * hollowFactorF, +0.5f * hollowFactorF, 0.0f);
238
239 SimpleHull holeHull = new SimpleHull();
240
241 holeHull.AddVertex(IMM);
242 holeHull.AddVertex(IMP);
243 holeHull.AddVertex(IPP);
244 holeHull.AddVertex(IPM);
245
246 SimpleHull hollowedHull = SimpleHull.SubtractHull(outerHull, holeHull);
247
248 outerHull = hollowedHull;
249
250 }
251
252 Mesh m = new Mesh();
253
254 Vertex Seed1 = new Vertex(0.0f, -10.0f, 0.0f);
255 Vertex Seed2 = new Vertex(-10.0f, 10.0f, 0.0f);
256 Vertex Seed3 = new Vertex(10.0f, 10.0f, 0.0f);
257
258 m.Add(Seed1);
259 m.Add(Seed2);
260 m.Add(Seed3);
261
262 m.Add(new Triangle(Seed1, Seed2, Seed3));
263 m.Add(outerHull.getVertices());
264
265 InsertVertices(m.vertices, 3, m.triangles);
266 m.DumpRaw(baseDir, primName, "Proto first Mesh");
267
268 m.Remove(Seed1);
269 m.Remove(Seed2);
270 m.Remove(Seed3);
271 m.DumpRaw(baseDir, primName, "Proto seeds removed");
272
273 m.RemoveTrianglesOutside(outerHull);
274 m.DumpRaw(baseDir, primName, "Proto outsides removed");
275
276 foreach (Triangle t in m.triangles)
277 {
278 PhysicsVector n = t.getNormal();
279 if (n.Z < 0.0)
280 t.invertNormal();
281 }
282
283 Extruder extr = new Extruder();
284
285 extr.size = size;
286
287 Mesh result = extr.Extrude(m);
288 result.DumpRaw(baseDir, primName, "Z extruded");
289 return result;
290 }
291
292 public static void CalcNormals(Mesh mesh)
293 {
294 int iTriangles = mesh.triangles.Count;
295
296 mesh.normals = new float[iTriangles*3];
297
298 int i = 0;
299 foreach (Triangle t in mesh.triangles)
300 {
301 float ux, uy, uz;
302 float vx, vy, vz;
303 float wx, wy, wz;
304
305 ux = t.v1.X;
306 uy = t.v1.Y;
307 uz = t.v1.Z;
308
309 vx = t.v2.X;
310 vy = t.v2.Y;
311 vz = t.v2.Z;
312
313 wx = t.v3.X;
314 wy = t.v3.Y;
315 wz = t.v3.Z;
316
317
318 // Vectors for edges
319 float e1x, e1y, e1z;
320 float e2x, e2y, e2z;
321
322 e1x = ux - vx;
323 e1y = uy - vy;
324 e1z = uz - vz;
325
326 e2x = ux - wx;
327 e2y = uy - wy;
328 e2z = uz - wz;
329
330
331 // Cross product for normal
332 float nx, ny, nz;
333 nx = e1y*e2z - e1z*e2y;
334 ny = e1z*e2x - e1x*e2z;
335 nz = e1x*e2y - e1y*e2x;
336
337 // Length
338 float l = (float) Math.Sqrt(nx*nx + ny*ny + nz*nz);
339
340 // Normalized "normal"
341 nx /= l;
342 ny /= l;
343 nz /= l;
344
345 mesh.normals[i] = nx;
346 mesh.normals[i + 1] = ny;
347 mesh.normals[i + 2] = nz;
348
349 i += 3;
350 }
351 }
352
353 public static Mesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size)
354 {
355 Mesh mesh = null;
356
357 switch (primShape.ProfileShape)
358 {
359 case ProfileShape.Square:
360 mesh=CreateBoxMesh(primName, primShape, size);
361 CalcNormals(mesh);
362 break;
363 default:
364 mesh = CreateBoxMesh(primName, primShape, size);
365 CalcNormals(mesh);
366 //Set default mesh to cube otherwise it'll return
367 // null and crash on the 'setMesh' method in the physics plugins.
368 //mesh = null;
369 break;
370 }
371
372 return mesh;
373 }
374 }
375}