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