aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/Meshing
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/Meshing')
-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 f469ad6..56eb359 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 /// <summary> 81 /// <summary>
81 /// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may 82 /// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may
@@ -170,9 +171,62 @@ namespace OpenSim.Region.Physics.Meshing
170 171
171 } 172 }
172 173
173 public Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod) 174 private ulong GetMeshKey(PrimitiveBaseShape pbs, PhysicsVector size, float lod)
175 {
176 ulong hash = 5381;
177
178 hash = djb2(hash, pbs.PathCurve);
179 hash = djb2(hash, (byte)((byte)pbs.HollowShape | (byte)pbs.ProfileShape));
180 hash = djb2(hash, pbs.PathBegin);
181 hash = djb2(hash, pbs.PathEnd);
182 hash = djb2(hash, pbs.PathScaleX);
183 hash = djb2(hash, pbs.PathScaleY);
184 hash = djb2(hash, pbs.PathShearX);
185 hash = djb2(hash, pbs.PathShearY);
186 hash = djb2(hash, (byte)pbs.PathTwist);
187 hash = djb2(hash, (byte)pbs.PathTwistBegin);
188 hash = djb2(hash, (byte)pbs.PathRadiusOffset);
189 hash = djb2(hash, (byte)pbs.PathTaperX);
190 hash = djb2(hash, (byte)pbs.PathTaperY);
191 hash = djb2(hash, pbs.PathRevolutions);
192 hash = djb2(hash, (byte)pbs.PathSkew);
193 hash = djb2(hash, pbs.ProfileBegin);
194 hash = djb2(hash, pbs.ProfileEnd);
195 hash = djb2(hash, pbs.ProfileHollow);
196
197 // TODO: Separate scale out from the primitive shape data (after
198 // scaling is supported at the physics engine level)
199 byte[] scaleBytes = size.GetBytes();
200 for (int i = 0; i < scaleBytes.Length; i++)
201 hash = djb2(hash, scaleBytes[i]);
202
203 // Include LOD in hash, accounting for endianness
204 byte[] lodBytes = new byte[4];
205 Buffer.BlockCopy(BitConverter.GetBytes(lod), 0, lodBytes, 0, 4);
206 if (!BitConverter.IsLittleEndian)
207 {
208 Array.Reverse(lodBytes, 0, 4);
209 }
210 for (int i = 0; i < lodBytes.Length; i++)
211 hash = djb2(hash, lodBytes[i]);
212
213 return hash;
214 }
215
216 private ulong djb2(ulong hash, byte c)
217 {
218 return ((hash << 5) + hash) + (ulong)c;
219 }
220
221 private ulong djb2(ulong hash, ushort c)
222 {
223 hash = ((hash << 5) + hash) + (ulong)((byte)c);
224 return ((hash << 5) + hash) + (ulong)(c >> 8);
225 }
226
227
228 private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod)
174 { 229 {
175 Mesh mesh = new Mesh();
176 PrimMesh primMesh; 230 PrimMesh primMesh;
177 PrimMesher.SculptMesh sculptMesh; 231 PrimMesher.SculptMesh sculptMesh;
178 232
@@ -385,8 +439,6 @@ namespace OpenSim.Region.Physics.Meshing
385 439
386 coords = primMesh.coords; 440 coords = primMesh.coords;
387 faces = primMesh.faces; 441 faces = primMesh.faces;
388
389
390 } 442 }
391 443
392 444
@@ -401,13 +453,13 @@ namespace OpenSim.Region.Physics.Meshing
401 vertices.Add(new Vertex(c.X, c.Y, c.Z)); 453 vertices.Add(new Vertex(c.X, c.Y, c.Z));
402 } 454 }
403 455
456 Mesh mesh = new Mesh();
404 // Add the corresponding triangles to the mesh 457 // Add the corresponding triangles to the mesh
405 for (int i = 0; i < numFaces; i++) 458 for (int i = 0; i < numFaces; i++)
406 { 459 {
407 Face f = faces[i]; 460 Face f = faces[i];
408 mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3])); 461 mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3]));
409 } 462 }
410
411 return mesh; 463 return mesh;
412 } 464 }
413 465
@@ -418,7 +470,12 @@ namespace OpenSim.Region.Physics.Meshing
418 470
419 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod, bool isPhysical) 471 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, PhysicsVector size, float lod, bool isPhysical)
420 { 472 {
473 // If this mesh has been created already, return it instead of creating another copy
474 // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory
475 ulong key = GetMeshKey(primShape, size, lod);
421 Mesh mesh = null; 476 Mesh mesh = null;
477 if (m_uniqueMeshes.TryGetValue(key, out mesh))
478 return mesh;
422 479
423 if (size.X < 0.01f) size.X = 0.01f; 480 if (size.X < 0.01f) size.X = 0.01f;
424 if (size.Y < 0.01f) size.Y = 0.01f; 481 if (size.Y < 0.01f) size.Y = 0.01f;
@@ -441,7 +498,7 @@ namespace OpenSim.Region.Physics.Meshing
441 // trim the vertex and triangle lists to free up memory 498 // trim the vertex and triangle lists to free up memory
442 mesh.TrimExcess(); 499 mesh.TrimExcess();
443 } 500 }
444 501 m_uniqueMeshes.Add(key, mesh);
445 return mesh; 502 return mesh;
446 } 503 }
447 } 504 }
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++)