aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs')
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs633
1 files changed, 633 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs
new file mode 100644
index 0000000..97501a4
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs
@@ -0,0 +1,633 @@
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 OpenSimulator 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
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Runtime.InteropServices;
32using OpenSim.Region.PhysicsModules.SharedBase;
33using PrimMesher;
34using OpenMetaverse;
35using System.Runtime.Serialization;
36using System.Runtime.Serialization.Formatters.Binary;
37
38namespace OpenSim.Region.PhysicsModule.ubODEMeshing
39{
40 public class MeshBuildingData
41 {
42 public Dictionary<Vertex, int> m_vertices;
43 public List<Triangle> m_triangles;
44 public float m_obbXmin;
45 public float m_obbXmax;
46 public float m_obbYmin;
47 public float m_obbYmax;
48 public float m_obbZmin;
49 public float m_obbZmax;
50 public Vector3 m_centroid;
51 public int m_centroidDiv;
52 }
53
54 [Serializable()]
55 public class Mesh : IMesh
56 {
57 float[] vertices;
58 int[] indexes;
59 Vector3 m_obb;
60 Vector3 m_obboffset;
61 [NonSerialized()]
62 MeshBuildingData m_bdata;
63 [NonSerialized()]
64 GCHandle vhandler;
65 [NonSerialized()]
66 GCHandle ihandler;
67 [NonSerialized()]
68 IntPtr m_verticesPtr = IntPtr.Zero;
69 [NonSerialized()]
70 IntPtr m_indicesPtr = IntPtr.Zero;
71 [NonSerialized()]
72 int m_vertexCount = 0;
73 [NonSerialized()]
74 int m_indexCount = 0;
75
76 public int RefCount { get; set; }
77 public AMeshKey Key { get; set; }
78
79 private class vertexcomp : IEqualityComparer<Vertex>
80 {
81 public bool Equals(Vertex v1, Vertex v2)
82 {
83 if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z)
84 return true;
85 else
86 return false;
87 }
88 public int GetHashCode(Vertex v)
89 {
90 int a = v.X.GetHashCode();
91 int b = v.Y.GetHashCode();
92 int c = v.Z.GetHashCode();
93 return (a << 16) ^ (b << 8) ^ c;
94 }
95 }
96
97 public Mesh()
98 {
99 vertexcomp vcomp = new vertexcomp();
100
101 m_bdata = new MeshBuildingData();
102 m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp);
103 m_bdata.m_triangles = new List<Triangle>();
104 m_bdata.m_centroid = Vector3.Zero;
105 m_bdata.m_centroidDiv = 0;
106 m_bdata.m_obbXmin = float.MaxValue;
107 m_bdata.m_obbXmax = float.MinValue;
108 m_bdata.m_obbYmin = float.MaxValue;
109 m_bdata.m_obbYmax = float.MinValue;
110 m_bdata.m_obbZmin = float.MaxValue;
111 m_bdata.m_obbZmax = float.MinValue;
112 m_obb = new Vector3(0.5f, 0.5f, 0.5f);
113 m_obboffset = Vector3.Zero;
114 }
115
116
117 public Mesh Scale(Vector3 scale)
118 {
119 if (m_verticesPtr == null || m_indicesPtr == null)
120 return null;
121
122 Mesh result = new Mesh();
123
124 float x = scale.X;
125 float y = scale.Y;
126 float z = scale.Z;
127
128 float tmp;
129 tmp = m_obb.X * x;
130 if(tmp < 0.0005f)
131 tmp = 0.0005f;
132 result.m_obb.X = tmp;
133
134 tmp = m_obb.Y * y;
135 if(tmp < 0.0005f)
136 tmp = 0.0005f;
137 result.m_obb.Y = tmp;
138
139 tmp = m_obb.Z * z;
140 if(tmp < 0.0005f)
141 tmp = 0.0005f;
142 result.m_obb.Z = tmp;
143
144 result.m_obboffset.X = m_obboffset.X * x;
145 result.m_obboffset.Y = m_obboffset.Y * y;
146 result.m_obboffset.Z = m_obboffset.Z * z;
147
148 result.vertices = new float[vertices.Length];
149 int j = 0;
150 for (int i = 0; i < m_vertexCount; i++)
151 {
152 result.vertices[j] = vertices[j] * x;
153 j++;
154 result.vertices[j] = vertices[j] * y;
155 j++;
156 result.vertices[j] = vertices[j] * z;
157 j++;
158 }
159
160 result.indexes = new int[indexes.Length];
161 indexes.CopyTo(result.indexes,0);
162
163 result.pinMemory();
164
165 return result;
166 }
167
168 public Mesh Clone()
169 {
170 Mesh result = new Mesh();
171
172 if (m_bdata != null)
173 {
174 result.m_bdata = new MeshBuildingData();
175 foreach (Triangle t in m_bdata.m_triangles)
176 {
177 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
178 }
179 result.m_bdata.m_centroid = m_bdata.m_centroid;
180 result.m_bdata.m_centroidDiv = m_bdata.m_centroidDiv;
181 result.m_bdata.m_obbXmin = m_bdata.m_obbXmin;
182 result.m_bdata.m_obbXmax = m_bdata.m_obbXmax;
183 result.m_bdata.m_obbYmin = m_bdata.m_obbYmin;
184 result.m_bdata.m_obbYmax = m_bdata.m_obbYmax;
185 result.m_bdata.m_obbZmin = m_bdata.m_obbZmin;
186 result.m_bdata.m_obbZmax = m_bdata.m_obbZmax;
187 }
188 result.m_obb = m_obb;
189 result.m_obboffset = m_obboffset;
190 return result;
191 }
192
193 public void addVertexLStats(Vertex v)
194 {
195 float x = v.X;
196 float y = v.Y;
197 float z = v.Z;
198
199 m_bdata.m_centroid.X += x;
200 m_bdata.m_centroid.Y += y;
201 m_bdata.m_centroid.Z += z;
202 m_bdata.m_centroidDiv++;
203
204 if (x > m_bdata.m_obbXmax)
205 m_bdata.m_obbXmax = x;
206 if (x < m_bdata.m_obbXmin)
207 m_bdata.m_obbXmin = x;
208
209 if (y > m_bdata.m_obbYmax)
210 m_bdata.m_obbYmax = y;
211 if (y < m_bdata.m_obbYmin)
212 m_bdata.m_obbYmin = y;
213
214 if (z > m_bdata.m_obbZmax)
215 m_bdata.m_obbZmax = z;
216 if (z < m_bdata.m_obbZmin)
217 m_bdata.m_obbZmin = z;
218
219 }
220
221 public void Add(Triangle triangle)
222 {
223 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
224 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
225
226
227 triangle.v1.X = (float)Math.Round(triangle.v1.X, 6);
228 triangle.v1.Y = (float)Math.Round(triangle.v1.Y, 6);
229 triangle.v1.Z = (float)Math.Round(triangle.v1.Z, 6);
230 triangle.v2.X = (float)Math.Round(triangle.v2.X, 6);
231 triangle.v2.Y = (float)Math.Round(triangle.v2.Y, 6);
232 triangle.v2.Z = (float)Math.Round(triangle.v2.Z, 6);
233 triangle.v3.X = (float)Math.Round(triangle.v3.X, 6);
234 triangle.v3.Y = (float)Math.Round(triangle.v3.Y, 6);
235 triangle.v3.Z = (float)Math.Round(triangle.v3.Z, 6);
236
237 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
238 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
239 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
240 )
241 {
242 return;
243 }
244
245 if (m_bdata.m_vertices.Count == 0)
246 {
247 m_bdata.m_centroidDiv = 0;
248 m_bdata.m_centroid = Vector3.Zero;
249 }
250
251 if (!m_bdata.m_vertices.ContainsKey(triangle.v1))
252 {
253 m_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count;
254 addVertexLStats(triangle.v1);
255 }
256 if (!m_bdata.m_vertices.ContainsKey(triangle.v2))
257 {
258 m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count;
259 addVertexLStats(triangle.v2);
260 }
261 if (!m_bdata.m_vertices.ContainsKey(triangle.v3))
262 {
263 m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count;
264 addVertexLStats(triangle.v3);
265 }
266 m_bdata.m_triangles.Add(triangle);
267 }
268
269 public Vector3 GetCentroid()
270 {
271 return m_obboffset;
272
273 }
274
275 public Vector3 GetOBB()
276 {
277 return m_obb;
278/*
279 float x, y, z;
280 if (m_bdata.m_centroidDiv > 0)
281 {
282 x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
283 y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
284 z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
285 }
286 else // ??
287 {
288 x = 0.5f;
289 y = 0.5f;
290 z = 0.5f;
291 }
292 return new Vector3(x, y, z);
293*/
294 }
295
296 public int numberVertices()
297 {
298 return m_bdata.m_vertices.Count;
299 }
300
301 public int numberTriangles()
302 {
303 return m_bdata.m_triangles.Count;
304 }
305
306 public List<Vector3> getVertexList()
307 {
308 List<Vector3> result = new List<Vector3>();
309 foreach (Vertex v in m_bdata.m_vertices.Keys)
310 {
311 result.Add(new Vector3(v.X, v.Y, v.Z));
312 }
313 return result;
314 }
315
316 public float[] getVertexListAsFloat()
317 {
318 if (m_bdata.m_vertices == null)
319 throw new NotSupportedException();
320 float[] result = new float[m_bdata.m_vertices.Count * 3];
321 foreach (KeyValuePair<Vertex, int> kvp in m_bdata.m_vertices)
322 {
323 Vertex v = kvp.Key;
324 int i = kvp.Value;
325 result[3 * i + 0] = v.X;
326 result[3 * i + 1] = v.Y;
327 result[3 * i + 2] = v.Z;
328 }
329 return result;
330 }
331
332 public float[] getVertexListAsFloatLocked()
333 {
334 return null;
335 }
336
337 public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount)
338 {
339 // A vertex is 3 floats
340 vertexStride = 3 * sizeof(float);
341
342 // If there isn't an unmanaged array allocated yet, do it now
343 if (m_verticesPtr == IntPtr.Zero && m_bdata != null)
344 {
345 vertices = getVertexListAsFloat();
346 // Each vertex is 3 elements (floats)
347 m_vertexCount = vertices.Length / 3;
348 vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
349 m_verticesPtr = vhandler.AddrOfPinnedObject();
350 GC.AddMemoryPressure(Buffer.ByteLength(vertices));
351 }
352 _vertices = m_verticesPtr;
353 vertexCount = m_vertexCount;
354 }
355
356 public int[] getIndexListAsInt()
357 {
358 if (m_bdata.m_triangles == null)
359 throw new NotSupportedException();
360 int[] result = new int[m_bdata.m_triangles.Count * 3];
361 for (int i = 0; i < m_bdata.m_triangles.Count; i++)
362 {
363 Triangle t = m_bdata.m_triangles[i];
364 result[3 * i + 0] = m_bdata.m_vertices[t.v1];
365 result[3 * i + 1] = m_bdata.m_vertices[t.v2];
366 result[3 * i + 2] = m_bdata.m_vertices[t.v3];
367 }
368 return result;
369 }
370
371 /// <summary>
372 /// creates a list of index values that defines triangle faces. THIS METHOD FREES ALL NON-PINNED MESH DATA
373 /// </summary>
374 /// <returns></returns>
375 public int[] getIndexListAsIntLocked()
376 {
377 return null;
378 }
379
380 public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
381 {
382 // If there isn't an unmanaged array allocated yet, do it now
383 if (m_indicesPtr == IntPtr.Zero && m_bdata != null)
384 {
385 indexes = getIndexListAsInt();
386 m_indexCount = indexes.Length;
387 ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
388 m_indicesPtr = ihandler.AddrOfPinnedObject();
389 GC.AddMemoryPressure(Buffer.ByteLength(indexes));
390 }
391 // A triangle is 3 ints (indices)
392 triStride = 3 * sizeof(int);
393 indices = m_indicesPtr;
394 indexCount = m_indexCount;
395 }
396
397 public void releasePinned()
398 {
399 if (m_verticesPtr != IntPtr.Zero)
400 {
401 vhandler.Free();
402 vertices = null;
403 m_verticesPtr = IntPtr.Zero;
404 }
405 if (m_indicesPtr != IntPtr.Zero)
406 {
407 ihandler.Free();
408 indexes = null;
409 m_indicesPtr = IntPtr.Zero;
410 }
411 }
412
413 /// <summary>
414 /// frees up the source mesh data to minimize memory - call this method after calling get*Locked() functions
415 /// </summary>
416 public void releaseSourceMeshData()
417 {
418 if (m_bdata != null)
419 {
420 m_bdata.m_triangles = null;
421 m_bdata.m_vertices = null;
422 }
423 }
424
425 public void releaseBuildingMeshData()
426 {
427 if (m_bdata != null)
428 {
429 m_bdata.m_triangles = null;
430 m_bdata.m_vertices = null;
431 m_bdata = null;
432 }
433 }
434
435 public void Append(IMesh newMesh)
436 {
437 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
438 throw new NotSupportedException("Attempt to Append to a pinned Mesh");
439
440 if (!(newMesh is Mesh))
441 return;
442
443 foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles)
444 Add(t);
445 }
446
447 // Do a linear transformation of mesh.
448 public void TransformLinear(float[,] matrix, float[] offset)
449 {
450 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
451 throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
452
453 foreach (Vertex v in m_bdata.m_vertices.Keys)
454 {
455 if (v == null)
456 continue;
457 float x, y, z;
458 x = v.X*matrix[0, 0] + v.Y*matrix[1, 0] + v.Z*matrix[2, 0];
459 y = v.X*matrix[0, 1] + v.Y*matrix[1, 1] + v.Z*matrix[2, 1];
460 z = v.X*matrix[0, 2] + v.Y*matrix[1, 2] + v.Z*matrix[2, 2];
461 v.X = x + offset[0];
462 v.Y = y + offset[1];
463 v.Z = z + offset[2];
464 }
465 }
466
467 public void DumpRaw(String path, String name, String title)
468 {
469 if (path == null)
470 return;
471 if (m_bdata == null)
472 return;
473 String fileName = name + "_" + title + ".raw";
474 String completePath = System.IO.Path.Combine(path, fileName);
475 StreamWriter sw = new StreamWriter(completePath);
476 foreach (Triangle t in m_bdata.m_triangles)
477 {
478 String s = t.ToStringRaw();
479 sw.WriteLine(s);
480 }
481 sw.Close();
482 }
483
484 public void TrimExcess()
485 {
486 m_bdata.m_triangles.TrimExcess();
487 }
488
489 public void pinMemory()
490 {
491 m_vertexCount = vertices.Length / 3;
492 vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
493 m_verticesPtr = vhandler.AddrOfPinnedObject();
494 GC.AddMemoryPressure(Buffer.ByteLength(vertices));
495
496 m_indexCount = indexes.Length;
497 ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
498 m_indicesPtr = ihandler.AddrOfPinnedObject();
499 GC.AddMemoryPressure(Buffer.ByteLength(indexes));
500 }
501
502 public void PrepForOde()
503 {
504 // If there isn't an unmanaged array allocated yet, do it now
505 if (m_verticesPtr == IntPtr.Zero)
506 vertices = getVertexListAsFloat();
507
508 // If there isn't an unmanaged array allocated yet, do it now
509 if (m_indicesPtr == IntPtr.Zero)
510 indexes = getIndexListAsInt();
511
512 pinMemory();
513
514 float x, y, z;
515
516 if (m_bdata.m_centroidDiv > 0)
517 {
518 m_obboffset = new Vector3(m_bdata.m_centroid.X / m_bdata.m_centroidDiv, m_bdata.m_centroid.Y / m_bdata.m_centroidDiv, m_bdata.m_centroid.Z / m_bdata.m_centroidDiv);
519 x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
520 if(x < 0.0005f)
521 x = 0.0005f;
522 y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
523 if(y < 0.0005f)
524 y = 0.0005f;
525 z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
526 if(z < 0.0005f)
527 z = 0.0005f;
528 }
529
530 else
531 {
532 m_obboffset = Vector3.Zero;
533 x = 0.5f;
534 y = 0.5f;
535 z = 0.5f;
536 }
537
538 m_obb = new Vector3(x, y, z);
539
540 releaseBuildingMeshData();
541 }
542 public bool ToStream(Stream st)
543 {
544 if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero)
545 return false;
546
547 BinaryWriter bw = new BinaryWriter(st);
548 bool ok = true;
549
550 try
551 {
552
553 bw.Write(m_vertexCount);
554 bw.Write(m_indexCount);
555
556 for (int i = 0; i < 3 * m_vertexCount; i++)
557 bw.Write(vertices[i]);
558 for (int i = 0; i < m_indexCount; i++)
559 bw.Write(indexes[i]);
560 bw.Write(m_obb.X);
561 bw.Write(m_obb.Y);
562 bw.Write(m_obb.Z);
563 bw.Write(m_obboffset.X);
564 bw.Write(m_obboffset.Y);
565 bw.Write(m_obboffset.Z);
566 }
567 catch
568 {
569 ok = false;
570 }
571
572 if (bw != null)
573 {
574 bw.Flush();
575 bw.Close();
576 }
577
578 return ok;
579 }
580
581 public static Mesh FromStream(Stream st, AMeshKey key)
582 {
583 Mesh mesh = new Mesh();
584 mesh.releaseBuildingMeshData();
585
586 BinaryReader br = new BinaryReader(st);
587
588 bool ok = true;
589 try
590 {
591 mesh.m_vertexCount = br.ReadInt32();
592 mesh.m_indexCount = br.ReadInt32();
593
594 int n = 3 * mesh.m_vertexCount;
595 mesh.vertices = new float[n];
596 for (int i = 0; i < n; i++)
597 mesh.vertices[i] = br.ReadSingle();
598
599 mesh.indexes = new int[mesh.m_indexCount];
600 for (int i = 0; i < mesh.m_indexCount; i++)
601 mesh.indexes[i] = br.ReadInt32();
602
603 mesh.m_obb.X = br.ReadSingle();
604 mesh.m_obb.Y = br.ReadSingle();
605 mesh.m_obb.Z = br.ReadSingle();
606
607 mesh.m_obboffset.X = br.ReadSingle();
608 mesh.m_obboffset.Y = br.ReadSingle();
609 mesh.m_obboffset.Z = br.ReadSingle();
610 }
611 catch
612 {
613 ok = false;
614 }
615
616 br.Close();
617
618 if (ok)
619 {
620 mesh.pinMemory();
621
622 mesh.Key = key;
623 mesh.RefCount = 1;
624
625 return mesh;
626 }
627
628 mesh.vertices = null;
629 mesh.indexes = null;
630 return null;
631 }
632 }
633}