aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/Meshing
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/Meshing/Mesh.cs87
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs69
-rw-r--r--OpenSim/Region/Physics/Meshing/PrimMesher.cs27
-rw-r--r--OpenSim/Region/Physics/Meshing/SculptMesh.cs14
4 files changed, 132 insertions, 65 deletions
diff --git a/OpenSim/Region/Physics/Meshing/Mesh.cs b/OpenSim/Region/Physics/Meshing/Mesh.cs
index ceafaad..aae8871 100644
--- a/OpenSim/Region/Physics/Meshing/Mesh.cs
+++ b/OpenSim/Region/Physics/Meshing/Mesh.cs
@@ -40,7 +40,6 @@ namespace OpenSim.Region.Physics.Meshing
40 private List<Triangle> triangles; 40 private List<Triangle> triangles;
41 GCHandle pinnedVirtexes; 41 GCHandle pinnedVirtexes;
42 GCHandle pinnedIndex; 42 GCHandle pinnedIndex;
43 public PrimMesh primMesh = null;
44 public float[] normals; 43 public float[] normals;
45 44
46 public Mesh() 45 public Mesh()
@@ -63,6 +62,8 @@ namespace OpenSim.Region.Physics.Meshing
63 62
64 public void Add(Triangle triangle) 63 public void Add(Triangle triangle)
65 { 64 {
65 if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated)
66 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
66 // If a vertex of the triangle is not yet in the vertices list, 67 // If a vertex of the triangle is not yet in the vertices list,
67 // add it and set its index to the current index count 68 // add it and set its index to the current index count
68 if (!vertices.ContainsKey(triangle.v1)) 69 if (!vertices.ContainsKey(triangle.v1))
@@ -148,40 +149,22 @@ namespace OpenSim.Region.Physics.Meshing
148 149
149 public float[] getVertexListAsFloatLocked() 150 public float[] getVertexListAsFloatLocked()
150 { 151 {
152 if (pinnedVirtexes.IsAllocated)
153 return (float[])(pinnedVirtexes.Target);
151 float[] result; 154 float[] result;
152 155
153 if (primMesh == null) 156 //m_log.WarnFormat("vertices.Count = {0}", vertices.Count);
157 result = new float[vertices.Count * 3];
158 foreach (KeyValuePair<Vertex, int> kvp in vertices)
154 { 159 {
155 //m_log.WarnFormat("vertices.Count = {0}", vertices.Count); 160 Vertex v = kvp.Key;
156 result = new float[vertices.Count * 3]; 161 int i = kvp.Value;
157 foreach (KeyValuePair<Vertex, int> kvp in vertices) 162 //m_log.WarnFormat("kvp.Value = {0}", i);
158 { 163 result[3 * i + 0] = v.X;
159 Vertex v = kvp.Key; 164 result[3 * i + 1] = v.Y;
160 int i = kvp.Value; 165 result[3 * i + 2] = v.Z;
161 //m_log.WarnFormat("kvp.Value = {0}", i);
162 result[3 * i + 0] = v.X;
163 result[3 * i + 1] = v.Y;
164 result[3 * i + 2] = v.Z;
165 }
166 pinnedVirtexes = GCHandle.Alloc(result, GCHandleType.Pinned);
167 }
168 else
169 {
170 int count = primMesh.coords.Count;
171 result = new float[count * 3];
172 for (int i = 0; i < count; i++)
173 {
174 Coord c = primMesh.coords[i];
175 {
176 int resultIndex = 3 * i;
177 result[resultIndex] = c.X;
178 result[resultIndex + 1] = c.Y;
179 result[resultIndex + 2] = c.Z;
180 }
181
182 }
183 pinnedVirtexes = GCHandle.Alloc(result, GCHandleType.Pinned);
184 } 166 }
167 pinnedVirtexes = GCHandle.Alloc(result, GCHandleType.Pinned);
185 return result; 168 return result;
186 } 169 }
187 170
@@ -189,33 +172,13 @@ namespace OpenSim.Region.Physics.Meshing
189 { 172 {
190 int[] result; 173 int[] result;
191 174
192 if (primMesh == null) 175 result = new int[triangles.Count * 3];
193 { 176 for (int i = 0; i < triangles.Count; i++)
194 result = new int[triangles.Count * 3];
195 for (int i = 0; i < triangles.Count; i++)
196 {
197 Triangle t = triangles[i];
198 result[3 * i + 0] = vertices[t.v1];
199 result[3 * i + 1] = vertices[t.v2];
200 result[3 * i + 2] = vertices[t.v3];
201 }
202 }
203 else
204 { 177 {
205 int numFaces = primMesh.faces.Count; 178 Triangle t = triangles[i];
206 result = new int[numFaces * 3]; 179 result[3 * i + 0] = vertices[t.v1];
207 for (int i = 0; i < numFaces; i++) 180 result[3 * i + 1] = vertices[t.v2];
208 { 181 result[3 * i + 2] = vertices[t.v3];
209 Face f = primMesh.faces[i];
210// Coord c1 = primMesh.coords[f.v1];
211// Coord c2 = primMesh.coords[f.v2];
212// Coord c3 = primMesh.coords[f.v3];
213
214 int resultIndex = i * 3;
215 result[resultIndex] = f.v1;
216 result[resultIndex + 1] = f.v2;
217 result[resultIndex + 2] = f.v3;
218 }
219 } 182 }
220 return result; 183 return result;
221 } 184 }
@@ -226,6 +189,9 @@ namespace OpenSim.Region.Physics.Meshing
226 /// <returns></returns> 189 /// <returns></returns>
227 public int[] getIndexListAsIntLocked() 190 public int[] getIndexListAsIntLocked()
228 { 191 {
192 if (pinnedIndex.IsAllocated)
193 return (int[])(pinnedIndex.Target);
194
229 int[] result = getIndexListAsInt(); 195 int[] result = getIndexListAsInt();
230 pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned); 196 pinnedIndex = GCHandle.Alloc(result, GCHandleType.Pinned);
231 197
@@ -245,11 +211,13 @@ namespace OpenSim.Region.Physics.Meshing
245 { 211 {
246 triangles = null; 212 triangles = null;
247 vertices = null; 213 vertices = null;
248 primMesh = null;
249 } 214 }
250 215
251 public void Append(IMesh newMesh) 216 public void Append(IMesh newMesh)
252 { 217 {
218 if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated)
219 throw new NotSupportedException("Attempt to Append to a pinned Mesh");
220
253 if (!(newMesh is Mesh)) 221 if (!(newMesh is Mesh))
254 return; 222 return;
255 223
@@ -260,6 +228,9 @@ namespace OpenSim.Region.Physics.Meshing
260 // Do a linear transformation of mesh. 228 // Do a linear transformation of mesh.
261 public void TransformLinear(float[,] matrix, float[] offset) 229 public void TransformLinear(float[,] matrix, float[] offset)
262 { 230 {
231 if (pinnedIndex.IsAllocated || pinnedVirtexes.IsAllocated)
232 throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
233
263 foreach (Vertex v in vertices.Keys) 234 foreach (Vertex v in vertices.Keys)
264 { 235 {
265 if (v == null) 236 if (v == null)
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index aa8df23..d56ddc8 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -76,6 +76,7 @@ namespace OpenSim.Region.Physics.Meshing
76 76
77 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh 77 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
78 78
79 private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
79 80
80 public Meshmerizer() 81 public Meshmerizer()
81 { 82 {
@@ -184,9 +185,62 @@ namespace OpenSim.Region.Physics.Meshing
184 185
185 } 186 }
186 187
187 public Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod) 188 private ulong GetMeshKey(PrimitiveBaseShape pbs, PhysicsVector size, float lod)
189 {
190 ulong hash = 5381;
191
192 hash = djb2(hash, pbs.PathCurve);
193 hash = djb2(hash, (byte)((byte)pbs.HollowShape | (byte)pbs.ProfileShape));
194 hash = djb2(hash, pbs.PathBegin);
195 hash = djb2(hash, pbs.PathEnd);
196 hash = djb2(hash, pbs.PathScaleX);
197 hash = djb2(hash, pbs.PathScaleY);
198 hash = djb2(hash, pbs.PathShearX);
199 hash = djb2(hash, pbs.PathShearY);
200 hash = djb2(hash, (byte)pbs.PathTwist);
201 hash = djb2(hash, (byte)pbs.PathTwistBegin);
202 hash = djb2(hash, (byte)pbs.PathRadiusOffset);
203 hash = djb2(hash, (byte)pbs.PathTaperX);
204 hash = djb2(hash, (byte)pbs.PathTaperY);
205 hash = djb2(hash, pbs.PathRevolutions);
206 hash = djb2(hash, (byte)pbs.PathSkew);
207 hash = djb2(hash, pbs.ProfileBegin);
208 hash = djb2(hash, pbs.ProfileEnd);
209 hash = djb2(hash, pbs.ProfileHollow);
210
211 // TODO: Separate scale out from the primitive shape data (after
212 // scaling is supported at the physics engine level)
213 byte[] scaleBytes = size.GetBytes();
214 for (int i = 0; i < scaleBytes.Length; i++)
215 hash = djb2(hash, scaleBytes[i]);
216
217 // Include LOD in hash, accounting for endianness
218 byte[] lodBytes = new byte[4];
219 Buffer.BlockCopy(BitConverter.GetBytes(lod), 0, lodBytes, 0, 4);
220 if (!BitConverter.IsLittleEndian)
221 {
222 Array.Reverse(lodBytes, 0, 4);
223 }
224 for (int i = 0; i < lodBytes.Length; i++)
225 hash = djb2(hash, lodBytes[i]);
226
227 return hash;
228 }
229
230 private ulong djb2(ulong hash, byte c)
231 {
232 return ((hash << 5) + hash) + (ulong)c;
233 }
234
235 private ulong djb2(ulong hash, ushort c)
236 {
237 hash = ((hash << 5) + hash) + (ulong)((byte)c);
238 return ((hash << 5) + hash) + (ulong)(c >> 8);
239 }
240
241
242 private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod)
188 { 243 {
189 Mesh mesh = new Mesh();
190 PrimMesh primMesh; 244 PrimMesh primMesh;
191 PrimMesher.SculptMesh sculptMesh; 245 PrimMesher.SculptMesh sculptMesh;
192 246
@@ -399,8 +453,6 @@ namespace OpenSim.Region.Physics.Meshing
399 453
400 coords = primMesh.coords; 454 coords = primMesh.coords;
401 faces = primMesh.faces; 455 faces = primMesh.faces;
402
403
404 } 456 }
405 457
406 458
@@ -415,13 +467,13 @@ namespace OpenSim.Region.Physics.Meshing
415 vertices.Add(new Vertex(c.X, c.Y, c.Z)); 467 vertices.Add(new Vertex(c.X, c.Y, c.Z));
416 } 468 }
417 469
470 Mesh mesh = new Mesh();
418 // Add the corresponding triangles to the mesh 471 // Add the corresponding triangles to the mesh
419 for (int i = 0; i < numFaces; i++) 472 for (int i = 0; i < numFaces; i++)
420 { 473 {
421 Face f = faces[i]; 474 Face f = faces[i];
422 mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3])); 475 mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3]));
423 } 476 }
424
425 return mesh; 477 return mesh;
426 } 478 }
427 479
@@ -432,7 +484,12 @@ namespace OpenSim.Region.Physics.Meshing
432 484
433 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod, bool isPhysical) 485 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod, bool isPhysical)
434 { 486 {
487 // If this mesh has been created already, return it instead of creating another copy
488 // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory
489 ulong key = GetMeshKey(primShape, size, lod);
435 Mesh mesh = null; 490 Mesh mesh = null;
491 if (m_uniqueMeshes.TryGetValue(key, out mesh))
492 return mesh;
436 493
437 if (size.X < 0.01f) size.X = 0.01f; 494 if (size.X < 0.01f) size.X = 0.01f;
438 if (size.Y < 0.01f) size.Y = 0.01f; 495 if (size.Y < 0.01f) size.Y = 0.01f;
@@ -455,7 +512,7 @@ namespace OpenSim.Region.Physics.Meshing
455 // trim the vertex and triangle lists to free up memory 512 // trim the vertex and triangle lists to free up memory
456 mesh.TrimExcess(); 513 mesh.TrimExcess();
457 } 514 }
458 515 m_uniqueMeshes.Add(key, mesh);
459 return mesh; 516 return mesh;
460 } 517 }
461 } 518 }
diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
index 0d19c01..abfd400 100644
--- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs
+++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs
@@ -345,6 +345,21 @@ namespace PrimMesher
345 this.v3.Z *= z; 345 this.v3.Z *= z;
346 } 346 }
347 347
348 public void AddPos(float x, float y, float z)
349 {
350 this.v1.X += x;
351 this.v2.X += x;
352 this.v3.X += x;
353
354 this.v1.Y += y;
355 this.v2.Y += y;
356 this.v3.Y += y;
357
358 this.v1.Z += z;
359 this.v2.Z += z;
360 this.v3.Z += z;
361 }
362
348 public void AddRot(Quat q) 363 public void AddRot(Quat q)
349 { 364 {
350 this.v1 *= q; 365 this.v1 *= q;
@@ -2141,6 +2156,18 @@ namespace PrimMesher
2141 vert.Z += z; 2156 vert.Z += z;
2142 this.coords[i] = vert; 2157 this.coords[i] = vert;
2143 } 2158 }
2159
2160 if (this.viewerFaces != null)
2161 {
2162 int numViewerFaces = this.viewerFaces.Count;
2163
2164 for (i = 0; i < numViewerFaces; i++)
2165 {
2166 ViewerFace v = this.viewerFaces[i];
2167 v.AddPos(x, y, z);
2168 this.viewerFaces[i] = v;
2169 }
2170 }
2144 } 2171 }
2145 2172
2146 /// <summary> 2173 /// <summary>
diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
index bf42fee..bd63aef 100644
--- a/OpenSim/Region/Physics/Meshing/SculptMesh.cs
+++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs
@@ -494,6 +494,18 @@ namespace PrimMesher
494 vert.Z += z; 494 vert.Z += z;
495 this.coords[i] = vert; 495 this.coords[i] = vert;
496 } 496 }
497
498 if (this.viewerFaces != null)
499 {
500 int numViewerFaces = this.viewerFaces.Count;
501
502 for (i = 0; i < numViewerFaces; i++)
503 {
504 ViewerFace v = this.viewerFaces[i];
505 v.AddPos(x, y, z);
506 this.viewerFaces[i] = v;
507 }
508 }
497 } 509 }
498 510
499 /// <summary> 511 /// <summary>
@@ -556,7 +568,7 @@ namespace PrimMesher
556 if (path == null) 568 if (path == null)
557 return; 569 return;
558 String fileName = name + "_" + title + ".raw"; 570 String fileName = name + "_" + title + ".raw";
559 String completePath = Path.Combine(path, fileName); 571 String completePath = System.IO.Path.Combine(path, fileName);
560 StreamWriter sw = new StreamWriter(completePath); 572 StreamWriter sw = new StreamWriter(completePath);
561 573
562 for (int i = 0; i < this.faces.Count; i++) 574 for (int i = 0; i < this.faces.Count; i++)