diff options
Diffstat (limited to 'OpenSim/Region/Physics/Meshing/Meshmerizer.cs')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 69 |
1 files changed, 63 insertions, 6 deletions
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 | } |