diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Mesh.cs | 87 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 69 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Meshing/PrimMesher.cs | 27 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Meshing/SculptMesh.cs | 14 |
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++) |