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