diff options
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs | 4 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Manager/IMesher.cs | 14 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Manager/ZeroMesher.cs | 2 | ||||
-rw-r--r-- | OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 2 | ||||
-rw-r--r-- | OpenSim/Region/Physics/UbitMeshing/Mesh.cs | 57 | ||||
-rw-r--r-- | OpenSim/Region/Physics/UbitMeshing/Meshmerizer.cs | 183 | ||||
-rw-r--r-- | OpenSim/Region/Physics/UbitMeshing/SculptMap.cs | 95 | ||||
-rw-r--r-- | OpenSim/Region/Physics/UbitMeshing/SculptMesh.cs | 440 | ||||
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs | 53 | ||||
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs | 19 |
10 files changed, 345 insertions, 524 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index d039111..ae4d52a 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs | |||
@@ -596,9 +596,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
596 | } | 596 | } |
597 | break; | 597 | break; |
598 | case "R": | 598 | case "R": |
599 | Font newFont = new Font(myFont, FontStyle.Regular); | 599 | Font anewFont = new Font(myFont, FontStyle.Regular); |
600 | myFont.Dispose(); | 600 | myFont.Dispose(); |
601 | myFont = newFont; | 601 | myFont = anewFont; |
602 | break; | 602 | break; |
603 | } | 603 | } |
604 | } | 604 | } |
diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs index c32cf38..a8c99f7 100644 --- a/OpenSim/Region/Physics/Manager/IMesher.cs +++ b/OpenSim/Region/Physics/Manager/IMesher.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Runtime.InteropServices; | ||
30 | using OpenSim.Framework; | 31 | using OpenSim.Framework; |
31 | using OpenMetaverse; | 32 | using OpenMetaverse; |
32 | 33 | ||
@@ -37,6 +38,8 @@ namespace OpenSim.Region.Physics.Manager | |||
37 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); | 38 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); |
38 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); | 39 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); |
39 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical,bool convex); | 40 | IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical,bool convex); |
41 | void ReleaseMesh(IMesh mesh); | ||
42 | void ExpireReleaseMeshs(); | ||
40 | } | 43 | } |
41 | 44 | ||
42 | // Values for level of detail to be passed to the mesher. | 45 | // Values for level of detail to be passed to the mesher. |
@@ -54,6 +57,17 @@ namespace OpenSim.Region.Physics.Manager | |||
54 | { | 57 | { |
55 | } | 58 | } |
56 | 59 | ||
60 | [StructLayout(LayoutKind.Explicit)] | ||
61 | public struct AMeshKey | ||
62 | { | ||
63 | [FieldOffset(0)] | ||
64 | public UUID uuid; | ||
65 | [FieldOffset(0)] | ||
66 | public ulong hashA; | ||
67 | [FieldOffset(8)] | ||
68 | public ulong hashB; | ||
69 | } | ||
70 | |||
57 | public interface IMesh | 71 | public interface IMesh |
58 | { | 72 | { |
59 | List<Vector3> getVertexList(); | 73 | List<Vector3> getVertexList(); |
diff --git a/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/OpenSim/Region/Physics/Manager/ZeroMesher.cs index 8a3b50b..f555cb9 100644 --- a/OpenSim/Region/Physics/Manager/ZeroMesher.cs +++ b/OpenSim/Region/Physics/Manager/ZeroMesher.cs | |||
@@ -79,5 +79,7 @@ namespace OpenSim.Region.Physics.Manager | |||
79 | 79 | ||
80 | return null; | 80 | return null; |
81 | } | 81 | } |
82 | public void ReleaseMesh(IMesh mesh) { } | ||
83 | public void ExpireReleaseMeshs() { } | ||
82 | } | 84 | } |
83 | } | 85 | } |
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 825b858..3c4f737 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs | |||
@@ -763,5 +763,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
763 | 763 | ||
764 | return mesh; | 764 | return mesh; |
765 | } | 765 | } |
766 | public void ReleaseMesh(IMesh imesh) { } | ||
767 | public void ExpireReleaseMeshs() { } | ||
766 | } | 768 | } |
767 | } | 769 | } |
diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs index c715642..98c0f0b 100644 --- a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs +++ b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs | |||
@@ -37,6 +37,7 @@ namespace OpenSim.Region.Physics.Meshing | |||
37 | { | 37 | { |
38 | public class Mesh : IMesh | 38 | public class Mesh : IMesh |
39 | { | 39 | { |
40 | |||
40 | private Dictionary<Vertex, int> m_vertices; | 41 | private Dictionary<Vertex, int> m_vertices; |
41 | private List<Triangle> m_triangles; | 42 | private List<Triangle> m_triangles; |
42 | GCHandle m_pinnedVertexes; | 43 | GCHandle m_pinnedVertexes; |
@@ -46,8 +47,9 @@ namespace OpenSim.Region.Physics.Meshing | |||
46 | IntPtr m_indicesPtr = IntPtr.Zero; | 47 | IntPtr m_indicesPtr = IntPtr.Zero; |
47 | int m_indexCount = 0; | 48 | int m_indexCount = 0; |
48 | public float[] m_normals; | 49 | public float[] m_normals; |
49 | Vector3 _centroid; | 50 | Vector3 m_centroid; |
50 | int _centroidDiv; | 51 | int m_centroidDiv; |
52 | |||
51 | 53 | ||
52 | private class vertexcomp : IEqualityComparer<Vertex> | 54 | private class vertexcomp : IEqualityComparer<Vertex> |
53 | { | 55 | { |
@@ -65,7 +67,6 @@ namespace OpenSim.Region.Physics.Meshing | |||
65 | int c = v.Z.GetHashCode(); | 67 | int c = v.Z.GetHashCode(); |
66 | return (a << 16) ^ (b << 8) ^ c; | 68 | return (a << 16) ^ (b << 8) ^ c; |
67 | } | 69 | } |
68 | |||
69 | } | 70 | } |
70 | 71 | ||
71 | public Mesh() | 72 | public Mesh() |
@@ -74,8 +75,18 @@ namespace OpenSim.Region.Physics.Meshing | |||
74 | 75 | ||
75 | m_vertices = new Dictionary<Vertex, int>(vcomp); | 76 | m_vertices = new Dictionary<Vertex, int>(vcomp); |
76 | m_triangles = new List<Triangle>(); | 77 | m_triangles = new List<Triangle>(); |
77 | _centroid = Vector3.Zero; | 78 | m_centroid = Vector3.Zero; |
78 | _centroidDiv = 0; | 79 | m_centroidDiv = 0; |
80 | } | ||
81 | |||
82 | public int RefCount { get; set; } | ||
83 | |||
84 | public AMeshKey Key { get; set; } | ||
85 | |||
86 | public void Scale(Vector3 scale) | ||
87 | { | ||
88 | |||
89 | |||
79 | } | 90 | } |
80 | 91 | ||
81 | public Mesh Clone() | 92 | public Mesh Clone() |
@@ -86,8 +97,8 @@ namespace OpenSim.Region.Physics.Meshing | |||
86 | { | 97 | { |
87 | result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); | 98 | result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); |
88 | } | 99 | } |
89 | result._centroid = _centroid; | 100 | result.m_centroid = m_centroid; |
90 | result._centroidDiv = _centroidDiv; | 101 | result.m_centroidDiv = m_centroidDiv; |
91 | return result; | 102 | return result; |
92 | } | 103 | } |
93 | 104 | ||
@@ -109,41 +120,41 @@ namespace OpenSim.Region.Physics.Meshing | |||
109 | 120 | ||
110 | if (m_vertices.Count == 0) | 121 | if (m_vertices.Count == 0) |
111 | { | 122 | { |
112 | _centroidDiv = 0; | 123 | m_centroidDiv = 0; |
113 | _centroid = Vector3.Zero; | 124 | m_centroid = Vector3.Zero; |
114 | } | 125 | } |
115 | 126 | ||
116 | if (!m_vertices.ContainsKey(triangle.v1)) | 127 | if (!m_vertices.ContainsKey(triangle.v1)) |
117 | { | 128 | { |
118 | m_vertices[triangle.v1] = m_vertices.Count; | 129 | m_vertices[triangle.v1] = m_vertices.Count; |
119 | _centroid.X += triangle.v1.X; | 130 | m_centroid.X += triangle.v1.X; |
120 | _centroid.Y += triangle.v1.Y; | 131 | m_centroid.Y += triangle.v1.Y; |
121 | _centroid.Z += triangle.v1.Z; | 132 | m_centroid.Z += triangle.v1.Z; |
122 | _centroidDiv++; | 133 | m_centroidDiv++; |
123 | } | 134 | } |
124 | if (!m_vertices.ContainsKey(triangle.v2)) | 135 | if (!m_vertices.ContainsKey(triangle.v2)) |
125 | { | 136 | { |
126 | m_vertices[triangle.v2] = m_vertices.Count; | 137 | m_vertices[triangle.v2] = m_vertices.Count; |
127 | _centroid.X += triangle.v2.X; | 138 | m_centroid.X += triangle.v2.X; |
128 | _centroid.Y += triangle.v2.Y; | 139 | m_centroid.Y += triangle.v2.Y; |
129 | _centroid.Z += triangle.v2.Z; | 140 | m_centroid.Z += triangle.v2.Z; |
130 | _centroidDiv++; | 141 | m_centroidDiv++; |
131 | } | 142 | } |
132 | if (!m_vertices.ContainsKey(triangle.v3)) | 143 | if (!m_vertices.ContainsKey(triangle.v3)) |
133 | { | 144 | { |
134 | m_vertices[triangle.v3] = m_vertices.Count; | 145 | m_vertices[triangle.v3] = m_vertices.Count; |
135 | _centroid.X += triangle.v3.X; | 146 | m_centroid.X += triangle.v3.X; |
136 | _centroid.Y += triangle.v3.Y; | 147 | m_centroid.Y += triangle.v3.Y; |
137 | _centroid.Z += triangle.v3.Z; | 148 | m_centroid.Z += triangle.v3.Z; |
138 | _centroidDiv++; | 149 | m_centroidDiv++; |
139 | } | 150 | } |
140 | m_triangles.Add(triangle); | 151 | m_triangles.Add(triangle); |
141 | } | 152 | } |
142 | 153 | ||
143 | public Vector3 GetCentroid() | 154 | public Vector3 GetCentroid() |
144 | { | 155 | { |
145 | if (_centroidDiv > 0) | 156 | if (m_centroidDiv > 0) |
146 | return new Vector3(_centroid.X / _centroidDiv, _centroid.Y / _centroidDiv, _centroid.Z / _centroidDiv); | 157 | return new Vector3(m_centroid.X / m_centroidDiv, m_centroid.Y / m_centroidDiv, m_centroid.Z / m_centroidDiv); |
147 | else | 158 | else |
148 | return Vector3.Zero; | 159 | return Vector3.Zero; |
149 | } | 160 | } |
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 | } |
diff --git a/OpenSim/Region/Physics/UbitMeshing/SculptMap.cs b/OpenSim/Region/Physics/UbitMeshing/SculptMap.cs index b3d9cb6..1c75db6 100644 --- a/OpenSim/Region/Physics/UbitMeshing/SculptMap.cs +++ b/OpenSim/Region/Physics/UbitMeshing/SculptMap.cs | |||
@@ -25,14 +25,10 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | // to build without references to System.Drawing, comment this out | ||
29 | #define SYSTEM_DRAWING | ||
30 | |||
31 | using System; | 28 | using System; |
32 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
33 | using System.Text; | 30 | using System.Text; |
34 | 31 | ||
35 | #if SYSTEM_DRAWING | ||
36 | using System.Drawing; | 32 | using System.Drawing; |
37 | using System.Drawing.Imaging; | 33 | using System.Drawing.Imaging; |
38 | 34 | ||
@@ -60,11 +56,12 @@ namespace PrimMesher | |||
60 | 56 | ||
61 | int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image | 57 | int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image |
62 | 58 | ||
63 | bool smallMap = bmW * bmH <= numLodPixels; | ||
64 | bool needsScaling = false; | 59 | bool needsScaling = false; |
60 | bool smallMap = false; | ||
65 | 61 | ||
66 | width = bmW; | 62 | width = bmW; |
67 | height = bmH; | 63 | height = bmH; |
64 | |||
68 | while (width * height > numLodPixels * 4) | 65 | while (width * height > numLodPixels * 4) |
69 | { | 66 | { |
70 | width >>= 1; | 67 | width >>= 1; |
@@ -85,9 +82,12 @@ namespace PrimMesher | |||
85 | 82 | ||
86 | if (width * height > numLodPixels) | 83 | if (width * height > numLodPixels) |
87 | { | 84 | { |
85 | smallMap = false; | ||
88 | width >>= 1; | 86 | width >>= 1; |
89 | height >>= 1; | 87 | height >>= 1; |
90 | } | 88 | } |
89 | else | ||
90 | smallMap = true; | ||
91 | 91 | ||
92 | int numBytes = (width + 1) * (height + 1); | 92 | int numBytes = (width + 1) * (height + 1); |
93 | redBytes = new byte[numBytes]; | 93 | redBytes = new byte[numBytes]; |
@@ -95,21 +95,18 @@ namespace PrimMesher | |||
95 | blueBytes = new byte[numBytes]; | 95 | blueBytes = new byte[numBytes]; |
96 | 96 | ||
97 | int byteNdx = 0; | 97 | int byteNdx = 0; |
98 | Color c; | ||
98 | 99 | ||
99 | try | 100 | try |
100 | { | 101 | { |
101 | for (int y = 0; y <= height; y++) | 102 | for (int y = 0; y <= height; y++) |
102 | { | 103 | { |
103 | for (int x = 0; x <= width; x++) | 104 | for (int x = 0; x < width; x++) |
104 | { | 105 | { |
105 | Color c; | ||
106 | |||
107 | if (smallMap) | 106 | if (smallMap) |
108 | c = bm.GetPixel(x < width ? x : x - 1, | 107 | c = bm.GetPixel(x, y < height ? y : y - 1); |
109 | y < height ? y : y - 1); | ||
110 | else | 108 | else |
111 | c = bm.GetPixel(x < width ? x * 2 : x * 2 - 1, | 109 | c = bm.GetPixel(x * 2, y < height ? y * 2 : y * 2 - 1); |
112 | y < height ? y * 2 : y * 2 - 1); | ||
113 | 110 | ||
114 | redBytes[byteNdx] = c.R; | 111 | redBytes[byteNdx] = c.R; |
115 | greenBytes[byteNdx] = c.G; | 112 | greenBytes[byteNdx] = c.G; |
@@ -117,6 +114,17 @@ namespace PrimMesher | |||
117 | 114 | ||
118 | ++byteNdx; | 115 | ++byteNdx; |
119 | } | 116 | } |
117 | |||
118 | if (smallMap) | ||
119 | c = bm.GetPixel(width - 1, y < height ? y : y - 1); | ||
120 | else | ||
121 | c = bm.GetPixel(width * 2 - 1, y < height ? y * 2 : y * 2 - 1); | ||
122 | |||
123 | redBytes[byteNdx] = c.R; | ||
124 | greenBytes[byteNdx] = c.G; | ||
125 | blueBytes[byteNdx] = c.B; | ||
126 | |||
127 | ++byteNdx; | ||
120 | } | 128 | } |
121 | } | 129 | } |
122 | catch (Exception e) | 130 | catch (Exception e) |
@@ -140,7 +148,6 @@ namespace PrimMesher | |||
140 | int rowNdx, colNdx; | 148 | int rowNdx, colNdx; |
141 | int smNdx = 0; | 149 | int smNdx = 0; |
142 | 150 | ||
143 | |||
144 | for (rowNdx = 0; rowNdx < numRows; rowNdx++) | 151 | for (rowNdx = 0; rowNdx < numRows; rowNdx++) |
145 | { | 152 | { |
146 | List<Coord> row = new List<Coord>(numCols); | 153 | List<Coord> row = new List<Coord>(numCols); |
@@ -163,16 +170,27 @@ namespace PrimMesher | |||
163 | { | 170 | { |
164 | 171 | ||
165 | Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb); | 172 | Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb); |
166 | 173 | ||
167 | Color c; | 174 | Color c; |
168 | float xscale = srcImage.Width / destWidth; | ||
169 | float yscale = srcImage.Height / destHeight; | ||
170 | 175 | ||
176 | |||
177 | // will let last step to be eventually diferent, as seems to be in sl | ||
178 | |||
179 | float xscale = (float)srcImage.Width / (float)destWidth; | ||
180 | float yscale = (float)srcImage.Height / (float)destHeight; | ||
181 | |||
182 | int lastsx = srcImage.Width - 1; | ||
183 | int lastsy = srcImage.Height - 1; | ||
184 | int lastdx = destWidth - 1; | ||
185 | int lastdy = destHeight - 1; | ||
186 | |||
171 | float sy = 0.5f; | 187 | float sy = 0.5f; |
172 | for (int y = 0; y < destHeight; y++) | 188 | float sx; |
189 | |||
190 | for (int y = 0; y < lastdy; y++) | ||
173 | { | 191 | { |
174 | float sx = 0.5f; | 192 | sx = 0.5f; |
175 | for (int x = 0; x < destWidth; x++) | 193 | for (int x = 0; x < lastdx; x++) |
176 | { | 194 | { |
177 | try | 195 | try |
178 | { | 196 | { |
@@ -182,16 +200,45 @@ namespace PrimMesher | |||
182 | catch (IndexOutOfRangeException) | 200 | catch (IndexOutOfRangeException) |
183 | { | 201 | { |
184 | } | 202 | } |
185 | |||
186 | sx += xscale; | 203 | sx += xscale; |
187 | } | 204 | } |
205 | try | ||
206 | { | ||
207 | c = srcImage.GetPixel(lastsx, (int)(sy)); | ||
208 | scaledImage.SetPixel(lastdx, y, Color.FromArgb(c.R, c.G, c.B)); | ||
209 | } | ||
210 | catch (IndexOutOfRangeException) | ||
211 | { | ||
212 | } | ||
213 | |||
188 | sy += yscale; | 214 | sy += yscale; |
189 | } | 215 | } |
216 | |||
217 | sx = 0.5f; | ||
218 | for (int x = 0; x < lastdx; x++) | ||
219 | { | ||
220 | try | ||
221 | { | ||
222 | c = srcImage.GetPixel((int)(sx), lastsy); | ||
223 | scaledImage.SetPixel(x, lastdy, Color.FromArgb(c.R, c.G, c.B)); | ||
224 | } | ||
225 | catch (IndexOutOfRangeException) | ||
226 | { | ||
227 | } | ||
228 | |||
229 | sx += xscale; | ||
230 | } | ||
231 | try | ||
232 | { | ||
233 | c = srcImage.GetPixel(lastsx, lastsy); | ||
234 | scaledImage.SetPixel(lastdx, lastdy, Color.FromArgb(c.R, c.G, c.B)); | ||
235 | } | ||
236 | catch (IndexOutOfRangeException) | ||
237 | { | ||
238 | } | ||
239 | |||
190 | srcImage.Dispose(); | 240 | srcImage.Dispose(); |
191 | return scaledImage; | 241 | return scaledImage; |
192 | } | 242 | } |
193 | |||
194 | } | ||
195 | |||
196 | } | 243 | } |
197 | #endif | 244 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Physics/UbitMeshing/SculptMesh.cs b/OpenSim/Region/Physics/UbitMeshing/SculptMesh.cs index 4a7f3ad..bc1375b 100644 --- a/OpenSim/Region/Physics/UbitMeshing/SculptMesh.cs +++ b/OpenSim/Region/Physics/UbitMeshing/SculptMesh.cs | |||
@@ -25,18 +25,13 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | // to build without references to System.Drawing, comment this out | ||
29 | #define SYSTEM_DRAWING | ||
30 | |||
31 | using System; | 28 | using System; |
32 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
33 | using System.Text; | 30 | using System.Text; |
34 | using System.IO; | 31 | using System.IO; |
35 | 32 | ||
36 | #if SYSTEM_DRAWING | ||
37 | using System.Drawing; | 33 | using System.Drawing; |
38 | using System.Drawing.Imaging; | 34 | using System.Drawing.Imaging; |
39 | #endif | ||
40 | 35 | ||
41 | namespace PrimMesher | 36 | namespace PrimMesher |
42 | { | 37 | { |
@@ -46,274 +41,28 @@ namespace PrimMesher | |||
46 | public List<Coord> coords; | 41 | public List<Coord> coords; |
47 | public List<Face> faces; | 42 | public List<Face> faces; |
48 | 43 | ||
49 | public List<ViewerFace> viewerFaces; | ||
50 | public List<Coord> normals; | ||
51 | public List<UVCoord> uvs; | ||
52 | |||
53 | public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; | 44 | public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; |
54 | 45 | ||
55 | #if SYSTEM_DRAWING | ||
56 | |||
57 | public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode) | ||
58 | { | ||
59 | Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); | ||
60 | SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode); | ||
61 | bitmap.Dispose(); | ||
62 | return sculptMesh; | ||
63 | } | ||
64 | |||
65 | |||
66 | public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert) | ||
67 | { | ||
68 | Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); | ||
69 | _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0); | ||
70 | bitmap.Dispose(); | ||
71 | } | ||
72 | #endif | ||
73 | |||
74 | /// <summary> | ||
75 | /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications | ||
76 | /// Construct a sculpt mesh from a 2D array of floats | ||
77 | /// </summary> | ||
78 | /// <param name="zMap"></param> | ||
79 | /// <param name="xBegin"></param> | ||
80 | /// <param name="xEnd"></param> | ||
81 | /// <param name="yBegin"></param> | ||
82 | /// <param name="yEnd"></param> | ||
83 | /// <param name="viewerMode"></param> | ||
84 | public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode) | ||
85 | { | ||
86 | float xStep, yStep; | ||
87 | float uStep, vStep; | ||
88 | |||
89 | int numYElements = zMap.GetLength(0); | ||
90 | int numXElements = zMap.GetLength(1); | ||
91 | |||
92 | try | ||
93 | { | ||
94 | xStep = (xEnd - xBegin) / (float)(numXElements - 1); | ||
95 | yStep = (yEnd - yBegin) / (float)(numYElements - 1); | ||
96 | |||
97 | uStep = 1.0f / (numXElements - 1); | ||
98 | vStep = 1.0f / (numYElements - 1); | ||
99 | } | ||
100 | catch (DivideByZeroException) | ||
101 | { | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | coords = new List<Coord>(); | ||
106 | faces = new List<Face>(); | ||
107 | normals = new List<Coord>(); | ||
108 | uvs = new List<UVCoord>(); | ||
109 | |||
110 | viewerFaces = new List<ViewerFace>(); | ||
111 | |||
112 | int p1, p2, p3, p4; | ||
113 | |||
114 | int x, y; | ||
115 | int xStart = 0, yStart = 0; | ||
116 | |||
117 | for (y = yStart; y < numYElements; y++) | ||
118 | { | ||
119 | int rowOffset = y * numXElements; | ||
120 | |||
121 | for (x = xStart; x < numXElements; x++) | ||
122 | { | ||
123 | /* | ||
124 | * p1-----p2 | ||
125 | * | \ f2 | | ||
126 | * | \ | | ||
127 | * | f1 \| | ||
128 | * p3-----p4 | ||
129 | */ | ||
130 | |||
131 | p4 = rowOffset + x; | ||
132 | p3 = p4 - 1; | ||
133 | |||
134 | p2 = p4 - numXElements; | ||
135 | p1 = p3 - numXElements; | ||
136 | |||
137 | Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]); | ||
138 | this.coords.Add(c); | ||
139 | if (viewerMode) | ||
140 | { | ||
141 | this.normals.Add(new Coord()); | ||
142 | this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y)); | ||
143 | } | ||
144 | |||
145 | if (y > 0 && x > 0) | ||
146 | { | ||
147 | Face f1, f2; | ||
148 | |||
149 | if (viewerMode) | ||
150 | { | ||
151 | f1 = new Face(p1, p4, p3, p1, p4, p3); | ||
152 | f1.uv1 = p1; | ||
153 | f1.uv2 = p4; | ||
154 | f1.uv3 = p3; | ||
155 | |||
156 | f2 = new Face(p1, p2, p4, p1, p2, p4); | ||
157 | f2.uv1 = p1; | ||
158 | f2.uv2 = p2; | ||
159 | f2.uv3 = p4; | ||
160 | } | ||
161 | else | ||
162 | { | ||
163 | f1 = new Face(p1, p4, p3); | ||
164 | f2 = new Face(p1, p2, p4); | ||
165 | } | ||
166 | |||
167 | this.faces.Add(f1); | ||
168 | this.faces.Add(f2); | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | |||
173 | if (viewerMode) | ||
174 | calcVertexNormals(SculptType.plane, numXElements, numYElements); | ||
175 | } | ||
176 | |||
177 | #if SYSTEM_DRAWING | ||
178 | public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode) | ||
179 | { | ||
180 | _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false); | ||
181 | } | ||
182 | 46 | ||
183 | public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) | 47 | public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool mirror, bool invert) |
184 | { | 48 | { |
185 | _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert); | 49 | if (mirror) |
186 | } | 50 | invert = !invert; |
187 | #endif | ||
188 | |||
189 | public SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) | ||
190 | { | ||
191 | _SculptMesh(rows, sculptType, viewerMode, mirror, invert); | ||
192 | } | ||
193 | |||
194 | #if SYSTEM_DRAWING | ||
195 | /// <summary> | ||
196 | /// converts a bitmap to a list of lists of coords, while scaling the image. | ||
197 | /// the scaling is done in floating point so as to allow for reduced vertex position | ||
198 | /// quantization as the position will be averaged between pixel values. this routine will | ||
199 | /// likely fail if the bitmap width and height are not powers of 2. | ||
200 | /// </summary> | ||
201 | /// <param name="bitmap"></param> | ||
202 | /// <param name="scale"></param> | ||
203 | /// <param name="mirror"></param> | ||
204 | /// <returns></returns> | ||
205 | private List<List<Coord>> bitmap2Coords(Bitmap bitmap, int scale, bool mirror) | ||
206 | { | ||
207 | int numRows = bitmap.Height / scale; | ||
208 | int numCols = bitmap.Width / scale; | ||
209 | List<List<Coord>> rows = new List<List<Coord>>(numRows); | ||
210 | |||
211 | float pixScale = 1.0f / (scale * scale); | ||
212 | pixScale /= 255; | ||
213 | |||
214 | int imageX, imageY = 0; | ||
215 | |||
216 | int rowNdx, colNdx; | ||
217 | |||
218 | for (rowNdx = 0; rowNdx < numRows; rowNdx++) | ||
219 | { | ||
220 | List<Coord> row = new List<Coord>(numCols); | ||
221 | for (colNdx = 0; colNdx < numCols; colNdx++) | ||
222 | { | ||
223 | imageX = colNdx * scale; | ||
224 | int imageYStart = rowNdx * scale; | ||
225 | int imageYEnd = imageYStart + scale; | ||
226 | int imageXEnd = imageX + scale; | ||
227 | float rSum = 0.0f; | ||
228 | float gSum = 0.0f; | ||
229 | float bSum = 0.0f; | ||
230 | for (; imageX < imageXEnd; imageX++) | ||
231 | { | ||
232 | for (imageY = imageYStart; imageY < imageYEnd; imageY++) | ||
233 | { | ||
234 | Color c = bitmap.GetPixel(imageX, imageY); | ||
235 | if (c.A != 255) | ||
236 | { | ||
237 | bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B)); | ||
238 | c = bitmap.GetPixel(imageX, imageY); | ||
239 | } | ||
240 | rSum += c.R; | ||
241 | gSum += c.G; | ||
242 | bSum += c.B; | ||
243 | } | ||
244 | } | ||
245 | if (mirror) | ||
246 | row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); | ||
247 | else | ||
248 | row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); | ||
249 | |||
250 | } | ||
251 | rows.Add(row); | ||
252 | } | ||
253 | return rows; | ||
254 | } | ||
255 | |||
256 | private List<List<Coord>> bitmap2CoordsSampled(Bitmap bitmap, int scale, bool mirror) | ||
257 | { | ||
258 | int numRows = bitmap.Height / scale; | ||
259 | int numCols = bitmap.Width / scale; | ||
260 | List<List<Coord>> rows = new List<List<Coord>>(numRows); | ||
261 | |||
262 | float pixScale = 1.0f / 256.0f; | ||
263 | |||
264 | int imageX, imageY = 0; | ||
265 | |||
266 | int rowNdx, colNdx; | ||
267 | |||
268 | for (rowNdx = 0; rowNdx <= numRows; rowNdx++) | ||
269 | { | ||
270 | List<Coord> row = new List<Coord>(numCols); | ||
271 | imageY = rowNdx * scale; | ||
272 | if (rowNdx == numRows) imageY--; | ||
273 | for (colNdx = 0; colNdx <= numCols; colNdx++) | ||
274 | { | ||
275 | imageX = colNdx * scale; | ||
276 | if (colNdx == numCols) imageX--; | ||
277 | |||
278 | Color c = bitmap.GetPixel(imageX, imageY); | ||
279 | if (c.A != 255) | ||
280 | { | ||
281 | bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B)); | ||
282 | c = bitmap.GetPixel(imageX, imageY); | ||
283 | } | ||
284 | |||
285 | if (mirror) | ||
286 | row.Add(new Coord(-(c.R * pixScale - 0.5f), c.G * pixScale - 0.5f, c.B * pixScale - 0.5f)); | ||
287 | else | ||
288 | row.Add(new Coord(c.R * pixScale - 0.5f, c.G * pixScale - 0.5f, c.B * pixScale - 0.5f)); | ||
289 | 51 | ||
290 | } | 52 | SculptMap smap = new SculptMap(sculptBitmap, lod); |
291 | rows.Add(row); | ||
292 | } | ||
293 | return rows; | ||
294 | } | ||
295 | 53 | ||
54 | List<List<Coord>> rows = smap.ToRows(mirror); | ||
296 | 55 | ||
297 | void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) | 56 | _SculptMesh(rows, sculptType, invert); |
298 | { | ||
299 | _SculptMesh(new SculptMap(sculptBitmap, lod).ToRows(mirror), sculptType, viewerMode, mirror, invert); | ||
300 | } | 57 | } |
301 | #endif | ||
302 | 58 | ||
303 | void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) | 59 | private void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool invert) |
304 | { | 60 | { |
305 | coords = new List<Coord>(); | 61 | coords = new List<Coord>(); |
306 | faces = new List<Face>(); | 62 | faces = new List<Face>(); |
307 | normals = new List<Coord>(); | ||
308 | uvs = new List<UVCoord>(); | ||
309 | 63 | ||
310 | sculptType = (SculptType)(((int)sculptType) & 0x07); | 64 | sculptType = (SculptType)(((int)sculptType) & 0x07); |
311 | 65 | ||
312 | if (mirror) | ||
313 | invert = !invert; | ||
314 | |||
315 | viewerFaces = new List<ViewerFace>(); | ||
316 | |||
317 | int width = rows[0].Count; | 66 | int width = rows[0].Count; |
318 | 67 | ||
319 | int p1, p2, p3, p4; | 68 | int p1, p2, p3, p4; |
@@ -375,7 +124,6 @@ namespace PrimMesher | |||
375 | 124 | ||
376 | int coordsDown = rows.Count; | 125 | int coordsDown = rows.Count; |
377 | int coordsAcross = rows[0].Count; | 126 | int coordsAcross = rows[0].Count; |
378 | // int lastColumn = coordsAcross - 1; | ||
379 | 127 | ||
380 | float widthUnit = 1.0f / (coordsAcross - 1); | 128 | float widthUnit = 1.0f / (coordsAcross - 1); |
381 | float heightUnit = 1.0f / (coordsDown - 1); | 129 | float heightUnit = 1.0f / (coordsDown - 1); |
@@ -401,45 +149,11 @@ namespace PrimMesher | |||
401 | p1 = p3 - coordsAcross; | 149 | p1 = p3 - coordsAcross; |
402 | 150 | ||
403 | this.coords.Add(rows[imageY][imageX]); | 151 | this.coords.Add(rows[imageY][imageX]); |
404 | if (viewerMode) | ||
405 | { | ||
406 | this.normals.Add(new Coord()); | ||
407 | this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY)); | ||
408 | } | ||
409 | 152 | ||
410 | if (imageY > 0 && imageX > 0) | 153 | if (imageY > 0 && imageX > 0) |
411 | { | 154 | { |
412 | Face f1, f2; | 155 | Face f1, f2; |
413 | 156 | ||
414 | if (viewerMode) | ||
415 | { | ||
416 | if (invert) | ||
417 | { | ||
418 | f1 = new Face(p1, p4, p3, p1, p4, p3); | ||
419 | f1.uv1 = p1; | ||
420 | f1.uv2 = p4; | ||
421 | f1.uv3 = p3; | ||
422 | |||
423 | f2 = new Face(p1, p2, p4, p1, p2, p4); | ||
424 | f2.uv1 = p1; | ||
425 | f2.uv2 = p2; | ||
426 | f2.uv3 = p4; | ||
427 | } | ||
428 | else | ||
429 | { | ||
430 | f1 = new Face(p1, p3, p4, p1, p3, p4); | ||
431 | f1.uv1 = p1; | ||
432 | f1.uv2 = p3; | ||
433 | f1.uv3 = p4; | ||
434 | |||
435 | f2 = new Face(p1, p4, p2, p1, p4, p2); | ||
436 | f2.uv1 = p1; | ||
437 | f2.uv2 = p4; | ||
438 | f2.uv3 = p2; | ||
439 | } | ||
440 | } | ||
441 | else | ||
442 | { | ||
443 | if (invert) | 157 | if (invert) |
444 | { | 158 | { |
445 | f1 = new Face(p1, p4, p3); | 159 | f1 = new Face(p1, p4, p3); |
@@ -450,16 +164,12 @@ namespace PrimMesher | |||
450 | f1 = new Face(p1, p3, p4); | 164 | f1 = new Face(p1, p3, p4); |
451 | f2 = new Face(p1, p4, p2); | 165 | f2 = new Face(p1, p4, p2); |
452 | } | 166 | } |
453 | } | ||
454 | 167 | ||
455 | this.faces.Add(f1); | 168 | this.faces.Add(f1); |
456 | this.faces.Add(f2); | 169 | this.faces.Add(f2); |
457 | } | 170 | } |
458 | } | 171 | } |
459 | } | 172 | } |
460 | |||
461 | if (viewerMode) | ||
462 | calcVertexNormals(sculptType, coordsAcross, coordsDown); | ||
463 | } | 173 | } |
464 | 174 | ||
465 | /// <summary> | 175 | /// <summary> |
@@ -475,129 +185,6 @@ namespace PrimMesher | |||
475 | { | 185 | { |
476 | coords = new List<Coord>(sm.coords); | 186 | coords = new List<Coord>(sm.coords); |
477 | faces = new List<Face>(sm.faces); | 187 | faces = new List<Face>(sm.faces); |
478 | viewerFaces = new List<ViewerFace>(sm.viewerFaces); | ||
479 | normals = new List<Coord>(sm.normals); | ||
480 | uvs = new List<UVCoord>(sm.uvs); | ||
481 | } | ||
482 | |||
483 | private void calcVertexNormals(SculptType sculptType, int xSize, int ySize) | ||
484 | { // compute vertex normals by summing all the surface normals of all the triangles sharing | ||
485 | // each vertex and then normalizing | ||
486 | int numFaces = this.faces.Count; | ||
487 | for (int i = 0; i < numFaces; i++) | ||
488 | { | ||
489 | Face face = this.faces[i]; | ||
490 | Coord surfaceNormal = face.SurfaceNormal(this.coords); | ||
491 | this.normals[face.n1] += surfaceNormal; | ||
492 | this.normals[face.n2] += surfaceNormal; | ||
493 | this.normals[face.n3] += surfaceNormal; | ||
494 | } | ||
495 | |||
496 | int numNormals = this.normals.Count; | ||
497 | for (int i = 0; i < numNormals; i++) | ||
498 | this.normals[i] = this.normals[i].Normalize(); | ||
499 | |||
500 | if (sculptType != SculptType.plane) | ||
501 | { // blend the vertex normals at the cylinder seam | ||
502 | for (int y = 0; y < ySize; y++) | ||
503 | { | ||
504 | int rowOffset = y * xSize; | ||
505 | |||
506 | this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize(); | ||
507 | } | ||
508 | } | ||
509 | |||
510 | foreach (Face face in this.faces) | ||
511 | { | ||
512 | ViewerFace vf = new ViewerFace(0); | ||
513 | vf.v1 = this.coords[face.v1]; | ||
514 | vf.v2 = this.coords[face.v2]; | ||
515 | vf.v3 = this.coords[face.v3]; | ||
516 | |||
517 | vf.coordIndex1 = face.v1; | ||
518 | vf.coordIndex2 = face.v2; | ||
519 | vf.coordIndex3 = face.v3; | ||
520 | |||
521 | vf.n1 = this.normals[face.n1]; | ||
522 | vf.n2 = this.normals[face.n2]; | ||
523 | vf.n3 = this.normals[face.n3]; | ||
524 | |||
525 | vf.uv1 = this.uvs[face.uv1]; | ||
526 | vf.uv2 = this.uvs[face.uv2]; | ||
527 | vf.uv3 = this.uvs[face.uv3]; | ||
528 | |||
529 | this.viewerFaces.Add(vf); | ||
530 | } | ||
531 | } | ||
532 | |||
533 | /// <summary> | ||
534 | /// Adds a value to each XYZ vertex coordinate in the mesh | ||
535 | /// </summary> | ||
536 | /// <param name="x"></param> | ||
537 | /// <param name="y"></param> | ||
538 | /// <param name="z"></param> | ||
539 | public void AddPos(float x, float y, float z) | ||
540 | { | ||
541 | int i; | ||
542 | int numVerts = this.coords.Count; | ||
543 | Coord vert; | ||
544 | |||
545 | for (i = 0; i < numVerts; i++) | ||
546 | { | ||
547 | vert = this.coords[i]; | ||
548 | vert.X += x; | ||
549 | vert.Y += y; | ||
550 | vert.Z += z; | ||
551 | this.coords[i] = vert; | ||
552 | } | ||
553 | |||
554 | if (this.viewerFaces != null) | ||
555 | { | ||
556 | int numViewerFaces = this.viewerFaces.Count; | ||
557 | |||
558 | for (i = 0; i < numViewerFaces; i++) | ||
559 | { | ||
560 | ViewerFace v = this.viewerFaces[i]; | ||
561 | v.AddPos(x, y, z); | ||
562 | this.viewerFaces[i] = v; | ||
563 | } | ||
564 | } | ||
565 | } | ||
566 | |||
567 | /// <summary> | ||
568 | /// Rotates the mesh | ||
569 | /// </summary> | ||
570 | /// <param name="q"></param> | ||
571 | public void AddRot(Quat q) | ||
572 | { | ||
573 | int i; | ||
574 | int numVerts = this.coords.Count; | ||
575 | |||
576 | for (i = 0; i < numVerts; i++) | ||
577 | this.coords[i] *= q; | ||
578 | |||
579 | int numNormals = this.normals.Count; | ||
580 | for (i = 0; i < numNormals; i++) | ||
581 | this.normals[i] *= q; | ||
582 | |||
583 | if (this.viewerFaces != null) | ||
584 | { | ||
585 | int numViewerFaces = this.viewerFaces.Count; | ||
586 | |||
587 | for (i = 0; i < numViewerFaces; i++) | ||
588 | { | ||
589 | ViewerFace v = this.viewerFaces[i]; | ||
590 | v.v1 *= q; | ||
591 | v.v2 *= q; | ||
592 | v.v3 *= q; | ||
593 | |||
594 | v.n1 *= q; | ||
595 | v.n2 *= q; | ||
596 | v.n3 *= q; | ||
597 | |||
598 | this.viewerFaces[i] = v; | ||
599 | } | ||
600 | } | ||
601 | } | 188 | } |
602 | 189 | ||
603 | public void Scale(float x, float y, float z) | 190 | public void Scale(float x, float y, float z) |
@@ -608,19 +195,6 @@ namespace PrimMesher | |||
608 | Coord m = new Coord(x, y, z); | 195 | Coord m = new Coord(x, y, z); |
609 | for (i = 0; i < numVerts; i++) | 196 | for (i = 0; i < numVerts; i++) |
610 | this.coords[i] *= m; | 197 | this.coords[i] *= m; |
611 | |||
612 | if (this.viewerFaces != null) | ||
613 | { | ||
614 | int numViewerFaces = this.viewerFaces.Count; | ||
615 | for (i = 0; i < numViewerFaces; i++) | ||
616 | { | ||
617 | ViewerFace v = this.viewerFaces[i]; | ||
618 | v.v1 *= m; | ||
619 | v.v2 *= m; | ||
620 | v.v3 *= m; | ||
621 | this.viewerFaces[i] = v; | ||
622 | } | ||
623 | } | ||
624 | } | 198 | } |
625 | 199 | ||
626 | public void DumpRaw(String path, String name, String title) | 200 | public void DumpRaw(String path, String name, String title) |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index 6bf5be1..fbc6134 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs | |||
@@ -57,7 +57,6 @@ using OdeAPI; | |||
57 | using OpenSim.Framework; | 57 | using OpenSim.Framework; |
58 | using OpenSim.Region.Physics.Manager; | 58 | using OpenSim.Region.Physics.Manager; |
59 | 59 | ||
60 | |||
61 | namespace OpenSim.Region.Physics.OdePlugin | 60 | namespace OpenSim.Region.Physics.OdePlugin |
62 | { | 61 | { |
63 | public class OdePrim : PhysicsActor | 62 | public class OdePrim : PhysicsActor |
@@ -538,24 +537,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
538 | { | 537 | { |
539 | set | 538 | set |
540 | { | 539 | { |
541 | /* | ||
542 | IMesh mesh = null; | ||
543 | if (_parent_scene.needsMeshing(value)) | ||
544 | { | ||
545 | bool convex; | ||
546 | if (m_shapetype == 0) | ||
547 | convex = false; | ||
548 | else | ||
549 | convex = true; | ||
550 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex); | ||
551 | } | ||
552 | |||
553 | if (mesh != null) | ||
554 | { | ||
555 | lock (m_meshlock) | ||
556 | m_mesh = mesh; | ||
557 | } | ||
558 | */ | ||
559 | AddChange(changes.Shape, value); | 540 | AddChange(changes.Shape, value); |
560 | } | 541 | } |
561 | } | 542 | } |
@@ -1092,18 +1073,21 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1092 | CalcPrimBodyData(); | 1073 | CalcPrimBodyData(); |
1093 | 1074 | ||
1094 | m_mesh = null; | 1075 | m_mesh = null; |
1095 | if (_parent_scene.needsMeshing(pbs)) | 1076 | if (_parent_scene.needsMeshing(pbs) && (pbs.SculptData.Length > 0)) |
1096 | { | 1077 | { |
1097 | bool convex; | 1078 | bool convex; |
1079 | int clod = (int)LevelOfDetail.High; | ||
1098 | if (m_shapetype == 0) | 1080 | if (m_shapetype == 0) |
1099 | convex = false; | 1081 | convex = false; |
1100 | else | 1082 | else |
1083 | { | ||
1101 | convex = true; | 1084 | convex = true; |
1102 | 1085 | if (_pbs.SculptType != (byte)SculptType.Mesh) | |
1103 | m_mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex); | 1086 | clod = (int)LevelOfDetail.Low; |
1087 | } | ||
1088 | m_mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex); | ||
1104 | } | 1089 | } |
1105 | 1090 | ||
1106 | |||
1107 | m_building = true; // control must set this to false when done | 1091 | m_building = true; // control must set this to false when done |
1108 | 1092 | ||
1109 | AddChange(changes.Add, null); | 1093 | AddChange(changes.Add, null); |
@@ -1354,18 +1338,23 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1354 | 1338 | ||
1355 | IMesh mesh = null; | 1339 | IMesh mesh = null; |
1356 | 1340 | ||
1357 | |||
1358 | lock (m_meshlock) | 1341 | lock (m_meshlock) |
1359 | { | 1342 | { |
1360 | if (m_mesh == null) | 1343 | if (m_mesh == null) |
1361 | { | 1344 | { |
1362 | bool convex; | 1345 | bool convex; |
1346 | int clod = (int)LevelOfDetail.High; | ||
1347 | |||
1363 | if (m_shapetype == 0) | 1348 | if (m_shapetype == 0) |
1364 | convex = false; | 1349 | convex = false; |
1365 | else | 1350 | else |
1351 | { | ||
1366 | convex = true; | 1352 | convex = true; |
1353 | if (_pbs.SculptType != (byte)SculptType.Mesh) | ||
1354 | clod = (int)LevelOfDetail.Low; | ||
1355 | } | ||
1367 | 1356 | ||
1368 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, (int)LevelOfDetail.High, true, convex); | 1357 | mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex); |
1369 | } | 1358 | } |
1370 | else | 1359 | else |
1371 | { | 1360 | { |
@@ -1373,7 +1362,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1373 | } | 1362 | } |
1374 | 1363 | ||
1375 | if (mesh == null) | 1364 | if (mesh == null) |
1376 | { | 1365 | { |
1377 | m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z); | 1366 | m_log.WarnFormat("[PHYSICS]: CreateMesh Failed on prim {0} at <{1},{2},{3}>.", Name, _position.X, _position.Y, _position.Z); |
1378 | return false; | 1367 | return false; |
1379 | } | 1368 | } |
@@ -1394,7 +1383,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1394 | hasOOBoffsetFromMesh = true; | 1383 | hasOOBoffsetFromMesh = true; |
1395 | 1384 | ||
1396 | mesh.releaseSourceMeshData(); | 1385 | mesh.releaseSourceMeshData(); |
1397 | m_mesh = null; | 1386 | m_mesh = mesh; |
1398 | } | 1387 | } |
1399 | 1388 | ||
1400 | IntPtr geo = IntPtr.Zero; | 1389 | IntPtr geo = IntPtr.Zero; |
@@ -1536,7 +1525,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1536 | d.GeomTriMeshDataDestroy(_triMeshData); | 1525 | d.GeomTriMeshDataDestroy(_triMeshData); |
1537 | _triMeshData = IntPtr.Zero; | 1526 | _triMeshData = IntPtr.Zero; |
1538 | } | 1527 | } |
1528 | |||
1539 | } | 1529 | } |
1530 | |||
1531 | |||
1540 | // catch (System.AccessViolationException) | 1532 | // catch (System.AccessViolationException) |
1541 | catch (Exception e) | 1533 | catch (Exception e) |
1542 | { | 1534 | { |
@@ -1550,6 +1542,13 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1550 | { | 1542 | { |
1551 | m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name); | 1543 | m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name); |
1552 | } | 1544 | } |
1545 | |||
1546 | if (m_mesh != null) | ||
1547 | { | ||
1548 | _parent_scene.mesher.ReleaseMesh(m_mesh); | ||
1549 | m_mesh = null; | ||
1550 | } | ||
1551 | |||
1553 | Body = IntPtr.Zero; | 1552 | Body = IntPtr.Zero; |
1554 | hasOOBoffsetFromMesh = false; | 1553 | hasOOBoffsetFromMesh = false; |
1555 | } | 1554 | } |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index f3ac3ca..3ee5198 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs | |||
@@ -194,7 +194,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
194 | private float metersInSpace = 25.6f; | 194 | private float metersInSpace = 25.6f; |
195 | private float m_timeDilation = 1.0f; | 195 | private float m_timeDilation = 1.0f; |
196 | 196 | ||
197 | DateTime m_lastframe; | 197 | private DateTime m_lastframe; |
198 | private DateTime m_lastMeshExpire; | ||
198 | 199 | ||
199 | public float gravityx = 0f; | 200 | public float gravityx = 0f; |
200 | public float gravityy = 0f; | 201 | public float gravityy = 0f; |
@@ -203,6 +204,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
203 | private float waterlevel = 0f; | 204 | private float waterlevel = 0f; |
204 | private int framecount = 0; | 205 | private int framecount = 0; |
205 | 206 | ||
207 | private int m_meshExpireCntr; | ||
208 | |||
206 | // private IntPtr WaterGeom = IntPtr.Zero; | 209 | // private IntPtr WaterGeom = IntPtr.Zero; |
207 | // private IntPtr WaterHeightmapData = IntPtr.Zero; | 210 | // private IntPtr WaterHeightmapData = IntPtr.Zero; |
208 | // private GCHandle WaterMapHandler = new GCHandle(); | 211 | // private GCHandle WaterMapHandler = new GCHandle(); |
@@ -263,7 +266,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
263 | const int maxContactsbeforedeath = 4000; | 266 | const int maxContactsbeforedeath = 4000; |
264 | private volatile int m_global_contactcount = 0; | 267 | private volatile int m_global_contactcount = 0; |
265 | 268 | ||
266 | |||
267 | private IntPtr contactgroup; | 269 | private IntPtr contactgroup; |
268 | 270 | ||
269 | public ContactData[] m_materialContactsData = new ContactData[8]; | 271 | public ContactData[] m_materialContactsData = new ContactData[8]; |
@@ -594,6 +596,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
594 | } | 596 | } |
595 | 597 | ||
596 | m_lastframe = DateTime.UtcNow; | 598 | m_lastframe = DateTime.UtcNow; |
599 | m_lastMeshExpire = m_lastframe; | ||
597 | } | 600 | } |
598 | 601 | ||
599 | internal void waitForSpaceUnlock(IntPtr space) | 602 | internal void waitForSpaceUnlock(IntPtr space) |
@@ -1768,9 +1771,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1768 | { | 1771 | { |
1769 | 1772 | ||
1770 | DateTime now = DateTime.UtcNow; | 1773 | DateTime now = DateTime.UtcNow; |
1771 | TimeSpan SinceLastFrame = now - m_lastframe; | 1774 | TimeSpan timedif = now - m_lastframe; |
1772 | m_lastframe = now; | 1775 | m_lastframe = now; |
1773 | timeStep = (float)SinceLastFrame.TotalSeconds; | 1776 | timeStep = (float)timedif.TotalSeconds; |
1774 | 1777 | ||
1775 | // acumulate time so we can reduce error | 1778 | // acumulate time so we can reduce error |
1776 | step_time += timeStep; | 1779 | step_time += timeStep; |
@@ -1972,6 +1975,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1972 | _badCharacter.Clear(); | 1975 | _badCharacter.Clear(); |
1973 | } | 1976 | } |
1974 | } | 1977 | } |
1978 | |||
1979 | timedif = now - m_lastMeshExpire; | ||
1980 | |||
1981 | if (timedif.Seconds > 10) | ||
1982 | { | ||
1983 | mesher.ExpireReleaseMeshs(); | ||
1984 | m_lastMeshExpire = now; | ||
1985 | } | ||
1975 | /* | 1986 | /* |
1976 | int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); | 1987 | int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); |
1977 | int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace); | 1988 | int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace); |