aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs306
1 files changed, 194 insertions, 112 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index cc414e9..d1fb576 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -45,6 +45,7 @@ public sealed class BSPrim : PhysicsActor
45 private IMesh _mesh; 45 private IMesh _mesh;
46 private PrimitiveBaseShape _pbs; 46 private PrimitiveBaseShape _pbs;
47 private ShapeData.PhysicsShapeType _shapeType; 47 private ShapeData.PhysicsShapeType _shapeType;
48 private ulong _meshKey;
48 private ulong _hullKey; 49 private ulong _hullKey;
49 private List<ConvexResult> _hulls; 50 private List<ConvexResult> _hulls;
50 51
@@ -117,6 +118,7 @@ public sealed class BSPrim : PhysicsActor
117 _rotationalVelocity = OMV.Vector3.Zero; 118 _rotationalVelocity = OMV.Vector3.Zero;
118 _angularVelocity = OMV.Vector3.Zero; 119 _angularVelocity = OMV.Vector3.Zero;
119 _hullKey = 0; 120 _hullKey = 0;
121 _meshKey = 0;
120 _pbs = pbs; 122 _pbs = pbs;
121 _isPhysical = pisPhysical; 123 _isPhysical = pisPhysical;
122 _isVolumeDetect = false; 124 _isVolumeDetect = false;
@@ -147,6 +149,7 @@ public sealed class BSPrim : PhysicsActor
147 _scene.RemoveVehiclePrim(this); // just to make sure 149 _scene.RemoveVehiclePrim(this); // just to make sure
148 _scene.TaintedObject(delegate() 150 _scene.TaintedObject(delegate()
149 { 151 {
152 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
150 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 153 BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
151 }); 154 });
152 } 155 }
@@ -283,11 +286,6 @@ public sealed class BSPrim : PhysicsActor
283 set { _parentPrim = value; } 286 set { _parentPrim = value; }
284 } 287 }
285 288
286 public ulong HullKey
287 {
288 get { return _hullKey; }
289 }
290
291 // return true if we are the root of a linkset (there are children to manage) 289 // return true if we are the root of a linkset (there are children to manage)
292 public bool IsRootOfLinkset 290 public bool IsRootOfLinkset
293 { 291 {
@@ -463,7 +461,18 @@ public sealed class BSPrim : PhysicsActor
463 private void SetObjectDynamic() 461 private void SetObjectDynamic()
464 { 462 {
465 // non-physical things work best with a mass of zero 463 // non-physical things work best with a mass of zero
466 _mass = IsStatic ? 0f : CalculateMass(); 464 if (IsStatic)
465 {
466 _mass = 0f;
467 }
468 else
469 {
470 _mass = CalculateMass();
471 // If it's dynamic, make sure the hull has been created for it
472 // This shouldn't do much work if the object had previously been built
473 RecreateGeomAndObject();
474
475 }
467 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass); 476 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass);
468 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}, mass={4}", LogHeader, _localID, IsStatic, IsSolid, _mass); 477 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}, mass={4}", LogHeader, _localID, IsStatic, IsSolid, _mass);
469 } 478 }
@@ -896,26 +905,19 @@ public sealed class BSPrim : PhysicsActor
896 #endregion Mass Calculation 905 #endregion Mass Calculation
897 906
898 // Create the geometry information in Bullet for later use 907 // Create the geometry information in Bullet for later use
908 // The objects needs a hull if it's physical otherwise a mesh is enough
899 // No locking here because this is done when we know physics is not simulating 909 // No locking here because this is done when we know physics is not simulating
900 private void CreateGeom() 910 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used
911 private void CreateGeom(bool forceRebuild)
901 { 912 {
902 // Since we're recreating new, get rid of any previously generated shape 913 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
903 if (_hullKey != 0) 914 if (!_scene.NeedsMeshing(_pbs))
904 { 915 {
905 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
906 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
907 _hullKey = 0;
908 _hulls.Clear();
909 }
910
911 if (_mesh == null)
912 {
913 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
914 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 916 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
915 { 917 {
916 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 918 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
917 { 919 {
918 // m_log.DebugFormat("{0}: CreateGeom: mesh null. Defaulting to sphere of size {1}", LogHeader, _size); 920 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
919 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 921 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
920 // Bullet native objects are scaled by the Bullet engine so pass the size in 922 // Bullet native objects are scaled by the Bullet engine so pass the size in
921 _scale = _size; 923 _scale = _size;
@@ -923,99 +925,190 @@ public sealed class BSPrim : PhysicsActor
923 } 925 }
924 else 926 else
925 { 927 {
926 // m_log.DebugFormat("{0}: CreateGeom: mesh null. Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); 928 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size);
927 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 929 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
928 _scale = _size; 930 _scale = _size;
929 } 931 }
930 } 932 }
931 else 933 else
932 { 934 {
933 int[] indices = _mesh.getIndexListAsInt(); 935 if (IsPhysical)
934 List<OMV.Vector3> vertices = _mesh.getVertexList();
935
936 //format conversion from IMesh format to DecompDesc format
937 List<int> convIndices = new List<int>();
938 List<float3> convVertices = new List<float3>();
939 for (int ii = 0; ii < indices.GetLength(0); ii++)
940 { 936 {
941 convIndices.Add(indices[ii]); 937 if (forceRebuild || _hullKey == 0)
938 {
939 // physical objects require a hull for interaction.
940 // This will create the mesh if it doesn't already exist
941 CreateGeomHull();
942 }
942 } 943 }
943 foreach (OMV.Vector3 vv in vertices) 944 else
944 { 945 {
945 convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); 946 if (forceRebuild || _meshKey == 0)
947 {
948 // Static (non-physical) objects only need a mesh for bumping into
949 CreateGeomMesh();
950 }
946 } 951 }
952 }
953 }
954
955 // No locking here because this is done when we know physics is not simulating
956 private void CreateGeomMesh()
957 {
958 ulong newMeshKey = (ulong)_pbs.GetHashCode();
959
960 // if this new shape is the same as last time, don't recreate the mesh
961 if (_meshKey == newMeshKey) return;
962
963 // Since we're recreating new, get rid of any previously generated shape
964 if (_meshKey != 0)
965 {
966 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _meshKey);
967 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
968 _mesh = null;
969 _meshKey = 0;
970 }
971
972 _meshKey = newMeshKey;
973 int lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
974 // always pass false for physicalness as this creates some sort of bounding box which we don't need
975 _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, lod, false);
976
977 int[] indices = _mesh.getIndexListAsInt();
978 List<OMV.Vector3> vertices = _mesh.getVertexList();
979
980 float[] verticesAsFloats = new float[vertices.Count * 3];
981 int vi = 0;
982 foreach (OMV.Vector3 vv in vertices)
983 {
984 // m_log.DebugFormat("{0}: {1}: <{2:0.00}, {3:0.00}, {4:0.00}>", LogHeader, vi / 3, vv.X, vv.Y, vv.Z);
985 verticesAsFloats[vi++] = vv.X;
986 verticesAsFloats[vi++] = vv.Y;
987 verticesAsFloats[vi++] = vv.Z;
988 }
947 989
948 // setup and do convex hull conversion 990 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
949 _hulls = new List<ConvexResult>(); 991 // LogHeader, _localID, _meshKey, indices.Length, vertices.Count);
950 DecompDesc dcomp = new DecompDesc(); 992 BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices,
951 dcomp.mIndices = convIndices; 993 vertices.Count, verticesAsFloats);
952 dcomp.mVertices = convVertices; 994
953 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); 995 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
954 // create the hull into the _hulls variable 996 // meshes are already scaled by the meshmerizer
955 convexBuilder.process(dcomp); 997 _scale = new OMV.Vector3(1f, 1f, 1f);
956 998 return;
957 // Convert the vertices and indices for passing to unmanaged 999 }
958 // The hull information is passed as a large floating point array. 1000
959 // The format is: 1001 // No locking here because this is done when we know physics is not simulating
960 // convHulls[0] = number of hulls 1002 private void CreateGeomHull()
961 // convHulls[1] = number of vertices in first hull 1003 {
962 // convHulls[2] = hull centroid X coordinate 1004 ulong newHullKey = (ulong)_pbs.GetHashCode();
963 // convHulls[3] = hull centroid Y coordinate 1005
964 // convHulls[4] = hull centroid Z coordinate 1006 // if the hull hasn't changed, don't rebuild it
965 // convHulls[5] = first hull vertex X 1007 if (newHullKey == _hullKey) return;
966 // convHulls[6] = first hull vertex Y 1008
967 // convHulls[7] = first hull vertex Z 1009 // Since we're recreating new, get rid of any previously generated shape
968 // convHulls[8] = second hull vertex X 1010 if (_hullKey != 0)
969 // ... 1011 {
970 // convHulls[n] = number of vertices in second hull 1012 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
971 // convHulls[n+1] = second hull centroid X coordinate 1013 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
972 // ... 1014 _hullKey = 0;
973 // 1015 _hulls.Clear();
974 // TODO: is is very inefficient. Someday change the convex hull generator to return 1016 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
975 // data structures that do not need to be converted in order to pass to Bullet. 1017 _mesh = null; // the mesh cannot match either
976 // And maybe put the values directly into pinned memory rather than marshaling. 1018 _meshKey = 0;
977 int hullCount = _hulls.Count; 1019 }
978 int totalVertices = 1; // include one for the count of the hulls 1020
979 foreach (ConvexResult cr in _hulls) 1021 _hullKey = newHullKey;
1022 if (_meshKey != _hullKey)
1023 {
1024 // if the underlying mesh has changed, rebuild it
1025 CreateGeomMesh();
1026 }
1027
1028 int[] indices = _mesh.getIndexListAsInt();
1029 List<OMV.Vector3> vertices = _mesh.getVertexList();
1030
1031 //format conversion from IMesh format to DecompDesc format
1032 List<int> convIndices = new List<int>();
1033 List<float3> convVertices = new List<float3>();
1034 for (int ii = 0; ii < indices.GetLength(0); ii++)
1035 {
1036 convIndices.Add(indices[ii]);
1037 }
1038 foreach (OMV.Vector3 vv in vertices)
1039 {
1040 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
1041 }
1042
1043 // setup and do convex hull conversion
1044 _hulls = new List<ConvexResult>();
1045 DecompDesc dcomp = new DecompDesc();
1046 dcomp.mIndices = convIndices;
1047 dcomp.mVertices = convVertices;
1048 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
1049 // create the hull into the _hulls variable
1050 convexBuilder.process(dcomp);
1051
1052 // Convert the vertices and indices for passing to unmanaged
1053 // The hull information is passed as a large floating point array.
1054 // The format is:
1055 // convHulls[0] = number of hulls
1056 // convHulls[1] = number of vertices in first hull
1057 // convHulls[2] = hull centroid X coordinate
1058 // convHulls[3] = hull centroid Y coordinate
1059 // convHulls[4] = hull centroid Z coordinate
1060 // convHulls[5] = first hull vertex X
1061 // convHulls[6] = first hull vertex Y
1062 // convHulls[7] = first hull vertex Z
1063 // convHulls[8] = second hull vertex X
1064 // ...
1065 // convHulls[n] = number of vertices in second hull
1066 // convHulls[n+1] = second hull centroid X coordinate
1067 // ...
1068 //
1069 // TODO: is is very inefficient. Someday change the convex hull generator to return
1070 // data structures that do not need to be converted in order to pass to Bullet.
1071 // And maybe put the values directly into pinned memory rather than marshaling.
1072 int hullCount = _hulls.Count;
1073 int totalVertices = 1; // include one for the count of the hulls
1074 foreach (ConvexResult cr in _hulls)
1075 {
1076 totalVertices += 4; // add four for the vertex count and centroid
1077 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
1078 }
1079 float[] convHulls = new float[totalVertices];
1080
1081 convHulls[0] = (float)hullCount;
1082 int jj = 1;
1083 foreach (ConvexResult cr in _hulls)
1084 {
1085 // copy vertices for index access
1086 float3[] verts = new float3[cr.HullVertices.Count];
1087 int kk = 0;
1088 foreach (float3 ff in cr.HullVertices)
980 { 1089 {
981 totalVertices += 4; // add four for the vertex count and centroid 1090 verts[kk++] = ff;
982 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
983 } 1091 }
984 float[] convHulls = new float[totalVertices];
985 1092
986 convHulls[0] = (float)hullCount; 1093 // add to the array one hull's worth of data
987 int jj = 1; 1094 convHulls[jj++] = cr.HullIndices.Count;
988 foreach (ConvexResult cr in _hulls) 1095 convHulls[jj++] = 0f; // centroid x,y,z
1096 convHulls[jj++] = 0f;
1097 convHulls[jj++] = 0f;
1098 foreach (int ind in cr.HullIndices)
989 { 1099 {
990 // copy vertices for index access 1100 convHulls[jj++] = verts[ind].x;
991 float3[] verts = new float3[cr.HullVertices.Count]; 1101 convHulls[jj++] = verts[ind].y;
992 int kk = 0; 1102 convHulls[jj++] = verts[ind].z;
993 foreach (float3 ff in cr.HullVertices)
994 {
995 verts[kk++] = ff;
996 }
997
998 // add to the array one hull's worth of data
999 convHulls[jj++] = cr.HullIndices.Count;
1000 convHulls[jj++] = 0f; // centroid x,y,z
1001 convHulls[jj++] = 0f;
1002 convHulls[jj++] = 0f;
1003 foreach (int ind in cr.HullIndices)
1004 {
1005 convHulls[jj++] = verts[ind].x;
1006 convHulls[jj++] = verts[ind].y;
1007 convHulls[jj++] = verts[ind].z;
1008 }
1009 } 1103 }
1010
1011 // create the hull definition in Bullet
1012 _hullKey = (ulong)_pbs.GetHashCode();
1013 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
1014 BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls);
1015 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1016 // meshes are already scaled by the meshmerizer
1017 _scale = new OMV.Vector3(1f, 1f, 1f);
1018 } 1104 }
1105
1106 // create the hull definition in Bullet
1107 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
1108 BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls);
1109 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1110 // meshes are already scaled by the meshmerizer
1111 _scale = new OMV.Vector3(1f, 1f, 1f);
1019 return; 1112 return;
1020 } 1113 }
1021 1114
@@ -1040,6 +1133,7 @@ public sealed class BSPrim : PhysicsActor
1040 else 1133 else
1041 { 1134 {
1042 // simple object 1135 // simple object
1136 // the mesh or hull must have already been created in Bullet
1043 ShapeData shape; 1137 ShapeData shape;
1044 FillShapeInfo(out shape); 1138 FillShapeInfo(out shape);
1045 BulletSimAPI.CreateObject(_scene.WorldID, shape); 1139 BulletSimAPI.CreateObject(_scene.WorldID, shape);
@@ -1081,7 +1175,8 @@ public sealed class BSPrim : PhysicsActor
1081 shape.Scale = _scale; 1175 shape.Scale = _scale;
1082 shape.Mass = _isPhysical ? _mass : 0f; 1176 shape.Mass = _isPhysical ? _mass : 0f;
1083 shape.Buoyancy = _buoyancy; 1177 shape.Buoyancy = _buoyancy;
1084 shape.MeshKey = _hullKey; 1178 shape.HullKey = _hullKey;
1179 shape.MeshKey = _meshKey;
1085 shape.Friction = _friction; 1180 shape.Friction = _friction;
1086 shape.Restitution = _restitution; 1181 shape.Restitution = _restitution;
1087 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; 1182 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
@@ -1098,13 +1193,13 @@ public sealed class BSPrim : PhysicsActor
1098 // remove any constraints that might be in place 1193 // remove any constraints that might be in place
1099 foreach (BSPrim prim in _childrenPrims) 1194 foreach (BSPrim prim in _childrenPrims)
1100 { 1195 {
1101 // m_log.DebugFormat("{0}: CreateObject: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); 1196 // m_log.DebugFormat("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1102 BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID); 1197 BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID);
1103 } 1198 }
1104 // create constraints between the root prim and each of the children 1199 // create constraints between the root prim and each of the children
1105 foreach (BSPrim prim in _childrenPrims) 1200 foreach (BSPrim prim in _childrenPrims)
1106 { 1201 {
1107 // m_log.DebugFormat("{0}: CreateObject: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); 1202 // m_log.DebugFormat("{0}: CreateLinkset: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1108 1203
1109 // Zero motion for children so they don't interpolate 1204 // Zero motion for children so they don't interpolate
1110 prim.ZeroMotion(); 1205 prim.ZeroMotion();
@@ -1132,20 +1227,7 @@ public sealed class BSPrim : PhysicsActor
1132 // No locking here because this is done when the physics engine is not simulating 1227 // No locking here because this is done when the physics engine is not simulating
1133 private void RecreateGeomAndObject() 1228 private void RecreateGeomAndObject()
1134 { 1229 {
1135 // If this object is complex or we are the root of a linkset, build a mesh. 1230 CreateGeom(true);
1136 // The root of a linkset must be a mesh so we can create the linked compound object.
1137 // if (_scene.NeedsMeshing(_pbs) || IsRootOfLinkset )
1138 if (_scene.NeedsMeshing(_pbs)) // linksets with constraints don't need a root mesh
1139 {
1140 // m_log.DebugFormat("{0}: RecreateGeomAndObject: creating mesh", LogHeader);
1141 _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, _scene.MeshLOD, _isPhysical);
1142 }
1143 else
1144 {
1145 // implement the shape with a Bullet native shape.
1146 _mesh = null;
1147 }
1148 CreateGeom();
1149 CreateObject(); 1231 CreateObject();
1150 return; 1232 return;
1151 } 1233 }