diff options
Diffstat (limited to 'OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs')
-rw-r--r-- | OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs | 183 |
1 files changed, 172 insertions, 11 deletions
diff --git a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs index f002bba..4c40175 100644 --- a/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs | |||
@@ -82,7 +82,10 @@ namespace OpenSim.Region.Physics.Meshing | |||
82 | 82 | ||
83 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh | 83 | private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh |
84 | 84 | ||
85 | private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); | 85 | // private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); |
86 | // private Dictionary<ulong, Mesh> m_uniqueReleasedMeshes = new Dictionary<ulong, Mesh>(); | ||
87 | private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>(); | ||
88 | private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>(); | ||
86 | 89 | ||
87 | public Meshmerizer(IConfigSource config) | 90 | public Meshmerizer(IConfigSource config) |
88 | { | 91 | { |
@@ -314,6 +317,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
314 | coords[f.v3].X, coords[f.v3].Y, coords[f.v3].Z)); | 317 | coords[f.v3].X, coords[f.v3].Y, coords[f.v3].Z)); |
315 | } | 318 | } |
316 | 319 | ||
320 | coords.Clear(); | ||
321 | faces.Clear(); | ||
322 | |||
317 | return mesh; | 323 | return mesh; |
318 | } | 324 | } |
319 | 325 | ||
@@ -780,7 +786,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
780 | } | 786 | } |
781 | 787 | ||
782 | PrimMesher.SculptMesh.SculptType sculptType; | 788 | PrimMesher.SculptMesh.SculptType sculptType; |
783 | switch ((OpenMetaverse.SculptType)primShape.SculptType) | 789 | // remove mirror and invert bits |
790 | OpenMetaverse.SculptType pbsSculptType = ((OpenMetaverse.SculptType)(primShape.SculptType & 0x3f)); | ||
791 | switch (pbsSculptType) | ||
784 | { | 792 | { |
785 | case OpenMetaverse.SculptType.Cylinder: | 793 | case OpenMetaverse.SculptType.Cylinder: |
786 | sculptType = PrimMesher.SculptMesh.SculptType.cylinder; | 794 | sculptType = PrimMesher.SculptMesh.SculptType.cylinder; |
@@ -802,7 +810,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
802 | bool mirror = ((primShape.SculptType & 128) != 0); | 810 | bool mirror = ((primShape.SculptType & 128) != 0); |
803 | bool invert = ((primShape.SculptType & 64) != 0); | 811 | bool invert = ((primShape.SculptType & 64) != 0); |
804 | 812 | ||
805 | sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); | 813 | sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, mirror, invert); |
806 | 814 | ||
807 | idata.Dispose(); | 815 | idata.Dispose(); |
808 | 816 | ||
@@ -971,6 +979,76 @@ namespace OpenSim.Region.Physics.Meshing | |||
971 | return true; | 979 | return true; |
972 | } | 980 | } |
973 | 981 | ||
982 | public AMeshKey GetMeshUniqueKey(PrimitiveBaseShape primShape, Vector3 size, byte lod, bool convex) | ||
983 | { | ||
984 | AMeshKey key = new AMeshKey(); | ||
985 | Byte[] someBytes; | ||
986 | |||
987 | key.hashB = 5181; | ||
988 | ulong hash = 5381; | ||
989 | |||
990 | if (primShape.SculptEntry) | ||
991 | { | ||
992 | key.uuid = primShape.SculptTexture; | ||
993 | key.hashB = mdjb2(key.hashB, primShape.SculptType); | ||
994 | } | ||
995 | else | ||
996 | { | ||
997 | hash = mdjb2(hash, primShape.PathCurve); | ||
998 | hash = mdjb2(hash, (byte)primShape.HollowShape); | ||
999 | hash = mdjb2(hash, (byte)primShape.ProfileShape); | ||
1000 | hash = mdjb2(hash, primShape.PathBegin); | ||
1001 | hash = mdjb2(hash, primShape.PathEnd); | ||
1002 | hash = mdjb2(hash, primShape.PathScaleX); | ||
1003 | hash = mdjb2(hash, primShape.PathScaleY); | ||
1004 | hash = mdjb2(hash, primShape.PathShearX); | ||
1005 | hash = mdjb2(hash, primShape.PathShearY); | ||
1006 | hash = mdjb2(hash, (byte)primShape.PathTwist); | ||
1007 | hash = mdjb2(hash, (byte)primShape.PathTwistBegin); | ||
1008 | hash = mdjb2(hash, (byte)primShape.PathRadiusOffset); | ||
1009 | hash = mdjb2(hash, (byte)primShape.PathTaperX); | ||
1010 | hash = mdjb2(hash, (byte)primShape.PathTaperY); | ||
1011 | hash = mdjb2(hash, primShape.PathRevolutions); | ||
1012 | hash = mdjb2(hash, (byte)primShape.PathSkew); | ||
1013 | hash = mdjb2(hash, primShape.ProfileBegin); | ||
1014 | hash = mdjb2(hash, primShape.ProfileEnd); | ||
1015 | hash = mdjb2(hash, primShape.ProfileHollow); | ||
1016 | key.hashA = hash; | ||
1017 | } | ||
1018 | |||
1019 | hash = key.hashB; | ||
1020 | |||
1021 | someBytes = size.GetBytes(); | ||
1022 | for (int i = 0; i < someBytes.Length; i++) | ||
1023 | hash = mdjb2(hash, someBytes[i]); | ||
1024 | |||
1025 | hash = mdjb2(hash, lod); | ||
1026 | |||
1027 | hash &= 0x3fffffffffffffff; | ||
1028 | |||
1029 | if (convex) | ||
1030 | hash |= 0x4000000000000000; | ||
1031 | |||
1032 | if (primShape.SculptEntry) | ||
1033 | hash |= 0x8000000000000000; | ||
1034 | |||
1035 | key.hashB = hash; | ||
1036 | |||
1037 | return key; | ||
1038 | } | ||
1039 | |||
1040 | private ulong mdjb2(ulong hash, byte c) | ||
1041 | { | ||
1042 | return ((hash << 5) + hash) + (ulong)c; | ||
1043 | } | ||
1044 | |||
1045 | private ulong mdjb2(ulong hash, ushort c) | ||
1046 | { | ||
1047 | hash = ((hash << 5) + hash) + (ulong)((byte)c); | ||
1048 | return ((hash << 5) + hash) + (ulong)(c >> 8); | ||
1049 | } | ||
1050 | |||
1051 | |||
974 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) | 1052 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) |
975 | { | 1053 | { |
976 | return CreateMesh(primName, primShape, size, lod, false,false); | 1054 | return CreateMesh(primName, primShape, size, lod, false,false); |
@@ -981,6 +1059,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
981 | return CreateMesh(primName, primShape, size, lod, false,false); | 1059 | return CreateMesh(primName, primShape, size, lod, false,false); |
982 | } | 1060 | } |
983 | 1061 | ||
1062 | private static Vector3 m_MeshUnitSize = new Vector3(0.5f, 0.5f, 0.5f); | ||
1063 | |||
984 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) | 1064 | public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex) |
985 | { | 1065 | { |
986 | #if SPAM | 1066 | #if SPAM |
@@ -988,18 +1068,42 @@ namespace OpenSim.Region.Physics.Meshing | |||
988 | #endif | 1068 | #endif |
989 | 1069 | ||
990 | Mesh mesh = null; | 1070 | Mesh mesh = null; |
991 | ulong key = 0; | 1071 | // ulong key = 0; |
992 | 1072 | ||
993 | // If this mesh has been created already, return it instead of creating another copy | ||
994 | // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory | ||
995 | key = primShape.GetMeshKey(size, lod, convex); | ||
996 | if (m_uniqueMeshes.TryGetValue(key, out mesh)) | ||
997 | return mesh; | ||
998 | 1073 | ||
999 | if (size.X < 0.01f) size.X = 0.01f; | 1074 | if (size.X < 0.01f) size.X = 0.01f; |
1000 | if (size.Y < 0.01f) size.Y = 0.01f; | 1075 | if (size.Y < 0.01f) size.Y = 0.01f; |
1001 | if (size.Z < 0.01f) size.Z = 0.01f; | 1076 | if (size.Z < 0.01f) size.Z = 0.01f; |
1002 | 1077 | ||
1078 | // try to find a identical mesh on meshs in use | ||
1079 | // key = primShape.GetMeshKey(size, lod, convex); | ||
1080 | AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex); | ||
1081 | |||
1082 | lock (m_uniqueMeshes) | ||
1083 | { | ||
1084 | m_uniqueMeshes.TryGetValue(key, out mesh); | ||
1085 | |||
1086 | if (mesh != null) | ||
1087 | { | ||
1088 | mesh.RefCount++; | ||
1089 | return mesh; | ||
1090 | } | ||
1091 | } | ||
1092 | |||
1093 | // try to find a identical mesh on meshs recently released | ||
1094 | lock (m_uniqueReleasedMeshes) | ||
1095 | { | ||
1096 | m_uniqueReleasedMeshes.TryGetValue(key, out mesh); | ||
1097 | if (mesh != null) | ||
1098 | { | ||
1099 | m_uniqueReleasedMeshes.Remove(key); | ||
1100 | lock (m_uniqueMeshes) | ||
1101 | m_uniqueMeshes.Add(key, mesh); | ||
1102 | mesh.RefCount = 1; | ||
1103 | return mesh; | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1003 | mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex); | 1107 | mesh = CreateMeshFromPrimMesher(primName, primShape, size, lod,convex); |
1004 | 1108 | ||
1005 | if (mesh != null) | 1109 | if (mesh != null) |
@@ -1016,11 +1120,68 @@ namespace OpenSim.Region.Physics.Meshing | |||
1016 | 1120 | ||
1017 | // trim the vertex and triangle lists to free up memory | 1121 | // trim the vertex and triangle lists to free up memory |
1018 | mesh.TrimExcess(); | 1122 | mesh.TrimExcess(); |
1123 | mesh.Key = key; | ||
1124 | mesh.RefCount = 1; | ||
1019 | 1125 | ||
1020 | m_uniqueMeshes.Add(key, mesh); | 1126 | lock(m_uniqueMeshes) |
1127 | m_uniqueMeshes.Add(key, mesh); | ||
1021 | } | 1128 | } |
1022 | 1129 | ||
1023 | return mesh; | 1130 | return mesh; |
1024 | } | 1131 | } |
1132 | |||
1133 | public void ReleaseMesh(IMesh imesh) | ||
1134 | { | ||
1135 | if (imesh == null) | ||
1136 | return; | ||
1137 | |||
1138 | Mesh mesh = (Mesh)imesh; | ||
1139 | |||
1140 | int curRefCount = mesh.RefCount; | ||
1141 | curRefCount--; | ||
1142 | |||
1143 | if (curRefCount > 0) | ||
1144 | { | ||
1145 | mesh.RefCount = curRefCount; | ||
1146 | return; | ||
1147 | } | ||
1148 | |||
1149 | lock (m_uniqueMeshes) | ||
1150 | { | ||
1151 | mesh.RefCount = 0; | ||
1152 | m_uniqueMeshes.Remove(mesh.Key); | ||
1153 | lock (m_uniqueReleasedMeshes) | ||
1154 | m_uniqueReleasedMeshes.Add(mesh.Key, mesh); | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | public void ExpireReleaseMeshs() | ||
1159 | { | ||
1160 | if (m_uniqueReleasedMeshes.Count == 0) | ||
1161 | return; | ||
1162 | |||
1163 | List<Mesh> meshstodelete = new List<Mesh>(); | ||
1164 | int refcntr; | ||
1165 | |||
1166 | lock (m_uniqueReleasedMeshes) | ||
1167 | { | ||
1168 | foreach (Mesh m in m_uniqueReleasedMeshes.Values) | ||
1169 | { | ||
1170 | refcntr = m.RefCount; | ||
1171 | refcntr--; | ||
1172 | if (refcntr > -6) | ||
1173 | m.RefCount = refcntr; | ||
1174 | else | ||
1175 | meshstodelete.Add(m); | ||
1176 | } | ||
1177 | |||
1178 | foreach (Mesh m in meshstodelete) | ||
1179 | { | ||
1180 | m_uniqueReleasedMeshes.Remove(m.Key); | ||
1181 | m.releaseSourceMeshData(); | ||
1182 | m.releasePinned(); | ||
1183 | } | ||
1184 | } | ||
1185 | } | ||
1025 | } | 1186 | } |
1026 | } | 1187 | } |