diff options
author | Robert Adams | 2011-08-26 15:51:21 -0700 |
---|---|---|
committer | Mic Bowman | 2011-08-26 15:51:21 -0700 |
commit | 21708b832b1d6679d5f6de27eb3bd0b920ef0fa7 (patch) | |
tree | dba3bb4565adfdd1aaad9720c002f1f1ca3ce990 /OpenSim/Region/Physics | |
parent | Merge branch 'master' into bulletsim (diff) | |
download | opensim-SC-21708b832b1d6679d5f6de27eb3bd0b920ef0fa7.zip opensim-SC-21708b832b1d6679d5f6de27eb3bd0b920ef0fa7.tar.gz opensim-SC-21708b832b1d6679d5f6de27eb3bd0b920ef0fa7.tar.bz2 opensim-SC-21708b832b1d6679d5f6de27eb3bd0b920ef0fa7.tar.xz |
BulletSim: add mesh representation. Use meshes for static objects and switch to hulls for physical objects.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 306 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 20 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 31 |
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; | |||
37 | using OpenSim.Region.Framework; | 37 | using 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 | // |
59 | namespace OpenSim.Region.Physics.BulletSPlugin | 56 | namespace 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] |
160 | public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, | 162 | public 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] |
167 | public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, int hullCount, | 169 | public 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] | ||
174 | public 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] |
172 | public static extern bool DestroyHull(uint worldID, System.UInt64 meshKey); | 180 | public 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] |
183 | public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey); | ||
184 | |||
185 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
175 | public static extern bool CreateObject(uint worldID, ShapeData shapeData); | 186 | public 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] |
181 | public static extern void AddConstraint(uint worldID, uint id1, uint id2, | 192 | public 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] |
187 | public static extern bool RemoveConstraintByID(uint worldID, uint id1); | 198 | public static extern bool RemoveConstraintByID(uint worldID, uint id1); |