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/BulletSPlugin/BSPrim.cs | |
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 |
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 | } |