aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorRobert Adams2011-08-26 15:51:21 -0700
committerMic Bowman2011-08-26 15:51:21 -0700
commit21708b832b1d6679d5f6de27eb3bd0b920ef0fa7 (patch)
treedba3bb4565adfdd1aaad9720c002f1f1ca3ce990 /OpenSim/Region/Physics
parentMerge branch 'master' into bulletsim (diff)
downloadopensim-SC_OLD-21708b832b1d6679d5f6de27eb3bd0b920ef0fa7.zip
opensim-SC_OLD-21708b832b1d6679d5f6de27eb3bd0b920ef0fa7.tar.gz
opensim-SC_OLD-21708b832b1d6679d5f6de27eb3bd0b920ef0fa7.tar.bz2
opensim-SC_OLD-21708b832b1d6679d5f6de27eb3bd0b920ef0fa7.tar.xz
BulletSim: add mesh representation. Use meshes for static objects and switch to hulls for physical objects.
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs306
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs20
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs31
3 files changed, 228 insertions, 129 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 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 518be09..e91455a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -37,7 +37,6 @@ using OpenMetaverse;
37using OpenSim.Region.Framework; 37using OpenSim.Region.Framework;
38 38
39// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 39// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
40// Parameterize BulletSim. Pass a structure of parameters to the C++ code. Capsule size, friction, ...
41// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) 40// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
42// Test sculpties 41// Test sculpties
43// Compute physics FPS reasonably 42// Compute physics FPS reasonably
@@ -52,8 +51,6 @@ using OpenSim.Region.Framework;
52// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) 51// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
53// Implement LockAngularMotion 52// Implement LockAngularMotion
54// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 53// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
55// Built Galton board (lots of MoveTo's) and some slats were not positioned correctly (mistakes scattered)
56// No mistakes with ODE. Shape creation race condition?
57// Does NeedsMeshing() really need to exclude all the different shapes? 54// Does NeedsMeshing() really need to exclude all the different shapes?
58// 55//
59namespace OpenSim.Region.Physics.BulletSPlugin 56namespace OpenSim.Region.Physics.BulletSPlugin
@@ -81,6 +78,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
81 { 78 {
82 get { return m_meshLOD; } 79 get { return m_meshLOD; }
83 } 80 }
81 private int m_sculptLOD;
82 public int SculptLOD
83 {
84 get { return m_sculptLOD; }
85 }
84 86
85 private int m_maxSubSteps; 87 private int m_maxSubSteps;
86 private float m_fixedTimeStep; 88 private float m_fixedTimeStep;
@@ -187,7 +189,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
187 _meshSculptedPrim = true; // mesh sculpted prims 189 _meshSculptedPrim = true; // mesh sculpted prims
188 _forceSimplePrimMeshing = false; // use complex meshing if called for 190 _forceSimplePrimMeshing = false; // use complex meshing if called for
189 191
190 m_meshLOD = 32; 192 m_meshLOD = 8;
193 m_sculptLOD = 32;
191 194
192 m_maxSubSteps = 10; 195 m_maxSubSteps = 10;
193 m_fixedTimeStep = 1f / 60f; 196 m_fixedTimeStep = 1f / 60f;
@@ -229,6 +232,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
229 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); 232 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing);
230 233
231 m_meshLOD = pConfig.GetInt("MeshLevelOfDetail", m_meshLOD); 234 m_meshLOD = pConfig.GetInt("MeshLevelOfDetail", m_meshLOD);
235 m_sculptLOD = pConfig.GetInt("SculptLevelOfDetail", m_sculptLOD);
232 236
233 m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps); 237 m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps);
234 m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep); 238 m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep);
@@ -489,10 +493,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
489 // can use an internal representation for the prim 493 // can use an internal representation for the prim
490 if (!_forceSimplePrimMeshing) 494 if (!_forceSimplePrimMeshing)
491 { 495 {
492 // m_log.DebugFormat("{0}: NeedsMeshing: simple mesh: profshape={1}, curve={2}", LogHeader, pbs.ProfileShape, pbs.PathCurve);
493 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 496 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
494 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 497 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
495 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) 498 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
496 { 499 {
497 500
498 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 501 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
@@ -663,7 +666,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
663 #region Runtime settable parameters 666 #region Runtime settable parameters
664 public static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[] 667 public static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[]
665 { 668 {
666 new PhysParameterEntry("MeshLOD", "Level of detail to render meshes (Power of two. Default 32)"), 669 new PhysParameterEntry("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)"),
670 new PhysParameterEntry("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)"),
667 new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), 671 new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"),
668 new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), 672 new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"),
669 new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), 673 new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"),
@@ -712,6 +716,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
712 switch (lparm) 716 switch (lparm)
713 { 717 {
714 case "meshlod": m_meshLOD = (int)val; break; 718 case "meshlod": m_meshLOD = (int)val; break;
719 case "sculptlod": m_sculptLOD = (int)val; break;
715 case "maxsubstep": m_maxSubSteps = (int)val; break; 720 case "maxsubstep": m_maxSubSteps = (int)val; break;
716 case "fixedtimestep": m_fixedTimeStep = val; break; 721 case "fixedtimestep": m_fixedTimeStep = val; break;
717 case "maxobjectmass": m_maximumObjectMass = val; break; 722 case "maxobjectmass": m_maximumObjectMass = val; break;
@@ -812,6 +817,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
812 switch (parm.ToLower()) 817 switch (parm.ToLower())
813 { 818 {
814 case "meshlod": val = (float)m_meshLOD; break; 819 case "meshlod": val = (float)m_meshLOD; break;
820 case "sculptlod": val = (float)m_sculptLOD; break;
815 case "maxsubstep": val = (float)m_maxSubSteps; break; 821 case "maxsubstep": val = (float)m_maxSubSteps; break;
816 case "fixedtimestep": val = m_fixedTimeStep; break; 822 case "fixedtimestep": val = m_fixedTimeStep; break;
817 case "maxobjectmass": val = m_maximumObjectMass; break; 823 case "maxobjectmass": val = m_maximumObjectMass; break;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index bf953df..a610c8d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -49,7 +49,8 @@ public struct ShapeData
49 SHAPE_CONE = 2, 49 SHAPE_CONE = 2,
50 SHAPE_CYLINDER = 3, 50 SHAPE_CYLINDER = 3,
51 SHAPE_SPHERE = 4, 51 SHAPE_SPHERE = 4,
52 SHAPE_HULL = 5 52 SHAPE_MESH = 5,
53 SHAPE_HULL = 6
53 }; 54 };
54 public uint ID; 55 public uint ID;
55 public PhysicsShapeType Type; 56 public PhysicsShapeType Type;
@@ -59,6 +60,7 @@ public struct ShapeData
59 public Vector3 Scale; 60 public Vector3 Scale;
60 public float Mass; 61 public float Mass;
61 public float Buoyancy; 62 public float Buoyancy;
63 public System.UInt64 HullKey;
62 public System.UInt64 MeshKey; 64 public System.UInt64 MeshKey;
63 public float Friction; 65 public float Friction;
64 public float Restitution; 66 public float Restitution;
@@ -158,20 +160,29 @@ public static extern void Shutdown(uint worldID);
158 160
159[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 161[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
160public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, 162public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep,
161 out int updatedEntityCount, 163 out int updatedEntityCount,
162 out IntPtr updatedEntitiesPtr, 164 out IntPtr updatedEntitiesPtr,
163 out int collidersCount, 165 out int collidersCount,
164 out IntPtr collidersPtr); 166 out IntPtr collidersPtr);
165 167
166[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 168[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
167public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, int hullCount, 169public static extern bool CreateHull(uint worldID, System.UInt64 meshKey,
168 [MarshalAs(UnmanagedType.LPArray)] float[] hulls 170 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls
171 );
172
173[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
174public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey,
175 int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
176 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices
169 ); 177 );
170 178
171[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 179[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
172public static extern bool DestroyHull(uint worldID, System.UInt64 meshKey); 180public static extern bool DestroyHull(uint worldID, System.UInt64 meshKey);
173 181
174[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 182[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
183public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
184
185[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
175public static extern bool CreateObject(uint worldID, ShapeData shapeData); 186public static extern bool CreateObject(uint worldID, ShapeData shapeData);
176 187
177[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 188[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -179,9 +190,9 @@ public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData
179 190
180[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 191[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
181public static extern void AddConstraint(uint worldID, uint id1, uint id2, 192public static extern void AddConstraint(uint worldID, uint id1, uint id2,
182 Vector3 frame1, Quaternion frame1rot, 193 Vector3 frame1, Quaternion frame1rot,
183 Vector3 frame2, Quaternion frame2rot, 194 Vector3 frame2, Quaternion frame2rot,
184 Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular); 195 Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular);
185 196
186[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 197[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
187public static extern bool RemoveConstraintByID(uint worldID, uint id1); 198public static extern bool RemoveConstraintByID(uint worldID, uint id1);