aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs')
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs408
1 files changed, 408 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
new file mode 100644
index 0000000..8c97f2f
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
@@ -0,0 +1,408 @@
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;
35
36namespace OpenSim.Region.PhysicsModules.Meshing
37{
38 public class Mesh : IMesh
39 {
40 private Dictionary<Vertex, int> m_vertices;
41 private List<Triangle> m_triangles;
42 GCHandle m_pinnedVertexes;
43 GCHandle m_pinnedIndex;
44 IntPtr m_verticesPtr = IntPtr.Zero;
45 int m_vertexCount = 0;
46 IntPtr m_indicesPtr = IntPtr.Zero;
47 int m_indexCount = 0;
48 public float[] m_normals;
49 Vector3 _centroid;
50 int _centroidDiv;
51
52 private class vertexcomp : IEqualityComparer<Vertex>
53 {
54 public bool Equals(Vertex v1, Vertex v2)
55 {
56 if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z)
57 return true;
58 else
59 return false;
60 }
61 public int GetHashCode(Vertex v)
62 {
63 int a = v.X.GetHashCode();
64 int b = v.Y.GetHashCode();
65 int c = v.Z.GetHashCode();
66 return (a << 16) ^ (b << 8) ^ c;
67 }
68
69 }
70
71 public Mesh()
72 {
73 vertexcomp vcomp = new vertexcomp();
74
75 m_vertices = new Dictionary<Vertex, int>(vcomp);
76 m_triangles = new List<Triangle>();
77 _centroid = Vector3.Zero;
78 _centroidDiv = 0;
79 }
80
81 public Mesh Clone()
82 {
83 Mesh result = new Mesh();
84
85 foreach (Triangle t in m_triangles)
86 {
87 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
88 }
89 result._centroid = _centroid;
90 result._centroidDiv = _centroidDiv;
91 return result;
92 }
93
94 public void Add(Triangle triangle)
95 {
96 if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
97 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
98 // If a vertex of the triangle is not yet in the vertices list,
99 // add it and set its index to the current index count
100 // vertex == seems broken
101 // skip colapsed triangles
102 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
103 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
104 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
105 )
106 {
107 return;
108 }
109
110 if (m_vertices.Count == 0)
111 {
112 _centroidDiv = 0;
113 _centroid = Vector3.Zero;
114 }
115
116 if (!m_vertices.ContainsKey(triangle.v1))
117 {
118 m_vertices[triangle.v1] = m_vertices.Count;
119 _centroid.X += triangle.v1.X;
120 _centroid.Y += triangle.v1.Y;
121 _centroid.Z += triangle.v1.Z;
122 _centroidDiv++;
123 }
124 if (!m_vertices.ContainsKey(triangle.v2))
125 {
126 m_vertices[triangle.v2] = m_vertices.Count;
127 _centroid.X += triangle.v2.X;
128 _centroid.Y += triangle.v2.Y;
129 _centroid.Z += triangle.v2.Z;
130 _centroidDiv++;
131 }
132 if (!m_vertices.ContainsKey(triangle.v3))
133 {
134 m_vertices[triangle.v3] = m_vertices.Count;
135 _centroid.X += triangle.v3.X;
136 _centroid.Y += triangle.v3.Y;
137 _centroid.Z += triangle.v3.Z;
138 _centroidDiv++;
139 }
140 m_triangles.Add(triangle);
141 }
142
143 public Vector3 GetCentroid()
144 {
145 if (_centroidDiv > 0)
146 return new Vector3(_centroid.X / _centroidDiv, _centroid.Y / _centroidDiv, _centroid.Z / _centroidDiv);
147 else
148 return Vector3.Zero;
149 }
150
151 // not functional
152 public Vector3 GetOBB()
153 {
154 return new Vector3(0.5f, 0.5f, 0.5f);
155 }
156
157 public void CalcNormals()
158 {
159 int iTriangles = m_triangles.Count;
160
161 this.m_normals = new float[iTriangles * 3];
162
163 int i = 0;
164 foreach (Triangle t in m_triangles)
165 {
166 float ux, uy, uz;
167 float vx, vy, vz;
168 float wx, wy, wz;
169
170 ux = t.v1.X;
171 uy = t.v1.Y;
172 uz = t.v1.Z;
173
174 vx = t.v2.X;
175 vy = t.v2.Y;
176 vz = t.v2.Z;
177
178 wx = t.v3.X;
179 wy = t.v3.Y;
180 wz = t.v3.Z;
181
182
183 // Vectors for edges
184 float e1x, e1y, e1z;
185 float e2x, e2y, e2z;
186
187 e1x = ux - vx;
188 e1y = uy - vy;
189 e1z = uz - vz;
190
191 e2x = ux - wx;
192 e2y = uy - wy;
193 e2z = uz - wz;
194
195
196 // Cross product for normal
197 float nx, ny, nz;
198 nx = e1y * e2z - e1z * e2y;
199 ny = e1z * e2x - e1x * e2z;
200 nz = e1x * e2y - e1y * e2x;
201
202 // Length
203 float l = (float)Math.Sqrt(nx * nx + ny * ny + nz * nz);
204 float lReciprocal = 1.0f / l;
205
206 // Normalized "normal"
207 //nx /= l;
208 //ny /= l;
209 //nz /= l;
210
211 m_normals[i] = nx * lReciprocal;
212 m_normals[i + 1] = ny * lReciprocal;
213 m_normals[i + 2] = nz * lReciprocal;
214
215 i += 3;
216 }
217 }
218
219 public List<Vector3> getVertexList()
220 {
221 List<Vector3> result = new List<Vector3>();
222 foreach (Vertex v in m_vertices.Keys)
223 {
224 result.Add(new Vector3(v.X, v.Y, v.Z));
225 }
226 return result;
227 }
228
229 public float[] getVertexListAsFloat()
230 {
231 if (m_vertices == null)
232 throw new NotSupportedException();
233 float[] result = new float[m_vertices.Count * 3];
234 foreach (KeyValuePair<Vertex, int> kvp in m_vertices)
235 {
236 Vertex v = kvp.Key;
237 int i = kvp.Value;
238 result[3 * i + 0] = v.X;
239 result[3 * i + 1] = v.Y;
240 result[3 * i + 2] = v.Z;
241 }
242 return result;
243 }
244
245 public float[] getVertexListAsFloatLocked()
246 {
247 if (m_pinnedVertexes.IsAllocated)
248 return (float[])(m_pinnedVertexes.Target);
249
250 float[] result = getVertexListAsFloat();
251 m_pinnedVertexes = GCHandle.Alloc(result, GCHandleType.Pinned);
252 // Inform the garbage collector of this unmanaged allocation so it can schedule
253 // the next GC round more intelligently
254 GC.AddMemoryPressure(Buffer.ByteLength(result));
255
256 return result;
257 }
258
259 public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount)
260 {
261 // A vertex is 3 floats
262
263 vertexStride = 3 * sizeof(float);
264
265 // If there isn't an unmanaged array allocated yet, do it now
266 if (m_verticesPtr == IntPtr.Zero)
267 {
268 float[] vertexList = getVertexListAsFloat();
269 // Each vertex is 3 elements (floats)
270 m_vertexCount = vertexList.Length / 3;
271 int byteCount = m_vertexCount * vertexStride;
272 m_verticesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
273 System.Runtime.InteropServices.Marshal.Copy(vertexList, 0, m_verticesPtr, m_vertexCount * 3);
274 }
275 vertices = m_verticesPtr;
276 vertexCount = m_vertexCount;
277 }
278
279 public int[] getIndexListAsInt()
280 {
281 if (m_triangles == null)
282 throw new NotSupportedException();
283 int[] result = new int[m_triangles.Count * 3];
284 for (int i = 0; i < m_triangles.Count; i++)
285 {
286 Triangle t = m_triangles[i];
287 result[3 * i + 0] = m_vertices[t.v1];
288 result[3 * i + 1] = m_vertices[t.v2];
289 result[3 * i + 2] = m_vertices[t.v3];
290 }
291 return result;
292 }
293
294 /// <summary>
295 /// creates a list of index values that defines triangle faces. THIS METHOD FREES ALL NON-PINNED MESH DATA
296 /// </summary>
297 /// <returns></returns>
298 public int[] getIndexListAsIntLocked()
299 {
300 if (m_pinnedIndex.IsAllocated)
301 return (int[])(m_pinnedIndex.Target);
302
303 int[] result = getIndexListAsInt();
304 m_pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned);
305 // Inform the garbage collector of this unmanaged allocation so it can schedule
306 // the next GC round more intelligently
307 GC.AddMemoryPressure(Buffer.ByteLength(result));
308
309 return result;
310 }
311
312 public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
313 {
314 // If there isn't an unmanaged array allocated yet, do it now
315 if (m_indicesPtr == IntPtr.Zero)
316 {
317 int[] indexList = getIndexListAsInt();
318 m_indexCount = indexList.Length;
319 int byteCount = m_indexCount * sizeof(int);
320 m_indicesPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(byteCount);
321 System.Runtime.InteropServices.Marshal.Copy(indexList, 0, m_indicesPtr, m_indexCount);
322 }
323 // A triangle is 3 ints (indices)
324 triStride = 3 * sizeof(int);
325 indices = m_indicesPtr;
326 indexCount = m_indexCount;
327 }
328
329 public void releasePinned()
330 {
331 if (m_pinnedVertexes.IsAllocated)
332 m_pinnedVertexes.Free();
333 if (m_pinnedIndex.IsAllocated)
334 m_pinnedIndex.Free();
335 if (m_verticesPtr != IntPtr.Zero)
336 {
337 System.Runtime.InteropServices.Marshal.FreeHGlobal(m_verticesPtr);
338 m_verticesPtr = IntPtr.Zero;
339 }
340 if (m_indicesPtr != IntPtr.Zero)
341 {
342 System.Runtime.InteropServices.Marshal.FreeHGlobal(m_indicesPtr);
343 m_indicesPtr = IntPtr.Zero;
344 }
345 }
346
347 /// <summary>
348 /// frees up the source mesh data to minimize memory - call this method after calling get*Locked() functions
349 /// </summary>
350 public void releaseSourceMeshData()
351 {
352 m_triangles = null;
353 m_vertices = null;
354 }
355
356 public void Append(IMesh newMesh)
357 {
358 if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
359 throw new NotSupportedException("Attempt to Append to a pinned Mesh");
360
361 if (!(newMesh is Mesh))
362 return;
363
364 foreach (Triangle t in ((Mesh)newMesh).m_triangles)
365 Add(t);
366 }
367
368 // Do a linear transformation of mesh.
369 public void TransformLinear(float[,] matrix, float[] offset)
370 {
371 if (m_pinnedIndex.IsAllocated || m_pinnedVertexes.IsAllocated || m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
372 throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
373
374 foreach (Vertex v in m_vertices.Keys)
375 {
376 if (v == null)
377 continue;
378 float x, y, z;
379 x = v.X*matrix[0, 0] + v.Y*matrix[1, 0] + v.Z*matrix[2, 0];
380 y = v.X*matrix[0, 1] + v.Y*matrix[1, 1] + v.Z*matrix[2, 1];
381 z = v.X*matrix[0, 2] + v.Y*matrix[1, 2] + v.Z*matrix[2, 2];
382 v.X = x + offset[0];
383 v.Y = y + offset[1];
384 v.Z = z + offset[2];
385 }
386 }
387
388 public void DumpRaw(String path, String name, String title)
389 {
390 if (path == null)
391 return;
392 String fileName = name + "_" + title + ".raw";
393 String completePath = System.IO.Path.Combine(path, fileName);
394 StreamWriter sw = new StreamWriter(completePath);
395 foreach (Triangle t in m_triangles)
396 {
397 String s = t.ToStringRaw();
398 sw.WriteLine(s);
399 }
400 sw.Close();
401 }
402
403 public void TrimExcess()
404 {
405 m_triangles.TrimExcess();
406 }
407 }
408}