diff options
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r-- | OpenSim/Region/Physics/Manager/IMesher.cs | 11 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 99 |
2 files changed, 43 insertions, 67 deletions
diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs index 1181b8d..3a9ca1b 100644 --- a/OpenSim/Region/Physics/Manager/IMesher.cs +++ b/OpenSim/Region/Physics/Manager/IMesher.cs | |||
@@ -38,6 +38,17 @@ namespace OpenSim.Region.Physics.Manager | |||
38 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); | 38 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); |
39 | } | 39 | } |
40 | 40 | ||
41 | // Values for level of detail to be passed to the mesher. | ||
42 | // Values origionally chosen for the LOD of sculpties (the sqrt(width*heigth) of sculpt texture) | ||
43 | // Lower level of detail reduces the number of vertices used to represent the meshed shape. | ||
44 | public enum LevelOfDetail | ||
45 | { | ||
46 | High = 32, | ||
47 | Medium = 16, | ||
48 | Low = 8, | ||
49 | VeryLow = 4 | ||
50 | } | ||
51 | |||
41 | public interface IVertex | 52 | public interface IVertex |
42 | { | 53 | { |
43 | } | 54 | } |
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index e81b982..53d5e4c 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -193,67 +193,6 @@ namespace OpenSim.Region.Physics.Meshing | |||
193 | m_log.Error("****** PrimMesh Parameters ******\n" + primMesh.ParamsToDisplayString()); | 193 | m_log.Error("****** PrimMesh Parameters ******\n" + primMesh.ParamsToDisplayString()); |
194 | } | 194 | } |
195 | 195 | ||
196 | private ulong GetMeshKey(PrimitiveBaseShape pbs, Vector3 size, float lod) | ||
197 | { | ||
198 | ulong hash = 5381; | ||
199 | |||
200 | hash = djb2(hash, pbs.PathCurve); | ||
201 | hash = djb2(hash, (byte)((byte)pbs.HollowShape | (byte)pbs.ProfileShape)); | ||
202 | hash = djb2(hash, pbs.PathBegin); | ||
203 | hash = djb2(hash, pbs.PathEnd); | ||
204 | hash = djb2(hash, pbs.PathScaleX); | ||
205 | hash = djb2(hash, pbs.PathScaleY); | ||
206 | hash = djb2(hash, pbs.PathShearX); | ||
207 | hash = djb2(hash, pbs.PathShearY); | ||
208 | hash = djb2(hash, (byte)pbs.PathTwist); | ||
209 | hash = djb2(hash, (byte)pbs.PathTwistBegin); | ||
210 | hash = djb2(hash, (byte)pbs.PathRadiusOffset); | ||
211 | hash = djb2(hash, (byte)pbs.PathTaperX); | ||
212 | hash = djb2(hash, (byte)pbs.PathTaperY); | ||
213 | hash = djb2(hash, pbs.PathRevolutions); | ||
214 | hash = djb2(hash, (byte)pbs.PathSkew); | ||
215 | hash = djb2(hash, pbs.ProfileBegin); | ||
216 | hash = djb2(hash, pbs.ProfileEnd); | ||
217 | hash = djb2(hash, pbs.ProfileHollow); | ||
218 | |||
219 | // TODO: Separate scale out from the primitive shape data (after | ||
220 | // scaling is supported at the physics engine level) | ||
221 | byte[] scaleBytes = size.GetBytes(); | ||
222 | for (int i = 0; i < scaleBytes.Length; i++) | ||
223 | hash = djb2(hash, scaleBytes[i]); | ||
224 | |||
225 | // Include LOD in hash, accounting for endianness | ||
226 | byte[] lodBytes = new byte[4]; | ||
227 | Buffer.BlockCopy(BitConverter.GetBytes(lod), 0, lodBytes, 0, 4); | ||
228 | if (!BitConverter.IsLittleEndian) | ||
229 | { | ||
230 | Array.Reverse(lodBytes, 0, 4); | ||
231 | } | ||
232 | for (int i = 0; i < lodBytes.Length; i++) | ||
233 | hash = djb2(hash, lodBytes[i]); | ||
234 | |||
235 | // include sculpt UUID | ||
236 | if (pbs.SculptEntry) | ||
237 | { | ||
238 | scaleBytes = pbs.SculptTexture.GetBytes(); | ||
239 | for (int i = 0; i < scaleBytes.Length; i++) | ||
240 | hash = djb2(hash, scaleBytes[i]); | ||
241 | } | ||
242 | |||
243 | return hash; | ||
244 | } | ||
245 | |||
246 | private ulong djb2(ulong hash, byte c) | ||
247 | { | ||
248 | return ((hash << 5) + hash) + (ulong)c; | ||
249 | } | ||
250 | |||
251 | private ulong djb2(ulong hash, ushort c) | ||
252 | { | ||
253 | hash = ((hash << 5) + hash) + (ulong)((byte)c); | ||
254 | return ((hash << 5) + hash) + (ulong)(c >> 8); | ||
255 | } | ||
256 | |||
257 | /// <summary> | 196 | /// <summary> |
258 | /// Add a submesh to an existing list of coords and faces. | 197 | /// Add a submesh to an existing list of coords and faces. |
259 | /// </summary> | 198 | /// </summary> |
@@ -336,7 +275,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
336 | } | 275 | } |
337 | else | 276 | else |
338 | { | 277 | { |
339 | if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, out coords, out faces)) | 278 | if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, lod, out coords, out faces)) |
340 | return null; | 279 | return null; |
341 | } | 280 | } |
342 | 281 | ||
@@ -616,7 +555,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
616 | /// <param name="faces">Faces are added to this list by the method.</param> | 555 | /// <param name="faces">Faces are added to this list by the method.</param> |
617 | /// <returns>true if coords and faces were successfully generated, false if not</returns> | 556 | /// <returns>true if coords and faces were successfully generated, false if not</returns> |
618 | private bool GenerateCoordsAndFacesFromPrimShapeData( | 557 | private bool GenerateCoordsAndFacesFromPrimShapeData( |
619 | string primName, PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces) | 558 | string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces) |
620 | { | 559 | { |
621 | PrimMesh primMesh; | 560 | PrimMesh primMesh; |
622 | coords = new List<Coord>(); | 561 | coords = new List<Coord>(); |
@@ -636,13 +575,30 @@ namespace OpenSim.Region.Physics.Meshing | |||
636 | profileHollow = 0.95f; | 575 | profileHollow = 0.95f; |
637 | 576 | ||
638 | int sides = 4; | 577 | int sides = 4; |
578 | LevelOfDetail iLOD = (LevelOfDetail)lod; | ||
639 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | 579 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) |
640 | sides = 3; | 580 | sides = 3; |
641 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | 581 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) |
642 | sides = 24; | 582 | { |
583 | switch (iLOD) | ||
584 | { | ||
585 | case LevelOfDetail.High: sides = 24; break; | ||
586 | case LevelOfDetail.Medium: sides = 12; break; | ||
587 | case LevelOfDetail.Low: sides = 6; break; | ||
588 | case LevelOfDetail.VeryLow: sides = 3; break; | ||
589 | default: sides = 24; break; | ||
590 | } | ||
591 | } | ||
643 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | 592 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) |
644 | { // half circle, prim is a sphere | 593 | { // half circle, prim is a sphere |
645 | sides = 24; | 594 | switch (iLOD) |
595 | { | ||
596 | case LevelOfDetail.High: sides = 24; break; | ||
597 | case LevelOfDetail.Medium: sides = 12; break; | ||
598 | case LevelOfDetail.Low: sides = 6; break; | ||
599 | case LevelOfDetail.VeryLow: sides = 3; break; | ||
600 | default: sides = 24; break; | ||
601 | } | ||
646 | 602 | ||
647 | profileBegin = 0.5f * profileBegin + 0.5f; | 603 | profileBegin = 0.5f * profileBegin + 0.5f; |
648 | profileEnd = 0.5f * profileEnd + 0.5f; | 604 | profileEnd = 0.5f * profileEnd + 0.5f; |
@@ -650,7 +606,16 @@ namespace OpenSim.Region.Physics.Meshing | |||
650 | 606 | ||
651 | int hollowSides = sides; | 607 | int hollowSides = sides; |
652 | if (primShape.HollowShape == HollowShape.Circle) | 608 | if (primShape.HollowShape == HollowShape.Circle) |
653 | hollowSides = 24; | 609 | { |
610 | switch (iLOD) | ||
611 | { | ||
612 | case LevelOfDetail.High: hollowSides = 24; break; | ||
613 | case LevelOfDetail.Medium: hollowSides = 12; break; | ||
614 | case LevelOfDetail.Low: hollowSides = 6; break; | ||
615 | case LevelOfDetail.VeryLow: hollowSides = 3; break; | ||
616 | default: hollowSides = 24; break; | ||
617 | } | ||
618 | } | ||
654 | else if (primShape.HollowShape == HollowShape.Square) | 619 | else if (primShape.HollowShape == HollowShape.Square) |
655 | hollowSides = 4; | 620 | hollowSides = 4; |
656 | else if (primShape.HollowShape == HollowShape.Triangle) | 621 | else if (primShape.HollowShape == HollowShape.Triangle) |
@@ -751,7 +716,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
751 | 716 | ||
752 | // If this mesh has been created already, return it instead of creating another copy | 717 | // If this mesh has been created already, return it instead of creating another copy |
753 | // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory | 718 | // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory |
754 | key = GetMeshKey(primShape, size, lod); | 719 | key = primShape.GetMeshKey(size, lod); |
755 | if (m_uniqueMeshes.TryGetValue(key, out mesh)) | 720 | if (m_uniqueMeshes.TryGetValue(key, out mesh)) |
756 | return mesh; | 721 | return mesh; |
757 | 722 | ||