aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
authorDavid Walter Seikel2016-11-03 21:44:39 +1000
committerDavid Walter Seikel2016-11-03 21:44:39 +1000
commit134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch)
tree216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Region/Physics/BulletSPlugin
parentMore changing to production grid. Double oops. (diff)
downloadopensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs1839
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs1622
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs662
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs827
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs138
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs151
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs180
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs55
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs1383
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs329
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs392
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs312
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs200
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs347
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs582
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs386
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs76
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs1513
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs946
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs1009
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs232
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs171
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs458
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs265
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs263
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt272
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs33
27 files changed, 0 insertions, 14643 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
deleted file mode 100755
index 8c6e7d6..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ /dev/null
@@ -1,1839 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using System.Runtime.InteropServices;
31using System.Security;
32using System.Text;
33
34using OpenSim.Framework;
35
36using OpenMetaverse;
37
38namespace OpenSim.Region.Physics.BulletSPlugin
39{
40public sealed class BSAPIUnman : BSAPITemplate
41{
42
43private sealed class BulletWorldUnman : BulletWorld
44{
45 public IntPtr ptr;
46 public BulletWorldUnman(uint id, BSScene physScene, IntPtr xx)
47 : base(id, physScene)
48 {
49 ptr = xx;
50 }
51}
52
53private sealed class BulletBodyUnman : BulletBody
54{
55 public IntPtr ptr;
56 public BulletBodyUnman(uint id, IntPtr xx)
57 : base(id)
58 {
59 ptr = xx;
60 }
61 public override bool HasPhysicalBody
62 {
63 get { return ptr != IntPtr.Zero; }
64 }
65 public override void Clear()
66 {
67 ptr = IntPtr.Zero;
68 }
69 public override string AddrString
70 {
71 get { return ptr.ToString("X"); }
72 }
73}
74
75private sealed class BulletShapeUnman : BulletShape
76{
77 public IntPtr ptr;
78 public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ)
79 : base()
80 {
81 ptr = xx;
82 type = typ;
83 }
84 public override bool HasPhysicalShape
85 {
86 get { return ptr != IntPtr.Zero; }
87 }
88 public override void Clear()
89 {
90 ptr = IntPtr.Zero;
91 }
92 public override BulletShape Clone()
93 {
94 return new BulletShapeUnman(ptr, type);
95 }
96 public override bool ReferenceSame(BulletShape other)
97 {
98 BulletShapeUnman otheru = other as BulletShapeUnman;
99 return (otheru != null) && (this.ptr == otheru.ptr);
100
101 }
102 public override string AddrString
103 {
104 get { return ptr.ToString("X"); }
105 }
106}
107private sealed class BulletConstraintUnman : BulletConstraint
108{
109 public BulletConstraintUnman(IntPtr xx) : base()
110 {
111 ptr = xx;
112 }
113 public IntPtr ptr;
114
115 public override void Clear()
116 {
117 ptr = IntPtr.Zero;
118 }
119 public override bool HasPhysicalConstraint { get { return ptr != IntPtr.Zero; } }
120
121 // Used for log messages for a unique display of the memory/object allocated to this instance
122 public override string AddrString
123 {
124 get { return ptr.ToString("X"); }
125 }
126}
127
128// We pin the memory passed between the managed and unmanaged code.
129GCHandle m_paramsHandle;
130private GCHandle m_collisionArrayPinnedHandle;
131private GCHandle m_updateArrayPinnedHandle;
132
133// Handle to the callback used by the unmanaged code to call into the managed code.
134// Used for debug logging.
135// Need to store the handle in a persistant variable so it won't be freed.
136private BSAPICPP.DebugLogCallback m_DebugLogCallbackHandle;
137
138private BSScene PhysicsScene { get; set; }
139
140public override string BulletEngineName { get { return "BulletUnmanaged"; } }
141public override string BulletEngineVersion { get; protected set; }
142
143public BSAPIUnman(string paramName, BSScene physScene)
144{
145 PhysicsScene = physScene;
146
147 // Do something fancy with the paramName to get the right DLL implementation
148 // like "Bullet-2.80-OpenCL-Intel" loading the version for Intel based OpenCL implementation, etc.
149 if (Util.IsWindows())
150 Util.LoadArchSpecificWindowsDll("BulletSim.dll");
151 // If not Windows, loading is performed by the
152 // Mono loader as specified in
153 // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config".
154}
155
156// Initialization and simulation
157public override BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
158 int maxCollisions, ref CollisionDesc[] collisionArray,
159 int maxUpdates, ref EntityProperties[] updateArray
160 )
161{
162 // Pin down the memory that will be used to pass object collisions and updates back from unmanaged code
163 m_paramsHandle = GCHandle.Alloc(parms, GCHandleType.Pinned);
164 m_collisionArrayPinnedHandle = GCHandle.Alloc(collisionArray, GCHandleType.Pinned);
165 m_updateArrayPinnedHandle = GCHandle.Alloc(updateArray, GCHandleType.Pinned);
166
167 // If Debug logging level, enable logging from the unmanaged code
168 m_DebugLogCallbackHandle = null;
169 if (BSScene.m_log.IsDebugEnabled || PhysicsScene.PhysicsLogging.Enabled)
170 {
171 BSScene.m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", BSScene.LogHeader);
172 if (PhysicsScene.PhysicsLogging.Enabled)
173 // The handle is saved in a variable to make sure it doesn't get freed after this call
174 m_DebugLogCallbackHandle = new BSAPICPP.DebugLogCallback(BulletLoggerPhysLog);
175 else
176 m_DebugLogCallbackHandle = new BSAPICPP.DebugLogCallback(BulletLogger);
177 }
178
179 // Get the version of the DLL
180 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
181 // BulletEngineVersion = BulletSimAPI.GetVersion2();
182 BulletEngineVersion = "";
183
184 // Call the unmanaged code with the buffers and other information
185 return new BulletWorldUnman(0, PhysicsScene, BSAPICPP.Initialize2(maxPosition, m_paramsHandle.AddrOfPinnedObject(),
186 maxCollisions, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
187 maxUpdates, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
188 m_DebugLogCallbackHandle));
189
190}
191
192// Called directly from unmanaged code so don't do much
193private void BulletLogger(string msg)
194{
195 BSScene.m_log.Debug("[BULLETS UNMANAGED]:" + msg);
196}
197
198// Called directly from unmanaged code so don't do much
199private void BulletLoggerPhysLog(string msg)
200{
201 PhysicsScene.DetailLog("[BULLETS UNMANAGED]:" + msg);
202}
203
204public override int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
205 out int updatedEntityCount, out int collidersCount)
206{
207 BulletWorldUnman worldu = world as BulletWorldUnman;
208 return BSAPICPP.PhysicsStep2(worldu.ptr, timeStep, maxSubSteps, fixedTimeStep, out updatedEntityCount, out collidersCount);
209}
210
211public override void Shutdown(BulletWorld world)
212{
213 BulletWorldUnman worldu = world as BulletWorldUnman;
214 BSAPICPP.Shutdown2(worldu.ptr);
215}
216
217public override bool PushUpdate(BulletBody obj)
218{
219 BulletBodyUnman bodyu = obj as BulletBodyUnman;
220 return BSAPICPP.PushUpdate2(bodyu.ptr);
221}
222
223public override bool UpdateParameter(BulletWorld world, uint localID, String parm, float value)
224{
225 BulletWorldUnman worldu = world as BulletWorldUnman;
226 return BSAPICPP.UpdateParameter2(worldu.ptr, localID, parm, value);
227}
228
229// =====================================================================================
230// Mesh, hull, shape and body creation helper routines
231public override BulletShape CreateMeshShape(BulletWorld world,
232 int indicesCount, int[] indices,
233 int verticesCount, float[] vertices)
234{
235 BulletWorldUnman worldu = world as BulletWorldUnman;
236 return new BulletShapeUnman(
237 BSAPICPP.CreateMeshShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices),
238 BSPhysicsShapeType.SHAPE_MESH);
239}
240
241public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls)
242{
243 BulletWorldUnman worldu = world as BulletWorldUnman;
244 return new BulletShapeUnman(
245 BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls),
246 BSPhysicsShapeType.SHAPE_HULL);
247}
248
249public override BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
250{
251 BulletWorldUnman worldu = world as BulletWorldUnman;
252 BulletShapeUnman shapeu = meshShape as BulletShapeUnman;
253 return new BulletShapeUnman(
254 BSAPICPP.BuildHullShapeFromMesh2(worldu.ptr, shapeu.ptr),
255 BSPhysicsShapeType.SHAPE_HULL);
256}
257
258public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData)
259{
260 BulletWorldUnman worldu = world as BulletWorldUnman;
261 return new BulletShapeUnman(BSAPICPP.BuildNativeShape2(worldu.ptr, shapeData), shapeData.Type);
262}
263
264public override bool IsNativeShape(BulletShape shape)
265{
266 BulletShapeUnman shapeu = shape as BulletShapeUnman;
267 if (shapeu != null && shapeu.HasPhysicalShape)
268 return BSAPICPP.IsNativeShape2(shapeu.ptr);
269 return false;
270}
271
272public override void SetShapeCollisionMargin(BulletShape shape, float margin)
273{
274 BulletShapeUnman shapeu = shape as BulletShapeUnman;
275 if (shapeu != null && shapeu.HasPhysicalShape)
276 BSAPICPP.SetShapeCollisionMargin2(shapeu.ptr, margin);
277}
278
279public override BulletShape BuildCapsuleShape(BulletWorld world, float radius, float height, Vector3 scale)
280{
281 BulletWorldUnman worldu = world as BulletWorldUnman;
282 return new BulletShapeUnman(
283 BSAPICPP.BuildCapsuleShape2(worldu.ptr, radius, height, scale),
284 BSPhysicsShapeType.SHAPE_CAPSULE);
285}
286
287public override BulletShape CreateCompoundShape(BulletWorld world, bool enableDynamicAabbTree)
288{
289 BulletWorldUnman worldu = world as BulletWorldUnman;
290 return new BulletShapeUnman(
291 BSAPICPP.CreateCompoundShape2(worldu.ptr, enableDynamicAabbTree),
292 BSPhysicsShapeType.SHAPE_COMPOUND);
293
294}
295
296public override int GetNumberOfCompoundChildren(BulletShape shape)
297{
298 BulletShapeUnman shapeu = shape as BulletShapeUnman;
299 if (shapeu != null && shapeu.HasPhysicalShape)
300 return BSAPICPP.GetNumberOfCompoundChildren2(shapeu.ptr);
301 return 0;
302}
303
304public override void AddChildShapeToCompoundShape(BulletShape shape, BulletShape addShape, Vector3 pos, Quaternion rot)
305{
306 BulletShapeUnman shapeu = shape as BulletShapeUnman;
307 BulletShapeUnman addShapeu = addShape as BulletShapeUnman;
308 BSAPICPP.AddChildShapeToCompoundShape2(shapeu.ptr, addShapeu.ptr, pos, rot);
309}
310
311public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape shape, int indx)
312{
313 BulletShapeUnman shapeu = shape as BulletShapeUnman;
314 return new BulletShapeUnman(BSAPICPP.GetChildShapeFromCompoundShapeIndex2(shapeu.ptr, indx), BSPhysicsShapeType.SHAPE_UNKNOWN);
315}
316
317public override BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape shape, int indx)
318{
319 BulletShapeUnman shapeu = shape as BulletShapeUnman;
320 return new BulletShapeUnman(BSAPICPP.RemoveChildShapeFromCompoundShapeIndex2(shapeu.ptr, indx), BSPhysicsShapeType.SHAPE_UNKNOWN);
321}
322
323public override void RemoveChildShapeFromCompoundShape(BulletShape shape, BulletShape removeShape)
324{
325 BulletShapeUnman shapeu = shape as BulletShapeUnman;
326 BulletShapeUnman removeShapeu = removeShape as BulletShapeUnman;
327 BSAPICPP.RemoveChildShapeFromCompoundShape2(shapeu.ptr, removeShapeu.ptr);
328}
329
330public override void RecalculateCompoundShapeLocalAabb(BulletShape shape)
331{
332 BulletShapeUnman shapeu = shape as BulletShapeUnman;
333 BSAPICPP.RecalculateCompoundShapeLocalAabb2(shapeu.ptr);
334}
335
336public override BulletShape DuplicateCollisionShape(BulletWorld world, BulletShape srcShape, uint id)
337{
338 BulletWorldUnman worldu = world as BulletWorldUnman;
339 BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman;
340 return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.type);
341}
342
343public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape)
344{
345 BulletWorldUnman worldu = world as BulletWorldUnman;
346 BulletShapeUnman shapeu = shape as BulletShapeUnman;
347 return BSAPICPP.DeleteCollisionShape2(worldu.ptr, shapeu.ptr);
348}
349
350public override CollisionObjectTypes GetBodyType(BulletBody obj)
351{
352 BulletBodyUnman bodyu = obj as BulletBodyUnman;
353 return (CollisionObjectTypes)BSAPICPP.GetBodyType2(bodyu.ptr);
354}
355
356public override BulletBody CreateBodyFromShape(BulletWorld world, BulletShape shape, uint id, Vector3 pos, Quaternion rot)
357{
358 BulletWorldUnman worldu = world as BulletWorldUnman;
359 BulletShapeUnman shapeu = shape as BulletShapeUnman;
360 return new BulletBodyUnman(id, BSAPICPP.CreateBodyFromShape2(worldu.ptr, shapeu.ptr, id, pos, rot));
361}
362
363public override BulletBody CreateBodyWithDefaultMotionState(BulletShape shape, uint id, Vector3 pos, Quaternion rot)
364{
365 BulletShapeUnman shapeu = shape as BulletShapeUnman;
366 return new BulletBodyUnman(id, BSAPICPP.CreateBodyWithDefaultMotionState2(shapeu.ptr, id, pos, rot));
367}
368
369public override BulletBody CreateGhostFromShape(BulletWorld world, BulletShape shape, uint id, Vector3 pos, Quaternion rot)
370{
371 BulletWorldUnman worldu = world as BulletWorldUnman;
372 BulletShapeUnman shapeu = shape as BulletShapeUnman;
373 return new BulletBodyUnman(id, BSAPICPP.CreateGhostFromShape2(worldu.ptr, shapeu.ptr, id, pos, rot));
374}
375
376public override void DestroyObject(BulletWorld world, BulletBody obj)
377{
378 BulletWorldUnman worldu = world as BulletWorldUnman;
379 BulletBodyUnman bodyu = obj as BulletBodyUnman;
380 BSAPICPP.DestroyObject2(worldu.ptr, bodyu.ptr);
381}
382
383// =====================================================================================
384// Terrain creation and helper routines
385public override BulletShape CreateGroundPlaneShape(uint id, float height, float collisionMargin)
386{
387 return new BulletShapeUnman(BSAPICPP.CreateGroundPlaneShape2(id, height, collisionMargin), BSPhysicsShapeType.SHAPE_GROUNDPLANE);
388}
389
390public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
391 float scaleFactor, float collisionMargin)
392{
393 return new BulletShapeUnman(BSAPICPP.CreateTerrainShape2(id, size, minHeight, maxHeight, heightMap, scaleFactor, collisionMargin),
394 BSPhysicsShapeType.SHAPE_TERRAIN);
395}
396
397// =====================================================================================
398// Constraint creation and helper routines
399public override BulletConstraint Create6DofConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
400 Vector3 frame1loc, Quaternion frame1rot,
401 Vector3 frame2loc, Quaternion frame2rot,
402 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
403{
404 BulletWorldUnman worldu = world as BulletWorldUnman;
405 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
406 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
407 return new BulletConstraintUnman(BSAPICPP.Create6DofConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, frame1loc, frame1rot,
408 frame2loc, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
409}
410
411public override BulletConstraint Create6DofConstraintToPoint(BulletWorld world, BulletBody obj1, BulletBody obj2,
412 Vector3 joinPoint,
413 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
414{
415 BulletWorldUnman worldu = world as BulletWorldUnman;
416 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
417 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
418 return new BulletConstraintUnman(BSAPICPP.Create6DofConstraintToPoint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr,
419 joinPoint, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
420}
421
422public override BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
423 Vector3 pivotinA, Vector3 pivotinB,
424 Vector3 axisInA, Vector3 axisInB,
425 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
426{
427 BulletWorldUnman worldu = world as BulletWorldUnman;
428 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
429 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
430 return new BulletConstraintUnman(BSAPICPP.CreateHingeConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr,
431 pivotinA, pivotinB, axisInA, axisInB, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
432}
433
434public override void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse)
435{
436 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
437 BSAPICPP.SetConstraintEnable2(constrainu.ptr, numericTrueFalse);
438}
439
440public override void SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations)
441{
442 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
443 BSAPICPP.SetConstraintNumSolverIterations2(constrainu.ptr, iterations);
444}
445
446public override bool SetFrames(BulletConstraint constrain,
447 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
448{
449 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
450 return BSAPICPP.SetFrames2(constrainu.ptr, frameA, frameArot, frameB, frameBrot);
451}
452
453public override bool SetLinearLimits(BulletConstraint constrain, Vector3 low, Vector3 hi)
454{
455 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
456 return BSAPICPP.SetLinearLimits2(constrainu.ptr, low, hi);
457}
458
459public override bool SetAngularLimits(BulletConstraint constrain, Vector3 low, Vector3 hi)
460{
461 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
462 return BSAPICPP.SetAngularLimits2(constrainu.ptr, low, hi);
463}
464
465public override bool UseFrameOffset(BulletConstraint constrain, float enable)
466{
467 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
468 return BSAPICPP.UseFrameOffset2(constrainu.ptr, enable);
469}
470
471public override bool TranslationalLimitMotor(BulletConstraint constrain, float enable, float targetVel, float maxMotorForce)
472{
473 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
474 return BSAPICPP.TranslationalLimitMotor2(constrainu.ptr, enable, targetVel, maxMotorForce);
475}
476
477public override bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold)
478{
479 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
480 return BSAPICPP.SetBreakingImpulseThreshold2(constrainu.ptr, threshold);
481}
482
483public override bool CalculateTransforms(BulletConstraint constrain)
484{
485 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
486 return BSAPICPP.CalculateTransforms2(constrainu.ptr);
487}
488
489public override bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis)
490{
491 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
492 return BSAPICPP.SetConstraintParam2(constrainu.ptr, paramIndex, value, axis);
493}
494
495public override bool DestroyConstraint(BulletWorld world, BulletConstraint constrain)
496{
497 BulletWorldUnman worldu = world as BulletWorldUnman;
498 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
499 return BSAPICPP.DestroyConstraint2(worldu.ptr, constrainu.ptr);
500}
501
502// =====================================================================================
503// btCollisionWorld entries
504public override void UpdateSingleAabb(BulletWorld world, BulletBody obj)
505{
506 BulletWorldUnman worldu = world as BulletWorldUnman;
507 BulletBodyUnman bodyu = obj as BulletBodyUnman;
508 BSAPICPP.UpdateSingleAabb2(worldu.ptr, bodyu.ptr);
509}
510
511public override void UpdateAabbs(BulletWorld world)
512{
513 BulletWorldUnman worldu = world as BulletWorldUnman;
514 BSAPICPP.UpdateAabbs2(worldu.ptr);
515}
516
517public override bool GetForceUpdateAllAabbs(BulletWorld world)
518{
519 BulletWorldUnman worldu = world as BulletWorldUnman;
520 return BSAPICPP.GetForceUpdateAllAabbs2(worldu.ptr);
521}
522
523public override void SetForceUpdateAllAabbs(BulletWorld world, bool force)
524{
525 BulletWorldUnman worldu = world as BulletWorldUnman;
526 BSAPICPP.SetForceUpdateAllAabbs2(worldu.ptr, force);
527}
528
529// =====================================================================================
530// btDynamicsWorld entries
531public override bool AddObjectToWorld(BulletWorld world, BulletBody obj)
532{
533 // Bullet resets several variables when an object is added to the world.
534 // Gravity is reset to world default depending on the static/dynamic
535 // type. Of course, the collision flags in the broadphase proxy are initialized to default.
536 BulletWorldUnman worldu = world as BulletWorldUnman;
537 BulletBodyUnman bodyu = obj as BulletBodyUnman;
538
539 Vector3 origGrav = BSAPICPP.GetGravity2(bodyu.ptr);
540
541 bool ret = BSAPICPP.AddObjectToWorld2(worldu.ptr, bodyu.ptr);
542
543 if (ret)
544 {
545 BSAPICPP.SetGravity2(bodyu.ptr, origGrav);
546 obj.ApplyCollisionMask(world.physicsScene);
547 }
548 return ret;
549}
550
551public override bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj)
552{
553 BulletWorldUnman worldu = world as BulletWorldUnman;
554 BulletBodyUnman bodyu = obj as BulletBodyUnman;
555 return BSAPICPP.RemoveObjectFromWorld2(worldu.ptr, bodyu.ptr);
556}
557
558public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects)
559{
560 BulletWorldUnman worldu = world as BulletWorldUnman;
561 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
562 return BSAPICPP.AddConstraintToWorld2(worldu.ptr, constrainu.ptr, disableCollisionsBetweenLinkedObjects);
563}
564
565public override bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain)
566{
567 BulletWorldUnman worldu = world as BulletWorldUnman;
568 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
569 return BSAPICPP.RemoveConstraintFromWorld2(worldu.ptr, constrainu.ptr);
570}
571// =====================================================================================
572// btCollisionObject entries
573public override Vector3 GetAnisotripicFriction(BulletConstraint constrain)
574{
575 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
576 return BSAPICPP.GetAnisotripicFriction2(constrainu.ptr);
577}
578
579public override Vector3 SetAnisotripicFriction(BulletConstraint constrain, Vector3 frict)
580{
581 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
582 return BSAPICPP.SetAnisotripicFriction2(constrainu.ptr, frict);
583}
584
585public override bool HasAnisotripicFriction(BulletConstraint constrain)
586{
587 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
588 return BSAPICPP.HasAnisotripicFriction2(constrainu.ptr);
589}
590
591public override void SetContactProcessingThreshold(BulletBody obj, float val)
592{
593 BulletBodyUnman bodyu = obj as BulletBodyUnman;
594 BSAPICPP.SetContactProcessingThreshold2(bodyu.ptr, val);
595}
596
597public override float GetContactProcessingThreshold(BulletBody obj)
598{
599 BulletBodyUnman bodyu = obj as BulletBodyUnman;
600 return BSAPICPP.GetContactProcessingThreshold2(bodyu.ptr);
601}
602
603public override bool IsStaticObject(BulletBody obj)
604{
605 BulletBodyUnman bodyu = obj as BulletBodyUnman;
606 return BSAPICPP.IsStaticObject2(bodyu.ptr);
607}
608
609public override bool IsKinematicObject(BulletBody obj)
610{
611 BulletBodyUnman bodyu = obj as BulletBodyUnman;
612 return BSAPICPP.IsKinematicObject2(bodyu.ptr);
613}
614
615public override bool IsStaticOrKinematicObject(BulletBody obj)
616{
617 BulletBodyUnman bodyu = obj as BulletBodyUnman;
618 return BSAPICPP.IsStaticOrKinematicObject2(bodyu.ptr);
619}
620
621public override bool HasContactResponse(BulletBody obj)
622{
623 BulletBodyUnman bodyu = obj as BulletBodyUnman;
624 return BSAPICPP.HasContactResponse2(bodyu.ptr);
625}
626
627public override void SetCollisionShape(BulletWorld world, BulletBody obj, BulletShape shape)
628{
629 BulletWorldUnman worldu = world as BulletWorldUnman;
630 BulletBodyUnman bodyu = obj as BulletBodyUnman;
631 BulletShapeUnman shapeu = shape as BulletShapeUnman;
632 if (worldu != null && bodyu != null)
633 {
634 // Special case to allow the caller to zero out the reference to any physical shape
635 if (shapeu != null)
636 BSAPICPP.SetCollisionShape2(worldu.ptr, bodyu.ptr, shapeu.ptr);
637 else
638 BSAPICPP.SetCollisionShape2(worldu.ptr, bodyu.ptr, IntPtr.Zero);
639 }
640}
641
642public override BulletShape GetCollisionShape(BulletBody obj)
643{
644 BulletBodyUnman bodyu = obj as BulletBodyUnman;
645 return new BulletShapeUnman(BSAPICPP.GetCollisionShape2(bodyu.ptr), BSPhysicsShapeType.SHAPE_UNKNOWN);
646}
647
648public override int GetActivationState(BulletBody obj)
649{
650 BulletBodyUnman bodyu = obj as BulletBodyUnman;
651 return BSAPICPP.GetActivationState2(bodyu.ptr);
652}
653
654public override void SetActivationState(BulletBody obj, int state)
655{
656 BulletBodyUnman bodyu = obj as BulletBodyUnman;
657 BSAPICPP.SetActivationState2(bodyu.ptr, state);
658}
659
660public override void SetDeactivationTime(BulletBody obj, float dtime)
661{
662 BulletBodyUnman bodyu = obj as BulletBodyUnman;
663 BSAPICPP.SetDeactivationTime2(bodyu.ptr, dtime);
664}
665
666public override float GetDeactivationTime(BulletBody obj)
667{
668 BulletBodyUnman bodyu = obj as BulletBodyUnman;
669 return BSAPICPP.GetDeactivationTime2(bodyu.ptr);
670}
671
672public override void ForceActivationState(BulletBody obj, ActivationState state)
673{
674 BulletBodyUnman bodyu = obj as BulletBodyUnman;
675 BSAPICPP.ForceActivationState2(bodyu.ptr, state);
676}
677
678public override void Activate(BulletBody obj, bool forceActivation)
679{
680 BulletBodyUnman bodyu = obj as BulletBodyUnman;
681 BSAPICPP.Activate2(bodyu.ptr, forceActivation);
682}
683
684public override bool IsActive(BulletBody obj)
685{
686 BulletBodyUnman bodyu = obj as BulletBodyUnman;
687 return BSAPICPP.IsActive2(bodyu.ptr);
688}
689
690public override void SetRestitution(BulletBody obj, float val)
691{
692 BulletBodyUnman bodyu = obj as BulletBodyUnman;
693 BSAPICPP.SetRestitution2(bodyu.ptr, val);
694}
695
696public override float GetRestitution(BulletBody obj)
697{
698 BulletBodyUnman bodyu = obj as BulletBodyUnman;
699 return BSAPICPP.GetRestitution2(bodyu.ptr);
700}
701
702public override void SetFriction(BulletBody obj, float val)
703{
704 BulletBodyUnman bodyu = obj as BulletBodyUnman;
705 BSAPICPP.SetFriction2(bodyu.ptr, val);
706}
707
708public override float GetFriction(BulletBody obj)
709{
710 BulletBodyUnman bodyu = obj as BulletBodyUnman;
711 return BSAPICPP.GetFriction2(bodyu.ptr);
712}
713
714public override Vector3 GetPosition(BulletBody obj)
715{
716 BulletBodyUnman bodyu = obj as BulletBodyUnman;
717 return BSAPICPP.GetPosition2(bodyu.ptr);
718}
719
720public override Quaternion GetOrientation(BulletBody obj)
721{
722 BulletBodyUnman bodyu = obj as BulletBodyUnman;
723 return BSAPICPP.GetOrientation2(bodyu.ptr);
724}
725
726public override void SetTranslation(BulletBody obj, Vector3 position, Quaternion rotation)
727{
728 BulletBodyUnman bodyu = obj as BulletBodyUnman;
729 BSAPICPP.SetTranslation2(bodyu.ptr, position, rotation);
730}
731
732 /*
733public override IntPtr GetBroadphaseHandle(BulletBody obj)
734{
735 BulletBodyUnman bodyu = obj as BulletBodyUnman;
736 return BSAPICPP.GetBroadphaseHandle2(bodyu.ptr);
737}
738
739public override void SetBroadphaseHandle(BulletBody obj, IntPtr handle)
740{
741 BulletBodyUnman bodyu = obj as BulletBodyUnman;
742 BSAPICPP.SetUserPointer2(bodyu.ptr, handle);
743}
744 */
745
746public override void SetInterpolationLinearVelocity(BulletBody obj, Vector3 vel)
747{
748 BulletBodyUnman bodyu = obj as BulletBodyUnman;
749 BSAPICPP.SetInterpolationLinearVelocity2(bodyu.ptr, vel);
750}
751
752public override void SetInterpolationAngularVelocity(BulletBody obj, Vector3 vel)
753{
754 BulletBodyUnman bodyu = obj as BulletBodyUnman;
755 BSAPICPP.SetInterpolationAngularVelocity2(bodyu.ptr, vel);
756}
757
758public override void SetInterpolationVelocity(BulletBody obj, Vector3 linearVel, Vector3 angularVel)
759{
760 BulletBodyUnman bodyu = obj as BulletBodyUnman;
761 BSAPICPP.SetInterpolationVelocity2(bodyu.ptr, linearVel, angularVel);
762}
763
764public override float GetHitFraction(BulletBody obj)
765{
766 BulletBodyUnman bodyu = obj as BulletBodyUnman;
767 return BSAPICPP.GetHitFraction2(bodyu.ptr);
768}
769
770public override void SetHitFraction(BulletBody obj, float val)
771{
772 BulletBodyUnman bodyu = obj as BulletBodyUnman;
773 BSAPICPP.SetHitFraction2(bodyu.ptr, val);
774}
775
776public override CollisionFlags GetCollisionFlags(BulletBody obj)
777{
778 BulletBodyUnman bodyu = obj as BulletBodyUnman;
779 return BSAPICPP.GetCollisionFlags2(bodyu.ptr);
780}
781
782public override CollisionFlags SetCollisionFlags(BulletBody obj, CollisionFlags flags)
783{
784 BulletBodyUnman bodyu = obj as BulletBodyUnman;
785 return BSAPICPP.SetCollisionFlags2(bodyu.ptr, flags);
786}
787
788public override CollisionFlags AddToCollisionFlags(BulletBody obj, CollisionFlags flags)
789{
790 BulletBodyUnman bodyu = obj as BulletBodyUnman;
791 return BSAPICPP.AddToCollisionFlags2(bodyu.ptr, flags);
792}
793
794public override CollisionFlags RemoveFromCollisionFlags(BulletBody obj, CollisionFlags flags)
795{
796 BulletBodyUnman bodyu = obj as BulletBodyUnman;
797 return BSAPICPP.RemoveFromCollisionFlags2(bodyu.ptr, flags);
798}
799
800public override float GetCcdMotionThreshold(BulletBody obj)
801{
802 BulletBodyUnman bodyu = obj as BulletBodyUnman;
803 return BSAPICPP.GetCcdMotionThreshold2(bodyu.ptr);
804}
805
806
807public override void SetCcdMotionThreshold(BulletBody obj, float val)
808{
809 BulletBodyUnman bodyu = obj as BulletBodyUnman;
810 BSAPICPP.SetCcdMotionThreshold2(bodyu.ptr, val);
811}
812
813public override float GetCcdSweptSphereRadius(BulletBody obj)
814{
815 BulletBodyUnman bodyu = obj as BulletBodyUnman;
816 return BSAPICPP.GetCcdSweptSphereRadius2(bodyu.ptr);
817}
818
819public override void SetCcdSweptSphereRadius(BulletBody obj, float val)
820{
821 BulletBodyUnman bodyu = obj as BulletBodyUnman;
822 BSAPICPP.SetCcdSweptSphereRadius2(bodyu.ptr, val);
823}
824
825public override IntPtr GetUserPointer(BulletBody obj)
826{
827 BulletBodyUnman bodyu = obj as BulletBodyUnman;
828 return BSAPICPP.GetUserPointer2(bodyu.ptr);
829}
830
831public override void SetUserPointer(BulletBody obj, IntPtr val)
832{
833 BulletBodyUnman bodyu = obj as BulletBodyUnman;
834 BSAPICPP.SetUserPointer2(bodyu.ptr, val);
835}
836
837// =====================================================================================
838// btRigidBody entries
839public override void ApplyGravity(BulletBody obj)
840{
841 BulletBodyUnman bodyu = obj as BulletBodyUnman;
842 BSAPICPP.ApplyGravity2(bodyu.ptr);
843}
844
845public override void SetGravity(BulletBody obj, Vector3 val)
846{
847 BulletBodyUnman bodyu = obj as BulletBodyUnman;
848 BSAPICPP.SetGravity2(bodyu.ptr, val);
849}
850
851public override Vector3 GetGravity(BulletBody obj)
852{
853 BulletBodyUnman bodyu = obj as BulletBodyUnman;
854 return BSAPICPP.GetGravity2(bodyu.ptr);
855}
856
857public override void SetDamping(BulletBody obj, float lin_damping, float ang_damping)
858{
859 BulletBodyUnman bodyu = obj as BulletBodyUnman;
860 BSAPICPP.SetDamping2(bodyu.ptr, lin_damping, ang_damping);
861}
862
863public override void SetLinearDamping(BulletBody obj, float lin_damping)
864{
865 BulletBodyUnman bodyu = obj as BulletBodyUnman;
866 BSAPICPP.SetLinearDamping2(bodyu.ptr, lin_damping);
867}
868
869public override void SetAngularDamping(BulletBody obj, float ang_damping)
870{
871 BulletBodyUnman bodyu = obj as BulletBodyUnman;
872 BSAPICPP.SetAngularDamping2(bodyu.ptr, ang_damping);
873}
874
875public override float GetLinearDamping(BulletBody obj)
876{
877 BulletBodyUnman bodyu = obj as BulletBodyUnman;
878 return BSAPICPP.GetLinearDamping2(bodyu.ptr);
879}
880
881public override float GetAngularDamping(BulletBody obj)
882{
883 BulletBodyUnman bodyu = obj as BulletBodyUnman;
884 return BSAPICPP.GetAngularDamping2(bodyu.ptr);
885}
886
887public override float GetLinearSleepingThreshold(BulletBody obj)
888{
889 BulletBodyUnman bodyu = obj as BulletBodyUnman;
890 return BSAPICPP.GetLinearSleepingThreshold2(bodyu.ptr);
891}
892
893public override void ApplyDamping(BulletBody obj, float timeStep)
894{
895 BulletBodyUnman bodyu = obj as BulletBodyUnman;
896 BSAPICPP.ApplyDamping2(bodyu.ptr, timeStep);
897}
898
899public override void SetMassProps(BulletBody obj, float mass, Vector3 inertia)
900{
901 BulletBodyUnman bodyu = obj as BulletBodyUnman;
902 BSAPICPP.SetMassProps2(bodyu.ptr, mass, inertia);
903}
904
905public override Vector3 GetLinearFactor(BulletBody obj)
906{
907 BulletBodyUnman bodyu = obj as BulletBodyUnman;
908 return BSAPICPP.GetLinearFactor2(bodyu.ptr);
909}
910
911public override void SetLinearFactor(BulletBody obj, Vector3 factor)
912{
913 BulletBodyUnman bodyu = obj as BulletBodyUnman;
914 BSAPICPP.SetLinearFactor2(bodyu.ptr, factor);
915}
916
917public override void SetCenterOfMassByPosRot(BulletBody obj, Vector3 pos, Quaternion rot)
918{
919 BulletBodyUnman bodyu = obj as BulletBodyUnman;
920 BSAPICPP.SetCenterOfMassByPosRot2(bodyu.ptr, pos, rot);
921}
922
923// Add a force to the object as if its mass is one.
924public override void ApplyCentralForce(BulletBody obj, Vector3 force)
925{
926 BulletBodyUnman bodyu = obj as BulletBodyUnman;
927 BSAPICPP.ApplyCentralForce2(bodyu.ptr, force);
928}
929
930// Set the force being applied to the object as if its mass is one.
931public override void SetObjectForce(BulletBody obj, Vector3 force)
932{
933 BulletBodyUnman bodyu = obj as BulletBodyUnman;
934 BSAPICPP.SetObjectForce2(bodyu.ptr, force);
935}
936
937public override Vector3 GetTotalForce(BulletBody obj)
938{
939 BulletBodyUnman bodyu = obj as BulletBodyUnman;
940 return BSAPICPP.GetTotalForce2(bodyu.ptr);
941}
942
943public override Vector3 GetTotalTorque(BulletBody obj)
944{
945 BulletBodyUnman bodyu = obj as BulletBodyUnman;
946 return BSAPICPP.GetTotalTorque2(bodyu.ptr);
947}
948
949public override Vector3 GetInvInertiaDiagLocal(BulletBody obj)
950{
951 BulletBodyUnman bodyu = obj as BulletBodyUnman;
952 return BSAPICPP.GetInvInertiaDiagLocal2(bodyu.ptr);
953}
954
955public override void SetInvInertiaDiagLocal(BulletBody obj, Vector3 inert)
956{
957 BulletBodyUnman bodyu = obj as BulletBodyUnman;
958 BSAPICPP.SetInvInertiaDiagLocal2(bodyu.ptr, inert);
959}
960
961public override void SetSleepingThresholds(BulletBody obj, float lin_threshold, float ang_threshold)
962{
963 BulletBodyUnman bodyu = obj as BulletBodyUnman;
964 BSAPICPP.SetSleepingThresholds2(bodyu.ptr, lin_threshold, ang_threshold);
965}
966
967public override void ApplyTorque(BulletBody obj, Vector3 torque)
968{
969 BulletBodyUnman bodyu = obj as BulletBodyUnman;
970 BSAPICPP.ApplyTorque2(bodyu.ptr, torque);
971}
972
973// Apply force at the given point. Will add torque to the object.
974public override void ApplyForce(BulletBody obj, Vector3 force, Vector3 pos)
975{
976 BulletBodyUnman bodyu = obj as BulletBodyUnman;
977 BSAPICPP.ApplyForce2(bodyu.ptr, force, pos);
978}
979
980// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
981public override void ApplyCentralImpulse(BulletBody obj, Vector3 imp)
982{
983 BulletBodyUnman bodyu = obj as BulletBodyUnman;
984 BSAPICPP.ApplyCentralImpulse2(bodyu.ptr, imp);
985}
986
987// Apply impulse to the object's torque. Force is scaled by object's mass.
988public override void ApplyTorqueImpulse(BulletBody obj, Vector3 imp)
989{
990 BulletBodyUnman bodyu = obj as BulletBodyUnman;
991 BSAPICPP.ApplyTorqueImpulse2(bodyu.ptr, imp);
992}
993
994// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
995public override void ApplyImpulse(BulletBody obj, Vector3 imp, Vector3 pos)
996{
997 BulletBodyUnman bodyu = obj as BulletBodyUnman;
998 BSAPICPP.ApplyImpulse2(bodyu.ptr, imp, pos);
999}
1000
1001public override void ClearForces(BulletBody obj)
1002{
1003 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1004 BSAPICPP.ClearForces2(bodyu.ptr);
1005}
1006
1007public override void ClearAllForces(BulletBody obj)
1008{
1009 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1010 BSAPICPP.ClearAllForces2(bodyu.ptr);
1011}
1012
1013public override void UpdateInertiaTensor(BulletBody obj)
1014{
1015 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1016 BSAPICPP.UpdateInertiaTensor2(bodyu.ptr);
1017}
1018
1019public override Vector3 GetLinearVelocity(BulletBody obj)
1020{
1021 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1022 return BSAPICPP.GetLinearVelocity2(bodyu.ptr);
1023}
1024
1025public override Vector3 GetAngularVelocity(BulletBody obj)
1026{
1027 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1028 return BSAPICPP.GetAngularVelocity2(bodyu.ptr);
1029}
1030
1031public override void SetLinearVelocity(BulletBody obj, Vector3 vel)
1032{
1033 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1034 BSAPICPP.SetLinearVelocity2(bodyu.ptr, vel);
1035}
1036
1037public override void SetAngularVelocity(BulletBody obj, Vector3 angularVelocity)
1038{
1039 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1040 BSAPICPP.SetAngularVelocity2(bodyu.ptr, angularVelocity);
1041}
1042
1043public override Vector3 GetVelocityInLocalPoint(BulletBody obj, Vector3 pos)
1044{
1045 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1046 return BSAPICPP.GetVelocityInLocalPoint2(bodyu.ptr, pos);
1047}
1048
1049public override void Translate(BulletBody obj, Vector3 trans)
1050{
1051 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1052 BSAPICPP.Translate2(bodyu.ptr, trans);
1053}
1054
1055public override void UpdateDeactivation(BulletBody obj, float timeStep)
1056{
1057 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1058 BSAPICPP.UpdateDeactivation2(bodyu.ptr, timeStep);
1059}
1060
1061public override bool WantsSleeping(BulletBody obj)
1062{
1063 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1064 return BSAPICPP.WantsSleeping2(bodyu.ptr);
1065}
1066
1067public override void SetAngularFactor(BulletBody obj, float factor)
1068{
1069 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1070 BSAPICPP.SetAngularFactor2(bodyu.ptr, factor);
1071}
1072
1073public override void SetAngularFactorV(BulletBody obj, Vector3 factor)
1074{
1075 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1076 BSAPICPP.SetAngularFactorV2(bodyu.ptr, factor);
1077}
1078
1079public override Vector3 GetAngularFactor(BulletBody obj)
1080{
1081 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1082 return BSAPICPP.GetAngularFactor2(bodyu.ptr);
1083}
1084
1085public override bool IsInWorld(BulletWorld world, BulletBody obj)
1086{
1087 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1088 return BSAPICPP.IsInWorld2(bodyu.ptr);
1089}
1090
1091public override void AddConstraintRef(BulletBody obj, BulletConstraint constrain)
1092{
1093 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1094 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
1095 BSAPICPP.AddConstraintRef2(bodyu.ptr, constrainu.ptr);
1096}
1097
1098public override void RemoveConstraintRef(BulletBody obj, BulletConstraint constrain)
1099{
1100 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1101 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
1102 BSAPICPP.RemoveConstraintRef2(bodyu.ptr, constrainu.ptr);
1103}
1104
1105public override BulletConstraint GetConstraintRef(BulletBody obj, int index)
1106{
1107 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1108 return new BulletConstraintUnman(BSAPICPP.GetConstraintRef2(bodyu.ptr, index));
1109}
1110
1111public override int GetNumConstraintRefs(BulletBody obj)
1112{
1113 BulletBodyUnman bodyu = obj as BulletBodyUnman;
1114 return BSAPICPP.GetNumConstraintRefs2(bodyu.ptr);
1115}
1116
1117public override bool SetCollisionGroupMask(BulletBody body, uint filter, uint mask)
1118{
1119 BulletBodyUnman bodyu = body as BulletBodyUnman;
1120 return BSAPICPP.SetCollisionGroupMask2(bodyu.ptr, filter, mask);
1121}
1122
1123// =====================================================================================
1124// btCollisionShape entries
1125
1126public override float GetAngularMotionDisc(BulletShape shape)
1127{
1128 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1129 return BSAPICPP.GetAngularMotionDisc2(shapeu.ptr);
1130}
1131
1132public override float GetContactBreakingThreshold(BulletShape shape, float defaultFactor)
1133{
1134 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1135 return BSAPICPP.GetContactBreakingThreshold2(shapeu.ptr, defaultFactor);
1136}
1137
1138public override bool IsPolyhedral(BulletShape shape)
1139{
1140 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1141 return BSAPICPP.IsPolyhedral2(shapeu.ptr);
1142}
1143
1144public override bool IsConvex2d(BulletShape shape)
1145{
1146 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1147 return BSAPICPP.IsConvex2d2(shapeu.ptr);
1148}
1149
1150public override bool IsConvex(BulletShape shape)
1151{
1152 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1153 return BSAPICPP.IsConvex2(shapeu.ptr);
1154}
1155
1156public override bool IsNonMoving(BulletShape shape)
1157{
1158 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1159 return BSAPICPP.IsNonMoving2(shapeu.ptr);
1160}
1161
1162public override bool IsConcave(BulletShape shape)
1163{
1164 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1165 return BSAPICPP.IsConcave2(shapeu.ptr);
1166}
1167
1168public override bool IsCompound(BulletShape shape)
1169{
1170 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1171 return BSAPICPP.IsCompound2(shapeu.ptr);
1172}
1173
1174public override bool IsSoftBody(BulletShape shape)
1175{
1176 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1177 return BSAPICPP.IsSoftBody2(shapeu.ptr);
1178}
1179
1180public override bool IsInfinite(BulletShape shape)
1181{
1182 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1183 return BSAPICPP.IsInfinite2(shapeu.ptr);
1184}
1185
1186public override void SetLocalScaling(BulletShape shape, Vector3 scale)
1187{
1188 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1189 BSAPICPP.SetLocalScaling2(shapeu.ptr, scale);
1190}
1191
1192public override Vector3 GetLocalScaling(BulletShape shape)
1193{
1194 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1195 return BSAPICPP.GetLocalScaling2(shapeu.ptr);
1196}
1197
1198public override Vector3 CalculateLocalInertia(BulletShape shape, float mass)
1199{
1200 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1201 return BSAPICPP.CalculateLocalInertia2(shapeu.ptr, mass);
1202}
1203
1204public override int GetShapeType(BulletShape shape)
1205{
1206 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1207 return BSAPICPP.GetShapeType2(shapeu.ptr);
1208}
1209
1210public override void SetMargin(BulletShape shape, float val)
1211{
1212 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1213 BSAPICPP.SetMargin2(shapeu.ptr, val);
1214}
1215
1216public override float GetMargin(BulletShape shape)
1217{
1218 BulletShapeUnman shapeu = shape as BulletShapeUnman;
1219 return BSAPICPP.GetMargin2(shapeu.ptr);
1220}
1221
1222// =====================================================================================
1223// Debugging
1224public override void DumpRigidBody(BulletWorld world, BulletBody collisionObject)
1225{
1226 BulletWorldUnman worldu = world as BulletWorldUnman;
1227 BulletBodyUnman bodyu = collisionObject as BulletBodyUnman;
1228 BSAPICPP.DumpRigidBody2(worldu.ptr, bodyu.ptr);
1229}
1230
1231public override void DumpCollisionShape(BulletWorld world, BulletShape collisionShape)
1232{
1233 BulletWorldUnman worldu = world as BulletWorldUnman;
1234 BulletShapeUnman shapeu = collisionShape as BulletShapeUnman;
1235 BSAPICPP.DumpCollisionShape2(worldu.ptr, shapeu.ptr);
1236}
1237
1238public override void DumpConstraint(BulletWorld world, BulletConstraint constrain)
1239{
1240 BulletWorldUnman worldu = world as BulletWorldUnman;
1241 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
1242 BSAPICPP.DumpConstraint2(worldu.ptr, constrainu.ptr);
1243}
1244
1245public override void DumpActivationInfo(BulletWorld world)
1246{
1247 BulletWorldUnman worldu = world as BulletWorldUnman;
1248 BSAPICPP.DumpActivationInfo2(worldu.ptr);
1249}
1250
1251public override void DumpAllInfo(BulletWorld world)
1252{
1253 BulletWorldUnman worldu = world as BulletWorldUnman;
1254 BSAPICPP.DumpAllInfo2(worldu.ptr);
1255}
1256
1257public override void DumpPhysicsStatistics(BulletWorld world)
1258{
1259 BulletWorldUnman worldu = world as BulletWorldUnman;
1260 BSAPICPP.DumpPhysicsStatistics2(worldu.ptr);
1261}
1262
1263// =====================================================================================
1264// =====================================================================================
1265// =====================================================================================
1266// =====================================================================================
1267// =====================================================================================
1268// The actual interface to the unmanaged code
1269static class BSAPICPP
1270{
1271// ===============================================================================
1272// Link back to the managed code for outputting log messages
1273[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
1274public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
1275
1276// ===============================================================================
1277// Initialization and simulation
1278[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1279public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
1280 int maxCollisions, IntPtr collisionArray,
1281 int maxUpdates, IntPtr updateArray,
1282 DebugLogCallback logRoutine);
1283
1284[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1285public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
1286 out int updatedEntityCount, out int collidersCount);
1287
1288[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1289public static extern void Shutdown2(IntPtr sim);
1290
1291[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1292public static extern bool PushUpdate2(IntPtr obj);
1293
1294[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1295public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
1296
1297// =====================================================================================
1298// Mesh, hull, shape and body creation helper routines
1299[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1300public static extern IntPtr CreateMeshShape2(IntPtr world,
1301 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
1302 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1303
1304[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1305public static extern IntPtr CreateHullShape2(IntPtr world,
1306 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
1307
1308[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1309public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
1310
1311[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1312public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
1313
1314[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1315public static extern bool IsNativeShape2(IntPtr shape);
1316
1317[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1318public static extern void SetShapeCollisionMargin2(IntPtr shape, float margin);
1319
1320[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1321public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
1322
1323[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1324public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree);
1325
1326[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1327public static extern int GetNumberOfCompoundChildren2(IntPtr cShape);
1328
1329[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1330public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
1331
1332[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1333public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
1334
1335[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1336public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
1337
1338[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1339public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
1340
1341[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1342public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape);
1343
1344[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1345public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id);
1346
1347[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1348public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
1349
1350[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1351public static extern int GetBodyType2(IntPtr obj);
1352
1353[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1354public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
1355
1356[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1357public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot);
1358
1359[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1360public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
1361
1362[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1363public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
1364
1365// =====================================================================================
1366// Terrain creation and helper routines
1367[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1368public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
1369
1370[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1371public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight,
1372 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap,
1373 float scaleFactor, float collisionMargin);
1374
1375// =====================================================================================
1376// Constraint creation and helper routines
1377[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1378public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1379 Vector3 frame1loc, Quaternion frame1rot,
1380 Vector3 frame2loc, Quaternion frame2rot,
1381 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
1382
1383[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1384public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1385 Vector3 joinPoint,
1386 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
1387
1388[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1389public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1390 Vector3 pivotinA, Vector3 pivotinB,
1391 Vector3 axisInA, Vector3 axisInB,
1392 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
1393
1394[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1395public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
1396
1397[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1398public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
1399
1400[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1401public static extern bool SetFrames2(IntPtr constrain,
1402 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
1403
1404[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1405public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
1406
1407[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1408public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
1409
1410[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1411public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
1412
1413[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1414public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
1415
1416[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1417public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
1418
1419[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1420public static extern bool CalculateTransforms2(IntPtr constrain);
1421
1422[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1423public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
1424
1425[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1426public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
1427
1428// =====================================================================================
1429// btCollisionWorld entries
1430[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1431public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj);
1432
1433[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1434public static extern void UpdateAabbs2(IntPtr world);
1435
1436[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1437public static extern bool GetForceUpdateAllAabbs2(IntPtr world);
1438
1439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1440public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force);
1441
1442// =====================================================================================
1443// btDynamicsWorld entries
1444[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1445public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
1446
1447[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1448public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
1449
1450[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1451public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
1452
1453[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1454public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain);
1455// =====================================================================================
1456// btCollisionObject entries
1457[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1458public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain);
1459
1460[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1461public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict);
1462
1463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1464public static extern bool HasAnisotripicFriction2(IntPtr constrain);
1465
1466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1467public static extern void SetContactProcessingThreshold2(IntPtr obj, float val);
1468
1469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1470public static extern float GetContactProcessingThreshold2(IntPtr obj);
1471
1472[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1473public static extern bool IsStaticObject2(IntPtr obj);
1474
1475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1476public static extern bool IsKinematicObject2(IntPtr obj);
1477
1478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1479public static extern bool IsStaticOrKinematicObject2(IntPtr obj);
1480
1481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1482public static extern bool HasContactResponse2(IntPtr obj);
1483
1484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1485public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape);
1486
1487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1488public static extern IntPtr GetCollisionShape2(IntPtr obj);
1489
1490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1491public static extern int GetActivationState2(IntPtr obj);
1492
1493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1494public static extern void SetActivationState2(IntPtr obj, int state);
1495
1496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1497public static extern void SetDeactivationTime2(IntPtr obj, float dtime);
1498
1499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1500public static extern float GetDeactivationTime2(IntPtr obj);
1501
1502[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1503public static extern void ForceActivationState2(IntPtr obj, ActivationState state);
1504
1505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1506public static extern void Activate2(IntPtr obj, bool forceActivation);
1507
1508[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1509public static extern bool IsActive2(IntPtr obj);
1510
1511[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1512public static extern void SetRestitution2(IntPtr obj, float val);
1513
1514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1515public static extern float GetRestitution2(IntPtr obj);
1516
1517[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1518public static extern void SetFriction2(IntPtr obj, float val);
1519
1520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1521public static extern float GetFriction2(IntPtr obj);
1522
1523 /* Haven't defined the type 'Transform'
1524[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1525public static extern Transform GetWorldTransform2(IntPtr obj);
1526
1527[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1528public static extern void setWorldTransform2(IntPtr obj, Transform trans);
1529 */
1530
1531[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1532public static extern Vector3 GetPosition2(IntPtr obj);
1533
1534[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1535public static extern Quaternion GetOrientation2(IntPtr obj);
1536
1537[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1538public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
1539
1540[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1541public static extern IntPtr GetBroadphaseHandle2(IntPtr obj);
1542
1543[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1544public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle);
1545
1546 /*
1547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1548public static extern Transform GetInterpolationWorldTransform2(IntPtr obj);
1549
1550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1551public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans);
1552 */
1553
1554[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1555public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel);
1556
1557[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1558public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel);
1559
1560[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1561public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel);
1562
1563[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1564public static extern float GetHitFraction2(IntPtr obj);
1565
1566[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1567public static extern void SetHitFraction2(IntPtr obj, float val);
1568
1569[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1570public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
1571
1572[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1573public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
1574
1575[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1576public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
1577
1578[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1579public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
1580
1581[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1582public static extern float GetCcdMotionThreshold2(IntPtr obj);
1583
1584[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1585public static extern void SetCcdMotionThreshold2(IntPtr obj, float val);
1586
1587[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1588public static extern float GetCcdSweptSphereRadius2(IntPtr obj);
1589
1590[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1591public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val);
1592
1593[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1594public static extern IntPtr GetUserPointer2(IntPtr obj);
1595
1596[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1597public static extern void SetUserPointer2(IntPtr obj, IntPtr val);
1598
1599// =====================================================================================
1600// btRigidBody entries
1601[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1602public static extern void ApplyGravity2(IntPtr obj);
1603
1604[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1605public static extern void SetGravity2(IntPtr obj, Vector3 val);
1606
1607[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1608public static extern Vector3 GetGravity2(IntPtr obj);
1609
1610[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1611public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
1612
1613[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1614public static extern void SetLinearDamping2(IntPtr obj, float lin_damping);
1615
1616[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1617public static extern void SetAngularDamping2(IntPtr obj, float ang_damping);
1618
1619[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1620public static extern float GetLinearDamping2(IntPtr obj);
1621
1622[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1623public static extern float GetAngularDamping2(IntPtr obj);
1624
1625[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1626public static extern float GetLinearSleepingThreshold2(IntPtr obj);
1627
1628[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1629public static extern float GetAngularSleepingThreshold2(IntPtr obj);
1630
1631[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1632public static extern void ApplyDamping2(IntPtr obj, float timeStep);
1633
1634[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1635public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
1636
1637[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1638public static extern Vector3 GetLinearFactor2(IntPtr obj);
1639
1640[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1641public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor);
1642
1643 /*
1644[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1645public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans);
1646 */
1647
1648[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1649public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot);
1650
1651// Add a force to the object as if its mass is one.
1652[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1653public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force);
1654
1655// Set the force being applied to the object as if its mass is one.
1656[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1657public static extern void SetObjectForce2(IntPtr obj, Vector3 force);
1658
1659[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1660public static extern Vector3 GetTotalForce2(IntPtr obj);
1661
1662[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1663public static extern Vector3 GetTotalTorque2(IntPtr obj);
1664
1665[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1666public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj);
1667
1668[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1669public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert);
1670
1671[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1672public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
1673
1674[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1675public static extern void ApplyTorque2(IntPtr obj, Vector3 torque);
1676
1677// Apply force at the given point. Will add torque to the object.
1678[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1679public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos);
1680
1681// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
1682[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1683public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp);
1684
1685// Apply impulse to the object's torque. Force is scaled by object's mass.
1686[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1687public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp);
1688
1689// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
1690[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1691public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos);
1692
1693[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1694public static extern void ClearForces2(IntPtr obj);
1695
1696[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1697public static extern void ClearAllForces2(IntPtr obj);
1698
1699[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1700public static extern void UpdateInertiaTensor2(IntPtr obj);
1701
1702[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1703public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj);
1704
1705 /*
1706[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1707public static extern Transform GetCenterOfMassTransform2(IntPtr obj);
1708 */
1709
1710[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1711public static extern Vector3 GetLinearVelocity2(IntPtr obj);
1712
1713[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1714public static extern Vector3 GetAngularVelocity2(IntPtr obj);
1715
1716[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1717public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val);
1718
1719[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1720public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
1721
1722[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1723public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos);
1724
1725[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1726public static extern void Translate2(IntPtr obj, Vector3 trans);
1727
1728[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1729public static extern void UpdateDeactivation2(IntPtr obj, float timeStep);
1730
1731[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1732public static extern bool WantsSleeping2(IntPtr obj);
1733
1734[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1735public static extern void SetAngularFactor2(IntPtr obj, float factor);
1736
1737[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1738public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor);
1739
1740[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1741public static extern Vector3 GetAngularFactor2(IntPtr obj);
1742
1743[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1744public static extern bool IsInWorld2(IntPtr obj);
1745
1746[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1747public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain);
1748
1749[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1750public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain);
1751
1752[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1753public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
1754
1755[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1756public static extern int GetNumConstraintRefs2(IntPtr obj);
1757
1758[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1759public static extern bool SetCollisionGroupMask2(IntPtr body, uint filter, uint mask);
1760
1761// =====================================================================================
1762// btCollisionShape entries
1763
1764[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1765public static extern float GetAngularMotionDisc2(IntPtr shape);
1766
1767[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1768public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor);
1769
1770[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1771public static extern bool IsPolyhedral2(IntPtr shape);
1772
1773[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1774public static extern bool IsConvex2d2(IntPtr shape);
1775
1776[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1777public static extern bool IsConvex2(IntPtr shape);
1778
1779[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1780public static extern bool IsNonMoving2(IntPtr shape);
1781
1782[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1783public static extern bool IsConcave2(IntPtr shape);
1784
1785[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1786public static extern bool IsCompound2(IntPtr shape);
1787
1788[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1789public static extern bool IsSoftBody2(IntPtr shape);
1790
1791[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1792public static extern bool IsInfinite2(IntPtr shape);
1793
1794[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1795public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale);
1796
1797[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1798public static extern Vector3 GetLocalScaling2(IntPtr shape);
1799
1800[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1801public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass);
1802
1803[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1804public static extern int GetShapeType2(IntPtr shape);
1805
1806[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1807public static extern void SetMargin2(IntPtr shape, float val);
1808
1809[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1810public static extern float GetMargin2(IntPtr shape);
1811
1812// =====================================================================================
1813// Debugging
1814[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1815public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
1816
1817[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1818public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
1819
1820[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1821public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
1822
1823[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1824public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
1825
1826[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1827public static extern void DumpActivationInfo2(IntPtr sim);
1828
1829[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1830public static extern void DumpAllInfo2(IntPtr sim);
1831
1832[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1833public static extern void DumpPhysicsStatistics2(IntPtr sim);
1834
1835}
1836
1837}
1838
1839}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
deleted file mode 100755
index 30a7bee..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ /dev/null
@@ -1,1622 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.IO;
30using System.Text;
31
32using OpenSim.Framework;
33
34using OpenMetaverse;
35
36using BulletXNA;
37using BulletXNA.LinearMath;
38using BulletXNA.BulletCollision;
39using BulletXNA.BulletDynamics;
40using BulletXNA.BulletCollision.CollisionDispatch;
41
42namespace OpenSim.Region.Physics.BulletSPlugin
43{
44public sealed class BSAPIXNA : BSAPITemplate
45{
46private sealed class BulletWorldXNA : BulletWorld
47{
48 public DiscreteDynamicsWorld world;
49 public BulletWorldXNA(uint id, BSScene physScene, DiscreteDynamicsWorld xx)
50 : base(id, physScene)
51 {
52 world = xx;
53 }
54}
55
56private sealed class BulletBodyXNA : BulletBody
57{
58 public CollisionObject body;
59 public RigidBody rigidBody { get { return RigidBody.Upcast(body); } }
60
61 public BulletBodyXNA(uint id, CollisionObject xx)
62 : base(id)
63 {
64 body = xx;
65 }
66 public override bool HasPhysicalBody
67 {
68 get { return body != null; }
69 }
70 public override void Clear()
71 {
72 body = null;
73 }
74 public override string AddrString
75 {
76 get { return "XNARigidBody"; }
77 }
78}
79
80private sealed class BulletShapeXNA : BulletShape
81{
82 public CollisionShape shape;
83 public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ)
84 : base()
85 {
86 shape = xx;
87 type = typ;
88 }
89 public override bool HasPhysicalShape
90 {
91 get { return shape != null; }
92 }
93 public override void Clear()
94 {
95 shape = null;
96 }
97 public override BulletShape Clone()
98 {
99 return new BulletShapeXNA(shape, type);
100 }
101 public override bool ReferenceSame(BulletShape other)
102 {
103 BulletShapeXNA otheru = other as BulletShapeXNA;
104 return (otheru != null) && (this.shape == otheru.shape);
105
106 }
107 public override string AddrString
108 {
109 get { return "XNACollisionShape"; }
110 }
111}
112private sealed class BulletConstraintXNA : BulletConstraint
113{
114 public TypedConstraint constrain;
115 public BulletConstraintXNA(TypedConstraint xx) : base()
116 {
117 constrain = xx;
118 }
119
120 public override void Clear()
121 {
122 constrain = null;
123 }
124 public override bool HasPhysicalConstraint { get { return constrain != null; } }
125
126 // Used for log messages for a unique display of the memory/object allocated to this instance
127 public override string AddrString
128 {
129 get { return "XNAConstraint"; }
130 }
131}
132
133 private static int m_collisionsThisFrame;
134 private BSScene PhysicsScene { get; set; }
135
136 public override string BulletEngineName { get { return "BulletXNA"; } }
137 public override string BulletEngineVersion { get; protected set; }
138
139 public BSAPIXNA(string paramName, BSScene physScene)
140 {
141 PhysicsScene = physScene;
142 }
143
144 /// <summary>
145 ///
146 /// </summary>
147 /// <param name="p"></param>
148 /// <param name="p_2"></param>
149 public override bool RemoveObjectFromWorld(BulletWorld pWorld, BulletBody pBody)
150 {
151 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
152 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
153 world.RemoveRigidBody(body);
154 return true;
155 }
156
157 public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects)
158 {
159 /* TODO */
160 return false;
161 }
162
163 public override bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain)
164 {
165 /* TODO */
166 return false;
167 }
168
169 public override void SetRestitution(BulletBody pBody, float pRestitution)
170 {
171 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
172 body.SetRestitution(pRestitution);
173 }
174
175 public override int GetShapeType(BulletShape pShape)
176 {
177 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
178 return (int)shape.GetShapeType();
179 }
180 public override void SetMargin(BulletShape pShape, float pMargin)
181 {
182 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
183 shape.SetMargin(pMargin);
184 }
185
186 public override float GetMargin(BulletShape pShape)
187 {
188 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
189 return shape.GetMargin();
190 }
191
192 public override void SetLocalScaling(BulletShape pShape, Vector3 pScale)
193 {
194 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
195 IndexedVector3 vec = new IndexedVector3(pScale.X, pScale.Y, pScale.Z);
196 shape.SetLocalScaling(ref vec);
197
198 }
199
200 public override void SetContactProcessingThreshold(BulletBody pBody, float contactprocessingthreshold)
201 {
202 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
203 body.SetContactProcessingThreshold(contactprocessingthreshold);
204 }
205
206 public override void SetCcdMotionThreshold(BulletBody pBody, float pccdMotionThreashold)
207 {
208 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
209 body.SetCcdMotionThreshold(pccdMotionThreashold);
210 }
211
212 public override void SetCcdSweptSphereRadius(BulletBody pBody, float pCcdSweptSphereRadius)
213 {
214 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
215 body.SetCcdSweptSphereRadius(pCcdSweptSphereRadius);
216 }
217
218 public override void SetAngularFactorV(BulletBody pBody, Vector3 pAngularFactor)
219 {
220 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
221 body.SetAngularFactor(new IndexedVector3(pAngularFactor.X, pAngularFactor.Y, pAngularFactor.Z));
222 }
223
224 public override CollisionFlags AddToCollisionFlags(BulletBody pBody, CollisionFlags pcollisionFlags)
225 {
226 CollisionObject body = ((BulletBodyXNA)pBody).body;
227 CollisionFlags existingcollisionFlags = (CollisionFlags)(uint)body.GetCollisionFlags();
228 existingcollisionFlags |= pcollisionFlags;
229 body.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags)(uint)existingcollisionFlags);
230 return (CollisionFlags) (uint) existingcollisionFlags;
231 }
232
233 public override bool AddObjectToWorld(BulletWorld pWorld, BulletBody pBody)
234 {
235 // Bullet resets several variables when an object is added to the world. In particular,
236 // BulletXNA resets position and rotation. Gravity is also reset depending on the static/dynamic
237 // type. Of course, the collision flags in the broadphase proxy are initialized to default.
238 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
239 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
240
241 IndexedMatrix origPos = body.GetWorldTransform();
242 IndexedVector3 origGrav = body.GetGravity();
243
244 //if (!(body.GetCollisionShape().GetShapeType() == BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE && body.GetCollisionShape().GetShapeType() == BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE))
245
246 world.AddRigidBody(body);
247
248 body.SetWorldTransform(origPos);
249 body.SetGravity(origGrav);
250
251 pBody.ApplyCollisionMask(pWorld.physicsScene);
252
253 //if (body.GetBroadphaseHandle() != null)
254 // world.UpdateSingleAabb(body);
255 return true;
256 }
257
258 public override void ForceActivationState(BulletBody pBody, ActivationState pActivationState)
259 {
260 CollisionObject body = ((BulletBodyXNA)pBody).body;
261 body.ForceActivationState((BulletXNA.BulletCollision.ActivationState)(uint)pActivationState);
262 }
263
264 public override void UpdateSingleAabb(BulletWorld pWorld, BulletBody pBody)
265 {
266 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
267 CollisionObject body = ((BulletBodyXNA)pBody).body;
268 world.UpdateSingleAabb(body);
269 }
270
271 public override void UpdateAabbs(BulletWorld world) { /* TODO */ }
272 public override bool GetForceUpdateAllAabbs(BulletWorld world) { /* TODO */ return false; }
273 public override void SetForceUpdateAllAabbs(BulletWorld world, bool force) { /* TODO */ }
274
275 public override bool SetCollisionGroupMask(BulletBody pBody, uint pGroup, uint pMask)
276 {
277 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
278 body.GetBroadphaseHandle().m_collisionFilterGroup = (BulletXNA.BulletCollision.CollisionFilterGroups) pGroup;
279 body.GetBroadphaseHandle().m_collisionFilterGroup = (BulletXNA.BulletCollision.CollisionFilterGroups) pGroup;
280 if ((uint) body.GetBroadphaseHandle().m_collisionFilterGroup == 0)
281 return false;
282 return true;
283 }
284
285 public override void ClearAllForces(BulletBody pBody)
286 {
287 CollisionObject body = ((BulletBodyXNA)pBody).body;
288 IndexedVector3 zeroVector = new IndexedVector3(0, 0, 0);
289 body.SetInterpolationLinearVelocity(ref zeroVector);
290 body.SetInterpolationAngularVelocity(ref zeroVector);
291 IndexedMatrix bodytransform = body.GetWorldTransform();
292
293 body.SetInterpolationWorldTransform(ref bodytransform);
294
295 if (body is RigidBody)
296 {
297 RigidBody rigidbody = body as RigidBody;
298 rigidbody.SetLinearVelocity(zeroVector);
299 rigidbody.SetAngularVelocity(zeroVector);
300 rigidbody.ClearForces();
301 }
302 }
303
304 public override void SetInterpolationAngularVelocity(BulletBody pBody, Vector3 pVector3)
305 {
306 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
307 IndexedVector3 vec = new IndexedVector3(pVector3.X, pVector3.Y, pVector3.Z);
308 body.SetInterpolationAngularVelocity(ref vec);
309 }
310
311 public override void SetAngularVelocity(BulletBody pBody, Vector3 pVector3)
312 {
313 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
314 IndexedVector3 vec = new IndexedVector3(pVector3.X, pVector3.Y, pVector3.Z);
315 body.SetAngularVelocity(ref vec);
316 }
317 public override Vector3 GetTotalForce(BulletBody pBody)
318 {
319 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
320 IndexedVector3 iv3 = body.GetTotalForce();
321 return new Vector3(iv3.X, iv3.Y, iv3.Z);
322 }
323 public override Vector3 GetTotalTorque(BulletBody pBody)
324 {
325 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
326 IndexedVector3 iv3 = body.GetTotalTorque();
327 return new Vector3(iv3.X, iv3.Y, iv3.Z);
328 }
329 public override Vector3 GetInvInertiaDiagLocal(BulletBody pBody)
330 {
331 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
332 IndexedVector3 iv3 = body.GetInvInertiaDiagLocal();
333 return new Vector3(iv3.X, iv3.Y, iv3.Z);
334 }
335 public override void SetInvInertiaDiagLocal(BulletBody pBody, Vector3 inert)
336 {
337 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
338 IndexedVector3 iv3 = new IndexedVector3(inert.X, inert.Y, inert.Z);
339 body.SetInvInertiaDiagLocal(ref iv3);
340 }
341 public override void ApplyForce(BulletBody pBody, Vector3 force, Vector3 pos)
342 {
343 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
344 IndexedVector3 forceiv3 = new IndexedVector3(force.X, force.Y, force.Z);
345 IndexedVector3 posiv3 = new IndexedVector3(pos.X, pos.Y, pos.Z);
346 body.ApplyForce(ref forceiv3, ref posiv3);
347 }
348 public override void ApplyImpulse(BulletBody pBody, Vector3 imp, Vector3 pos)
349 {
350 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
351 IndexedVector3 impiv3 = new IndexedVector3(imp.X, imp.Y, imp.Z);
352 IndexedVector3 posiv3 = new IndexedVector3(pos.X, pos.Y, pos.Z);
353 body.ApplyImpulse(ref impiv3, ref posiv3);
354 }
355
356 public override void ClearForces(BulletBody pBody)
357 {
358 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
359 body.ClearForces();
360 }
361
362 public override void SetTranslation(BulletBody pBody, Vector3 _position, Quaternion _orientation)
363 {
364 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
365 IndexedVector3 vposition = new IndexedVector3(_position.X, _position.Y, _position.Z);
366 IndexedQuaternion vquaternion = new IndexedQuaternion(_orientation.X, _orientation.Y, _orientation.Z,
367 _orientation.W);
368 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion);
369 mat._origin = vposition;
370 body.SetWorldTransform(mat);
371
372 }
373
374 public override Vector3 GetPosition(BulletBody pBody)
375 {
376 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
377 IndexedVector3 pos = body.GetInterpolationWorldTransform()._origin;
378 return new Vector3(pos.X, pos.Y, pos.Z);
379 }
380
381 public override Vector3 CalculateLocalInertia(BulletShape pShape, float pphysMass)
382 {
383 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
384 IndexedVector3 inertia = IndexedVector3.Zero;
385 shape.CalculateLocalInertia(pphysMass, out inertia);
386 return new Vector3(inertia.X, inertia.Y, inertia.Z);
387 }
388
389 public override void SetMassProps(BulletBody pBody, float pphysMass, Vector3 plocalInertia)
390 {
391 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
392 IndexedVector3 inertia = new IndexedVector3(plocalInertia.X, plocalInertia.Y, plocalInertia.Z);
393 body.SetMassProps(pphysMass, inertia);
394 }
395
396
397 public override void SetObjectForce(BulletBody pBody, Vector3 _force)
398 {
399 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
400 IndexedVector3 force = new IndexedVector3(_force.X, _force.Y, _force.Z);
401 body.SetTotalForce(ref force);
402 }
403
404 public override void SetFriction(BulletBody pBody, float _currentFriction)
405 {
406 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
407 body.SetFriction(_currentFriction);
408 }
409
410 public override void SetLinearVelocity(BulletBody pBody, Vector3 _velocity)
411 {
412 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
413 IndexedVector3 velocity = new IndexedVector3(_velocity.X, _velocity.Y, _velocity.Z);
414 body.SetLinearVelocity(velocity);
415 }
416
417 public override void Activate(BulletBody pBody, bool pforceactivation)
418 {
419 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
420 body.Activate(pforceactivation);
421
422 }
423
424 public override Quaternion GetOrientation(BulletBody pBody)
425 {
426 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
427 IndexedQuaternion mat = body.GetInterpolationWorldTransform().GetRotation();
428 return new Quaternion(mat.X, mat.Y, mat.Z, mat.W);
429 }
430
431 public override CollisionFlags RemoveFromCollisionFlags(BulletBody pBody, CollisionFlags pcollisionFlags)
432 {
433 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
434 CollisionFlags existingcollisionFlags = (CollisionFlags)(uint)body.GetCollisionFlags();
435 existingcollisionFlags &= ~pcollisionFlags;
436 body.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags)(uint)existingcollisionFlags);
437 return (CollisionFlags)(uint)existingcollisionFlags;
438 }
439
440 public override float GetCcdMotionThreshold(BulletBody obj) { /* TODO */ return 0f; }
441
442 public override float GetCcdSweptSphereRadius(BulletBody obj) { /* TODO */ return 0f; }
443
444 public override IntPtr GetUserPointer(BulletBody obj) { /* TODO */ return IntPtr.Zero; }
445
446 public override void SetUserPointer(BulletBody obj, IntPtr val) { /* TODO */ }
447
448 public override void SetGravity(BulletBody pBody, Vector3 pGravity)
449 {
450 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
451 IndexedVector3 gravity = new IndexedVector3(pGravity.X, pGravity.Y, pGravity.Z);
452 body.SetGravity(gravity);
453 }
454
455 public override bool DestroyConstraint(BulletWorld pWorld, BulletConstraint pConstraint)
456 {
457 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
458 TypedConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain;
459 world.RemoveConstraint(constraint);
460 return true;
461 }
462
463 public override bool SetLinearLimits(BulletConstraint pConstraint, Vector3 low, Vector3 high)
464 {
465 Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint;
466 IndexedVector3 lowlimit = new IndexedVector3(low.X, low.Y, low.Z);
467 IndexedVector3 highlimit = new IndexedVector3(high.X, high.Y, high.Z);
468 constraint.SetLinearLowerLimit(lowlimit);
469 constraint.SetLinearUpperLimit(highlimit);
470 return true;
471 }
472
473 public override bool SetAngularLimits(BulletConstraint pConstraint, Vector3 low, Vector3 high)
474 {
475 Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint;
476 IndexedVector3 lowlimit = new IndexedVector3(low.X, low.Y, low.Z);
477 IndexedVector3 highlimit = new IndexedVector3(high.X, high.Y, high.Z);
478 constraint.SetAngularLowerLimit(lowlimit);
479 constraint.SetAngularUpperLimit(highlimit);
480 return true;
481 }
482
483 public override void SetConstraintNumSolverIterations(BulletConstraint pConstraint, float cnt)
484 {
485 Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint;
486 constraint.SetOverrideNumSolverIterations((int)cnt);
487 }
488
489 public override bool CalculateTransforms(BulletConstraint pConstraint)
490 {
491 Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint;
492 constraint.CalculateTransforms();
493 return true;
494 }
495
496 public override void SetConstraintEnable(BulletConstraint pConstraint, float p_2)
497 {
498 Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint;
499 constraint.SetEnabled((p_2 == 0) ? false : true);
500 }
501
502
503 //BulletSimAPI.Create6DofConstraint(m_world.ptr, m_body1.ptr, m_body2.ptr,frame1, frame1rot,frame2, frame2rot,useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
504 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
505
506 {
507 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
508 RigidBody body1 = ((BulletBodyXNA)pBody1).rigidBody;
509 RigidBody body2 = ((BulletBodyXNA)pBody2).rigidBody;
510 IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
511 IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
512 IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
513 frame1._origin = frame1v;
514
515 IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z);
516 IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W);
517 IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot);
518 frame2._origin = frame1v;
519
520 Generic6DofConstraint consttr = new Generic6DofConstraint(body1, body2, ref frame1, ref frame2,
521 puseLinearReferenceFrameA);
522 consttr.CalculateTransforms();
523 world.AddConstraint(consttr,pdisableCollisionsBetweenLinkedBodies);
524
525 return new BulletConstraintXNA(consttr);
526 }
527
528
529 /// <summary>
530 ///
531 /// </summary>
532 /// <param name="pWorld"></param>
533 /// <param name="pBody1"></param>
534 /// <param name="pBody2"></param>
535 /// <param name="pjoinPoint"></param>
536 /// <param name="puseLinearReferenceFrameA"></param>
537 /// <param name="pdisableCollisionsBetweenLinkedBodies"></param>
538 /// <returns></returns>
539 public override BulletConstraint Create6DofConstraintToPoint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 pjoinPoint, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
540 {
541 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
542 RigidBody body1 = ((BulletBodyXNA)pBody1).rigidBody;
543 RigidBody body2 = ((BulletBodyXNA)pBody2).rigidBody;
544 IndexedMatrix frame1 = new IndexedMatrix(IndexedBasisMatrix.Identity, new IndexedVector3(0, 0, 0));
545 IndexedMatrix frame2 = new IndexedMatrix(IndexedBasisMatrix.Identity, new IndexedVector3(0, 0, 0));
546
547 IndexedVector3 joinPoint = new IndexedVector3(pjoinPoint.X, pjoinPoint.Y, pjoinPoint.Z);
548 IndexedMatrix mat = IndexedMatrix.Identity;
549 mat._origin = new IndexedVector3(pjoinPoint.X, pjoinPoint.Y, pjoinPoint.Z);
550 frame1._origin = body1.GetWorldTransform().Inverse()*joinPoint;
551 frame2._origin = body2.GetWorldTransform().Inverse()*joinPoint;
552
553 Generic6DofConstraint consttr = new Generic6DofConstraint(body1, body2, ref frame1, ref frame2, puseLinearReferenceFrameA);
554 consttr.CalculateTransforms();
555 world.AddConstraint(consttr, pdisableCollisionsBetweenLinkedBodies);
556
557 return new BulletConstraintXNA(consttr);
558 }
559 //SetFrames(m_constraint.ptr, frameA, frameArot, frameB, frameBrot);
560 public override bool SetFrames(BulletConstraint pConstraint, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot)
561 {
562 Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint;
563 IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
564 IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
565 IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
566 frame1._origin = frame1v;
567
568 IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z);
569 IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W);
570 IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot);
571 frame2._origin = frame1v;
572 constraint.SetFrames(ref frame1, ref frame2);
573 return true;
574 }
575
576 public override Vector3 GetLinearVelocity(BulletBody pBody)
577 {
578 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
579 IndexedVector3 iv3 = body.GetLinearVelocity();
580 return new Vector3(iv3.X, iv3.Y, iv3.Z);
581 }
582 public override Vector3 GetAngularVelocity(BulletBody pBody)
583 {
584 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
585 IndexedVector3 iv3 = body.GetAngularVelocity();
586 return new Vector3(iv3.X, iv3.Y, iv3.Z);
587 }
588 public override Vector3 GetVelocityInLocalPoint(BulletBody pBody, Vector3 pos)
589 {
590 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
591 IndexedVector3 posiv3 = new IndexedVector3(pos.X, pos.Y, pos.Z);
592 IndexedVector3 iv3 = body.GetVelocityInLocalPoint(ref posiv3);
593 return new Vector3(iv3.X, iv3.Y, iv3.Z);
594 }
595 public override void Translate(BulletBody pBody, Vector3 trans)
596 {
597 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
598 }
599 public override void UpdateDeactivation(BulletBody pBody, float timeStep)
600 {
601 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
602 body.UpdateDeactivation(timeStep);
603 }
604
605 public override bool WantsSleeping(BulletBody pBody)
606 {
607 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
608 return body.WantsSleeping();
609 }
610
611 public override void SetAngularFactor(BulletBody pBody, float factor)
612 {
613 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
614 body.SetAngularFactor(factor);
615 }
616
617 public override Vector3 GetAngularFactor(BulletBody pBody)
618 {
619 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
620 IndexedVector3 iv3 = body.GetAngularFactor();
621 return new Vector3(iv3.X, iv3.Y, iv3.Z);
622 }
623
624 public override bool IsInWorld(BulletWorld pWorld, BulletBody pBody)
625 {
626 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
627 CollisionObject body = ((BulletBodyXNA)pBody).body;
628 return world.IsInWorld(body);
629 }
630
631 public override void AddConstraintRef(BulletBody pBody, BulletConstraint pConstrain)
632 {
633 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
634 TypedConstraint constrain = ((BulletConstraintXNA)pConstrain).constrain;
635 body.AddConstraintRef(constrain);
636 }
637
638 public override void RemoveConstraintRef(BulletBody pBody, BulletConstraint pConstrain)
639 {
640 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
641 TypedConstraint constrain = ((BulletConstraintXNA)pConstrain).constrain;
642 body.RemoveConstraintRef(constrain);
643 }
644
645 public override BulletConstraint GetConstraintRef(BulletBody pBody, int index)
646 {
647 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
648 return new BulletConstraintXNA(body.GetConstraintRef(index));
649 }
650
651 public override int GetNumConstraintRefs(BulletBody pBody)
652 {
653 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
654 return body.GetNumConstraintRefs();
655 }
656
657 public override void SetInterpolationLinearVelocity(BulletBody pBody, Vector3 VehicleVelocity)
658 {
659 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
660 IndexedVector3 velocity = new IndexedVector3(VehicleVelocity.X, VehicleVelocity.Y, VehicleVelocity.Z);
661 body.SetInterpolationLinearVelocity(ref velocity);
662 }
663
664 public override bool UseFrameOffset(BulletConstraint pConstraint, float onOff)
665 {
666 Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint;
667 constraint.SetUseFrameOffset((onOff == 0) ? false : true);
668 return true;
669 }
670 //SetBreakingImpulseThreshold(m_constraint.ptr, threshold);
671 public override bool SetBreakingImpulseThreshold(BulletConstraint pConstraint, float threshold)
672 {
673 Generic6DofConstraint constraint = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint;
674 constraint.SetBreakingImpulseThreshold(threshold);
675 return true;
676 }
677 //BulletSimAPI.SetAngularDamping(Prim.PhysBody.ptr, angularDamping);
678 public override void SetAngularDamping(BulletBody pBody, float angularDamping)
679 {
680 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
681 float lineardamping = body.GetLinearDamping();
682 body.SetDamping(lineardamping, angularDamping);
683
684 }
685
686 public override void UpdateInertiaTensor(BulletBody pBody)
687 {
688 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
689 body.UpdateInertiaTensor();
690 }
691
692 public override void RecalculateCompoundShapeLocalAabb(BulletShape pCompoundShape)
693 {
694 CompoundShape shape = ((BulletShapeXNA)pCompoundShape).shape as CompoundShape;
695 shape.RecalculateLocalAabb();
696 }
697
698 //BulletSimAPI.GetCollisionFlags(PhysBody.ptr)
699 public override CollisionFlags GetCollisionFlags(BulletBody pBody)
700 {
701 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
702 uint flags = (uint)body.GetCollisionFlags();
703 return (CollisionFlags) flags;
704 }
705
706 public override void SetDamping(BulletBody pBody, float pLinear, float pAngular)
707 {
708 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
709 body.SetDamping(pLinear, pAngular);
710 }
711 //PhysBody.ptr, PhysicsScene.Params.deactivationTime);
712 public override void SetDeactivationTime(BulletBody pBody, float pDeactivationTime)
713 {
714 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
715 body.SetDeactivationTime(pDeactivationTime);
716 }
717 //SetSleepingThresholds(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
718 public override void SetSleepingThresholds(BulletBody pBody, float plinearSleepingThreshold, float pangularSleepingThreshold)
719 {
720 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
721 body.SetSleepingThresholds(plinearSleepingThreshold, pangularSleepingThreshold);
722 }
723
724 public override CollisionObjectTypes GetBodyType(BulletBody pBody)
725 {
726 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
727 return (CollisionObjectTypes)(int) body.GetInternalType();
728 }
729
730 public override void ApplyGravity(BulletBody obj) { /* TODO */ }
731
732 public override Vector3 GetGravity(BulletBody obj) { /* TODO */ return Vector3.Zero; }
733
734 public override void SetLinearDamping(BulletBody obj, float lin_damping) { /* TODO */ }
735
736 public override float GetLinearDamping(BulletBody obj) { /* TODO */ return 0f; }
737
738 public override float GetAngularDamping(BulletBody obj) { /* TODO */ return 0f; }
739
740 public override float GetLinearSleepingThreshold(BulletBody obj) { /* TODO */ return 0f; }
741
742 public override void ApplyDamping(BulletBody obj, float timeStep) { /* TODO */ }
743
744 public override Vector3 GetLinearFactor(BulletBody obj) { /* TODO */ return Vector3.Zero; }
745
746 public override void SetLinearFactor(BulletBody obj, Vector3 factor) { /* TODO */ }
747
748 public override void SetCenterOfMassByPosRot(BulletBody obj, Vector3 pos, Quaternion rot) { /* TODO */ }
749
750 //BulletSimAPI.ApplyCentralForce(PhysBody.ptr, fSum);
751 public override void ApplyCentralForce(BulletBody pBody, Vector3 pfSum)
752 {
753 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
754 IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z);
755 body.ApplyCentralForce(ref fSum);
756 }
757 public override void ApplyCentralImpulse(BulletBody pBody, Vector3 pfSum)
758 {
759 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
760 IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z);
761 body.ApplyCentralImpulse(ref fSum);
762 }
763 public override void ApplyTorque(BulletBody pBody, Vector3 pfSum)
764 {
765 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
766 IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z);
767 body.ApplyTorque(ref fSum);
768 }
769 public override void ApplyTorqueImpulse(BulletBody pBody, Vector3 pfSum)
770 {
771 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
772 IndexedVector3 fSum = new IndexedVector3(pfSum.X, pfSum.Y, pfSum.Z);
773 body.ApplyTorqueImpulse(ref fSum);
774 }
775
776 public override void DumpRigidBody(BulletWorld p, BulletBody p_2)
777 {
778 //TODO:
779 }
780
781 public override void DumpCollisionShape(BulletWorld p, BulletShape p_2)
782 {
783 //TODO:
784 }
785 public override void DumpConstraint(BulletWorld world, BulletConstraint constrain)
786 {
787 //TODO:
788 }
789
790 public override void DumpActivationInfo(BulletWorld world)
791 {
792 //TODO:
793 }
794
795 public override void DumpAllInfo(BulletWorld world)
796 {
797 //TODO:
798 }
799
800 public override void DumpPhysicsStatistics(BulletWorld world)
801 {
802 //TODO:
803 }
804
805 public override void DestroyObject(BulletWorld p, BulletBody p_2)
806 {
807 //TODO:
808 }
809
810 public override void Shutdown(BulletWorld pWorld)
811 {
812 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
813 world.Cleanup();
814 }
815
816 public override BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id)
817 {
818 return null;
819 }
820
821 public override bool DeleteCollisionShape(BulletWorld p, BulletShape p_2)
822 {
823 //TODO:
824 return false;
825 }
826 //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation);
827
828 public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
829 {
830 CollisionWorld world = ((BulletWorldXNA)pWorld).world;
831 IndexedMatrix mat =
832 IndexedMatrix.CreateFromQuaternion(new IndexedQuaternion(pRawOrientation.X, pRawOrientation.Y,
833 pRawOrientation.Z, pRawOrientation.W));
834 mat._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z);
835 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
836 //UpdateSingleAabb(world, shape);
837 // TODO: Feed Update array into null
838 RigidBody body = new RigidBody(0,new SimMotionState(world,pLocalID,mat,null),shape,IndexedVector3.Zero);
839
840 body.SetUserPointer(pLocalID);
841 return new BulletBodyXNA(pLocalID, body);
842 }
843
844
845 public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
846 {
847
848 IndexedMatrix mat =
849 IndexedMatrix.CreateFromQuaternion(new IndexedQuaternion(pRawOrientation.X, pRawOrientation.Y,
850 pRawOrientation.Z, pRawOrientation.W));
851 mat._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z);
852
853 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
854
855 // TODO: Feed Update array into null
856 RigidBody body = new RigidBody(0, new DefaultMotionState( mat, IndexedMatrix.Identity), shape, IndexedVector3.Zero);
857 body.SetWorldTransform(mat);
858 body.SetUserPointer(pLocalID);
859 return new BulletBodyXNA(pLocalID, body);
860 }
861 //(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
862 public override CollisionFlags SetCollisionFlags(BulletBody pBody, CollisionFlags collisionFlags)
863 {
864 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
865 body.SetCollisionFlags((BulletXNA.BulletCollision.CollisionFlags) (uint) collisionFlags);
866 return (CollisionFlags)body.GetCollisionFlags();
867 }
868
869 public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain) { /* TODO */ return Vector3.Zero; }
870 public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; }
871 public override bool HasAnisotripicFriction(BulletConstraint pconstrain) { /* TODO */ return false; }
872 public override float GetContactProcessingThreshold(BulletBody pBody) { /* TODO */ return 0f; }
873 public override bool IsStaticObject(BulletBody pBody) { /* TODO */ return false; }
874 public override bool IsKinematicObject(BulletBody pBody) { /* TODO */ return false; }
875 public override bool IsStaticOrKinematicObject(BulletBody pBody) { /* TODO */ return false; }
876 public override bool HasContactResponse(BulletBody pBody) { /* TODO */ return false; }
877 public override int GetActivationState(BulletBody pBody) { /* TODO */ return 0; }
878 public override void SetActivationState(BulletBody pBody, int state) { /* TODO */ }
879 public override float GetDeactivationTime(BulletBody pBody) { /* TODO */ return 0f; }
880 public override bool IsActive(BulletBody pBody) { /* TODO */ return false; }
881 public override float GetRestitution(BulletBody pBody) { /* TODO */ return 0f; }
882 public override float GetFriction(BulletBody pBody) { /* TODO */ return 0f; }
883 public override void SetInterpolationVelocity(BulletBody pBody, Vector3 linearVel, Vector3 angularVel) { /* TODO */ }
884 public override float GetHitFraction(BulletBody pBody) { /* TODO */ return 0f; }
885
886 //(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
887 public override void SetHitFraction(BulletBody pBody, float pHitFraction)
888 {
889 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
890 body.SetHitFraction(pHitFraction);
891 }
892 //BuildCapsuleShape(physicsScene.World.ptr, 1f, 1f, prim.Scale);
893 public override BulletShape BuildCapsuleShape(BulletWorld pWorld, float pRadius, float pHeight, Vector3 pScale)
894 {
895 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
896 IndexedVector3 scale = new IndexedVector3(pScale.X, pScale.Y, pScale.Z);
897 CapsuleShapeZ capsuleShapeZ = new CapsuleShapeZ(pRadius, pHeight);
898 capsuleShapeZ.SetMargin(world.WorldSettings.Params.collisionMargin);
899 capsuleShapeZ.SetLocalScaling(ref scale);
900
901 return new BulletShapeXNA(capsuleShapeZ, BSPhysicsShapeType.SHAPE_CAPSULE); ;
902 }
903
904 public override BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
905 int maxCollisions, ref CollisionDesc[] collisionArray,
906 int maxUpdates, ref EntityProperties[] updateArray
907 )
908 {
909 /* TODO */
910 return new BulletWorldXNA(1, null, null);
911 }
912
913 private static object Initialize2(Vector3 worldExtent,
914 ConfigurationParameters[] o,
915 int mMaxCollisionsPerFrame, ref List<BulletXNA.CollisionDesc> collisionArray,
916 int mMaxUpdatesPerFrame, ref List<BulletXNA.EntityProperties> updateArray,
917 object mDebugLogCallbackHandle)
918 {
919 CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData();
920
921 p.angularDamping = o[0].XangularDamping;
922 p.defaultFriction = o[0].defaultFriction;
923 p.defaultFriction = o[0].defaultFriction;
924 p.defaultDensity = o[0].defaultDensity;
925 p.defaultRestitution = o[0].defaultRestitution;
926 p.collisionMargin = o[0].collisionMargin;
927 p.gravity = o[0].gravity;
928
929 p.linearDamping = o[0].XlinearDamping;
930 p.angularDamping = o[0].XangularDamping;
931 p.deactivationTime = o[0].XdeactivationTime;
932 p.linearSleepingThreshold = o[0].XlinearSleepingThreshold;
933 p.angularSleepingThreshold = o[0].XangularSleepingThreshold;
934 p.ccdMotionThreshold = o[0].XccdMotionThreshold;
935 p.ccdSweptSphereRadius = o[0].XccdSweptSphereRadius;
936 p.contactProcessingThreshold = o[0].XcontactProcessingThreshold;
937
938 p.terrainImplementation = o[0].XterrainImplementation;
939 p.terrainFriction = o[0].XterrainFriction;
940
941 p.terrainHitFraction = o[0].XterrainHitFraction;
942 p.terrainRestitution = o[0].XterrainRestitution;
943 p.terrainCollisionMargin = o[0].XterrainCollisionMargin;
944
945 p.avatarFriction = o[0].XavatarFriction;
946 p.avatarStandingFriction = o[0].XavatarStandingFriction;
947 p.avatarDensity = o[0].XavatarDensity;
948 p.avatarRestitution = o[0].XavatarRestitution;
949 p.avatarCapsuleWidth = o[0].XavatarCapsuleWidth;
950 p.avatarCapsuleDepth = o[0].XavatarCapsuleDepth;
951 p.avatarCapsuleHeight = o[0].XavatarCapsuleHeight;
952 p.avatarContactProcessingThreshold = o[0].XavatarContactProcessingThreshold;
953
954 p.vehicleAngularDamping = o[0].XvehicleAngularDamping;
955
956 p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize;
957 p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize;
958 p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation;
959 p.shouldForceUpdateAllAabbs = o[0].shouldForceUpdateAllAabbs;
960 p.shouldRandomizeSolverOrder = o[0].shouldRandomizeSolverOrder;
961 p.shouldSplitSimulationIslands = o[0].shouldSplitSimulationIslands;
962 p.shouldEnableFrictionCaching = o[0].shouldEnableFrictionCaching;
963 p.numberOfSolverIterations = o[0].numberOfSolverIterations;
964
965 p.linksetImplementation = o[0].XlinksetImplementation;
966 p.linkConstraintUseFrameOffset = o[0].XlinkConstraintUseFrameOffset;
967 p.linkConstraintEnableTransMotor = o[0].XlinkConstraintEnableTransMotor;
968 p.linkConstraintTransMotorMaxVel = o[0].XlinkConstraintTransMotorMaxVel;
969 p.linkConstraintTransMotorMaxForce = o[0].XlinkConstraintTransMotorMaxForce;
970 p.linkConstraintERP = o[0].XlinkConstraintERP;
971 p.linkConstraintCFM = o[0].XlinkConstraintCFM;
972 p.linkConstraintSolverIterations = o[0].XlinkConstraintSolverIterations;
973 p.physicsLoggingFrames = o[0].XphysicsLoggingFrames;
974 DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo();
975
976 DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration();
977 CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci);
978
979
980 if (p.maxPersistantManifoldPoolSize > 0)
981 cci.m_persistentManifoldPoolSize = (int)p.maxPersistantManifoldPoolSize;
982 if (p.shouldDisableContactPoolDynamicAllocation !=0)
983 m_dispatcher.SetDispatcherFlags(DispatcherFlags.CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION);
984 //if (p.maxCollisionAlgorithmPoolSize >0 )
985
986 DbvtBroadphase m_broadphase = new DbvtBroadphase();
987 //IndexedVector3 aabbMin = new IndexedVector3(0, 0, 0);
988 //IndexedVector3 aabbMax = new IndexedVector3(256, 256, 256);
989
990 //AxisSweep3Internal m_broadphase2 = new AxisSweep3Internal(ref aabbMin, ref aabbMax, Convert.ToInt32(0xfffe), 0xffff, ushort.MaxValue/2, null, true);
991 m_broadphase.GetOverlappingPairCache().SetInternalGhostPairCallback(new GhostPairCallback());
992
993 SequentialImpulseConstraintSolver m_solver = new SequentialImpulseConstraintSolver();
994
995 DiscreteDynamicsWorld world = new DiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, cci);
996 world.UpdatedObjects = updateArray;
997 world.UpdatedCollisions = collisionArray;
998 world.WorldSettings.Params = p;
999 world.SetForceUpdateAllAabbs(p.shouldForceUpdateAllAabbs != 0);
1000 world.GetSolverInfo().m_solverMode = SolverMode.SOLVER_USE_WARMSTARTING | SolverMode.SOLVER_SIMD;
1001 if (p.shouldRandomizeSolverOrder != 0)
1002 world.GetSolverInfo().m_solverMode |= SolverMode.SOLVER_RANDMIZE_ORDER;
1003
1004 world.GetSimulationIslandManager().SetSplitIslands(p.shouldSplitSimulationIslands != 0);
1005 //world.GetDispatchInfo().m_enableSatConvex Not implemented in C# port
1006
1007 if (p.shouldEnableFrictionCaching != 0)
1008 world.GetSolverInfo().m_solverMode |= SolverMode.SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;
1009
1010 if (p.numberOfSolverIterations > 0)
1011 world.GetSolverInfo().m_numIterations = (int) p.numberOfSolverIterations;
1012
1013
1014 world.GetSolverInfo().m_damping = world.WorldSettings.Params.linearDamping;
1015 world.GetSolverInfo().m_restitution = world.WorldSettings.Params.defaultRestitution;
1016 world.GetSolverInfo().m_globalCfm = 0.0f;
1017 world.GetSolverInfo().m_tau = 0.6f;
1018 world.GetSolverInfo().m_friction = 0.3f;
1019 world.GetSolverInfo().m_maxErrorReduction = 20f;
1020 world.GetSolverInfo().m_numIterations = 10;
1021 world.GetSolverInfo().m_erp = 0.2f;
1022 world.GetSolverInfo().m_erp2 = 0.1f;
1023 world.GetSolverInfo().m_sor = 1.0f;
1024 world.GetSolverInfo().m_splitImpulse = false;
1025 world.GetSolverInfo().m_splitImpulsePenetrationThreshold = -0.02f;
1026 world.GetSolverInfo().m_linearSlop = 0.0f;
1027 world.GetSolverInfo().m_warmstartingFactor = 0.85f;
1028 world.GetSolverInfo().m_restingContactRestitutionThreshold = 2;
1029 world.SetForceUpdateAllAabbs(true);
1030
1031
1032 world.SetGravity(new IndexedVector3(0,0,p.gravity));
1033
1034 return world;
1035 }
1036 //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL
1037 public override bool SetConstraintParam(BulletConstraint pConstraint, ConstraintParams paramIndex, float paramvalue, ConstraintParamAxis axis)
1038 {
1039 Generic6DofConstraint constrain = ((BulletConstraintXNA)pConstraint).constrain as Generic6DofConstraint;
1040 if (axis == ConstraintParamAxis.AXIS_LINEAR_ALL || axis == ConstraintParamAxis.AXIS_ALL)
1041 {
1042 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 0);
1043 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 1);
1044 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams) (int) paramIndex, paramvalue, 2);
1045 }
1046 if (axis == ConstraintParamAxis.AXIS_ANGULAR_ALL || axis == ConstraintParamAxis.AXIS_ALL)
1047 {
1048 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 3);
1049 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 4);
1050 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, 5);
1051 }
1052 if (axis == ConstraintParamAxis.AXIS_LINEAR_ALL)
1053 {
1054 constrain.SetParam((BulletXNA.BulletDynamics.ConstraintParams)(int)paramIndex, paramvalue, (int)axis);
1055 }
1056 return true;
1057 }
1058
1059 public override bool PushUpdate(BulletBody pCollisionObject)
1060 {
1061 bool ret = false;
1062 RigidBody rb = ((BulletBodyXNA)pCollisionObject).rigidBody;
1063 if (rb != null)
1064 {
1065 SimMotionState sms = rb.GetMotionState() as SimMotionState;
1066 if (sms != null)
1067 {
1068 IndexedMatrix wt = IndexedMatrix.Identity;
1069 sms.GetWorldTransform(out wt);
1070 sms.SetWorldTransform(ref wt, true);
1071 ret = true;
1072 }
1073 }
1074 return ret;
1075
1076 }
1077
1078 public override float GetAngularMotionDisc(BulletShape pShape)
1079 {
1080 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1081 return shape.GetAngularMotionDisc();
1082 }
1083 public override float GetContactBreakingThreshold(BulletShape pShape, float defaultFactor)
1084 {
1085 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1086 return shape.GetContactBreakingThreshold(defaultFactor);
1087 }
1088 public override bool IsCompound(BulletShape pShape)
1089 {
1090 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1091 return shape.IsCompound();
1092 }
1093 public override bool IsSoftBody(BulletShape pShape)
1094 {
1095 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1096 return shape.IsSoftBody();
1097 }
1098 public override bool IsPolyhedral(BulletShape pShape)
1099 {
1100 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1101 return shape.IsPolyhedral();
1102 }
1103 public override bool IsConvex2d(BulletShape pShape)
1104 {
1105 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1106 return shape.IsConvex2d();
1107 }
1108 public override bool IsConvex(BulletShape pShape)
1109 {
1110 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1111 return shape.IsConvex();
1112 }
1113 public override bool IsNonMoving(BulletShape pShape)
1114 {
1115 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1116 return shape.IsNonMoving();
1117 }
1118 public override bool IsConcave(BulletShape pShape)
1119 {
1120 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1121 return shape.IsConcave();
1122 }
1123 public override bool IsInfinite(BulletShape pShape)
1124 {
1125 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1126 return shape.IsInfinite();
1127 }
1128 public override bool IsNativeShape(BulletShape pShape)
1129 {
1130 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1131 bool ret;
1132 switch (shape.GetShapeType())
1133 {
1134 case BroadphaseNativeTypes.BOX_SHAPE_PROXYTYPE:
1135 case BroadphaseNativeTypes.CONE_SHAPE_PROXYTYPE:
1136 case BroadphaseNativeTypes.SPHERE_SHAPE_PROXYTYPE:
1137 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
1138 ret = true;
1139 break;
1140 default:
1141 ret = false;
1142 break;
1143 }
1144 return ret;
1145 }
1146
1147 public override void SetShapeCollisionMargin(BulletShape shape, float margin) { /* TODO */ }
1148
1149 //sim.ptr, shape.ptr,prim.LocalID, prim.RawPosition, prim.RawOrientation
1150 public override BulletBody CreateGhostFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
1151 {
1152 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
1153 IndexedMatrix bodyTransform = new IndexedMatrix();
1154 bodyTransform._origin = new IndexedVector3(pRawPosition.X, pRawPosition.Y, pRawPosition.Z);
1155 bodyTransform.SetRotation(new IndexedQuaternion(pRawOrientation.X,pRawOrientation.Y,pRawOrientation.Z,pRawOrientation.W));
1156 GhostObject gObj = new PairCachingGhostObject();
1157 gObj.SetWorldTransform(bodyTransform);
1158 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1159 gObj.SetCollisionShape(shape);
1160 gObj.SetUserPointer(pLocalID);
1161 // TODO: Add to Special CollisionObjects!
1162 return new BulletBodyXNA(pLocalID, gObj);
1163 }
1164
1165 public override void SetCollisionShape(BulletWorld pWorld, BulletBody pObj, BulletShape pShape)
1166 {
1167 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
1168 CollisionObject obj = ((BulletBodyXNA)pObj).body;
1169 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1170 obj.SetCollisionShape(shape);
1171
1172 }
1173 public override BulletShape GetCollisionShape(BulletBody obj) { /* TODO */ return null; }
1174
1175 //(PhysicsScene.World.ptr, nativeShapeData)
1176 public override BulletShape BuildNativeShape(BulletWorld pWorld, ShapeData pShapeData)
1177 {
1178 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
1179 CollisionShape shape = null;
1180 switch (pShapeData.Type)
1181 {
1182 case BSPhysicsShapeType.SHAPE_BOX:
1183 shape = new BoxShape(new IndexedVector3(0.5f,0.5f,0.5f));
1184 break;
1185 case BSPhysicsShapeType.SHAPE_CONE:
1186 shape = new ConeShapeZ(0.5f, 1.0f);
1187 break;
1188 case BSPhysicsShapeType.SHAPE_CYLINDER:
1189 shape = new CylinderShapeZ(new IndexedVector3(0.5f, 0.5f, 0.5f));
1190 break;
1191 case BSPhysicsShapeType.SHAPE_SPHERE:
1192 shape = new SphereShape(0.5f);
1193 break;
1194
1195 }
1196 if (shape != null)
1197 {
1198 IndexedVector3 scaling = new IndexedVector3(pShapeData.Scale.X, pShapeData.Scale.Y, pShapeData.Scale.Z);
1199 shape.SetMargin(world.WorldSettings.Params.collisionMargin);
1200 shape.SetLocalScaling(ref scaling);
1201
1202 }
1203 return new BulletShapeXNA(shape, pShapeData.Type);
1204 }
1205 //PhysicsScene.World.ptr, false
1206 public override BulletShape CreateCompoundShape(BulletWorld pWorld, bool enableDynamicAabbTree)
1207 {
1208 return new BulletShapeXNA(new CompoundShape(enableDynamicAabbTree), BSPhysicsShapeType.SHAPE_COMPOUND);
1209 }
1210
1211 public override int GetNumberOfCompoundChildren(BulletShape pCompoundShape)
1212 {
1213 CompoundShape compoundshape = ((BulletShapeXNA)pCompoundShape).shape as CompoundShape;
1214 return compoundshape.GetNumChildShapes();
1215 }
1216 //LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot
1217 public override void AddChildShapeToCompoundShape(BulletShape pCShape, BulletShape paddShape, Vector3 displacementPos, Quaternion displacementRot)
1218 {
1219 IndexedMatrix relativeTransform = new IndexedMatrix();
1220 CompoundShape compoundshape = ((BulletShapeXNA)pCShape).shape as CompoundShape;
1221 CollisionShape addshape = ((BulletShapeXNA)paddShape).shape;
1222
1223 relativeTransform._origin = new IndexedVector3(displacementPos.X, displacementPos.Y, displacementPos.Z);
1224 relativeTransform.SetRotation(new IndexedQuaternion(displacementRot.X,displacementRot.Y,displacementRot.Z,displacementRot.W));
1225 compoundshape.AddChildShape(ref relativeTransform, addshape);
1226
1227 }
1228
1229 public override BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape pCShape, int pii)
1230 {
1231 CompoundShape compoundshape = ((BulletShapeXNA)pCShape).shape as CompoundShape;
1232 CollisionShape ret = null;
1233 ret = compoundshape.GetChildShape(pii);
1234 compoundshape.RemoveChildShapeByIndex(pii);
1235 return new BulletShapeXNA(ret, BSPhysicsShapeType.SHAPE_UNKNOWN);
1236 }
1237
1238 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { /* TODO */ return null; }
1239 public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ }
1240
1241 public override BulletShape CreateGroundPlaneShape(uint pLocalId, float pheight, float pcollisionMargin)
1242 {
1243 StaticPlaneShape m_planeshape = new StaticPlaneShape(new IndexedVector3(0,0,1),(int)pheight );
1244 m_planeshape.SetMargin(pcollisionMargin);
1245 m_planeshape.SetUserPointer(pLocalId);
1246 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE);
1247 }
1248
1249 public override BulletConstraint CreateHingeConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody ppBody2, Vector3 ppivotInA, Vector3 ppivotInB, Vector3 paxisInA, Vector3 paxisInB, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
1250 {
1251 HingeConstraint constrain = null;
1252 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
1253 RigidBody rb1 = ((BulletBodyXNA)pBody1).rigidBody;
1254 RigidBody rb2 = ((BulletBodyXNA)ppBody2).rigidBody;
1255 if (rb1 != null && rb2 != null)
1256 {
1257 IndexedVector3 pivotInA = new IndexedVector3(ppivotInA.X, ppivotInA.Y, ppivotInA.Z);
1258 IndexedVector3 pivotInB = new IndexedVector3(ppivotInB.X, ppivotInB.Y, ppivotInB.Z);
1259 IndexedVector3 axisInA = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.Z);
1260 IndexedVector3 axisInB = new IndexedVector3(paxisInB.X, paxisInB.Y, paxisInB.Z);
1261 world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
1262 }
1263 return new BulletConstraintXNA(constrain);
1264 }
1265
1266 public override BulletShape CreateHullShape(BulletWorld pWorld, int pHullCount, float[] pConvHulls)
1267 {
1268 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
1269 CompoundShape compoundshape = new CompoundShape(false);
1270
1271 compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin);
1272 int ii = 1;
1273
1274 for (int i = 0; i < pHullCount; i++)
1275 {
1276 int vertexCount = (int) pConvHulls[ii];
1277
1278 IndexedVector3 centroid = new IndexedVector3(pConvHulls[ii + 1], pConvHulls[ii + 2], pConvHulls[ii + 3]);
1279 IndexedMatrix childTrans = IndexedMatrix.Identity;
1280 childTrans._origin = centroid;
1281
1282 List<IndexedVector3> virts = new List<IndexedVector3>();
1283 int ender = ((ii + 4) + (vertexCount*3));
1284 for (int iii = ii + 4; iii < ender; iii+=3)
1285 {
1286
1287 virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2]));
1288 }
1289 ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount);
1290 convexShape.SetMargin(world.WorldSettings.Params.collisionMargin);
1291 compoundshape.AddChildShape(ref childTrans, convexShape);
1292 ii += (vertexCount*3 + 4);
1293 }
1294
1295 return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL);
1296 }
1297
1298 public override BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape) { /* TODO */ return null; }
1299
1300 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
1301 {
1302 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount);
1303
1304 for (int iter = 0; iter < pVerticesCount; iter++)
1305 {
1306 if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0;
1307 if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0;
1308 }
1309
1310 ObjectArray<int> indicesarr = new ObjectArray<int>(indices);
1311 ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats);
1312 DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount);
1313 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
1314 IndexedMesh mesh = new IndexedMesh();
1315 mesh.m_indexType = PHY_ScalarType.PHY_INTEGER;
1316 mesh.m_numTriangles = pIndicesCount/3;
1317 mesh.m_numVertices = pVerticesCount;
1318 mesh.m_triangleIndexBase = indicesarr;
1319 mesh.m_vertexBase = vertices;
1320 mesh.m_vertexStride = 3;
1321 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1322 mesh.m_triangleIndexStride = 3;
1323
1324 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1325 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1326 BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true);
1327 meshShape.SetMargin(world.WorldSettings.Params.collisionMargin);
1328 // world.UpdateSingleAabb(meshShape);
1329 return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH);
1330
1331 }
1332 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount )
1333 {
1334
1335 String fileName = "objTest3.raw";
1336 String completePath = System.IO.Path.Combine(Util.configDir(), fileName);
1337 StreamWriter sw = new StreamWriter(completePath);
1338 IndexedMesh mesh = new IndexedMesh();
1339
1340 mesh.m_indexType = PHY_ScalarType.PHY_INTEGER;
1341 mesh.m_numTriangles = pIndicesCount / 3;
1342 mesh.m_numVertices = pVerticesCount;
1343 mesh.m_triangleIndexBase = indices;
1344 mesh.m_vertexBase = vertices;
1345 mesh.m_vertexStride = 3;
1346 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1347 mesh.m_triangleIndexStride = 3;
1348
1349 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1350 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1351
1352
1353
1354 for (int i = 0; i < pVerticesCount; i++)
1355 {
1356
1357 string s = vertices[indices[i * 3]].ToString("0.0000");
1358 s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000");
1359 s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000");
1360
1361 sw.Write(s + "\n");
1362 }
1363
1364 sw.Close();
1365 }
1366 public static void DumpRaw(int[] indices, float[] vertices, int pIndicesCount, int pVerticesCount)
1367 {
1368
1369 String fileName = "objTest6.raw";
1370 String completePath = System.IO.Path.Combine(Util.configDir(), fileName);
1371 StreamWriter sw = new StreamWriter(completePath);
1372 IndexedMesh mesh = new IndexedMesh();
1373
1374 mesh.m_indexType = PHY_ScalarType.PHY_INTEGER;
1375 mesh.m_numTriangles = pIndicesCount / 3;
1376 mesh.m_numVertices = pVerticesCount;
1377 mesh.m_triangleIndexBase = indices;
1378 mesh.m_vertexBase = vertices;
1379 mesh.m_vertexStride = 3;
1380 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1381 mesh.m_triangleIndexStride = 3;
1382
1383 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1384 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1385
1386
1387 sw.WriteLine("Indices");
1388 sw.WriteLine(string.Format("int[] indices = new int[{0}];",pIndicesCount));
1389 for (int iter = 0; iter < indices.Length; iter++)
1390 {
1391 sw.WriteLine(string.Format("indices[{0}]={1};",iter,indices[iter]));
1392 }
1393 sw.WriteLine("VerticesFloats");
1394 sw.WriteLine(string.Format("float[] vertices = new float[{0}];", pVerticesCount));
1395 for (int iter = 0; iter < vertices.Length; iter++)
1396 {
1397 sw.WriteLine(string.Format("Vertices[{0}]={1};", iter, vertices[iter].ToString("0.0000")));
1398 }
1399
1400 // for (int i = 0; i < pVerticesCount; i++)
1401 // {
1402 //
1403 // string s = vertices[indices[i * 3]].ToString("0.0000");
1404 // s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000");
1405 // s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000");
1406 //
1407 // sw.Write(s + "\n");
1408 //}
1409
1410 sw.Close();
1411 }
1412
1413 public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
1414 float scaleFactor, float collisionMargin)
1415 {
1416 const int upAxis = 2;
1417 HeightfieldTerrainShape terrainShape = new HeightfieldTerrainShape((int)size.X, (int)size.Y,
1418 heightMap, scaleFactor,
1419 minHeight, maxHeight, upAxis,
1420 false);
1421 terrainShape.SetMargin(collisionMargin + 0.5f);
1422 terrainShape.SetUseDiamondSubdivision(true);
1423 terrainShape.SetUserPointer(id);
1424 return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN);
1425 }
1426
1427 public override bool TranslationalLimitMotor(BulletConstraint pConstraint, float ponOff, float targetVelocity, float maxMotorForce)
1428 {
1429 TypedConstraint tconstrain = ((BulletConstraintXNA)pConstraint).constrain;
1430 bool onOff = ponOff != 0;
1431 bool ret = false;
1432
1433 switch (tconstrain.GetConstraintType())
1434 {
1435 case TypedConstraintType.D6_CONSTRAINT_TYPE:
1436 Generic6DofConstraint constrain = tconstrain as Generic6DofConstraint;
1437 constrain.GetTranslationalLimitMotor().m_enableMotor[0] = onOff;
1438 constrain.GetTranslationalLimitMotor().m_targetVelocity[0] = targetVelocity;
1439 constrain.GetTranslationalLimitMotor().m_maxMotorForce[0] = maxMotorForce;
1440 ret = true;
1441 break;
1442 }
1443
1444
1445 return ret;
1446
1447 }
1448
1449 public override int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
1450 out int updatedEntityCount, out int collidersCount)
1451 {
1452 /* TODO */
1453 updatedEntityCount = 0;
1454 collidersCount = 0;
1455 return 1;
1456 }
1457
1458 private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep,
1459 out int updatedEntityCount, out List<BulletXNA.EntityProperties> updatedEntities,
1460 out int collidersCount, out List<BulletXNA.CollisionDesc>colliders)
1461 {
1462 int epic = PhysicsStepint(pWorld, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntities,
1463 out collidersCount, out colliders);
1464 return epic;
1465 }
1466
1467 private static int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount, out List<BulletXNA.EntityProperties> updatedEntities, out int collidersCount, out List<BulletXNA.CollisionDesc> colliders)
1468 {
1469 int numSimSteps = 0;
1470
1471
1472 //if (updatedEntities is null)
1473 // updatedEntities = new List<BulletXNA.EntityProperties>();
1474
1475 //if (colliders is null)
1476 // colliders = new List<BulletXNA.CollisionDesc>();
1477
1478
1479 if (pWorld is BulletWorldXNA)
1480 {
1481 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
1482
1483 numSimSteps = world.StepSimulation(timeStep, m_maxSubSteps, m_fixedTimeStep);
1484 int updates = 0;
1485
1486 updatedEntityCount = world.UpdatedObjects.Count;
1487 updatedEntities = new List<BulletXNA.EntityProperties>(world.UpdatedObjects);
1488 updatedEntityCount = updatedEntities.Count;
1489 world.UpdatedObjects.Clear();
1490
1491
1492 collidersCount = world.UpdatedCollisions.Count;
1493 colliders = new List<BulletXNA.CollisionDesc>(world.UpdatedCollisions);
1494
1495 world.UpdatedCollisions.Clear();
1496 m_collisionsThisFrame = 0;
1497 int numManifolds = world.GetDispatcher().GetNumManifolds();
1498 for (int j = 0; j < numManifolds; j++)
1499 {
1500 PersistentManifold contactManifold = world.GetDispatcher().GetManifoldByIndexInternal(j);
1501 int numContacts = contactManifold.GetNumContacts();
1502 if (numContacts == 0)
1503 continue;
1504
1505 CollisionObject objA = contactManifold.GetBody0() as CollisionObject;
1506 CollisionObject objB = contactManifold.GetBody1() as CollisionObject;
1507
1508 ManifoldPoint manifoldPoint = contactManifold.GetContactPoint(0);
1509 IndexedVector3 contactPoint = manifoldPoint.GetPositionWorldOnB();
1510 IndexedVector3 contactNormal = -manifoldPoint.m_normalWorldOnB; // make relative to A
1511
1512 RecordCollision(world, objA, objB, contactPoint, contactNormal);
1513 m_collisionsThisFrame ++;
1514 if (m_collisionsThisFrame >= 9999999)
1515 break;
1516
1517
1518 }
1519
1520
1521 }
1522 else
1523 {
1524 //if (updatedEntities is null)
1525 updatedEntities = new List<BulletXNA.EntityProperties>();
1526 updatedEntityCount = 0;
1527 //if (colliders is null)
1528 colliders = new List<BulletXNA.CollisionDesc>();
1529 collidersCount = 0;
1530 }
1531 return numSimSteps;
1532 }
1533
1534 private static void RecordCollision(CollisionWorld world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm)
1535 {
1536
1537 IndexedVector3 contactNormal = norm;
1538 if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 &&
1539 (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0)
1540 {
1541 return;
1542 }
1543 uint idA = (uint)objA.GetUserPointer();
1544 uint idB = (uint)objB.GetUserPointer();
1545 if (idA > idB)
1546 {
1547 uint temp = idA;
1548 idA = idB;
1549 idB = temp;
1550 contactNormal = -contactNormal;
1551 }
1552
1553 ulong collisionID = ((ulong) idA << 32) | idB;
1554
1555 BulletXNA.CollisionDesc cDesc = new BulletXNA.CollisionDesc()
1556 {
1557 aID = idA,
1558 bID = idB,
1559 point = contact,
1560 normal = contactNormal
1561 };
1562 world.UpdatedCollisions.Add(cDesc);
1563 m_collisionsThisFrame++;
1564
1565
1566 }
1567 private static EntityProperties GetDebugProperties(BulletWorld pWorld, BulletBody pBody)
1568 {
1569 EntityProperties ent = new EntityProperties();
1570 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
1571 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
1572 IndexedMatrix transform = body.GetWorldTransform();
1573 IndexedVector3 LinearVelocity = body.GetInterpolationLinearVelocity();
1574 IndexedVector3 AngularVelocity = body.GetInterpolationAngularVelocity();
1575 IndexedQuaternion rotation = transform.GetRotation();
1576 ent.Acceleration = Vector3.Zero;
1577 ent.ID = (uint)body.GetUserPointer();
1578 ent.Position = new Vector3(transform._origin.X,transform._origin.Y,transform._origin.Z);
1579 ent.Rotation = new Quaternion(rotation.X,rotation.Y,rotation.Z,rotation.W);
1580 ent.Velocity = new Vector3(LinearVelocity.X, LinearVelocity.Y, LinearVelocity.Z);
1581 ent.RotationalVelocity = new Vector3(AngularVelocity.X, AngularVelocity.Y, AngularVelocity.Z);
1582 return ent;
1583 }
1584
1585 public override bool UpdateParameter(BulletWorld world, uint localID, String parm, float value) { /* TODO */ return false; }
1586
1587 public override Vector3 GetLocalScaling(BulletShape pShape)
1588 {
1589 CollisionShape shape = ((BulletShapeXNA)pShape).shape;
1590 IndexedVector3 scale = shape.GetLocalScaling();
1591 return new Vector3(scale.X,scale.Y,scale.Z);
1592 }
1593
1594 public bool RayCastGround(BulletWorld pWorld, Vector3 _RayOrigin, float pRayHeight, BulletBody NotMe)
1595 {
1596 DiscreteDynamicsWorld world = ((BulletWorldXNA)pWorld).world;
1597 if (world != null)
1598 {
1599 if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody)
1600 {
1601 CollisionObject AvoidBody = ((BulletBodyXNA)NotMe).body;
1602
1603 IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z);
1604 IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight);
1605 using (
1606 ClosestNotMeRayResultCallback rayCallback =
1607 new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody)
1608 )
1609 {
1610 world.RayTest(ref rOrigin, ref rEnd, rayCallback);
1611 if (rayCallback.HasHit())
1612 {
1613 IndexedVector3 hitLocation = rayCallback.m_hitPointWorld;
1614 }
1615 return rayCallback.HasHit();
1616 }
1617 }
1618 }
1619 return false;
1620 }
1621}
1622}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
deleted file mode 100644
index 8ad78ca..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ /dev/null
@@ -1,662 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Runtime.InteropServices;
30using System.Security;
31using System.Text;
32using OpenMetaverse;
33
34namespace OpenSim.Region.Physics.BulletSPlugin {
35
36 // Constraint type values as defined by Bullet
37public enum ConstraintType : int
38{
39 POINT2POINT_CONSTRAINT_TYPE = 3,
40 HINGE_CONSTRAINT_TYPE,
41 CONETWIST_CONSTRAINT_TYPE,
42 D6_CONSTRAINT_TYPE,
43 SLIDER_CONSTRAINT_TYPE,
44 CONTACT_CONSTRAINT_TYPE,
45 D6_SPRING_CONSTRAINT_TYPE,
46 MAX_CONSTRAINT_TYPE
47}
48
49// ===============================================================================
50[StructLayout(LayoutKind.Sequential)]
51public struct ConvexHull
52{
53 Vector3 Offset;
54 int VertexCount;
55 Vector3[] Vertices;
56}
57public enum BSPhysicsShapeType
58{
59 SHAPE_UNKNOWN = 0,
60 SHAPE_CAPSULE = 1,
61 SHAPE_BOX = 2,
62 SHAPE_CONE = 3,
63 SHAPE_CYLINDER = 4,
64 SHAPE_SPHERE = 5,
65 SHAPE_MESH = 6,
66 SHAPE_HULL = 7,
67 // following defined by BulletSim
68 SHAPE_GROUNDPLANE = 20,
69 SHAPE_TERRAIN = 21,
70 SHAPE_COMPOUND = 22,
71 SHAPE_HEIGHTMAP = 23,
72 SHAPE_AVATAR = 24,
73};
74
75// The native shapes have predefined shape hash keys
76public enum FixedShapeKey : ulong
77{
78 KEY_NONE = 0,
79 KEY_BOX = 1,
80 KEY_SPHERE = 2,
81 KEY_CONE = 3,
82 KEY_CYLINDER = 4,
83 KEY_CAPSULE = 5,
84 KEY_AVATAR = 6,
85}
86
87[StructLayout(LayoutKind.Sequential)]
88public struct ShapeData
89{
90 public uint ID;
91 public BSPhysicsShapeType Type;
92 public Vector3 Position;
93 public Quaternion Rotation;
94 public Vector3 Velocity;
95 public Vector3 Scale;
96 public float Mass;
97 public float Buoyancy;
98 public System.UInt64 HullKey;
99 public System.UInt64 MeshKey;
100 public float Friction;
101 public float Restitution;
102 public float Collidable; // true of things bump into this
103 public float Static; // true if a static object. Otherwise gravity, etc.
104 public float Solid; // true if object cannot be passed through
105 public Vector3 Size;
106
107 // note that bools are passed as floats since bool size changes by language and architecture
108 public const float numericTrue = 1f;
109 public const float numericFalse = 0f;
110}
111[StructLayout(LayoutKind.Sequential)]
112public struct SweepHit
113{
114 public uint ID;
115 public float Fraction;
116 public Vector3 Normal;
117 public Vector3 Point;
118}
119[StructLayout(LayoutKind.Sequential)]
120public struct RaycastHit
121{
122 public uint ID;
123 public float Fraction;
124 public Vector3 Normal;
125}
126[StructLayout(LayoutKind.Sequential)]
127public struct CollisionDesc
128{
129 public uint aID;
130 public uint bID;
131 public Vector3 point;
132 public Vector3 normal;
133}
134[StructLayout(LayoutKind.Sequential)]
135public struct EntityProperties
136{
137 public uint ID;
138 public Vector3 Position;
139 public Quaternion Rotation;
140 public Vector3 Velocity;
141 public Vector3 Acceleration;
142 public Vector3 RotationalVelocity;
143}
144
145// Format of this structure must match the definition in the C++ code
146// NOTE: adding the X causes compile breaks if used. These are unused symbols
147// that can be removed from both here and the unmanaged definition of this structure.
148[StructLayout(LayoutKind.Sequential)]
149public struct ConfigurationParameters
150{
151 public float defaultFriction;
152 public float defaultDensity;
153 public float defaultRestitution;
154 public float collisionMargin;
155 public float gravity;
156
157 public float XlinearDamping;
158 public float XangularDamping;
159 public float XdeactivationTime;
160 public float XlinearSleepingThreshold;
161 public float XangularSleepingThreshold;
162 public float XccdMotionThreshold;
163 public float XccdSweptSphereRadius;
164 public float XcontactProcessingThreshold;
165
166 public float XterrainImplementation;
167 public float XterrainFriction;
168 public float XterrainHitFraction;
169 public float XterrainRestitution;
170 public float XterrainCollisionMargin;
171
172 public float XavatarFriction;
173 public float XavatarStandingFriction;
174 public float XavatarDensity;
175 public float XavatarRestitution;
176 public float XavatarCapsuleWidth;
177 public float XavatarCapsuleDepth;
178 public float XavatarCapsuleHeight;
179 public float XavatarContactProcessingThreshold;
180
181 public float XvehicleAngularDamping;
182
183 public float maxPersistantManifoldPoolSize;
184 public float maxCollisionAlgorithmPoolSize;
185 public float shouldDisableContactPoolDynamicAllocation;
186 public float shouldForceUpdateAllAabbs;
187 public float shouldRandomizeSolverOrder;
188 public float shouldSplitSimulationIslands;
189 public float shouldEnableFrictionCaching;
190 public float numberOfSolverIterations;
191
192 public float XlinksetImplementation;
193 public float XlinkConstraintUseFrameOffset;
194 public float XlinkConstraintEnableTransMotor;
195 public float XlinkConstraintTransMotorMaxVel;
196 public float XlinkConstraintTransMotorMaxForce;
197 public float XlinkConstraintERP;
198 public float XlinkConstraintCFM;
199 public float XlinkConstraintSolverIterations;
200
201 public float XphysicsLoggingFrames;
202
203 public const float numericTrue = 1f;
204 public const float numericFalse = 0f;
205}
206
207
208// The states a bullet collision object can have
209public enum ActivationState : uint
210{
211 ACTIVE_TAG = 1,
212 ISLAND_SLEEPING,
213 WANTS_DEACTIVATION,
214 DISABLE_DEACTIVATION,
215 DISABLE_SIMULATION,
216}
217
218public enum CollisionObjectTypes : int
219{
220 CO_COLLISION_OBJECT = 1 << 0,
221 CO_RIGID_BODY = 1 << 1,
222 CO_GHOST_OBJECT = 1 << 2,
223 CO_SOFT_BODY = 1 << 3,
224 CO_HF_FLUID = 1 << 4,
225 CO_USER_TYPE = 1 << 5,
226}
227
228// Values used by Bullet and BulletSim to control object properties.
229// Bullet's "CollisionFlags" has more to do with operations on the
230// object (if collisions happen, if gravity effects it, ...).
231public enum CollisionFlags : uint
232{
233 CF_STATIC_OBJECT = 1 << 0,
234 CF_KINEMATIC_OBJECT = 1 << 1,
235 CF_NO_CONTACT_RESPONSE = 1 << 2,
236 CF_CUSTOM_MATERIAL_CALLBACK = 1 << 3,
237 CF_CHARACTER_OBJECT = 1 << 4,
238 CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
239 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
240 // Following used by BulletSim to control collisions and updates
241 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
242 BS_FLOATS_ON_WATER = 1 << 11,
243 BS_VEHICLE_COLLISIONS = 1 << 12,
244 BS_NONE = 0,
245 BS_ALL = 0xFFFFFFFF
246};
247
248// Values f collisions groups and masks
249public enum CollisionFilterGroups : uint
250{
251 // Don't use the bit definitions!! Define the use in a
252 // filter/mask definition below. This way collision interactions
253 // are more easily found and debugged.
254 BNoneGroup = 0,
255 BDefaultGroup = 1 << 0, // 0001
256 BStaticGroup = 1 << 1, // 0002
257 BKinematicGroup = 1 << 2, // 0004
258 BDebrisGroup = 1 << 3, // 0008
259 BSensorTrigger = 1 << 4, // 0010
260 BCharacterGroup = 1 << 5, // 0020
261 BAllGroup = 0x000FFFFF,
262 // Filter groups defined by BulletSim
263 BGroundPlaneGroup = 1 << 10, // 0400
264 BTerrainGroup = 1 << 11, // 0800
265 BRaycastGroup = 1 << 12, // 1000
266 BSolidGroup = 1 << 13, // 2000
267 // BLinksetGroup = xx // a linkset proper is either static or dynamic
268 BLinksetChildGroup = 1 << 14, // 4000
269};
270
271// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
272// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
273public enum ConstraintParams : int
274{
275 BT_CONSTRAINT_ERP = 1, // this one is not used in Bullet as of 20120730
276 BT_CONSTRAINT_STOP_ERP,
277 BT_CONSTRAINT_CFM,
278 BT_CONSTRAINT_STOP_CFM,
279};
280public enum ConstraintParamAxis : int
281{
282 AXIS_LINEAR_X = 0,
283 AXIS_LINEAR_Y,
284 AXIS_LINEAR_Z,
285 AXIS_ANGULAR_X,
286 AXIS_ANGULAR_Y,
287 AXIS_ANGULAR_Z,
288 AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls
289 AXIS_ANGULAR_ALL,
290 AXIS_ALL
291};
292
293public abstract class BSAPITemplate
294{
295// Returns the name of the underlying Bullet engine
296public abstract string BulletEngineName { get; }
297public abstract string BulletEngineVersion { get; protected set;}
298
299// Initialization and simulation
300public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
301 int maxCollisions, ref CollisionDesc[] collisionArray,
302 int maxUpdates, ref EntityProperties[] updateArray
303 );
304
305public abstract int PhysicsStep(BulletWorld world, float timeStep, int maxSubSteps, float fixedTimeStep,
306 out int updatedEntityCount, out int collidersCount);
307
308public abstract bool UpdateParameter(BulletWorld world, uint localID, String parm, float value);
309
310public abstract void Shutdown(BulletWorld sim);
311
312public abstract bool PushUpdate(BulletBody obj);
313
314// =====================================================================================
315// Mesh, hull, shape and body creation helper routines
316public abstract BulletShape CreateMeshShape(BulletWorld world,
317 int indicesCount, int[] indices,
318 int verticesCount, float[] vertices );
319
320public abstract BulletShape CreateHullShape(BulletWorld world,
321 int hullCount, float[] hulls);
322
323public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape);
324
325public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData);
326
327public abstract bool IsNativeShape(BulletShape shape);
328
329public abstract void SetShapeCollisionMargin(BulletShape shape, float margin);
330
331public abstract BulletShape BuildCapsuleShape(BulletWorld world, float radius, float height, Vector3 scale);
332
333public abstract BulletShape CreateCompoundShape(BulletWorld sim, bool enableDynamicAabbTree);
334
335public abstract int GetNumberOfCompoundChildren(BulletShape cShape);
336
337public abstract void AddChildShapeToCompoundShape(BulletShape cShape, BulletShape addShape, Vector3 pos, Quaternion rot);
338
339public abstract BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx);
340
341public abstract BulletShape RemoveChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx);
342
343public abstract void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape);
344
345public abstract void RecalculateCompoundShapeLocalAabb(BulletShape cShape);
346
347public abstract BulletShape DuplicateCollisionShape(BulletWorld sim, BulletShape srcShape, uint id);
348
349public abstract bool DeleteCollisionShape(BulletWorld world, BulletShape shape);
350
351public abstract CollisionObjectTypes GetBodyType(BulletBody obj);
352
353public abstract BulletBody CreateBodyFromShape(BulletWorld sim, BulletShape shape, uint id, Vector3 pos, Quaternion rot);
354
355public abstract BulletBody CreateBodyWithDefaultMotionState(BulletShape shape, uint id, Vector3 pos, Quaternion rot);
356
357public abstract BulletBody CreateGhostFromShape(BulletWorld sim, BulletShape shape, uint id, Vector3 pos, Quaternion rot);
358
359public abstract void DestroyObject(BulletWorld sim, BulletBody obj);
360
361// =====================================================================================
362public abstract BulletShape CreateGroundPlaneShape(uint id, float height, float collisionMargin);
363
364public abstract BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
365 float scaleFactor, float collisionMargin);
366
367// =====================================================================================
368// Constraint creation and helper routines
369public abstract BulletConstraint Create6DofConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
370 Vector3 frame1loc, Quaternion frame1rot,
371 Vector3 frame2loc, Quaternion frame2rot,
372 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
373
374public abstract BulletConstraint Create6DofConstraintToPoint(BulletWorld world, BulletBody obj1, BulletBody obj2,
375 Vector3 joinPoint,
376 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
377
378public abstract BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
379 Vector3 pivotinA, Vector3 pivotinB,
380 Vector3 axisInA, Vector3 axisInB,
381 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
382
383public abstract void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse);
384
385public abstract void SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations);
386
387public abstract bool SetFrames(BulletConstraint constrain,
388 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
389
390public abstract bool SetLinearLimits(BulletConstraint constrain, Vector3 low, Vector3 hi);
391
392public abstract bool SetAngularLimits(BulletConstraint constrain, Vector3 low, Vector3 hi);
393
394public abstract bool UseFrameOffset(BulletConstraint constrain, float enable);
395
396public abstract bool TranslationalLimitMotor(BulletConstraint constrain, float enable, float targetVel, float maxMotorForce);
397
398public abstract bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold);
399
400public abstract bool CalculateTransforms(BulletConstraint constrain);
401
402public abstract bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
403
404public abstract bool DestroyConstraint(BulletWorld world, BulletConstraint constrain);
405
406// =====================================================================================
407// btCollisionWorld entries
408public abstract void UpdateSingleAabb(BulletWorld world, BulletBody obj);
409
410public abstract void UpdateAabbs(BulletWorld world);
411
412public abstract bool GetForceUpdateAllAabbs(BulletWorld world);
413
414public abstract void SetForceUpdateAllAabbs(BulletWorld world, bool force);
415
416// =====================================================================================
417// btDynamicsWorld entries
418// public abstract bool AddObjectToWorld(BulletWorld world, BulletBody obj, Vector3 pos, Quaternion rot);
419public abstract bool AddObjectToWorld(BulletWorld world, BulletBody obj);
420
421public abstract bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj);
422
423public abstract bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects);
424
425public abstract bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain);
426// =====================================================================================
427// btCollisionObject entries
428public abstract Vector3 GetAnisotripicFriction(BulletConstraint constrain);
429
430public abstract Vector3 SetAnisotripicFriction(BulletConstraint constrain, Vector3 frict);
431
432public abstract bool HasAnisotripicFriction(BulletConstraint constrain);
433
434public abstract void SetContactProcessingThreshold(BulletBody obj, float val);
435
436public abstract float GetContactProcessingThreshold(BulletBody obj);
437
438public abstract bool IsStaticObject(BulletBody obj);
439
440public abstract bool IsKinematicObject(BulletBody obj);
441
442public abstract bool IsStaticOrKinematicObject(BulletBody obj);
443
444public abstract bool HasContactResponse(BulletBody obj);
445
446public abstract void SetCollisionShape(BulletWorld sim, BulletBody obj, BulletShape shape);
447
448public abstract BulletShape GetCollisionShape(BulletBody obj);
449
450public abstract int GetActivationState(BulletBody obj);
451
452public abstract void SetActivationState(BulletBody obj, int state);
453
454public abstract void SetDeactivationTime(BulletBody obj, float dtime);
455
456public abstract float GetDeactivationTime(BulletBody obj);
457
458public abstract void ForceActivationState(BulletBody obj, ActivationState state);
459
460public abstract void Activate(BulletBody obj, bool forceActivation);
461
462public abstract bool IsActive(BulletBody obj);
463
464public abstract void SetRestitution(BulletBody obj, float val);
465
466public abstract float GetRestitution(BulletBody obj);
467
468public abstract void SetFriction(BulletBody obj, float val);
469
470public abstract float GetFriction(BulletBody obj);
471
472public abstract Vector3 GetPosition(BulletBody obj);
473
474public abstract Quaternion GetOrientation(BulletBody obj);
475
476public abstract void SetTranslation(BulletBody obj, Vector3 position, Quaternion rotation);
477
478// public abstract IntPtr GetBroadphaseHandle(BulletBody obj);
479
480// public abstract void SetBroadphaseHandle(BulletBody obj, IntPtr handle);
481
482public abstract void SetInterpolationLinearVelocity(BulletBody obj, Vector3 vel);
483
484public abstract void SetInterpolationAngularVelocity(BulletBody obj, Vector3 vel);
485
486public abstract void SetInterpolationVelocity(BulletBody obj, Vector3 linearVel, Vector3 angularVel);
487
488public abstract float GetHitFraction(BulletBody obj);
489
490public abstract void SetHitFraction(BulletBody obj, float val);
491
492public abstract CollisionFlags GetCollisionFlags(BulletBody obj);
493
494public abstract CollisionFlags SetCollisionFlags(BulletBody obj, CollisionFlags flags);
495
496public abstract CollisionFlags AddToCollisionFlags(BulletBody obj, CollisionFlags flags);
497
498public abstract CollisionFlags RemoveFromCollisionFlags(BulletBody obj, CollisionFlags flags);
499
500public abstract float GetCcdMotionThreshold(BulletBody obj);
501
502public abstract void SetCcdMotionThreshold(BulletBody obj, float val);
503
504public abstract float GetCcdSweptSphereRadius(BulletBody obj);
505
506public abstract void SetCcdSweptSphereRadius(BulletBody obj, float val);
507
508public abstract IntPtr GetUserPointer(BulletBody obj);
509
510public abstract void SetUserPointer(BulletBody obj, IntPtr val);
511
512// =====================================================================================
513// btRigidBody entries
514public abstract void ApplyGravity(BulletBody obj);
515
516public abstract void SetGravity(BulletBody obj, Vector3 val);
517
518public abstract Vector3 GetGravity(BulletBody obj);
519
520public abstract void SetDamping(BulletBody obj, float lin_damping, float ang_damping);
521
522public abstract void SetLinearDamping(BulletBody obj, float lin_damping);
523
524public abstract void SetAngularDamping(BulletBody obj, float ang_damping);
525
526public abstract float GetLinearDamping(BulletBody obj);
527
528public abstract float GetAngularDamping(BulletBody obj);
529
530public abstract float GetLinearSleepingThreshold(BulletBody obj);
531
532public abstract void ApplyDamping(BulletBody obj, float timeStep);
533
534public abstract void SetMassProps(BulletBody obj, float mass, Vector3 inertia);
535
536public abstract Vector3 GetLinearFactor(BulletBody obj);
537
538public abstract void SetLinearFactor(BulletBody obj, Vector3 factor);
539
540public abstract void SetCenterOfMassByPosRot(BulletBody obj, Vector3 pos, Quaternion rot);
541
542// Add a force to the object as if its mass is one.
543public abstract void ApplyCentralForce(BulletBody obj, Vector3 force);
544
545// Set the force being applied to the object as if its mass is one.
546public abstract void SetObjectForce(BulletBody obj, Vector3 force);
547
548public abstract Vector3 GetTotalForce(BulletBody obj);
549
550public abstract Vector3 GetTotalTorque(BulletBody obj);
551
552public abstract Vector3 GetInvInertiaDiagLocal(BulletBody obj);
553
554public abstract void SetInvInertiaDiagLocal(BulletBody obj, Vector3 inert);
555
556public abstract void SetSleepingThresholds(BulletBody obj, float lin_threshold, float ang_threshold);
557
558public abstract void ApplyTorque(BulletBody obj, Vector3 torque);
559
560// Apply force at the given point. Will add torque to the object.
561public abstract void ApplyForce(BulletBody obj, Vector3 force, Vector3 pos);
562
563// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
564public abstract void ApplyCentralImpulse(BulletBody obj, Vector3 imp);
565
566// Apply impulse to the object's torque. Force is scaled by object's mass.
567public abstract void ApplyTorqueImpulse(BulletBody obj, Vector3 imp);
568
569// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
570public abstract void ApplyImpulse(BulletBody obj, Vector3 imp, Vector3 pos);
571
572public abstract void ClearForces(BulletBody obj);
573
574public abstract void ClearAllForces(BulletBody obj);
575
576public abstract void UpdateInertiaTensor(BulletBody obj);
577
578public abstract Vector3 GetLinearVelocity(BulletBody obj);
579
580public abstract Vector3 GetAngularVelocity(BulletBody obj);
581
582public abstract void SetLinearVelocity(BulletBody obj, Vector3 val);
583
584public abstract void SetAngularVelocity(BulletBody obj, Vector3 angularVelocity);
585
586public abstract Vector3 GetVelocityInLocalPoint(BulletBody obj, Vector3 pos);
587
588public abstract void Translate(BulletBody obj, Vector3 trans);
589
590public abstract void UpdateDeactivation(BulletBody obj, float timeStep);
591
592public abstract bool WantsSleeping(BulletBody obj);
593
594public abstract void SetAngularFactor(BulletBody obj, float factor);
595
596public abstract void SetAngularFactorV(BulletBody obj, Vector3 factor);
597
598public abstract Vector3 GetAngularFactor(BulletBody obj);
599
600public abstract bool IsInWorld(BulletWorld world, BulletBody obj);
601
602public abstract void AddConstraintRef(BulletBody obj, BulletConstraint constrain);
603
604public abstract void RemoveConstraintRef(BulletBody obj, BulletConstraint constrain);
605
606public abstract BulletConstraint GetConstraintRef(BulletBody obj, int index);
607
608public abstract int GetNumConstraintRefs(BulletBody obj);
609
610public abstract bool SetCollisionGroupMask(BulletBody body, uint filter, uint mask);
611
612// =====================================================================================
613// btCollisionShape entries
614
615public abstract float GetAngularMotionDisc(BulletShape shape);
616
617public abstract float GetContactBreakingThreshold(BulletShape shape, float defaultFactor);
618
619public abstract bool IsPolyhedral(BulletShape shape);
620
621public abstract bool IsConvex2d(BulletShape shape);
622
623public abstract bool IsConvex(BulletShape shape);
624
625public abstract bool IsNonMoving(BulletShape shape);
626
627public abstract bool IsConcave(BulletShape shape);
628
629public abstract bool IsCompound(BulletShape shape);
630
631public abstract bool IsSoftBody(BulletShape shape);
632
633public abstract bool IsInfinite(BulletShape shape);
634
635public abstract void SetLocalScaling(BulletShape shape, Vector3 scale);
636
637public abstract Vector3 GetLocalScaling(BulletShape shape);
638
639public abstract Vector3 CalculateLocalInertia(BulletShape shape, float mass);
640
641public abstract int GetShapeType(BulletShape shape);
642
643public abstract void SetMargin(BulletShape shape, float val);
644
645public abstract float GetMargin(BulletShape shape);
646
647// =====================================================================================
648// Debugging
649public abstract void DumpRigidBody(BulletWorld sim, BulletBody collisionObject);
650
651public abstract void DumpCollisionShape(BulletWorld sim, BulletShape collisionShape);
652
653public abstract void DumpConstraint(BulletWorld sim, BulletConstraint constrain);
654
655public abstract void DumpActivationInfo(BulletWorld sim);
656
657public abstract void DumpAllInfo(BulletWorld sim);
658
659public abstract void DumpPhysicsStatistics(BulletWorld sim);
660
661};
662}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
deleted file mode 100644
index 103d8fc..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ /dev/null
@@ -1,827 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using log4net;
31using OMV = OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37public sealed class BSCharacter : BSPhysObject
38{
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 private static readonly string LogHeader = "[BULLETS CHAR]";
41
42 // private bool _stopped;
43 private OMV.Vector3 _size;
44 private bool _grabbed;
45 private bool _selected;
46 private OMV.Vector3 _position;
47 private float _mass;
48 private float _avatarDensity;
49 private float _avatarVolume;
50 private OMV.Vector3 _force;
51 private OMV.Vector3 _velocity;
52 private OMV.Vector3 _torque;
53 private float _collisionScore;
54 private OMV.Vector3 _acceleration;
55 private OMV.Quaternion _orientation;
56 private int _physicsActorType;
57 private bool _isPhysical;
58 private bool _flying;
59 private bool _setAlwaysRun;
60 private bool _throttleUpdates;
61 private bool _isColliding;
62 private bool _collidingObj;
63 private bool _floatOnWater;
64 private OMV.Vector3 _rotationalVelocity;
65 private bool _kinematic;
66 private float _buoyancy;
67
68 // The friction and velocity of the avatar is modified depending on whether walking or not.
69 private float _currentFriction; // the friction currently being used (changed by setVelocity).
70
71 private BSVMotor _velocityMotor;
72
73 private OMV.Vector3 _PIDTarget;
74 private bool _usePID;
75 private float _PIDTau;
76 private bool _useHoverPID;
77 private float _PIDHoverHeight;
78 private PIDHoverType _PIDHoverType;
79 private float _PIDHoverTao;
80
81 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
82 : base(parent_scene, localID, avName, "BSCharacter")
83 {
84 _physicsActorType = (int)ActorTypes.Agent;
85 _position = pos;
86
87 _flying = isFlying;
88 _orientation = OMV.Quaternion.Identity;
89 _velocity = OMV.Vector3.Zero;
90 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
91 _currentFriction = BSParam.AvatarStandingFriction;
92 _avatarDensity = BSParam.AvatarDensity;
93
94 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
95 // replace with the default values.
96 _size = size;
97 if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth;
98 if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth;
99
100 // The dimensions of the physical capsule are kept in the scale.
101 // Physics creates a unit capsule which is scaled by the physics engine.
102 Scale = ComputeAvatarScale(_size);
103 // set _avatarVolume and _mass based on capsule size, _density and Scale
104 ComputeAvatarVolumeAndMass();
105
106 SetupMovementMotor();
107
108 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
109 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
110
111 // do actual creation in taint time
112 PhysicsScene.TaintedObject("BSCharacter.create", delegate()
113 {
114 DetailLog("{0},BSCharacter.create,taint", LocalID);
115 // New body and shape into PhysBody and PhysShape
116 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this);
117
118 SetPhysicalProperties();
119 });
120 return;
121 }
122
123 // called when this character is being destroyed and the resources should be released
124 public override void Destroy()
125 {
126 base.Destroy();
127
128 DetailLog("{0},BSCharacter.Destroy", LocalID);
129 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
130 {
131 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
132 PhysBody.Clear();
133 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
134 PhysShape.Clear();
135 });
136 }
137
138 private void SetPhysicalProperties()
139 {
140 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody);
141
142 ZeroMotion(true);
143 ForcePosition = _position;
144
145 // Set the velocity and compute the proper friction
146 _velocityMotor.Reset();
147 _velocityMotor.SetTarget(_velocity);
148 _velocityMotor.SetCurrent(_velocity);
149 ForceVelocity = _velocity;
150
151 // This will enable or disable the flying buoyancy of the avatar.
152 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
153 Flying = _flying;
154
155 PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution);
156 PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin);
157 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale);
158 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
159 if (BSParam.CcdMotionThreshold > 0f)
160 {
161 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
162 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
163 }
164
165 UpdatePhysicalMassProperties(RawMass, false);
166
167 // Make so capsule does not fall over
168 PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
169
170 PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
171
172 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody);
173
174 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
175 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION);
176 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody);
177
178 // Do this after the object has been added to the world
179 PhysBody.collisionType = CollisionType.Avatar;
180 PhysBody.ApplyCollisionMask(PhysicsScene);
181 }
182
183 // The avatar's movement is controlled by this motor that speeds up and slows down
184 // the avatar seeking to reach the motor's target speed.
185 // This motor runs as a prestep action for the avatar so it will keep the avatar
186 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
187 private void SetupMovementMotor()
188 {
189
190 // Someday, use a PID motor for asymmetric speed up and slow down
191 // _velocityMotor = new BSPIDVMotor("BSCharacter.Velocity", 3f, 5f, BSMotor.InfiniteVector, 1f);
192
193 // Infinite decay and timescale values so motor only changes current to target values.
194 _velocityMotor = new BSVMotor("BSCharacter.Velocity",
195 0.2f, // time scale
196 BSMotor.Infinite, // decay time scale
197 BSMotor.InfiniteVector, // friction timescale
198 1f // efficiency
199 );
200 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
201
202 RegisterPreStepAction("BSCharactor.Movement", LocalID, delegate(float timeStep)
203 {
204 // TODO: Decide if the step parameters should be changed depending on the avatar's
205 // state (flying, colliding, ...). There is code in ODE to do this.
206
207 OMV.Vector3 stepVelocity = _velocityMotor.Step(timeStep);
208
209 // If falling, we keep the world's downward vector no matter what the other axis specify.
210 if (!Flying && !IsColliding)
211 {
212 stepVelocity.Z = _velocity.Z;
213 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
214 }
215
216 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
217 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass / PhysicsScene.LastTimeStep;
218
219 /*
220 // If moveForce is very small, zero things so we don't keep sending microscopic updates to the user
221 float moveForceMagnitudeSquared = moveForce.LengthSquared();
222 if (moveForceMagnitudeSquared < 0.0001)
223 {
224 DetailLog("{0},BSCharacter.MoveMotor,zeroMovement,stepVel={1},vel={2},mass={3},magSq={4},moveForce={5}",
225 LocalID, stepVelocity, _velocity, Mass, moveForceMagnitudeSquared, moveForce);
226 ForceVelocity = OMV.Vector3.Zero;
227 }
228 else
229 {
230 AddForce(moveForce, false, true);
231 }
232 */
233 // DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
234 AddForce(moveForce, false, true);
235 });
236 }
237
238 public override void RequestPhysicsterseUpdate()
239 {
240 base.RequestPhysicsterseUpdate();
241 }
242 // No one calls this method so I don't know what it could possibly mean
243 public override bool Stopped { get { return false; } }
244
245 public override OMV.Vector3 Size {
246 get
247 {
248 // Avatar capsule size is kept in the scale parameter.
249 return _size;
250 }
251
252 set {
253 _size = value;
254 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
255 // replace with the default values.
256 if (_size.X == 0f) _size.X = BSParam.AvatarCapsuleDepth;
257 if (_size.Y == 0f) _size.Y = BSParam.AvatarCapsuleWidth;
258
259 Scale = ComputeAvatarScale(_size);
260 ComputeAvatarVolumeAndMass();
261 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
262 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
263
264 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
265 {
266 if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape)
267 {
268 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale);
269 UpdatePhysicalMassProperties(RawMass, true);
270 // Make sure this change appears as a property update event
271 PhysicsScene.PE.PushUpdate(PhysBody);
272 }
273 });
274
275 }
276 }
277
278 public override PrimitiveBaseShape Shape
279 {
280 set { BaseShape = value; }
281 }
282 // I want the physics engine to make an avatar capsule
283 public override BSPhysicsShapeType PreferredPhysicalShape
284 {
285 get {return BSPhysicsShapeType.SHAPE_CAPSULE; }
286 }
287
288 public override bool Grabbed {
289 set { _grabbed = value; }
290 }
291 public override bool Selected {
292 set { _selected = value; }
293 }
294 public override void CrossingFailure() { return; }
295 public override void link(PhysicsActor obj) { return; }
296 public override void delink() { return; }
297
298 // Set motion values to zero.
299 // Do it to the properties so the values get set in the physics engine.
300 // Push the setting of the values to the viewer.
301 // Called at taint time!
302 public override void ZeroMotion(bool inTaintTime)
303 {
304 _velocity = OMV.Vector3.Zero;
305 _acceleration = OMV.Vector3.Zero;
306 _rotationalVelocity = OMV.Vector3.Zero;
307
308 // Zero some other properties directly into the physics engine
309 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
310 {
311 if (PhysBody.HasPhysicalBody)
312 PhysicsScene.PE.ClearAllForces(PhysBody);
313 });
314 }
315 public override void ZeroAngularMotion(bool inTaintTime)
316 {
317 _rotationalVelocity = OMV.Vector3.Zero;
318
319 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
320 {
321 if (PhysBody.HasPhysicalBody)
322 {
323 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero);
324 PhysicsScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero);
325 // The next also get rid of applied linear force but the linear velocity is untouched.
326 PhysicsScene.PE.ClearForces(PhysBody);
327 }
328 });
329 }
330
331
332 public override void LockAngularMotion(OMV.Vector3 axis) { return; }
333
334 public override OMV.Vector3 RawPosition
335 {
336 get { return _position; }
337 set { _position = value; }
338 }
339 public override OMV.Vector3 Position {
340 get {
341 // Don't refetch the position because this function is called a zillion times
342 // _position = PhysicsScene.PE.GetObjectPosition(Scene.World, LocalID);
343 return _position;
344 }
345 set {
346 _position = value;
347 PositionSanityCheck();
348
349 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
350 {
351 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
352 if (PhysBody.HasPhysicalBody)
353 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
354 });
355 }
356 }
357 public override OMV.Vector3 ForcePosition {
358 get {
359 _position = PhysicsScene.PE.GetPosition(PhysBody);
360 return _position;
361 }
362 set {
363 _position = value;
364 PositionSanityCheck();
365 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
366 }
367 }
368
369
370 // Check that the current position is sane and, if not, modify the position to make it so.
371 // Check for being below terrain or on water.
372 // Returns 'true' of the position was made sane by some action.
373 private bool PositionSanityCheck()
374 {
375 bool ret = false;
376
377 // TODO: check for out of bounds
378 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position))
379 {
380 // The character is out of the known/simulated area.
381 // Upper levels of code will handle the transition to other areas so, for
382 // the time, we just ignore the position.
383 return ret;
384 }
385
386 // If below the ground, move the avatar up
387 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
388 if (Position.Z < terrainHeight)
389 {
390 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
391 _position.Z = terrainHeight + 2.0f;
392 ret = true;
393 }
394 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
395 {
396 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
397 if (Position.Z < waterHeight)
398 {
399 _position.Z = waterHeight;
400 ret = true;
401 }
402 }
403
404 return ret;
405 }
406
407 // A version of the sanity check that also makes sure a new position value is
408 // pushed back to the physics engine. This routine would be used by anyone
409 // who is not already pushing the value.
410 private bool PositionSanityCheck(bool inTaintTime)
411 {
412 bool ret = false;
413 if (PositionSanityCheck())
414 {
415 // The new position value must be pushed into the physics engine but we can't
416 // just assign to "Position" because of potential call loops.
417 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
418 {
419 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
420 if (PhysBody.HasPhysicalBody)
421 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
422 });
423 ret = true;
424 }
425 return ret;
426 }
427
428 public override float Mass { get { return _mass; } }
429
430 // used when we only want this prim's mass and not the linkset thing
431 public override float RawMass {
432 get {return _mass; }
433 }
434 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
435 {
436 OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass);
437 PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia);
438 }
439
440 public override OMV.Vector3 Force {
441 get { return _force; }
442 set {
443 _force = value;
444 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
445 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
446 {
447 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
448 if (PhysBody.HasPhysicalBody)
449 PhysicsScene.PE.SetObjectForce(PhysBody, _force);
450 });
451 }
452 }
453
454 // Avatars don't do vehicles
455 public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } }
456 public override void VehicleFloatParam(int param, float value) { }
457 public override void VehicleVectorParam(int param, OMV.Vector3 value) {}
458 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { }
459 public override void VehicleFlags(int param, bool remove) { }
460
461 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
462 public override void SetVolumeDetect(int param) { return; }
463
464 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
465 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
466
467 // Sets the target in the motor. This starts the changing of the avatar's velocity.
468 public override OMV.Vector3 TargetVelocity
469 {
470 get
471 {
472 return _velocityMotor.TargetValue;
473 }
474 set
475 {
476 DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value);
477 OMV.Vector3 targetVel = value;
478 if (_setAlwaysRun)
479 targetVel *= BSParam.AvatarAlwaysRunFactor;
480
481 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate()
482 {
483 _velocityMotor.Reset();
484 _velocityMotor.SetTarget(targetVel);
485 _velocityMotor.SetCurrent(_velocity);
486 _velocityMotor.Enabled = true;
487 });
488 }
489 }
490 // Directly setting velocity means this is what the user really wants now.
491 public override OMV.Vector3 Velocity {
492 get { return _velocity; }
493 set {
494 _velocity = value;
495 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
496 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
497 {
498 _velocityMotor.Reset();
499 _velocityMotor.SetCurrent(_velocity);
500 _velocityMotor.SetTarget(_velocity);
501 // Even though the motor is initialized, it's not used and the velocity goes straight into the avatar.
502 _velocityMotor.Enabled = false;
503
504 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
505 ForceVelocity = _velocity;
506 });
507 }
508 }
509 public override OMV.Vector3 ForceVelocity {
510 get { return _velocity; }
511 set {
512 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity");
513
514 _velocity = value;
515 // Depending on whether the avatar is moving or not, change the friction
516 // to keep the avatar from slipping around
517 if (_velocity.Length() == 0)
518 {
519 if (_currentFriction != BSParam.AvatarStandingFriction)
520 {
521 _currentFriction = BSParam.AvatarStandingFriction;
522 if (PhysBody.HasPhysicalBody)
523 PhysicsScene.PE.SetFriction(PhysBody, _currentFriction);
524 }
525 }
526 else
527 {
528 if (_currentFriction != BSParam.AvatarFriction)
529 {
530 _currentFriction = BSParam.AvatarFriction;
531 if (PhysBody.HasPhysicalBody)
532 PhysicsScene.PE.SetFriction(PhysBody, _currentFriction);
533 }
534 }
535
536 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
537 PhysicsScene.PE.Activate(PhysBody, true);
538 }
539 }
540 public override OMV.Vector3 Torque {
541 get { return _torque; }
542 set { _torque = value;
543 }
544 }
545 public override float CollisionScore {
546 get { return _collisionScore; }
547 set { _collisionScore = value;
548 }
549 }
550 public override OMV.Vector3 Acceleration {
551 get { return _acceleration; }
552 set { _acceleration = value; }
553 }
554 public override OMV.Quaternion RawOrientation
555 {
556 get { return _orientation; }
557 set { _orientation = value; }
558 }
559 public override OMV.Quaternion Orientation {
560 get { return _orientation; }
561 set {
562 // Orientation is set zillions of times when an avatar is walking. It's like
563 // the viewer doesn't trust us.
564 if (_orientation != value)
565 {
566 _orientation = value;
567 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
568 {
569 ForceOrientation = _orientation;
570 });
571 }
572 }
573 }
574 // Go directly to Bullet to get/set the value.
575 public override OMV.Quaternion ForceOrientation
576 {
577 get
578 {
579 _orientation = PhysicsScene.PE.GetOrientation(PhysBody);
580 return _orientation;
581 }
582 set
583 {
584 _orientation = value;
585 if (PhysBody.HasPhysicalBody)
586 {
587 // _position = PhysicsScene.PE.GetPosition(BSBody);
588 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
589 }
590 }
591 }
592 public override int PhysicsActorType {
593 get { return _physicsActorType; }
594 set { _physicsActorType = value;
595 }
596 }
597 public override bool IsPhysical {
598 get { return _isPhysical; }
599 set { _isPhysical = value;
600 }
601 }
602 public override bool IsSolid {
603 get { return true; }
604 }
605 public override bool IsStatic {
606 get { return false; }
607 }
608 public override bool Flying {
609 get { return _flying; }
610 set {
611 _flying = value;
612
613 // simulate flying by changing the effect of gravity
614 Buoyancy = ComputeBuoyancyFromFlying(_flying);
615 }
616 }
617 // Flying is implimented by changing the avatar's buoyancy.
618 // Would this be done better with a vehicle type?
619 private float ComputeBuoyancyFromFlying(bool ifFlying) {
620 return ifFlying ? 1f : 0f;
621 }
622 public override bool
623 SetAlwaysRun {
624 get { return _setAlwaysRun; }
625 set { _setAlwaysRun = value; }
626 }
627 public override bool ThrottleUpdates {
628 get { return _throttleUpdates; }
629 set { _throttleUpdates = value; }
630 }
631 public override bool FloatOnWater {
632 set {
633 _floatOnWater = value;
634 PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
635 {
636 if (PhysBody.HasPhysicalBody)
637 {
638 if (_floatOnWater)
639 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
640 else
641 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
642 }
643 });
644 }
645 }
646 public override OMV.Vector3 RotationalVelocity {
647 get { return _rotationalVelocity; }
648 set { _rotationalVelocity = value; }
649 }
650 public override OMV.Vector3 ForceRotationalVelocity {
651 get { return _rotationalVelocity; }
652 set { _rotationalVelocity = value; }
653 }
654 public override bool Kinematic {
655 get { return _kinematic; }
656 set { _kinematic = value; }
657 }
658 // neg=fall quickly, 0=1g, 1=0g, pos=float up
659 public override float Buoyancy {
660 get { return _buoyancy; }
661 set { _buoyancy = value;
662 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate()
663 {
664 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
665 ForceBuoyancy = _buoyancy;
666 });
667 }
668 }
669 public override float ForceBuoyancy {
670 get { return _buoyancy; }
671 set {
672 PhysicsScene.AssertInTaintTime("BSCharacter.ForceBuoyancy");
673
674 _buoyancy = value;
675 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
676 // Buoyancy is faked by changing the gravity applied to the object
677 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
678 if (PhysBody.HasPhysicalBody)
679 PhysicsScene.PE.SetGravity(PhysBody, new OMV.Vector3(0f, 0f, grav));
680 }
681 }
682
683 // Used for MoveTo
684 public override OMV.Vector3 PIDTarget {
685 set { _PIDTarget = value; }
686 }
687 public override bool PIDActive {
688 set { _usePID = value; }
689 }
690 public override float PIDTau {
691 set { _PIDTau = value; }
692 }
693
694 // Used for llSetHoverHeight and maybe vehicle height
695 // Hover Height will override MoveTo target's Z
696 public override bool PIDHoverActive {
697 set { _useHoverPID = value; }
698 }
699 public override float PIDHoverHeight {
700 set { _PIDHoverHeight = value; }
701 }
702 public override PIDHoverType PIDHoverType {
703 set { _PIDHoverType = value; }
704 }
705 public override float PIDHoverTau {
706 set { _PIDHoverTao = value; }
707 }
708
709 // For RotLookAt
710 public override OMV.Quaternion APIDTarget { set { return; } }
711 public override bool APIDActive { set { return; } }
712 public override float APIDStrength { set { return; } }
713 public override float APIDDamping { set { return; } }
714
715 public override void AddForce(OMV.Vector3 force, bool pushforce)
716 {
717 // Since this force is being applied in only one step, make this a force per second.
718 OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep;
719 AddForce(addForce, pushforce, false);
720 }
721 private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
722 if (force.IsFinite())
723 {
724 float magnitude = force.Length();
725 if (magnitude > BSParam.MaxAddForceMagnitude)
726 {
727 // Force has a limit
728 force = force / magnitude * BSParam.MaxAddForceMagnitude;
729 }
730
731 OMV.Vector3 addForce = force;
732 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce);
733
734 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate()
735 {
736 // Bullet adds this central force to the total force for this tick
737 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
738 if (PhysBody.HasPhysicalBody)
739 {
740 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce);
741 }
742 });
743 }
744 else
745 {
746 m_log.WarnFormat("{0}: Got a NaN force applied to a character. LocalID={1}", LogHeader, LocalID);
747 return;
748 }
749 }
750
751 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
752 }
753 public override void SetMomentum(OMV.Vector3 momentum) {
754 }
755
756 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size)
757 {
758 OMV.Vector3 newScale;
759
760 // Bullet's capsule total height is the "passed height + radius * 2";
761 // The base capsule is 1 diameter and 2 height (passed radius=0.5, passed height = 1)
762 // The number we pass in for 'scaling' is the multiplier to get that base
763 // shape to be the size desired.
764 // So, when creating the scale for the avatar height, we take the passed height
765 // (size.Z) and remove the caps.
766 // Another oddity of the Bullet capsule implementation is that it presumes the Y
767 // dimension is the radius of the capsule. Even though some of the code allows
768 // for a asymmetrical capsule, other parts of the code presume it is cylindrical.
769
770 // Scale is multiplier of radius with one of "0.5"
771 newScale.X = size.X / 2f;
772 newScale.Y = size.Y / 2f;
773
774 // The total scale height is the central cylindar plus the caps on the two ends.
775 newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2)) / 2f;
776 // If smaller than the endcaps, just fake like we're almost that small
777 if (newScale.Z < 0)
778 newScale.Z = 0.1f;
779
780 return newScale;
781 }
782
783 // set _avatarVolume and _mass based on capsule size, _density and Scale
784 private void ComputeAvatarVolumeAndMass()
785 {
786 _avatarVolume = (float)(
787 Math.PI
788 * Size.X / 2f
789 * Size.Y / 2f // the area of capsule cylinder
790 * Size.Z // times height of capsule cylinder
791 + 1.33333333f
792 * Math.PI
793 * Size.X / 2f
794 * Math.Min(Size.X, Size.Y) / 2
795 * Size.Y / 2f // plus the volume of the capsule end caps
796 );
797 _mass = _avatarDensity * _avatarVolume;
798 }
799
800 // The physics engine says that properties have updated. Update same and inform
801 // the world that things have changed.
802 public override void UpdateProperties(EntityProperties entprop)
803 {
804 _position = entprop.Position;
805 _orientation = entprop.Rotation;
806 _velocity = entprop.Velocity;
807 _acceleration = entprop.Acceleration;
808 _rotationalVelocity = entprop.RotationalVelocity;
809
810 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
811 PositionSanityCheck(true);
812
813 // remember the current and last set values
814 LastEntityProperties = CurrentEntityProperties;
815 CurrentEntityProperties = entprop;
816
817 // Tell the linkset about value changes
818 Linkset.UpdateProperties(this, true);
819
820 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
821 // base.RequestPhysicsterseUpdate();
822
823 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
824 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
825 }
826}
827}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
deleted file mode 100755
index b813974..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ /dev/null
@@ -1,138 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public abstract class BSConstraint : IDisposable
36{
37 private static string LogHeader = "[BULLETSIM CONSTRAINT]";
38
39 protected BulletWorld m_world;
40 protected BSScene PhysicsScene;
41 protected BulletBody m_body1;
42 protected BulletBody m_body2;
43 protected BulletConstraint m_constraint;
44 protected bool m_enabled = false;
45
46 public BulletBody Body1 { get { return m_body1; } }
47 public BulletBody Body2 { get { return m_body2; } }
48 public BulletConstraint Constraint { get { return m_constraint; } }
49 public abstract ConstraintType Type { get; }
50 public bool IsEnabled { get { return m_enabled; } }
51
52 public BSConstraint(BulletWorld world)
53 {
54 m_world = world;
55 PhysicsScene = m_world.physicsScene;
56 }
57
58 public virtual void Dispose()
59 {
60 if (m_enabled)
61 {
62 m_enabled = false;
63 if (m_constraint.HasPhysicalConstraint)
64 {
65 bool success = PhysicsScene.PE.DestroyConstraint(m_world, m_constraint);
66 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
67 BSScene.DetailLogZero,
68 m_body1.ID, m_body1.AddrString,
69 m_body2.ID, m_body2.AddrString,
70 success);
71 m_constraint.Clear();
72 }
73 }
74 }
75
76 public virtual bool SetLinearLimits(Vector3 low, Vector3 high)
77 {
78 bool ret = false;
79 if (m_enabled)
80 ret = PhysicsScene.PE.SetLinearLimits(m_constraint, low, high);
81 return ret;
82 }
83
84 public virtual bool SetAngularLimits(Vector3 low, Vector3 high)
85 {
86 bool ret = false;
87 if (m_enabled)
88 ret = PhysicsScene.PE.SetAngularLimits(m_constraint, low, high);
89 return ret;
90 }
91
92 public virtual bool SetSolverIterations(float cnt)
93 {
94 bool ret = false;
95 if (m_enabled)
96 {
97 PhysicsScene.PE.SetConstraintNumSolverIterations(m_constraint, cnt);
98 ret = true;
99 }
100 return ret;
101 }
102
103 public virtual bool CalculateTransforms()
104 {
105 bool ret = false;
106 if (m_enabled)
107 {
108 // Recompute the internal transforms
109 PhysicsScene.PE.CalculateTransforms(m_constraint);
110 ret = true;
111 }
112 return ret;
113 }
114
115 // Reset this constraint making sure it has all its internal structures
116 // recomputed and is enabled and ready to go.
117 public virtual bool RecomputeConstraintVariables(float mass)
118 {
119 bool ret = false;
120 if (m_enabled)
121 {
122 ret = CalculateTransforms();
123 if (ret)
124 {
125 // Setting an object's mass to zero (making it static like when it's selected)
126 // automatically disables the constraints.
127 // If the link is enabled, be sure to set the constraint itself to enabled.
128 PhysicsScene.PE.SetConstraintEnable(m_constraint, BSParam.NumericBool(true));
129 }
130 else
131 {
132 m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID);
133 }
134 }
135 return ret;
136 }
137}
138}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
deleted file mode 100755
index ecb1b32..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
+++ /dev/null
@@ -1,151 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraint6Dof : BSConstraint
36{
37 private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]";
38
39 public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
40
41 // Create a btGeneric6DofConstraint
42 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
43 Vector3 frame1, Quaternion frame1rot,
44 Vector3 frame2, Quaternion frame2rot,
45 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
46 : base(world)
47 {
48 m_body1 = obj1;
49 m_body2 = obj2;
50 m_constraint = PhysicsScene.PE.Create6DofConstraint(m_world, m_body1, m_body2,
51 frame1, frame1rot,
52 frame2, frame2rot,
53 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
54 m_enabled = true;
55 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
56 BSScene.DetailLogZero, world.worldID,
57 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
58 }
59
60 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
61 Vector3 joinPoint,
62 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
63 : base(world)
64 {
65 m_body1 = obj1;
66 m_body2 = obj2;
67 if (!obj1.HasPhysicalBody || !obj2.HasPhysicalBody)
68 {
69 world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
70 BSScene.DetailLogZero, world.worldID,
71 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
72 world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
73 LogHeader, world.worldID, obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
74 m_enabled = false;
75 }
76 else
77 {
78 m_constraint = PhysicsScene.PE.Create6DofConstraintToPoint(m_world, m_body1, m_body2,
79 joinPoint,
80 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
81 PhysicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
82 BSScene.DetailLogZero, world.worldID, m_constraint.AddrString,
83 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
84 if (!m_constraint.HasPhysicalConstraint)
85 {
86 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
87 LogHeader, obj1.ID, obj2.ID);
88 m_enabled = false;
89 }
90 else
91 {
92 m_enabled = true;
93 }
94 }
95 }
96
97 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
98 {
99 bool ret = false;
100 if (m_enabled)
101 {
102 PhysicsScene.PE.SetFrames(m_constraint, frameA, frameArot, frameB, frameBrot);
103 ret = true;
104 }
105 return ret;
106 }
107
108 public bool SetCFMAndERP(float cfm, float erp)
109 {
110 bool ret = false;
111 if (m_enabled)
112 {
113 PhysicsScene.PE.SetConstraintParam(m_constraint, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
114 PhysicsScene.PE.SetConstraintParam(m_constraint, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
115 PhysicsScene.PE.SetConstraintParam(m_constraint, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
116 ret = true;
117 }
118 return ret;
119 }
120
121 public bool UseFrameOffset(bool useOffset)
122 {
123 bool ret = false;
124 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
125 if (m_enabled)
126 ret = PhysicsScene.PE.UseFrameOffset(m_constraint, onOff);
127 return ret;
128 }
129
130 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
131 {
132 bool ret = false;
133 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
134 if (m_enabled)
135 {
136 ret = PhysicsScene.PE.TranslationalLimitMotor(m_constraint, onOff, targetVelocity, maxMotorForce);
137 m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}",
138 BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce);
139 }
140 return ret;
141 }
142
143 public bool SetBreakingImpulseThreshold(float threshold)
144 {
145 bool ret = false;
146 if (m_enabled)
147 ret = PhysicsScene.PE.SetBreakingImpulseThreshold(m_constraint, threshold);
148 return ret;
149 }
150}
151}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
deleted file mode 100755
index 2aeff25..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
+++ /dev/null
@@ -1,180 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using log4net;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35
36public sealed class BSConstraintCollection : IDisposable
37{
38 // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
39 // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]";
40
41 delegate bool ConstraintAction(BSConstraint constrain);
42
43 private List<BSConstraint> m_constraints;
44 private BulletWorld m_world;
45
46 public BSConstraintCollection(BulletWorld world)
47 {
48 m_world = world;
49 m_constraints = new List<BSConstraint>();
50 }
51
52 public void Dispose()
53 {
54 this.Clear();
55 }
56
57 public void Clear()
58 {
59 lock (m_constraints)
60 {
61 foreach (BSConstraint cons in m_constraints)
62 {
63 cons.Dispose();
64 }
65 m_constraints.Clear();
66 }
67 }
68
69 public bool AddConstraint(BSConstraint cons)
70 {
71 lock (m_constraints)
72 {
73 // There is only one constraint between any bodies. Remove any old just to make sure.
74 RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
75
76 m_constraints.Add(cons);
77 }
78
79 return true;
80 }
81
82 // Get the constraint between two bodies. There can be only one.
83 // Return 'true' if a constraint was found.
84 public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint)
85 {
86 bool found = false;
87 BSConstraint foundConstraint = null;
88
89 uint lookingID1 = body1.ID;
90 uint lookingID2 = body2.ID;
91 lock (m_constraints)
92 {
93 foreach (BSConstraint constrain in m_constraints)
94 {
95 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
96 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
97 {
98 foundConstraint = constrain;
99 found = true;
100 break;
101 }
102 }
103 }
104 returnConstraint = foundConstraint;
105 return found;
106 }
107
108 // Remove any constraint between the passed bodies.
109 // Presumed there is only one such constraint possible.
110 // Return 'true' if a constraint was found and destroyed.
111 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
112 {
113 bool ret = false;
114 lock (m_constraints)
115 {
116 BSConstraint constrain;
117 if (this.TryGetConstraint(body1, body2, out constrain))
118 {
119 // remove the constraint from our collection
120 RemoveAndDestroyConstraint(constrain);
121 ret = true;
122 }
123 }
124
125 return ret;
126 }
127
128 // The constraint MUST exist in the collection
129 public bool RemoveAndDestroyConstraint(BSConstraint constrain)
130 {
131 lock (m_constraints)
132 {
133 // remove the constraint from our collection
134 m_constraints.Remove(constrain);
135 }
136 // tell the engine that all its structures need to be freed
137 constrain.Dispose();
138 // we destroyed something
139 return true;
140 }
141
142 // Remove all constraints that reference the passed body.
143 // Return 'true' if any constraints were destroyed.
144 public bool RemoveAndDestroyConstraint(BulletBody body1)
145 {
146 List<BSConstraint> toRemove = new List<BSConstraint>();
147 uint lookingID = body1.ID;
148 lock (m_constraints)
149 {
150 foreach (BSConstraint constrain in m_constraints)
151 {
152 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
153 {
154 toRemove.Add(constrain);
155 }
156 }
157 foreach (BSConstraint constrain in toRemove)
158 {
159 m_constraints.Remove(constrain);
160 constrain.Dispose();
161 }
162 }
163 return (toRemove.Count > 0);
164 }
165
166 public bool RecalculateAllConstraints()
167 {
168 bool ret = false;
169 lock (m_constraints)
170 {
171 foreach (BSConstraint constrain in m_constraints)
172 {
173 constrain.CalculateTransforms();
174 ret = true;
175 }
176 }
177 return ret;
178 }
179}
180}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
deleted file mode 100755
index 7714a03..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
+++ /dev/null
@@ -1,55 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraintHinge : BSConstraint
36{
37 public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } }
38
39 public BSConstraintHinge(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 pivotInA, Vector3 pivotInB,
41 Vector3 axisInA, Vector3 axisInB,
42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
43 : base(world)
44 {
45 m_body1 = obj1;
46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2,
48 pivotInA, pivotInB, axisInA, axisInB,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
50 m_enabled = true;
51 }
52
53}
54
55}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
deleted file mode 100644
index 13c2539..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ /dev/null
@@ -1,1383 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial
28 * are Copyright (c) 2009 Linden Research, Inc and are used under their license
29 * of Creative Commons Attribution-Share Alike 3.0
30 * (http://creativecommons.org/licenses/by-sa/3.0/).
31 */
32
33using System;
34using System.Collections.Generic;
35using System.Reflection;
36using System.Runtime.InteropServices;
37using OpenMetaverse;
38using OpenSim.Region.Physics.Manager;
39
40namespace OpenSim.Region.Physics.BulletSPlugin
41{
42 public sealed class BSDynamics
43 {
44 private static string LogHeader = "[BULLETSIM VEHICLE]";
45
46 private BSScene PhysicsScene { get; set; }
47 // the prim this dynamic controller belongs to
48 private BSPrim Prim { get; set; }
49
50 // mass of the vehicle fetched each time we're calles
51 private float m_vehicleMass;
52
53 // Vehicle properties
54 public Vehicle Type { get; set; }
55
56 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
57 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
58 // HOVER_TERRAIN_ONLY
59 // HOVER_GLOBAL_HEIGHT
60 // NO_DEFLECTION_UP
61 // HOVER_WATER_ONLY
62 // HOVER_UP_ONLY
63 // LIMIT_MOTOR_UP
64 // LIMIT_ROLL_ONLY
65 private Vector3 m_BlockingEndPoint = Vector3.Zero;
66 private Quaternion m_RollreferenceFrame = Quaternion.Identity;
67 private Quaternion m_referenceFrame = Quaternion.Identity;
68
69 // Linear properties
70 private BSVMotor m_linearMotor = new BSVMotor("LinearMotor");
71 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
72 private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center
73 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
74 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
75 private float m_linearMotorDecayTimescale = 0;
76 private float m_linearMotorTimescale = 0;
77 private Vector3 m_lastLinearVelocityVector = Vector3.Zero;
78 private Vector3 m_lastPositionVector = Vector3.Zero;
79 // private bool m_LinearMotorSetLastFrame = false;
80 // private Vector3 m_linearMotorOffset = Vector3.Zero;
81
82 //Angular properties
83 private BSVMotor m_angularMotor = new BSVMotor("AngularMotor");
84 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
85 // private int m_angularMotorApply = 0; // application frame counter
86 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity
87 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
88 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
89 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
90 private Vector3 m_lastAngularVelocity = Vector3.Zero;
91 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
92
93 //Deflection properties
94 private BSVMotor m_angularDeflectionMotor = new BSVMotor("AngularDeflection");
95 private float m_angularDeflectionEfficiency = 0;
96 private float m_angularDeflectionTimescale = 0;
97 private float m_linearDeflectionEfficiency = 0;
98 private float m_linearDeflectionTimescale = 0;
99
100 //Banking properties
101 private float m_bankingEfficiency = 0;
102 private float m_bankingMix = 0;
103 private float m_bankingTimescale = 0;
104
105 //Hover and Buoyancy properties
106 private BSVMotor m_hoverMotor = new BSVMotor("Hover");
107 private float m_VhoverHeight = 0f;
108 private float m_VhoverEfficiency = 0f;
109 private float m_VhoverTimescale = 0f;
110 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
111 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
112 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
113 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
114 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
115
116 //Attractor properties
117 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
118 private float m_verticalAttractionEfficiency = 1.0f; // damped
119 private float m_verticalAttractionCutoff = 500f; // per the documentation
120 // Timescale > cutoff means no vert attractor.
121 private float m_verticalAttractionTimescale = 510f;
122
123 // Just some recomputed constants:
124 static readonly float PIOverFour = ((float)Math.PI) / 4f;
125 static readonly float PIOverTwo = ((float)Math.PI) / 2f;
126
127 public BSDynamics(BSScene myScene, BSPrim myPrim)
128 {
129 PhysicsScene = myScene;
130 Prim = myPrim;
131 Type = Vehicle.TYPE_NONE;
132 }
133
134 // Return 'true' if this vehicle is doing vehicle things
135 public bool IsActive
136 {
137 get { return Type != Vehicle.TYPE_NONE && Prim.IsPhysical; }
138 }
139
140 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
141 {
142 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
143 switch (pParam)
144 {
145 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
146 m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f);
147 break;
148 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
149 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
150 break;
151 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
152 m_angularMotorDecayTimescale = ClampInRange(0.01f, pValue, 120);
153 m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale;
154 break;
155 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
156 m_angularMotorTimescale = Math.Max(pValue, 0.01f);
157 m_angularMotor.TimeScale = m_angularMotorTimescale;
158 break;
159 case Vehicle.BANKING_EFFICIENCY:
160 m_bankingEfficiency = ClampInRange(-1f, pValue, 1f);
161 break;
162 case Vehicle.BANKING_MIX:
163 m_bankingMix = Math.Max(pValue, 0.01f);
164 break;
165 case Vehicle.BANKING_TIMESCALE:
166 m_bankingTimescale = Math.Max(pValue, 0.01f);
167 break;
168 case Vehicle.BUOYANCY:
169 m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f);
170 break;
171 case Vehicle.HOVER_EFFICIENCY:
172 m_VhoverEfficiency = ClampInRange(0f, pValue, 1f);
173 break;
174 case Vehicle.HOVER_HEIGHT:
175 m_VhoverHeight = pValue;
176 break;
177 case Vehicle.HOVER_TIMESCALE:
178 m_VhoverTimescale = Math.Max(pValue, 0.01f);
179 break;
180 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
181 m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f);
182 break;
183 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
184 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
185 break;
186 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
187 m_linearMotorDecayTimescale = ClampInRange(0.01f, pValue, 120);
188 m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale;
189 break;
190 case Vehicle.LINEAR_MOTOR_TIMESCALE:
191 m_linearMotorTimescale = Math.Max(pValue, 0.01f);
192 m_linearMotor.TimeScale = m_linearMotorTimescale;
193 break;
194 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
195 m_verticalAttractionEfficiency = ClampInRange(0.1f, pValue, 1f);
196 m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency;
197 break;
198 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
199 m_verticalAttractionTimescale = Math.Max(pValue, 0.01f);
200 m_verticalAttractionMotor.TimeScale = m_verticalAttractionTimescale;
201 break;
202
203 // These are vector properties but the engine lets you use a single float value to
204 // set all of the components to the same value
205 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
206 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
207 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
208 break;
209 case Vehicle.ANGULAR_MOTOR_DIRECTION:
210 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
211 m_angularMotor.SetTarget(m_angularMotorDirection);
212 break;
213 case Vehicle.LINEAR_FRICTION_TIMESCALE:
214 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
215 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
216 break;
217 case Vehicle.LINEAR_MOTOR_DIRECTION:
218 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
219 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
220 m_linearMotor.SetTarget(m_linearMotorDirection);
221 break;
222 case Vehicle.LINEAR_MOTOR_OFFSET:
223 m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
224 break;
225
226 }
227 }//end ProcessFloatVehicleParam
228
229 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
230 {
231 VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
232 switch (pParam)
233 {
234 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
235 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
236 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
237 break;
238 case Vehicle.ANGULAR_MOTOR_DIRECTION:
239 // Limit requested angular speed to 2 rps= 4 pi rads/sec
240 pValue.X = ClampInRange(-12.56f, pValue.X, 12.56f);
241 pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f);
242 pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f);
243 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
244 m_angularMotor.SetTarget(m_angularMotorDirection);
245 break;
246 case Vehicle.LINEAR_FRICTION_TIMESCALE:
247 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
248 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
249 break;
250 case Vehicle.LINEAR_MOTOR_DIRECTION:
251 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
252 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
253 m_linearMotor.SetTarget(m_linearMotorDirection);
254 break;
255 case Vehicle.LINEAR_MOTOR_OFFSET:
256 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
257 break;
258 case Vehicle.BLOCK_EXIT:
259 m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z);
260 break;
261 }
262 }//end ProcessVectorVehicleParam
263
264 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
265 {
266 VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
267 switch (pParam)
268 {
269 case Vehicle.REFERENCE_FRAME:
270 m_referenceFrame = pValue;
271 break;
272 case Vehicle.ROLL_FRAME:
273 m_RollreferenceFrame = pValue;
274 break;
275 }
276 }//end ProcessRotationVehicleParam
277
278 internal void ProcessVehicleFlags(int pParam, bool remove)
279 {
280 VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove);
281 VehicleFlag parm = (VehicleFlag)pParam;
282 if (pParam == -1)
283 m_flags = (VehicleFlag)0;
284 else
285 {
286 if (remove)
287 m_flags &= ~parm;
288 else
289 m_flags |= parm;
290 }
291 }
292
293 internal void ProcessTypeChange(Vehicle pType)
294 {
295 VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType);
296 // Set Defaults For Type
297 Type = pType;
298 switch (pType)
299 {
300 case Vehicle.TYPE_NONE:
301 m_linearMotorDirection = Vector3.Zero;
302 m_linearMotorTimescale = 0;
303 m_linearMotorDecayTimescale = 0;
304 m_linearFrictionTimescale = new Vector3(0, 0, 0);
305
306 m_angularMotorDirection = Vector3.Zero;
307 m_angularMotorDecayTimescale = 0;
308 m_angularMotorTimescale = 0;
309 m_angularFrictionTimescale = new Vector3(0, 0, 0);
310
311 m_VhoverHeight = 0;
312 m_VhoverEfficiency = 0;
313 m_VhoverTimescale = 0;
314 m_VehicleBuoyancy = 0;
315
316 m_linearDeflectionEfficiency = 1;
317 m_linearDeflectionTimescale = 1;
318
319 m_angularDeflectionEfficiency = 0;
320 m_angularDeflectionTimescale = 1000;
321
322 m_verticalAttractionEfficiency = 0;
323 m_verticalAttractionTimescale = 0;
324
325 m_bankingEfficiency = 0;
326 m_bankingTimescale = 1000;
327 m_bankingMix = 1;
328
329 m_referenceFrame = Quaternion.Identity;
330 m_flags = (VehicleFlag)0;
331
332 break;
333
334 case Vehicle.TYPE_SLED:
335 m_linearMotorDirection = Vector3.Zero;
336 m_linearMotorTimescale = 1000;
337 m_linearMotorDecayTimescale = 120;
338 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
339
340 m_angularMotorDirection = Vector3.Zero;
341 m_angularMotorTimescale = 1000;
342 m_angularMotorDecayTimescale = 120;
343 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
344
345 m_VhoverHeight = 0;
346 m_VhoverEfficiency = 10; // TODO: this looks wrong!!
347 m_VhoverTimescale = 10;
348 m_VehicleBuoyancy = 0;
349
350 m_linearDeflectionEfficiency = 1;
351 m_linearDeflectionTimescale = 1;
352
353 m_angularDeflectionEfficiency = 1;
354 m_angularDeflectionTimescale = 1000;
355
356 m_verticalAttractionEfficiency = 0;
357 m_verticalAttractionTimescale = 0;
358
359 m_bankingEfficiency = 0;
360 m_bankingTimescale = 10;
361 m_bankingMix = 1;
362
363 m_referenceFrame = Quaternion.Identity;
364 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
365 | VehicleFlag.HOVER_TERRAIN_ONLY
366 | VehicleFlag.HOVER_GLOBAL_HEIGHT
367 | VehicleFlag.HOVER_UP_ONLY);
368 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
369 | VehicleFlag.LIMIT_ROLL_ONLY
370 | VehicleFlag.LIMIT_MOTOR_UP);
371
372 break;
373 case Vehicle.TYPE_CAR:
374 m_linearMotorDirection = Vector3.Zero;
375 m_linearMotorTimescale = 1;
376 m_linearMotorDecayTimescale = 60;
377 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
378
379 m_angularMotorDirection = Vector3.Zero;
380 m_angularMotorTimescale = 1;
381 m_angularMotorDecayTimescale = 0.8f;
382 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
383
384 m_VhoverHeight = 0;
385 m_VhoverEfficiency = 0;
386 m_VhoverTimescale = 1000;
387 m_VehicleBuoyancy = 0;
388
389 m_linearDeflectionEfficiency = 1;
390 m_linearDeflectionTimescale = 2;
391
392 m_angularDeflectionEfficiency = 0;
393 m_angularDeflectionTimescale = 10;
394
395 m_verticalAttractionEfficiency = 1f;
396 m_verticalAttractionTimescale = 10f;
397
398 m_bankingEfficiency = -0.2f;
399 m_bankingMix = 1;
400 m_bankingTimescale = 1;
401
402 m_referenceFrame = Quaternion.Identity;
403 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
404 | VehicleFlag.HOVER_TERRAIN_ONLY
405 | VehicleFlag.HOVER_GLOBAL_HEIGHT);
406 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
407 | VehicleFlag.LIMIT_ROLL_ONLY
408 | VehicleFlag.LIMIT_MOTOR_UP
409 | VehicleFlag.HOVER_UP_ONLY);
410 break;
411 case Vehicle.TYPE_BOAT:
412 m_linearMotorDirection = Vector3.Zero;
413 m_linearMotorTimescale = 5;
414 m_linearMotorDecayTimescale = 60;
415 m_linearFrictionTimescale = new Vector3(10, 3, 2);
416
417 m_angularMotorDirection = Vector3.Zero;
418 m_angularMotorTimescale = 4;
419 m_angularMotorDecayTimescale = 4;
420 m_angularFrictionTimescale = new Vector3(10,10,10);
421
422 m_VhoverHeight = 0;
423 m_VhoverEfficiency = 0.5f;
424 m_VhoverTimescale = 2;
425 m_VehicleBuoyancy = 1;
426
427 m_linearDeflectionEfficiency = 0.5f;
428 m_linearDeflectionTimescale = 3;
429
430 m_angularDeflectionEfficiency = 0.5f;
431 m_angularDeflectionTimescale = 5;
432
433 m_verticalAttractionEfficiency = 0.5f;
434 m_verticalAttractionTimescale = 5f;
435
436 m_bankingEfficiency = -0.3f;
437 m_bankingMix = 0.8f;
438 m_bankingTimescale = 1;
439
440 m_referenceFrame = Quaternion.Identity;
441 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY
442 | VehicleFlag.HOVER_GLOBAL_HEIGHT
443 | VehicleFlag.LIMIT_ROLL_ONLY
444 | VehicleFlag.HOVER_UP_ONLY);
445 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
446 | VehicleFlag.LIMIT_MOTOR_UP
447 | VehicleFlag.HOVER_WATER_ONLY);
448 break;
449 case Vehicle.TYPE_AIRPLANE:
450 m_linearMotorDirection = Vector3.Zero;
451 m_linearMotorTimescale = 2;
452 m_linearMotorDecayTimescale = 60;
453 m_linearFrictionTimescale = new Vector3(200, 10, 5);
454
455 m_angularMotorDirection = Vector3.Zero;
456 m_angularMotorTimescale = 4;
457 m_angularMotorDecayTimescale = 4;
458 m_angularFrictionTimescale = new Vector3(20, 20, 20);
459
460 m_VhoverHeight = 0;
461 m_VhoverEfficiency = 0.5f;
462 m_VhoverTimescale = 1000;
463 m_VehicleBuoyancy = 0;
464
465 m_linearDeflectionEfficiency = 0.5f;
466 m_linearDeflectionTimescale = 3;
467
468 m_angularDeflectionEfficiency = 1;
469 m_angularDeflectionTimescale = 2;
470
471 m_verticalAttractionEfficiency = 0.9f;
472 m_verticalAttractionTimescale = 2f;
473
474 m_bankingEfficiency = 1;
475 m_bankingMix = 0.7f;
476 m_bankingTimescale = 2;
477
478 m_referenceFrame = Quaternion.Identity;
479 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
480 | VehicleFlag.HOVER_TERRAIN_ONLY
481 | VehicleFlag.HOVER_GLOBAL_HEIGHT
482 | VehicleFlag.HOVER_UP_ONLY
483 | VehicleFlag.NO_DEFLECTION_UP
484 | VehicleFlag.LIMIT_MOTOR_UP);
485 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
486 break;
487 case Vehicle.TYPE_BALLOON:
488 m_linearMotorDirection = Vector3.Zero;
489 m_linearMotorTimescale = 5;
490 m_linearFrictionTimescale = new Vector3(5, 5, 5);
491 m_linearMotorDecayTimescale = 60;
492
493 m_angularMotorDirection = Vector3.Zero;
494 m_angularMotorTimescale = 6;
495 m_angularFrictionTimescale = new Vector3(10, 10, 10);
496 m_angularMotorDecayTimescale = 10;
497
498 m_VhoverHeight = 5;
499 m_VhoverEfficiency = 0.8f;
500 m_VhoverTimescale = 10;
501 m_VehicleBuoyancy = 1;
502
503 m_linearDeflectionEfficiency = 0;
504 m_linearDeflectionTimescale = 5;
505
506 m_angularDeflectionEfficiency = 0;
507 m_angularDeflectionTimescale = 5;
508
509 m_verticalAttractionEfficiency = 1f;
510 m_verticalAttractionTimescale = 100f;
511
512 m_bankingEfficiency = 0;
513 m_bankingMix = 0.7f;
514 m_bankingTimescale = 5;
515
516 m_referenceFrame = Quaternion.Identity;
517
518 m_referenceFrame = Quaternion.Identity;
519 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
520 | VehicleFlag.HOVER_TERRAIN_ONLY
521 | VehicleFlag.HOVER_UP_ONLY
522 | VehicleFlag.NO_DEFLECTION_UP
523 | VehicleFlag.LIMIT_MOTOR_UP);
524 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY
525 | VehicleFlag.HOVER_GLOBAL_HEIGHT);
526 break;
527 }
528
529 // Update any physical parameters based on this type.
530 Refresh();
531
532 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
533 m_linearMotorDecayTimescale, m_linearFrictionTimescale,
534 1f);
535 m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
536
537 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale,
538 m_angularMotorDecayTimescale, m_angularFrictionTimescale,
539 1f);
540 m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
541
542 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
543 BSMotor.Infinite, BSMotor.InfiniteVector,
544 m_verticalAttractionEfficiency);
545 // Z goes away and we keep X and Y
546 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
547 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
548 }
549
550 // Some of the properties of this prim may have changed.
551 // Do any updating needed for a vehicle
552 public void Refresh()
553 {
554 if (IsActive)
555 {
556 // Remember the mass so we don't have to fetch it every step
557 m_vehicleMass = Prim.Linkset.LinksetMass;
558
559 // Friction affects are handled by this vehicle code
560 float friction = 0f;
561 PhysicsScene.PE.SetFriction(Prim.PhysBody, friction);
562
563 // Moderate angular movement introduced by Bullet.
564 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
565 // Maybe compute linear and angular factor and damping from params.
566 float angularDamping = BSParam.VehicleAngularDamping;
567 PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, angularDamping);
568
569 // Vehicles report collision events so we know when it's on the ground
570 PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
571
572 Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass);
573 PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, localInertia);
574 PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody);
575
576 Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy);
577 PhysicsScene.PE.SetGravity(Prim.PhysBody, grav);
578
579 VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}",
580 Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping);
581 }
582 else
583 {
584 PhysicsScene.PE.RemoveFromCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
585 }
586 }
587
588 public bool RemoveBodyDependencies(BSPhysObject prim)
589 {
590 // If active, we need to add our properties back when the body is rebuilt.
591 return IsActive;
592 }
593
594 public void RestoreBodyDependencies(BSPhysObject prim)
595 {
596 if (Prim.LocalID != prim.LocalID)
597 {
598 // The call should be on us by our prim. Error if not.
599 PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}",
600 LogHeader, prim.LocalID, Prim.LocalID);
601 return;
602 }
603 Refresh();
604 }
605
606 #region Known vehicle value functions
607 // Vehicle physical parameters that we buffer from constant getting and setting.
608 // The "m_known*" values are unknown until they are fetched and the m_knownHas flag is set.
609 // Changing is remembered and the parameter is stored back into the physics engine only if updated.
610 // This does two things: 1) saves continuious calls into unmanaged code, and
611 // 2) signals when a physics property update must happen back to the simulator
612 // to update values modified for the vehicle.
613 private int m_knownChanged;
614 private int m_knownHas;
615 private float m_knownTerrainHeight;
616 private float m_knownWaterLevel;
617 private Vector3 m_knownPosition;
618 private Vector3 m_knownVelocity;
619 private Vector3 m_knownForce;
620 private Quaternion m_knownOrientation;
621 private Vector3 m_knownRotationalVelocity;
622 private Vector3 m_knownRotationalForce;
623 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
624
625 private const int m_knownChangedPosition = 1 << 0;
626 private const int m_knownChangedVelocity = 1 << 1;
627 private const int m_knownChangedForce = 1 << 2;
628 private const int m_knownChangedOrientation = 1 << 3;
629 private const int m_knownChangedRotationalVelocity = 1 << 4;
630 private const int m_knownChangedRotationalForce = 1 << 5;
631 private const int m_knownChangedTerrainHeight = 1 << 6;
632 private const int m_knownChangedWaterLevel = 1 << 7;
633 private const int m_knownChangedForwardVelocity = 1 << 8;
634
635 private void ForgetKnownVehicleProperties()
636 {
637 m_knownHas = 0;
638 m_knownChanged = 0;
639 }
640 // Push all the changed values back into the physics engine
641 private void PushKnownChanged()
642 {
643 if (m_knownChanged != 0)
644 {
645 if ((m_knownChanged & m_knownChangedPosition) != 0)
646 Prim.ForcePosition = m_knownPosition;
647
648 if ((m_knownChanged & m_knownChangedOrientation) != 0)
649 Prim.ForceOrientation = m_knownOrientation;
650
651 if ((m_knownChanged & m_knownChangedVelocity) != 0)
652 {
653 Prim.ForceVelocity = m_knownVelocity;
654 PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, VehicleVelocity);
655 }
656
657 if ((m_knownChanged & m_knownChangedForce) != 0)
658 Prim.AddForce((Vector3)m_knownForce, false, true);
659
660 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
661 {
662 Prim.ForceRotationalVelocity = m_knownRotationalVelocity;
663 // Fake out Bullet by making it think the velocity is the same as last time.
664 PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity);
665 }
666
667 if ((m_knownChanged & m_knownChangedRotationalForce) != 0)
668 Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true);
669
670 // If we set one of the values (ie, the physics engine didn't do it) we must force
671 // an UpdateProperties event to send the changes up to the simulator.
672 PhysicsScene.PE.PushUpdate(Prim.PhysBody);
673 }
674 m_knownChanged = 0;
675 }
676
677 // Since the computation of terrain height can be a little involved, this routine
678 // is used to fetch the height only once for each vehicle simulation step.
679 private float GetTerrainHeight(Vector3 pos)
680 {
681 if ((m_knownHas & m_knownChangedTerrainHeight) == 0)
682 {
683 m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
684 m_knownHas |= m_knownChangedTerrainHeight;
685 }
686 return m_knownTerrainHeight;
687 }
688
689 // Since the computation of water level can be a little involved, this routine
690 // is used ot fetch the level only once for each vehicle simulation step.
691 private float GetWaterLevel(Vector3 pos)
692 {
693 if ((m_knownHas & m_knownChangedWaterLevel) == 0)
694 {
695 m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos);
696 m_knownHas |= m_knownChangedWaterLevel;
697 }
698 return (float)m_knownWaterLevel;
699 }
700
701 private Vector3 VehiclePosition
702 {
703 get
704 {
705 if ((m_knownHas & m_knownChangedPosition) == 0)
706 {
707 m_knownPosition = Prim.ForcePosition;
708 m_knownHas |= m_knownChangedPosition;
709 }
710 return m_knownPosition;
711 }
712 set
713 {
714 m_knownPosition = value;
715 m_knownChanged |= m_knownChangedPosition;
716 m_knownHas |= m_knownChangedPosition;
717 }
718 }
719
720 private Quaternion VehicleOrientation
721 {
722 get
723 {
724 if ((m_knownHas & m_knownChangedOrientation) == 0)
725 {
726 m_knownOrientation = Prim.ForceOrientation;
727 m_knownHas |= m_knownChangedOrientation;
728 }
729 return m_knownOrientation;
730 }
731 set
732 {
733 m_knownOrientation = value;
734 m_knownChanged |= m_knownChangedOrientation;
735 m_knownHas |= m_knownChangedOrientation;
736 }
737 }
738
739 private Vector3 VehicleVelocity
740 {
741 get
742 {
743 if ((m_knownHas & m_knownChangedVelocity) == 0)
744 {
745 m_knownVelocity = Prim.ForceVelocity;
746 m_knownHas |= m_knownChangedVelocity;
747 }
748 return (Vector3)m_knownVelocity;
749 }
750 set
751 {
752 m_knownVelocity = value;
753 m_knownChanged |= m_knownChangedVelocity;
754 m_knownHas |= m_knownChangedVelocity;
755 }
756 }
757
758 private void VehicleAddForce(Vector3 aForce)
759 {
760 if ((m_knownHas & m_knownChangedForce) == 0)
761 {
762 m_knownForce = Vector3.Zero;
763 }
764 m_knownForce += aForce;
765 m_knownChanged |= m_knownChangedForce;
766 m_knownHas |= m_knownChangedForce;
767 }
768
769 private Vector3 VehicleRotationalVelocity
770 {
771 get
772 {
773 if ((m_knownHas & m_knownChangedRotationalVelocity) == 0)
774 {
775 m_knownRotationalVelocity = Prim.ForceRotationalVelocity;
776 m_knownHas |= m_knownChangedRotationalVelocity;
777 }
778 return (Vector3)m_knownRotationalVelocity;
779 }
780 set
781 {
782 m_knownRotationalVelocity = value;
783 m_knownChanged |= m_knownChangedRotationalVelocity;
784 m_knownHas |= m_knownChangedRotationalVelocity;
785 }
786 }
787 private void VehicleAddAngularForce(Vector3 aForce)
788 {
789 if ((m_knownHas & m_knownChangedRotationalForce) == 0)
790 {
791 m_knownRotationalForce = Vector3.Zero;
792 }
793 m_knownRotationalForce += aForce;
794 m_knownChanged |= m_knownChangedRotationalForce;
795 m_knownHas |= m_knownChangedRotationalForce;
796 }
797 // Vehicle relative forward velocity
798 private Vector3 VehicleForwardVelocity
799 {
800 get
801 {
802 if ((m_knownHas & m_knownChangedForwardVelocity) == 0)
803 {
804 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
805 m_knownHas |= m_knownChangedForwardVelocity;
806 }
807 return m_knownForwardVelocity;
808 }
809 }
810 private float VehicleForwardSpeed
811 {
812 get
813 {
814 return VehicleForwardVelocity.X;
815 }
816 }
817
818 #endregion // Known vehicle value functions
819
820 // One step of the vehicle properties for the next 'pTimestep' seconds.
821 internal void Step(float pTimestep)
822 {
823 if (!IsActive) return;
824
825 if (PhysicsScene.VehiclePhysicalLoggingEnabled)
826 PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
827
828 ForgetKnownVehicleProperties();
829
830 MoveLinear(pTimestep);
831 MoveAngular(pTimestep);
832
833 LimitRotation(pTimestep);
834
835 // remember the position so next step we can limit absolute movement effects
836 m_lastPositionVector = VehiclePosition;
837
838 // If we forced the changing of some vehicle parameters, update the values and
839 // for the physics engine to note the changes so an UpdateProperties event will happen.
840 PushKnownChanged();
841
842 if (PhysicsScene.VehiclePhysicalLoggingEnabled)
843 PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody);
844
845 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
846 Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity);
847 }
848
849 // Apply the effect of the linear motor and other linear motions (like hover and float).
850 private void MoveLinear(float pTimestep)
851 {
852 Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep);
853
854 // The movement computed in the linear motor is relative to the vehicle
855 // coordinates. Rotate the movement to world coordinates.
856 linearMotorContribution *= VehicleOrientation;
857
858 // ==================================================================
859 // Buoyancy: force to overcome gravity.
860 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
861 // So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity.
862 Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy;
863
864 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep);
865
866 Vector3 hoverContribution = ComputeLinearHover(pTimestep);
867
868 ComputeLinearBlockingEndPoint(pTimestep);
869
870 Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep);
871
872 // ==================================================================
873 Vector3 newVelocity = linearMotorContribution
874 + terrainHeightContribution
875 + hoverContribution
876 + limitMotorUpContribution;
877
878 Vector3 newForce = buoyancyContribution;
879
880 // If not changing some axis, reduce out velocity
881 if ((m_flags & (VehicleFlag.NO_X)) != 0)
882 newVelocity.X = 0;
883 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
884 newVelocity.Y = 0;
885 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
886 newVelocity.Z = 0;
887
888 // ==================================================================
889 // Clamp high or low velocities
890 float newVelocityLengthSq = newVelocity.LengthSquared();
891 if (newVelocityLengthSq > 1000f)
892 {
893 newVelocity /= newVelocity.Length();
894 newVelocity *= 1000f;
895 }
896 else if (newVelocityLengthSq < 0.001f)
897 newVelocity = Vector3.Zero;
898
899 // ==================================================================
900 // Stuff new linear velocity into the vehicle.
901 // Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us.
902 VehicleVelocity = newVelocity;
903
904 // Other linear forces are applied as forces.
905 Vector3 totalDownForce = newForce * m_vehicleMass;
906 if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f))
907 {
908 VehicleAddForce(totalDownForce);
909 }
910
911 VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}",
912 Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding);
913 VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}",
914 Prim.LocalID,
915 linearMotorContribution, terrainHeightContribution, hoverContribution,
916 limitMotorUpContribution, buoyancyContribution
917 );
918
919 } // end MoveLinear()
920
921 public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep)
922 {
923 Vector3 ret = Vector3.Zero;
924 // If below the terrain, move us above the ground a little.
925 // TODO: Consider taking the rotated size of the object or possibly casting a ray.
926 if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition))
927 {
928 // TODO: correct position by applying force rather than forcing position.
929 Vector3 newPosition = VehiclePosition;
930 newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f;
931 VehiclePosition = newPosition;
932 VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}",
933 Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition);
934 }
935 return ret;
936 }
937
938 public Vector3 ComputeLinearHover(float pTimestep)
939 {
940 Vector3 ret = Vector3.Zero;
941
942 // m_VhoverEfficiency: 0=bouncy, 1=totally damped
943 // m_VhoverTimescale: time to achieve height
944 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
945 {
946 // We should hover, get the target height
947 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
948 {
949 m_VhoverTargetHeight = GetWaterLevel(VehiclePosition) + m_VhoverHeight;
950 }
951 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
952 {
953 m_VhoverTargetHeight = GetTerrainHeight(VehiclePosition) + m_VhoverHeight;
954 }
955 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
956 {
957 m_VhoverTargetHeight = m_VhoverHeight;
958 }
959
960 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
961 {
962 // If body is already heigher, use its height as target height
963 if (VehiclePosition.Z > m_VhoverTargetHeight)
964 m_VhoverTargetHeight = VehiclePosition.Z;
965 }
966
967 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
968 {
969 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
970 {
971 Vector3 pos = VehiclePosition;
972 pos.Z = m_VhoverTargetHeight;
973 VehiclePosition = pos;
974 }
975 }
976 else
977 {
978 // Error is positive if below the target and negative if above.
979 float verticalError = m_VhoverTargetHeight - VehiclePosition.Z;
980 float verticalCorrectionVelocity = verticalError / m_VhoverTimescale;
981
982 // TODO: implement m_VhoverEfficiency correctly
983 if (Math.Abs(verticalError) > m_VhoverEfficiency)
984 {
985 ret = new Vector3(0f, 0f, verticalCorrectionVelocity);
986 }
987 }
988
989 VDetailLog("{0}, MoveLinear,hover,pos={1},ret={2},hoverTS={3},height={4},target={5}",
990 Prim.LocalID, VehiclePosition, ret, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight);
991 }
992
993 return ret;
994 }
995
996 public bool ComputeLinearBlockingEndPoint(float pTimestep)
997 {
998 bool changed = false;
999
1000 Vector3 pos = VehiclePosition;
1001 Vector3 posChange = pos - m_lastPositionVector;
1002 if (m_BlockingEndPoint != Vector3.Zero)
1003 {
1004 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
1005 {
1006 pos.X -= posChange.X + 1;
1007 changed = true;
1008 }
1009 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
1010 {
1011 pos.Y -= posChange.Y + 1;
1012 changed = true;
1013 }
1014 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
1015 {
1016 pos.Z -= posChange.Z + 1;
1017 changed = true;
1018 }
1019 if (pos.X <= 0)
1020 {
1021 pos.X += posChange.X + 1;
1022 changed = true;
1023 }
1024 if (pos.Y <= 0)
1025 {
1026 pos.Y += posChange.Y + 1;
1027 changed = true;
1028 }
1029 if (changed)
1030 {
1031 VehiclePosition = pos;
1032 VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
1033 Prim.LocalID, m_BlockingEndPoint, posChange, pos);
1034 }
1035 }
1036 return changed;
1037 }
1038
1039 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1040 // Prevent ground vehicles from motoring into the sky. This flag has a subtle effect when
1041 // used with conjunction with banking: the strength of the banking will decay when the
1042 // vehicle no longer experiences collisions. The decay timescale is the same as
1043 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
1044 // when they are in mid jump.
1045 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
1046 // This is just using the ground and a general collision check. Should really be using
1047 // a downward raycast to find what is below.
1048 public Vector3 ComputeLinearMotorUp(float pTimestep)
1049 {
1050 Vector3 ret = Vector3.Zero;
1051 float distanceAboveGround = 0f;
1052
1053 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
1054 {
1055 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
1056 distanceAboveGround = VehiclePosition.Z - targetHeight;
1057 // Not colliding if the vehicle is off the ground
1058 if (!Prim.IsColliding)
1059 {
1060 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
1061 ret = new Vector3(0, 0, -distanceAboveGround);
1062 }
1063 // TODO: this calculation is wrong. From the description at
1064 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
1065 // has a decay factor. This says this force should
1066 // be computed with a motor.
1067 // TODO: add interaction with banking.
1068 }
1069 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
1070 Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret);
1071 return ret;
1072 }
1073
1074 // =======================================================================
1075 // =======================================================================
1076 // Apply the effect of the angular motor.
1077 // The 'contribution' is how much angular correction velocity each function wants.
1078 // All the contributions are added together and the resulting velocity is
1079 // set directly on the vehicle.
1080 private void MoveAngular(float pTimestep)
1081 {
1082 // The user wants this many radians per second angular change?
1083 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
1084
1085 // ==================================================================
1086 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1087 // This flag prevents linear deflection parallel to world z-axis. This is useful
1088 // for preventing ground vehicles with large linear deflection, like bumper cars,
1089 // from climbing their linear deflection into the sky.
1090 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
1091 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1092 {
1093 angularMotorContribution.X = 0f;
1094 angularMotorContribution.Y = 0f;
1095 VDetailLog("{0}, MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution);
1096 }
1097
1098 Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction();
1099
1100 Vector3 deflectionContribution = ComputeAngularDeflection();
1101
1102 Vector3 bankingContribution = ComputeAngularBanking();
1103
1104 // ==================================================================
1105 m_lastVertAttractor = verticalAttractionContribution;
1106
1107 m_lastAngularVelocity = angularMotorContribution
1108 + verticalAttractionContribution
1109 + deflectionContribution
1110 + bankingContribution;
1111
1112 // ==================================================================
1113 // Apply the correction velocity.
1114 // TODO: Should this be applied as an angular force (torque)?
1115 if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
1116 {
1117 VehicleRotationalVelocity = m_lastAngularVelocity;
1118
1119 VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5}",
1120 Prim.LocalID,
1121 angularMotorContribution, verticalAttractionContribution,
1122 bankingContribution, deflectionContribution,
1123 m_lastAngularVelocity
1124 );
1125 }
1126 else
1127 {
1128 // The vehicle is not adding anything angular wise.
1129 VehicleRotationalVelocity = Vector3.Zero;
1130 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID);
1131 }
1132
1133 // ==================================================================
1134 //Offset section
1135 if (m_linearMotorOffset != Vector3.Zero)
1136 {
1137 //Offset of linear velocity doesn't change the linear velocity,
1138 // but causes a torque to be applied, for example...
1139 //
1140 // IIIII >>> IIIII
1141 // IIIII >>> IIIII
1142 // IIIII >>> IIIII
1143 // ^
1144 // | Applying a force at the arrow will cause the object to move forward, but also rotate
1145 //
1146 //
1147 // The torque created is the linear velocity crossed with the offset
1148
1149 // TODO: this computation should be in the linear section
1150 // because that is where we know the impulse being applied.
1151 Vector3 torqueFromOffset = Vector3.Zero;
1152 // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse);
1153 if (float.IsNaN(torqueFromOffset.X))
1154 torqueFromOffset.X = 0;
1155 if (float.IsNaN(torqueFromOffset.Y))
1156 torqueFromOffset.Y = 0;
1157 if (float.IsNaN(torqueFromOffset.Z))
1158 torqueFromOffset.Z = 0;
1159
1160 VehicleAddAngularForce(torqueFromOffset * m_vehicleMass);
1161 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
1162 }
1163
1164 }
1165 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1166 // Some vehicles, like boats, should always keep their up-side up. This can be done by
1167 // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to
1168 // the world z-axis (a.k.a. "up"). To take advantage of this feature you would set the
1169 // VEHICLE_VERTICAL_ATTRACTION_TIMESCALE to control the period of the spring frequency,
1170 // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An
1171 // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an
1172 // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay.
1173 public Vector3 ComputeAngularVerticalAttraction()
1174 {
1175 Vector3 ret = Vector3.Zero;
1176
1177 // If vertical attaction timescale is reasonable
1178 if (m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1179 {
1180 // Take a vector pointing up and convert it from world to vehicle relative coords.
1181 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
1182
1183 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1184 // is now:
1185 // leaning to one side: rotated around the X axis with the Y value going
1186 // from zero (nearly straight up) to one (completely to the side)) or
1187 // leaning front-to-back: rotated around the Y axis with the value of X being between
1188 // zero and one.
1189 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1190
1191 // Y error means needed rotation around X axis and visa versa.
1192 // Since the error goes from zero to one, the asin is the corresponding angle.
1193 ret.X = (float)Math.Asin(verticalError.Y);
1194 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1195 ret.Y = -(float)Math.Asin(verticalError.X);
1196
1197 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1198 if (verticalError.Z < 0f)
1199 {
1200 ret.X += PIOverFour;
1201 ret.Y += PIOverFour;
1202 }
1203
1204 // 'ret' is now the necessary velocity to correct tilt in one second.
1205 // Correction happens over a number of seconds.
1206 Vector3 unscaledContrib = ret;
1207 ret /= m_verticalAttractionTimescale;
1208
1209 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}",
1210 Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, ret);
1211 }
1212 return ret;
1213 }
1214
1215 // Return the angular correction to correct the direction the vehicle is pointing to be
1216 // the direction is should want to be pointing.
1217 // The vehicle is moving in some direction and correct its orientation to it is pointing
1218 // in that direction.
1219 // TODO: implement reference frame.
1220 public Vector3 ComputeAngularDeflection()
1221 {
1222 Vector3 ret = Vector3.Zero;
1223 return ret; // DEBUG DEBUG DEBUG
1224 // Disable angular deflection for the moment.
1225 // Since angularMotorUp and angularDeflection are computed independently, they will calculate
1226 // approximately the same X or Y correction. When added together (when contributions are combined)
1227 // this creates an over-correction and then wabbling as the target is overshot.
1228 // TODO: rethink how the different correction computations inter-relate.
1229
1230 if (m_angularDeflectionEfficiency != 0)
1231 {
1232 // The direction the vehicle is moving
1233 Vector3 movingDirection = VehicleVelocity;
1234 movingDirection.Normalize();
1235
1236 // The direction the vehicle is pointing
1237 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1238 pointingDirection.Normalize();
1239
1240 // The difference between what is and what should be.
1241 Vector3 deflectionError = movingDirection - pointingDirection;
1242
1243 // Don't try to correct very large errors (not our job)
1244 if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f;
1245 if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f;
1246 if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f;
1247
1248 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1249
1250 // Scale the correction by recovery timescale and efficiency
1251 ret = (-deflectionError) * m_angularDeflectionEfficiency;
1252 ret /= m_angularDeflectionTimescale;
1253
1254 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1255 Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret);
1256 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}",
1257 Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale);
1258 }
1259 return ret;
1260 }
1261
1262 // Return an angular change to rotate the vehicle around the Z axis when the vehicle
1263 // is tipped around the X axis.
1264 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
1265 // The vertical attractor feature must be enabled in order for the banking behavior to
1266 // function. The way banking works is this: a rotation around the vehicle's roll-axis will
1267 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
1268 // of the yaw effect will be proportional to the
1269 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1270 // velocity along its preferred axis of motion.
1271 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
1272 // positive rotation (by the right-hand rule) about the roll-axis will effect a
1273 // (negative) torque around the yaw-axis, making it turn to the right--that is the
1274 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
1275 // Negating the banking coefficient will make it so that the vehicle leans to the
1276 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
1277 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
1278 // banking vehicles do what you want rather than what the laws of physics allow.
1279 // For example, consider a real motorcycle...it must be moving forward in order for
1280 // it to turn while banking, however video-game motorcycles are often configured
1281 // to turn in place when at a dead stop--because they are often easier to control
1282 // that way using the limited interface of the keyboard or game controller. The
1283 // VEHICLE_BANKING_MIX enables combinations of both realistic and non-realistic
1284 // banking by functioning as a slider between a banking that is correspondingly
1285 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
1286 // banking effect depends only on the vehicle's rotation about its roll-axis compared
1287 // to "dynamic" where the banking is also proportional to its velocity along its
1288 // roll-axis. Finding the best value of the "mixture" will probably require trial and error.
1289 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the
1290 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1291 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1292 // make a sluggish vehicle by giving it a timescale of several seconds.
1293 public Vector3 ComputeAngularBanking()
1294 {
1295 Vector3 ret = Vector3.Zero;
1296
1297 if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1298 {
1299 // This works by rotating a unit vector to the orientation of the vehicle. The
1300 // roll (tilt) will be Y component of a tilting Z vector (zero for no tilt
1301 // up to one for full over).
1302 Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation;
1303
1304 // Figure out the yaw value for this much roll.
1305 float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency;
1306 // Keep the sign
1307 if (rollComponents.Y < 0f)
1308 turnComponent = -turnComponent;
1309
1310 // TODO: there must be a better computation of the banking force.
1311 float bankingTurnForce = turnComponent;
1312
1313 // actual error = static turn error + dynamic turn error
1314 float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed;
1315 // TODO: the banking effect should not go to infinity but what to limit it to?
1316 mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f);
1317
1318 // Build the force vector to change rotation from what it is to what it should be
1319 ret.Z = -mixedBankingError;
1320
1321 // Don't do it all at once.
1322 ret /= m_bankingTimescale;
1323
1324 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},turnComp={3},bankErr={4},mixedBankErr={5},ret={6}",
1325 Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret);
1326 }
1327 return ret;
1328 }
1329
1330 // This is from previous instantiations of XXXDynamics.cs.
1331 // Applies roll reference frame.
1332 // TODO: is this the right way to separate the code to do this operation?
1333 // Should this be in MoveAngular()?
1334 internal void LimitRotation(float timestep)
1335 {
1336 Quaternion rotq = VehicleOrientation;
1337 Quaternion m_rot = rotq;
1338 if (m_RollreferenceFrame != Quaternion.Identity)
1339 {
1340 if (rotq.X >= m_RollreferenceFrame.X)
1341 {
1342 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2);
1343 }
1344 if (rotq.Y >= m_RollreferenceFrame.Y)
1345 {
1346 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2);
1347 }
1348 if (rotq.X <= -m_RollreferenceFrame.X)
1349 {
1350 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2);
1351 }
1352 if (rotq.Y <= -m_RollreferenceFrame.Y)
1353 {
1354 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2);
1355 }
1356 }
1357 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
1358 {
1359 m_rot.X = 0;
1360 m_rot.Y = 0;
1361 }
1362 if (rotq != m_rot)
1363 {
1364 VehicleOrientation = m_rot;
1365 VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot);
1366 }
1367
1368 }
1369
1370 private float ClampInRange(float low, float val, float high)
1371 {
1372 return Math.Max(low, Math.Min(val, high));
1373 // return Utils.Clamp(val, low, high);
1374 }
1375
1376 // Invoke the detailed logger and output something if it's enabled.
1377 private void VDetailLog(string msg, params Object[] args)
1378 {
1379 if (Prim.PhysicsScene.VehicleLoggingEnabled)
1380 Prim.PhysicsScene.DetailLog(msg, args);
1381 }
1382 }
1383}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
deleted file mode 100755
index 756faed..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ /dev/null
@@ -1,329 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35
36// A BSPrim can get individual information about its linkedness attached
37// to it through an instance of a subclass of LinksetInfo.
38// Each type of linkset will define the information needed for its type.
39public abstract class BSLinksetInfo
40{
41 public virtual void Clear() { }
42}
43
44public abstract class BSLinkset
45{
46 // private static string LogHeader = "[BULLETSIM LINKSET]";
47
48 public enum LinksetImplementation
49 {
50 Constraint = 0, // linkset tied together with constraints
51 Compound = 1, // linkset tied together as a compound object
52 Manual = 2 // linkset tied together manually (code moves all the pieces)
53 }
54 // Create the correct type of linkset for this child
55 public static BSLinkset Factory(BSScene physScene, BSPhysObject parent)
56 {
57 BSLinkset ret = null;
58
59 switch ((int)BSParam.LinksetImplementation)
60 {
61 case (int)LinksetImplementation.Constraint:
62 ret = new BSLinksetConstraints(physScene, parent);
63 break;
64 case (int)LinksetImplementation.Compound:
65 ret = new BSLinksetCompound(physScene, parent);
66 break;
67 case (int)LinksetImplementation.Manual:
68 // ret = new BSLinksetManual(physScene, parent);
69 break;
70 default:
71 ret = new BSLinksetCompound(physScene, parent);
72 break;
73 }
74 return ret;
75 }
76
77 public BSPhysObject LinksetRoot { get; protected set; }
78
79 public BSScene PhysicsScene { get; private set; }
80
81 static int m_nextLinksetID = 1;
82 public int LinksetID { get; private set; }
83
84 // The children under the root in this linkset.
85 protected HashSet<BSPhysObject> m_children;
86
87 // We lock the diddling of linkset classes to prevent any badness.
88 // This locks the modification of the instances of this class. Changes
89 // to the physical representation is done via the tainting mechenism.
90 protected object m_linksetActivityLock = new Object();
91
92 // Some linksets have a preferred physical shape.
93 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
94 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
95 {
96 return BSPhysicsShapeType.SHAPE_UNKNOWN;
97 }
98
99 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
100 public float LinksetMass { get; protected set; }
101
102 public virtual bool LinksetIsColliding { get { return false; } }
103
104 public OMV.Vector3 CenterOfMass
105 {
106 get { return ComputeLinksetCenterOfMass(); }
107 }
108
109 public OMV.Vector3 GeometricCenter
110 {
111 get { return ComputeLinksetGeometricCenter(); }
112 }
113
114 protected BSLinkset(BSScene scene, BSPhysObject parent)
115 {
116 // A simple linkset of one (no children)
117 LinksetID = m_nextLinksetID++;
118 // We create LOTS of linksets.
119 if (m_nextLinksetID <= 0)
120 m_nextLinksetID = 1;
121 PhysicsScene = scene;
122 LinksetRoot = parent;
123 m_children = new HashSet<BSPhysObject>();
124 LinksetMass = parent.RawMass;
125 Rebuilding = false;
126 }
127
128 // Link to a linkset where the child knows the parent.
129 // Parent changing should not happen so do some sanity checking.
130 // We return the parent's linkset so the child can track its membership.
131 // Called at runtime.
132 public BSLinkset AddMeToLinkset(BSPhysObject child)
133 {
134 lock (m_linksetActivityLock)
135 {
136 // Don't add the root to its own linkset
137 if (!IsRoot(child))
138 AddChildToLinkset(child);
139 LinksetMass = ComputeLinksetMass();
140 }
141 return this;
142 }
143
144 // Remove a child from a linkset.
145 // Returns a new linkset for the child which is a linkset of one (just the
146 // orphened child).
147 // Called at runtime.
148 public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
149 {
150 lock (m_linksetActivityLock)
151 {
152 if (IsRoot(child))
153 {
154 // Cannot remove the root from a linkset.
155 return this;
156 }
157 RemoveChildFromLinkset(child);
158 LinksetMass = ComputeLinksetMass();
159 }
160
161 // The child is down to a linkset of just itself
162 return BSLinkset.Factory(PhysicsScene, child);
163 }
164
165 // Return 'true' if the passed object is the root object of this linkset
166 public bool IsRoot(BSPhysObject requestor)
167 {
168 return (requestor.LocalID == LinksetRoot.LocalID);
169 }
170
171 public int NumberOfChildren { get { return m_children.Count; } }
172
173 // Return 'true' if this linkset has any children (more than the root member)
174 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
175
176 // Return 'true' if this child is in this linkset
177 public bool HasChild(BSPhysObject child)
178 {
179 bool ret = false;
180 lock (m_linksetActivityLock)
181 {
182 ret = m_children.Contains(child);
183 /* Safer version but the above should work
184 foreach (BSPhysObject bp in m_children)
185 {
186 if (child.LocalID == bp.LocalID)
187 {
188 ret = true;
189 break;
190 }
191 }
192 */
193 }
194 return ret;
195 }
196
197 // Perform an action on each member of the linkset including root prim.
198 // Depends on the action on whether this should be done at taint time.
199 public delegate bool ForEachMemberAction(BSPhysObject obj);
200 public virtual bool ForEachMember(ForEachMemberAction action)
201 {
202 bool ret = false;
203 lock (m_linksetActivityLock)
204 {
205 action(LinksetRoot);
206 foreach (BSPhysObject po in m_children)
207 {
208 if (action(po))
209 break;
210 }
211 }
212 return ret;
213 }
214
215 // I am the root of a linkset and a new child is being added
216 // Called while LinkActivity is locked.
217 protected abstract void AddChildToLinkset(BSPhysObject child);
218
219 // I am the root of a linkset and one of my children is being removed.
220 // Safe to call even if the child is not really in my linkset.
221 protected abstract void RemoveChildFromLinkset(BSPhysObject child);
222
223 // When physical properties are changed the linkset needs to recalculate
224 // its internal properties.
225 // May be called at runtime or taint-time.
226 public virtual void Refresh(BSPhysObject requestor)
227 {
228 LinksetMass = ComputeLinksetMass();
229 }
230
231 // Flag denoting the linkset is in the process of being rebuilt.
232 // Used to know not the schedule a rebuild in the middle of a rebuild.
233 protected bool Rebuilding { get; set; }
234
235 // The object is going dynamic (physical). Do any setup necessary
236 // for a dynamic linkset.
237 // Only the state of the passed object can be modified. The rest of the linkset
238 // has not yet been fully constructed.
239 // Return 'true' if any properties updated on the passed object.
240 // Called at taint-time!
241 public abstract bool MakeDynamic(BSPhysObject child);
242
243 // The object is going static (non-physical). Do any setup necessary
244 // for a static linkset.
245 // Return 'true' if any properties updated on the passed object.
246 // Called at taint-time!
247 public abstract bool MakeStatic(BSPhysObject child);
248
249 // Called when a parameter update comes from the physics engine for any object
250 // of the linkset is received.
251 // Passed flag is update came from physics engine (true) or the user (false).
252 // Called at taint-time!!
253 public abstract void UpdateProperties(BSPhysObject physObject, bool physicalUpdate);
254
255 // Routine used when rebuilding the body of the root of the linkset
256 // Destroy all the constraints have have been made to root.
257 // This is called when the root body is changing.
258 // Returns 'true' of something was actually removed and would need restoring
259 // Called at taint-time!!
260 public abstract bool RemoveBodyDependencies(BSPrim child);
261
262 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
263 // this routine will restore the removed constraints.
264 // Called at taint-time!!
265 public abstract void RestoreBodyDependencies(BSPrim child);
266
267 // ================================================================
268 protected virtual float ComputeLinksetMass()
269 {
270 float mass = LinksetRoot.RawMass;
271 if (HasAnyChildren)
272 {
273 lock (m_linksetActivityLock)
274 {
275 foreach (BSPhysObject bp in m_children)
276 {
277 mass += bp.RawMass;
278 }
279 }
280 }
281 return mass;
282 }
283
284 protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
285 {
286 OMV.Vector3 com;
287 lock (m_linksetActivityLock)
288 {
289 com = LinksetRoot.Position * LinksetRoot.RawMass;
290 float totalMass = LinksetRoot.RawMass;
291
292 foreach (BSPhysObject bp in m_children)
293 {
294 com += bp.Position * bp.RawMass;
295 totalMass += bp.RawMass;
296 }
297 if (totalMass != 0f)
298 com /= totalMass;
299 }
300
301 return com;
302 }
303
304 protected virtual OMV.Vector3 ComputeLinksetGeometricCenter()
305 {
306 OMV.Vector3 com;
307 lock (m_linksetActivityLock)
308 {
309 com = LinksetRoot.Position;
310
311 foreach (BSPhysObject bp in m_children)
312 {
313 com += bp.Position * bp.RawMass;
314 }
315 com /= (m_children.Count + 1);
316 }
317
318 return com;
319 }
320
321 // Invoke the detailed logger and output something if it's enabled.
322 protected void DetailLog(string msg, params Object[] args)
323 {
324 if (PhysicsScene.PhysicsLogging.Enabled)
325 PhysicsScene.DetailLog(msg, args);
326 }
327
328}
329}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
deleted file mode 100755
index bd03d31..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ /dev/null
@@ -1,392 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32
33using OMV = OpenMetaverse;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37
38// When a child is linked, the relationship position of the child to the parent
39// is remembered so the child's world position can be recomputed when it is
40// removed from the linkset.
41sealed class BSLinksetCompoundInfo : BSLinksetInfo
42{
43 public OMV.Vector3 OffsetPos;
44 public OMV.Quaternion OffsetRot;
45 public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r)
46 {
47 OffsetPos = p;
48 OffsetRot = r;
49 }
50 public override void Clear()
51 {
52 OffsetPos = OMV.Vector3.Zero;
53 OffsetRot = OMV.Quaternion.Identity;
54 }
55 public override string ToString()
56 {
57 StringBuilder buff = new StringBuilder();
58 buff.Append("<p=");
59 buff.Append(OffsetPos.ToString());
60 buff.Append(",r=");
61 buff.Append(OffsetRot.ToString());
62 buff.Append(">");
63 return buff.ToString();
64 }
65};
66
67public sealed class BSLinksetCompound : BSLinkset
68{
69 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
70
71 public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent)
72 {
73 }
74
75 // For compound implimented linksets, if there are children, use compound shape for the root.
76 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
77 {
78 // Returning 'unknown' means we don't have a preference.
79 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
80 if (IsRoot(requestor) && HasAnyChildren)
81 {
82 ret = BSPhysicsShapeType.SHAPE_COMPOUND;
83 }
84 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
85 return ret;
86 }
87
88 // When physical properties are changed the linkset needs to recalculate
89 // its internal properties.
90 public override void Refresh(BSPhysObject requestor)
91 {
92 base.Refresh(requestor);
93
94 // Something changed so do the rebuilding thing
95 // ScheduleRebuild();
96 }
97
98 // Schedule a refresh to happen after all the other taint processing.
99 private void ScheduleRebuild(BSPhysObject requestor)
100 {
101 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2}",
102 requestor.LocalID, Rebuilding, HasAnyChildren);
103 // When rebuilding, it is possible to set properties that would normally require a rebuild.
104 // If already rebuilding, don't request another rebuild.
105 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
106 if (!Rebuilding && HasAnyChildren)
107 {
108 PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
109 {
110 if (HasAnyChildren)
111 RecomputeLinksetCompound();
112 });
113 }
114 }
115
116 // The object is going dynamic (physical). Do any setup necessary for a dynamic linkset.
117 // Only the state of the passed object can be modified. The rest of the linkset
118 // has not yet been fully constructed.
119 // Return 'true' if any properties updated on the passed object.
120 // Called at taint-time!
121 public override bool MakeDynamic(BSPhysObject child)
122 {
123 bool ret = false;
124 DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
125 if (IsRoot(child))
126 {
127 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
128 ScheduleRebuild(LinksetRoot);
129 }
130 else
131 {
132 // The origional prims are removed from the world as the shape of the root compound
133 // shape takes over.
134 PhysicsScene.PE.AddToCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
135 PhysicsScene.PE.ForceActivationState(child.PhysBody, ActivationState.DISABLE_SIMULATION);
136 // We don't want collisions from the old linkset children.
137 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
138
139 child.PhysBody.collisionType = CollisionType.LinksetChild;
140
141 ret = true;
142 }
143 return ret;
144 }
145
146 // The object is going static (non-physical). Do any setup necessary for a static linkset.
147 // Return 'true' if any properties updated on the passed object.
148 // This doesn't normally happen -- OpenSim removes the objects from the physical
149 // world if it is a static linkset.
150 // Called at taint-time!
151 public override bool MakeStatic(BSPhysObject child)
152 {
153 bool ret = false;
154 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
155 if (IsRoot(child))
156 {
157 ScheduleRebuild(LinksetRoot);
158 }
159 else
160 {
161 // The non-physical children can come back to life.
162 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
163
164 child.PhysBody.collisionType = CollisionType.LinksetChild;
165
166 // Don't force activation so setting of DISABLE_SIMULATION can stay if used.
167 PhysicsScene.PE.Activate(child.PhysBody, false);
168 ret = true;
169 }
170 return ret;
171 }
172
173 public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate)
174 {
175 // The user moving a child around requires the rebuilding of the linkset compound shape
176 // One problem is this happens when a border is crossed -- the simulator implementation
177 // is to store the position into the group which causes the move of the object
178 // but it also means all the child positions get updated.
179 // What would cause an unnecessary rebuild so we make sure the linkset is in a
180 // region before bothering to do a rebuild.
181 if (!IsRoot(updated)
182 && !physicalUpdate
183 && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
184 {
185 updated.LinksetInfo = null;
186 ScheduleRebuild(updated);
187 }
188 }
189
190 // Routine called when rebuilding the body of some member of the linkset.
191 // Since we don't keep in world relationships, do nothing unless it's a child changing.
192 // Returns 'true' of something was actually removed and would need restoring
193 // Called at taint-time!!
194 public override bool RemoveBodyDependencies(BSPrim child)
195 {
196 bool ret = false;
197
198 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
199 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, IsRoot(child));
200
201 if (!IsRoot(child))
202 {
203 // Because it is a convenient time, recompute child world position and rotation based on
204 // its position in the linkset.
205 RecomputeChildWorldPosition(child, true);
206 }
207
208 // Cannot schedule a refresh/rebuild here because this routine is called when
209 // the linkset is being rebuilt.
210 // InternalRefresh(LinksetRoot);
211
212 return ret;
213 }
214
215 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
216 // this routine will restore the removed constraints.
217 // Called at taint-time!!
218 public override void RestoreBodyDependencies(BSPrim child)
219 {
220 }
221
222 // When the linkset is built, the child shape is added to the compound shape relative to the
223 // root shape. The linkset then moves around but this does not move the actual child
224 // prim. The child prim's location must be recomputed based on the location of the root shape.
225 private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime)
226 {
227 BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
228 if (lci != null)
229 {
230 if (inTaintTime)
231 {
232 OMV.Vector3 oldPos = child.RawPosition;
233 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos;
234 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
235 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
236 child.LocalID, oldPos, lci, child.RawPosition);
237 }
238 else
239 {
240 // TaintedObject is not used here so the raw position is set now and not at taint-time.
241 child.Position = LinksetRoot.RawPosition + lci.OffsetPos;
242 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
243 }
244 }
245 else
246 {
247 // This happens when children have been added to the linkset but the linkset
248 // has not been constructed yet. So like, at taint time, adding children to a linkset
249 // and then changing properties of the children (makePhysical, for instance)
250 // but the post-print action of actually rebuilding the linkset has not yet happened.
251 // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}",
252 // LogHeader, child.LocalID);
253 DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
254 }
255 }
256
257 // ================================================================
258
259 // Add a new child to the linkset.
260 // Called while LinkActivity is locked.
261 protected override void AddChildToLinkset(BSPhysObject child)
262 {
263 if (!HasChild(child))
264 {
265 m_children.Add(child);
266
267 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
268
269 // Rebuild the compound shape with the new child shape included
270 ScheduleRebuild(child);
271 }
272 return;
273 }
274
275 // Remove the specified child from the linkset.
276 // Safe to call even if the child is not really in the linkset.
277 protected override void RemoveChildFromLinkset(BSPhysObject child)
278 {
279 if (m_children.Remove(child))
280 {
281 DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
282 child.LocalID,
283 LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString,
284 child.LocalID, child.PhysBody.AddrString);
285
286 // Cause the child's body to be rebuilt and thus restored to normal operation
287 RecomputeChildWorldPosition(child, false);
288 child.ForceBodyShapeRebuild(false);
289
290 if (!HasAnyChildren)
291 {
292 // The linkset is now empty. The root needs rebuilding.
293 LinksetRoot.ForceBodyShapeRebuild(false);
294 }
295 else
296 {
297 // Rebuild the compound shape with the child removed
298 ScheduleRebuild(child);
299 }
300 }
301 return;
302 }
303
304 // Called before the simulation step to make sure the compound based linkset
305 // is all initialized.
306 // Constraint linksets are rebuilt every time.
307 // Note that this works for rebuilding just the root after a linkset is taken apart.
308 // Called at taint time!!
309 private void RecomputeLinksetCompound()
310 {
311 try
312 {
313 // Suppress rebuilding while rebuilding
314 Rebuilding = true;
315
316 // Cause the root shape to be rebuilt as a compound object with just the root in it
317 LinksetRoot.ForceBodyShapeRebuild(true);
318
319 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
320 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
321
322 // Add a shape for each of the other children in the linkset
323 ForEachMember(delegate(BSPhysObject cPrim)
324 {
325 if (!IsRoot(cPrim))
326 {
327 // Compute the displacement of the child from the root of the linkset.
328 // This info is saved in the child prim so the relationship does not
329 // change over time and the new child position can be computed
330 // when the linkset is being disassembled (the linkset may have moved).
331 BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
332 if (lci == null)
333 {
334 // Each child position and rotation is given relative to the root.
335 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
336 OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
337 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
338
339 // Save relative position for recomputing child's world position after moving linkset.
340 lci = new BSLinksetCompoundInfo(displacementPos, displacementRot);
341 cPrim.LinksetInfo = lci;
342 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
343 }
344
345 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
346 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
347
348 if (cPrim.PhysShape.isNativeShape)
349 {
350 // A native shape is turning into a hull collision shape because native
351 // shapes are not shared so we have to hullify it so it will be tracked
352 // and freed at the correct time. This also solves the scaling problem
353 // (native shapes scaled but hull/meshes are assumed to not be).
354 // TODO: decide of the native shape can just be used in the compound shape.
355 // Use call to CreateGeomNonSpecial().
356 BulletShape saveShape = cPrim.PhysShape;
357 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
358 // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
359 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
360 BulletShape newShape = cPrim.PhysShape;
361 cPrim.PhysShape = saveShape;
362 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetPos, lci.OffsetRot);
363 }
364 else
365 {
366 // For the shared shapes (meshes and hulls), just use the shape in the child.
367 // The reference count added here will be decremented when the compound shape
368 // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
369 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
370 {
371 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
372 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
373 }
374 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
375 }
376 }
377 return false; // 'false' says to move onto the next child in the list
378 });
379
380 // With all of the linkset packed into the root prim, it has the mass of everyone.
381 LinksetMass = ComputeLinksetMass();
382 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
383 }
384 finally
385 {
386 Rebuilding = false;
387 }
388
389 PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape);
390 }
391}
392} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
deleted file mode 100755
index d0b2a56..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ /dev/null
@@ -1,312 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public sealed class BSLinksetConstraints : BSLinkset
36{
37 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
38
39 public BSLinksetConstraints(BSScene scene, BSPhysObject parent) : base(scene, parent)
40 {
41 }
42
43 // When physical properties are changed the linkset needs to recalculate
44 // its internal properties.
45 // This is queued in the 'post taint' queue so the
46 // refresh will happen once after all the other taints are applied.
47 public override void Refresh(BSPhysObject requestor)
48 {
49 base.Refresh(requestor);
50
51 if (HasAnyChildren && IsRoot(requestor))
52 {
53 // Queue to happen after all the other taint processing
54 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
55 {
56 if (HasAnyChildren && IsRoot(requestor))
57 RecomputeLinksetConstraints();
58 });
59 }
60 }
61
62 // The object is going dynamic (physical). Do any setup necessary
63 // for a dynamic linkset.
64 // Only the state of the passed object can be modified. The rest of the linkset
65 // has not yet been fully constructed.
66 // Return 'true' if any properties updated on the passed object.
67 // Called at taint-time!
68 public override bool MakeDynamic(BSPhysObject child)
69 {
70 // What is done for each object in BSPrim is what we want.
71 return false;
72 }
73
74 // The object is going static (non-physical). Do any setup necessary for a static linkset.
75 // Return 'true' if any properties updated on the passed object.
76 // This doesn't normally happen -- OpenSim removes the objects from the physical
77 // world if it is a static linkset.
78 // Called at taint-time!
79 public override bool MakeStatic(BSPhysObject child)
80 {
81 // What is done for each object in BSPrim is what we want.
82 return false;
83 }
84
85 // Called at taint-time!!
86 public override void UpdateProperties(BSPhysObject updated, bool inTaintTime)
87 {
88 // Nothing to do for constraints on property updates
89 }
90
91 // Routine called when rebuilding the body of some member of the linkset.
92 // Destroy all the constraints have have been made to root and set
93 // up to rebuild the constraints before the next simulation step.
94 // Returns 'true' of something was actually removed and would need restoring
95 // Called at taint-time!!
96 public override bool RemoveBodyDependencies(BSPrim child)
97 {
98 bool ret = false;
99
100 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
101 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString);
102
103 lock (m_linksetActivityLock)
104 {
105 // Just undo all the constraints for this linkset. Rebuild at the end of the step.
106 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
107 // Cause the constraints, et al to be rebuilt before the next simulation step.
108 Refresh(LinksetRoot);
109 }
110 return ret;
111 }
112
113 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
114 // this routine will restore the removed constraints.
115 // Called at taint-time!!
116 public override void RestoreBodyDependencies(BSPrim child)
117 {
118 // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints.
119 }
120
121 // ================================================================
122
123 // Add a new child to the linkset.
124 // Called while LinkActivity is locked.
125 protected override void AddChildToLinkset(BSPhysObject child)
126 {
127 if (!HasChild(child))
128 {
129 m_children.Add(child);
130
131 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
132
133 // Cause constraints and assorted properties to be recomputed before the next simulation step.
134 Refresh(LinksetRoot);
135 }
136 return;
137 }
138
139 // Remove the specified child from the linkset.
140 // Safe to call even if the child is not really in my linkset.
141 protected override void RemoveChildFromLinkset(BSPhysObject child)
142 {
143 if (m_children.Remove(child))
144 {
145 BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
146 BSPhysObject childx = child;
147
148 DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
149 childx.LocalID,
150 rootx.LocalID, rootx.PhysBody.AddrString,
151 childx.LocalID, childx.PhysBody.AddrString);
152
153 PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate()
154 {
155 PhysicallyUnlinkAChildFromRoot(rootx, childx);
156 });
157 // See that the linkset parameters are recomputed at the end of the taint time.
158 Refresh(LinksetRoot);
159 }
160 else
161 {
162 // Non-fatal occurance.
163 // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
164 }
165 return;
166 }
167
168 // Create a constraint between me (root of linkset) and the passed prim (the child).
169 // Called at taint time!
170 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
171 {
172 // Don't build the constraint when asked. Put it off until just before the simulation step.
173 Refresh(rootPrim);
174 }
175
176 private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim)
177 {
178 // Zero motion for children so they don't interpolate
179 childPrim.ZeroMotion(true);
180
181 // Relative position normalized to the root prim
182 // Essentually a vector pointing from center of rootPrim to center of childPrim
183 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
184
185 // real world coordinate of midpoint between the two objects
186 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
187
188 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
189 rootPrim.LocalID,
190 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
191 childPrim.LocalID, childPrim.PhysBody.AddrString,
192 rootPrim.Position, childPrim.Position, midPoint);
193
194 // create a constraint that allows no freedom of movement between the two objects
195 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
196
197 BSConstraint6Dof constrain = new BSConstraint6Dof(
198 PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
199 // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );
200
201 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
202 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
203 * of the objects.
204 * Code left for future programmers.
205 // ==================================================================================
206 // relative position normalized to the root prim
207 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
208 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
209
210 // relative rotation of the child to the parent
211 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
212 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
213
214 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
215 BS6DofConstraint constrain = new BS6DofConstraint(
216 PhysicsScene.World, rootPrim.Body, childPrim.Body,
217 OMV.Vector3.Zero,
218 OMV.Quaternion.Inverse(rootPrim.Orientation),
219 OMV.Vector3.Zero,
220 OMV.Quaternion.Inverse(childPrim.Orientation),
221 true,
222 true
223 );
224 // ==================================================================================
225 */
226
227 PhysicsScene.Constraints.AddConstraint(constrain);
228
229 // zero linear and angular limits makes the objects unable to move in relation to each other
230 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
231 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
232
233 // tweek the constraint to increase stability
234 constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset));
235 constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor),
236 BSParam.LinkConstraintTransMotorMaxVel,
237 BSParam.LinkConstraintTransMotorMaxForce);
238 constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
239 if (BSParam.LinkConstraintSolverIterations != 0f)
240 {
241 constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations);
242 }
243 return constrain;
244 }
245
246 // Remove linkage between the linkset root and a particular child
247 // The root and child bodies are passed in because we need to remove the constraint between
248 // the bodies that were present at unlink time.
249 // Called at taint time!
250 private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
251 {
252 bool ret = false;
253 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
254 rootPrim.LocalID,
255 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
256 childPrim.LocalID, childPrim.PhysBody.AddrString);
257
258 // Find the constraint for this link and get rid of it from the overall collection and from my list
259 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
260 {
261 // Make the child refresh its location
262 PhysicsScene.PE.PushUpdate(childPrim.PhysBody);
263 ret = true;
264 }
265
266 return ret;
267 }
268
269 // Remove linkage between myself and any possible children I might have.
270 // Returns 'true' of any constraints were destroyed.
271 // Called at taint time!
272 private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
273 {
274 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
275
276 return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody);
277 }
278
279 // Call each of the constraints that make up this linkset and recompute the
280 // various transforms and variables. Create constraints of not created yet.
281 // Called before the simulation step to make sure the constraint based linkset
282 // is all initialized.
283 // Called at taint time!!
284 private void RecomputeLinksetConstraints()
285 {
286 float linksetMass = LinksetMass;
287 LinksetRoot.UpdatePhysicalMassProperties(linksetMass, true);
288
289 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}",
290 LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass);
291
292 foreach (BSPhysObject child in m_children)
293 {
294 // A child in the linkset physically shows the mass of the whole linkset.
295 // This allows Bullet to apply enough force on the child to move the whole linkset.
296 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
297 child.UpdatePhysicalMassProperties(linksetMass, true);
298
299 BSConstraint constrain;
300 if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain))
301 {
302 // If constraint doesn't exist yet, create it.
303 constrain = BuildConstraint(LinksetRoot, child);
304 }
305 constrain.RecomputeConstraintVariables(linksetMass);
306
307 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
308 }
309
310 }
311}
312}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
deleted file mode 100755
index 92d62ff..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
+++ /dev/null
@@ -1,200 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using System.Reflection;
31using Nini.Config;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35
36public struct MaterialAttributes
37{
38 // Material type values that correspond with definitions for LSL
39 public enum Material : int
40 {
41 Stone = 0,
42 Metal,
43 Glass,
44 Wood,
45 Flesh,
46 Plastic,
47 Rubber,
48 Light,
49 // Hereafter are BulletSim additions
50 Avatar,
51 NumberOfTypes // the count of types in the enum.
52 }
53
54 // Names must be in the order of the above enum.
55 // These names must coorespond to the lower case field names in the MaterialAttributes
56 // structure as reflection is used to select the field to put the value in.
57 public static readonly string[] MaterialAttribs = { "Density", "Friction", "Restitution"};
58
59 public MaterialAttributes(string t, float d, float f, float r)
60 {
61 type = t;
62 density = d;
63 friction = f;
64 restitution = r;
65 }
66 public string type;
67 public float density;
68 public float friction;
69 public float restitution;
70}
71
72public static class BSMaterials
73{
74 // Attributes for each material type
75 private static readonly MaterialAttributes[] Attributes;
76
77 // Map of material name to material type code
78 public static readonly Dictionary<string, MaterialAttributes.Material> MaterialMap;
79
80 static BSMaterials()
81 {
82 // Attribute sets for both the non-physical and physical instances of materials.
83 Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2];
84
85 // Map of name to type code.
86 MaterialMap = new Dictionary<string, MaterialAttributes.Material>();
87 MaterialMap.Add("Stone", MaterialAttributes.Material.Stone);
88 MaterialMap.Add("Metal", MaterialAttributes.Material.Metal);
89 MaterialMap.Add("Glass", MaterialAttributes.Material.Glass);
90 MaterialMap.Add("Wood", MaterialAttributes.Material.Wood);
91 MaterialMap.Add("Flesh", MaterialAttributes.Material.Flesh);
92 MaterialMap.Add("Plastic", MaterialAttributes.Material.Plastic);
93 MaterialMap.Add("Rubber", MaterialAttributes.Material.Rubber);
94 MaterialMap.Add("Light", MaterialAttributes.Material.Light);
95 MaterialMap.Add("Avatar", MaterialAttributes.Material.Avatar);
96 }
97
98 // This is where all the default material attributes are defined.
99 public static void InitializeFromDefaults(ConfigurationParameters parms)
100 {
101 // Values from http://wiki.secondlife.com/wiki/PRIM_MATERIAL
102 float dDensity = parms.defaultDensity;
103 float dFriction = parms.defaultFriction;
104 float dRestitution = parms.defaultRestitution;
105 Attributes[(int)MaterialAttributes.Material.Stone] =
106 new MaterialAttributes("stone",dDensity, 0.8f, 0.4f);
107 Attributes[(int)MaterialAttributes.Material.Metal] =
108 new MaterialAttributes("metal",dDensity, 0.3f, 0.4f);
109 Attributes[(int)MaterialAttributes.Material.Glass] =
110 new MaterialAttributes("glass",dDensity, 0.2f, 0.7f);
111 Attributes[(int)MaterialAttributes.Material.Wood] =
112 new MaterialAttributes("wood",dDensity, 0.6f, 0.5f);
113 Attributes[(int)MaterialAttributes.Material.Flesh] =
114 new MaterialAttributes("flesh",dDensity, 0.9f, 0.3f);
115 Attributes[(int)MaterialAttributes.Material.Plastic] =
116 new MaterialAttributes("plastic",dDensity, 0.4f, 0.7f);
117 Attributes[(int)MaterialAttributes.Material.Rubber] =
118 new MaterialAttributes("rubber",dDensity, 0.9f, 0.9f);
119 Attributes[(int)MaterialAttributes.Material.Light] =
120 new MaterialAttributes("light",dDensity, dFriction, dRestitution);
121 Attributes[(int)MaterialAttributes.Material.Avatar] =
122 new MaterialAttributes("avatar",3.5f, 0.2f, 0f);
123
124 Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
125 new MaterialAttributes("stonePhysical",dDensity, 0.8f, 0.4f);
126 Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
127 new MaterialAttributes("metalPhysical",dDensity, 0.3f, 0.4f);
128 Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
129 new MaterialAttributes("glassPhysical",dDensity, 0.2f, 0.7f);
130 Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
131 new MaterialAttributes("woodPhysical",dDensity, 0.6f, 0.5f);
132 Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
133 new MaterialAttributes("fleshPhysical",dDensity, 0.9f, 0.3f);
134 Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
135 new MaterialAttributes("plasticPhysical",dDensity, 0.4f, 0.7f);
136 Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
137 new MaterialAttributes("rubberPhysical",dDensity, 0.9f, 0.9f);
138 Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
139 new MaterialAttributes("lightPhysical",dDensity, dFriction, dRestitution);
140 Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
141 new MaterialAttributes("avatarPhysical",3.5f, 0.2f, 0f);
142 }
143
144 // Under the [BulletSim] section, one can change the individual material
145 // attribute values. The format of the configuration parameter is:
146 // <materialName><Attribute>["Physical"] = floatValue
147 // For instance:
148 // [BulletSim]
149 // StoneFriction = 0.2
150 // FleshRestitutionPhysical = 0.8
151 // Materials can have different parameters for their static and
152 // physical instantiations. When setting the non-physical value,
153 // both values are changed. Setting the physical value only changes
154 // the physical value.
155 public static void InitializefromParameters(IConfig pConfig)
156 {
157 foreach (KeyValuePair<string, MaterialAttributes.Material> kvp in MaterialMap)
158 {
159 string matName = kvp.Key;
160 foreach (string attribName in MaterialAttributes.MaterialAttribs)
161 {
162 string paramName = matName + attribName;
163 if (pConfig.Contains(paramName))
164 {
165 float paramValue = pConfig.GetFloat(paramName);
166 SetAttributeValue((int)kvp.Value, attribName, paramValue);
167 // set the physical value also
168 SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
169 }
170 paramName += "Physical";
171 if (pConfig.Contains(paramName))
172 {
173 float paramValue = pConfig.GetFloat(paramName);
174 SetAttributeValue((int)kvp.Value + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
175 }
176 }
177 }
178 }
179
180 // Use reflection to set the value in the attribute structure.
181 private static void SetAttributeValue(int matType, string attribName, float val)
182 {
183 MaterialAttributes thisAttrib = Attributes[matType];
184 FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName.ToLower());
185 if (fieldInfo != null)
186 {
187 fieldInfo.SetValue(thisAttrib, val);
188 Attributes[matType] = thisAttrib;
189 }
190 }
191
192 // Given a material type, return a structure of attributes.
193 public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical)
194 {
195 int ind = (int)type;
196 if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
197 return Attributes[ind];
198 }
199}
200}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
deleted file mode 100755
index 817a5f7..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ /dev/null
@@ -1,347 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28using System;
29using System.Collections.Generic;
30using System.Text;
31using OpenMetaverse;
32using OpenSim.Framework;
33
34namespace OpenSim.Region.Physics.BulletSPlugin
35{
36public abstract class BSMotor
37{
38 // Timescales and other things can be turned off by setting them to 'infinite'.
39 public const float Infinite = 12345.6f;
40 public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite);
41
42 public BSMotor(string useName)
43 {
44 UseName = useName;
45 PhysicsScene = null;
46 Enabled = true;
47 }
48 public virtual bool Enabled { get; set; }
49 public virtual void Reset() { }
50 public virtual void Zero() { }
51 public virtual void GenerateTestOutput(float timeStep) { }
52
53 // A name passed at motor creation for easily identifyable debugging messages.
54 public string UseName { get; private set; }
55
56 // Used only for outputting debug information. Might not be set so check for null.
57 public BSScene PhysicsScene { get; set; }
58 protected void MDetailLog(string msg, params Object[] parms)
59 {
60 if (PhysicsScene != null)
61 {
62 if (PhysicsScene.VehicleLoggingEnabled)
63 {
64 PhysicsScene.DetailLog(msg, parms);
65 }
66 }
67 }
68}
69
70// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
71// The TargetValue decays in TargetValueDecayTimeScale and
72// the CurrentValue will be held back by FrictionTimeScale.
73// This motor will "zero itself" over time in that the targetValue will
74// decay to zero and the currentValue will follow it to that zero.
75// The overall effect is for the returned correction value to go from large
76// values (the total difference between current and target minus friction)
77// to small and eventually zero values.
78// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay.
79
80// For instance, if something is moving at speed X and the desired speed is Y,
81// CurrentValue is X and TargetValue is Y. As the motor is stepped, new
82// values of CurrentValue are returned that approach the TargetValue.
83// The feature of decaying TargetValue is so vehicles will eventually
84// come to a stop rather than run forever. This can be disabled by
85// setting TargetValueDecayTimescale to 'infinite'.
86// The change from CurrentValue to TargetValue is linear over TimeScale seconds.
87public class BSVMotor : BSMotor
88{
89 // public Vector3 FrameOfReference { get; set; }
90 // public Vector3 Offset { get; set; }
91
92 public virtual float TimeScale { get; set; }
93 public virtual float TargetValueDecayTimeScale { get; set; }
94 public virtual Vector3 FrictionTimescale { get; set; }
95 public virtual float Efficiency { get; set; }
96
97 public virtual float ErrorZeroThreshold { get; set; }
98
99 public virtual Vector3 TargetValue { get; protected set; }
100 public virtual Vector3 CurrentValue { get; protected set; }
101 public virtual Vector3 LastError { get; protected set; }
102
103 public virtual bool ErrorIsZero
104 { get {
105 return (LastError == Vector3.Zero || LastError.LengthSquared() <= ErrorZeroThreshold);
106 }
107 }
108
109 public BSVMotor(string useName)
110 : base(useName)
111 {
112 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
113 Efficiency = 1f;
114 FrictionTimescale = BSMotor.InfiniteVector;
115 CurrentValue = TargetValue = Vector3.Zero;
116 ErrorZeroThreshold = 0.001f;
117 }
118 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
119 : this(useName)
120 {
121 TimeScale = timeScale;
122 TargetValueDecayTimeScale = decayTimeScale;
123 FrictionTimescale = frictionTimeScale;
124 Efficiency = efficiency;
125 CurrentValue = TargetValue = Vector3.Zero;
126 }
127 public void SetCurrent(Vector3 current)
128 {
129 CurrentValue = current;
130 }
131 public void SetTarget(Vector3 target)
132 {
133 TargetValue = target;
134 }
135 public override void Zero()
136 {
137 base.Zero();
138 CurrentValue = TargetValue = Vector3.Zero;
139 }
140
141 // Compute the next step and return the new current value
142 public virtual Vector3 Step(float timeStep)
143 {
144 if (!Enabled) return TargetValue;
145
146 Vector3 origTarget = TargetValue; // DEBUG
147 Vector3 origCurrVal = CurrentValue; // DEBUG
148
149 Vector3 correction = Vector3.Zero;
150 Vector3 error = TargetValue - CurrentValue;
151 if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold))
152 {
153 correction = Step(timeStep, error);
154
155 CurrentValue += correction;
156
157 // The desired value reduces to zero which also reduces the difference with current.
158 // If the decay time is infinite, don't decay at all.
159 float decayFactor = 0f;
160 if (TargetValueDecayTimeScale != BSMotor.Infinite)
161 {
162 decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep;
163 TargetValue *= (1f - decayFactor);
164 }
165
166 // The amount we can correct the error is reduced by the friction
167 Vector3 frictionFactor = Vector3.Zero;
168 if (FrictionTimescale != BSMotor.InfiniteVector)
169 {
170 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
171 // Individual friction components can be 'infinite' so compute each separately.
172 frictionFactor.X = (FrictionTimescale.X == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.X);
173 frictionFactor.Y = (FrictionTimescale.Y == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Y);
174 frictionFactor.Z = (FrictionTimescale.Z == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Z);
175 frictionFactor *= timeStep;
176 CurrentValue *= (Vector3.One - frictionFactor);
177 }
178
179 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
180 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
181 timeStep, error, correction);
182 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}",
183 BSScene.DetailLogZero, UseName,
184 TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
185 TargetValue, CurrentValue);
186 }
187 else
188 {
189 // Difference between what we have and target is small. Motor is done.
190 CurrentValue = TargetValue;
191 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}",
192 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue);
193 }
194
195 return CurrentValue;
196 }
197 public virtual Vector3 Step(float timeStep, Vector3 error)
198 {
199 if (!Enabled) return Vector3.Zero;
200
201 LastError = error;
202 Vector3 returnCorrection = Vector3.Zero;
203 if (!error.ApproxEquals(Vector3.Zero, ErrorZeroThreshold))
204 {
205 // correction = error / secondsItShouldTakeToCorrect
206 Vector3 correctionAmount;
207 if (TimeScale == 0f || TimeScale == BSMotor.Infinite)
208 correctionAmount = error * timeStep;
209 else
210 correctionAmount = error / TimeScale * timeStep;
211
212 returnCorrection = correctionAmount;
213 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},timeStep={2},timeScale={3},err={4},corr={5}",
214 BSScene.DetailLogZero, UseName, timeStep, TimeScale, error, correctionAmount);
215 }
216 return returnCorrection;
217 }
218
219 // The user sets all the parameters and calls this which outputs values until error is zero.
220 public override void GenerateTestOutput(float timeStep)
221 {
222 // maximum number of outputs to generate.
223 int maxOutput = 50;
224 MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName);
225 MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}",
226 BSScene.DetailLogZero, UseName,
227 TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency,
228 CurrentValue, TargetValue);
229
230 LastError = BSMotor.InfiniteVector;
231 while (maxOutput-- > 0 && !LastError.ApproxEquals(Vector3.Zero, ErrorZeroThreshold))
232 {
233 Vector3 lastStep = Step(timeStep);
234 MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}",
235 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep);
236 }
237 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName);
238
239
240 }
241
242 public override string ToString()
243 {
244 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>",
245 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale);
246 }
247}
248
249public class BSFMotor : BSMotor
250{
251 public float TimeScale { get; set; }
252 public float DecayTimeScale { get; set; }
253 public float Friction { get; set; }
254 public float Efficiency { get; set; }
255
256 public float Target { get; private set; }
257 public float CurrentValue { get; private set; }
258
259 public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency)
260 : base(useName)
261 {
262 }
263 public void SetCurrent(float target)
264 {
265 }
266 public void SetTarget(float target)
267 {
268 }
269 public virtual float Step(float timeStep)
270 {
271 return 0f;
272 }
273}
274
275// Proportional, Integral, Derivitive Motor
276// Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors.
277public class BSPIDVMotor : BSVMotor
278{
279 // Larger makes more overshoot, smaller means converge quicker. Range of 0.1 to 10.
280 public Vector3 proportionFactor { get; set; }
281 public Vector3 integralFactor { get; set; }
282 public Vector3 derivFactor { get; set; }
283
284 // Arbritrary factor range.
285 // EfficiencyHigh means move quickly to the correct number. EfficiencyLow means might over correct.
286 public float EfficiencyHigh = 0.4f;
287 public float EfficiencyLow = 4.0f;
288
289 // Running integration of the error
290 Vector3 RunningIntegration { get; set; }
291
292 public BSPIDVMotor(string useName)
293 : base(useName)
294 {
295 proportionFactor = new Vector3(1.00f, 1.00f, 1.00f);
296 integralFactor = new Vector3(1.00f, 1.00f, 1.00f);
297 derivFactor = new Vector3(1.00f, 1.00f, 1.00f);
298 RunningIntegration = Vector3.Zero;
299 LastError = Vector3.Zero;
300 }
301
302 public override void Zero()
303 {
304 base.Zero();
305 }
306
307 public override float Efficiency
308 {
309 get { return base.Efficiency; }
310 set
311 {
312 base.Efficiency = Util.Clamp(value, 0f, 1f);
313 // Compute factors based on efficiency.
314 // If efficiency is high (1f), use a factor value that moves the error value to zero with little overshoot.
315 // If efficiency is low (0f), use a factor value that overcorrects.
316 // TODO: might want to vary contribution of different factor depending on efficiency.
317 float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f;
318 // float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow;
319 proportionFactor = new Vector3(factor, factor, factor);
320 integralFactor = new Vector3(factor, factor, factor);
321 derivFactor = new Vector3(factor, factor, factor);
322 }
323 }
324
325 // Ignore Current and Target Values and just advance the PID computation on this error.
326 public override Vector3 Step(float timeStep, Vector3 error)
327 {
328 if (!Enabled) return Vector3.Zero;
329
330 // Add up the error so we can integrate over the accumulated errors
331 RunningIntegration += error * timeStep;
332
333 // A simple derivitive is the rate of change from the last error.
334 Vector3 derivFactor = (error - LastError) * timeStep;
335 LastError = error;
336
337 // Correction = -(proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError)
338 Vector3 ret = -(
339 error * proportionFactor
340 + RunningIntegration * integralFactor
341 + derivFactor * derivFactor
342 );
343
344 return ret;
345 }
346}
347}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
deleted file mode 100755
index 69ac8cd..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ /dev/null
@@ -1,582 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Region.Physics.Manager;
32
33using OpenMetaverse;
34using Nini.Config;
35
36namespace OpenSim.Region.Physics.BulletSPlugin
37{
38public static class BSParam
39{
40 // Level of Detail values kept as float because that's what the Meshmerizer wants
41 public static float MeshLOD { get; private set; }
42 public static float MeshMegaPrimLOD { get; private set; }
43 public static float MeshMegaPrimThreshold { get; private set; }
44 public static float SculptLOD { get; private set; }
45
46 public static float MinimumObjectMass { get; private set; }
47 public static float MaximumObjectMass { get; private set; }
48
49 public static float LinearDamping { get; private set; }
50 public static float AngularDamping { get; private set; }
51 public static float DeactivationTime { get; private set; }
52 public static float LinearSleepingThreshold { get; private set; }
53 public static float AngularSleepingThreshold { get; private set; }
54 public static float CcdMotionThreshold { get; private set; }
55 public static float CcdSweptSphereRadius { get; private set; }
56 public static float ContactProcessingThreshold { get; private set; }
57
58 public static bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
59 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
60 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
61
62 public static float TerrainImplementation { get; private set; }
63 public static float TerrainFriction { get; private set; }
64 public static float TerrainHitFraction { get; private set; }
65 public static float TerrainRestitution { get; private set; }
66 public static float TerrainCollisionMargin { get; private set; }
67
68 // Avatar parameters
69 public static float AvatarFriction { get; private set; }
70 public static float AvatarStandingFriction { get; private set; }
71 public static float AvatarAlwaysRunFactor { get; private set; }
72 public static float AvatarDensity { get; private set; }
73 public static float AvatarRestitution { get; private set; }
74 public static float AvatarCapsuleWidth { get; private set; }
75 public static float AvatarCapsuleDepth { get; private set; }
76 public static float AvatarCapsuleHeight { get; private set; }
77 public static float AvatarContactProcessingThreshold { get; private set; }
78
79 public static float VehicleAngularDamping { get; private set; }
80
81 public static float LinksetImplementation { get; private set; }
82 public static float LinkConstraintUseFrameOffset { get; private set; }
83 public static float LinkConstraintEnableTransMotor { get; private set; }
84 public static float LinkConstraintTransMotorMaxVel { get; private set; }
85 public static float LinkConstraintTransMotorMaxForce { get; private set; }
86 public static float LinkConstraintERP { get; private set; }
87 public static float LinkConstraintCFM { get; private set; }
88 public static float LinkConstraintSolverIterations { get; private set; }
89
90 public static float PID_D { get; private set; } // derivative
91 public static float PID_P { get; private set; } // proportional
92
93 // Various constants that come from that other virtual world that shall not be named
94 public const float MinGravityZ = -1f;
95 public const float MaxGravityZ = 28f;
96 public const float MinFriction = 0f;
97 public const float MaxFriction = 255f;
98 public const float MinDensity = 0f;
99 public const float MaxDensity = 22587f;
100 public const float MinRestitution = 0f;
101 public const float MaxRestitution = 1f;
102 public const float MaxAddForceMagnitude = 20000f;
103
104 // ===========================================================================
105 public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
106 public delegate float ParamGet(BSScene scene);
107 public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
108 public delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
109
110 public struct ParameterDefn
111 {
112 public string name; // string name of the parameter
113 public string desc; // a short description of what the parameter means
114 public float defaultValue; // default value if not specified anywhere else
115 public ParamUser userParam; // get the value from the configuration file
116 public ParamGet getter; // return the current value stored for this parameter
117 public ParamSet setter; // set the current value for this parameter
118 public SetOnObject onObject; // set the value on an object in the physical domain
119 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
120 {
121 name = n;
122 desc = d;
123 defaultValue = v;
124 userParam = u;
125 getter = g;
126 setter = s;
127 onObject = null;
128 }
129 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
130 {
131 name = n;
132 desc = d;
133 defaultValue = v;
134 userParam = u;
135 getter = g;
136 setter = s;
137 onObject = o;
138 }
139 }
140
141 // List of all of the externally visible parameters.
142 // For each parameter, this table maps a text name to getter and setters.
143 // To add a new externally referencable/settable parameter, add the paramter storage
144 // location somewhere in the program and make an entry in this table with the
145 // getters and setters.
146 // It is easiest to find an existing definition and copy it.
147 // Parameter values are floats. Booleans are converted to a floating value.
148 //
149 // A ParameterDefn() takes the following parameters:
150 // -- the text name of the parameter. This is used for console input and ini file.
151 // -- a short text description of the parameter. This shows up in the console listing.
152 // -- a default value (float)
153 // -- a delegate for fetching the parameter from the ini file.
154 // Should handle fetching the right type from the ini file and converting it.
155 // -- a delegate for getting the value as a float
156 // -- a delegate for setting the value from a float
157 // -- an optional delegate to update the value in the world. Most often used to
158 // push the new value to an in-world object.
159 //
160 // The single letter parameters for the delegates are:
161 // s = BSScene
162 // o = BSPhysObject
163 // p = string parameter name
164 // l = localID of referenced object
165 // v = value (float)
166 // cf = parameter configuration class (for fetching values from ini file)
167 private static ParameterDefn[] ParameterDefinitions =
168 {
169 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
170 ConfigurationParameters.numericTrue,
171 (s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
172 (s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); },
173 (s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ),
174 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
175 ConfigurationParameters.numericFalse,
176 (s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
177 (s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); },
178 (s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ),
179 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
180 ConfigurationParameters.numericTrue,
181 (s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
182 (s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); },
183 (s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ),
184
185 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
186 8f,
187 (s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); },
188 (s) => { return MeshLOD; },
189 (s,p,l,v) => { MeshLOD = v; } ),
190 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
191 16f,
192 (s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
193 (s) => { return MeshMegaPrimLOD; },
194 (s,p,l,v) => { MeshMegaPrimLOD = v; } ),
195 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
196 10f,
197 (s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
198 (s) => { return MeshMegaPrimThreshold; },
199 (s,p,l,v) => { MeshMegaPrimThreshold = v; } ),
200 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
201 32f,
202 (s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); },
203 (s) => { return SculptLOD; },
204 (s,p,l,v) => { SculptLOD = v; } ),
205
206 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
207 10f,
208 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
209 (s) => { return (float)s.m_maxSubSteps; },
210 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
211 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
212 1f / 60f,
213 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
214 (s) => { return (float)s.m_fixedTimeStep; },
215 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
216 new ParameterDefn("NominalFrameRate", "The base frame rate we claim",
217 55f,
218 (s,cf,p,v) => { s.NominalFrameRate = cf.GetInt(p, (int)v); },
219 (s) => { return (float)s.NominalFrameRate; },
220 (s,p,l,v) => { s.NominalFrameRate = (int)v; } ),
221 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
222 2048f,
223 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
224 (s) => { return (float)s.m_maxCollisionsPerFrame; },
225 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
226 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
227 8000f,
228 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
229 (s) => { return (float)s.m_maxUpdatesPerFrame; },
230 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
231 new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
232 500f,
233 (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
234 (s) => { return (float)s.m_taintsToProcessPerStep; },
235 (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
236 new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)",
237 0.0001f,
238 (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
239 (s) => { return (float)MinimumObjectMass; },
240 (s,p,l,v) => { MinimumObjectMass = v; } ),
241 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
242 10000.01f,
243 (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
244 (s) => { return (float)MaximumObjectMass; },
245 (s,p,l,v) => { MaximumObjectMass = v; } ),
246
247 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
248 2200f,
249 (s,cf,p,v) => { PID_D = cf.GetFloat(p, v); },
250 (s) => { return (float)PID_D; },
251 (s,p,l,v) => { PID_D = v; } ),
252 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
253 900f,
254 (s,cf,p,v) => { PID_P = cf.GetFloat(p, v); },
255 (s) => { return (float)PID_P; },
256 (s,p,l,v) => { PID_P = v; } ),
257
258 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
259 0.2f,
260 (s,cf,p,v) => { s.UnmanagedParams[0].defaultFriction = cf.GetFloat(p, v); },
261 (s) => { return s.UnmanagedParams[0].defaultFriction; },
262 (s,p,l,v) => { s.UnmanagedParams[0].defaultFriction = v; } ),
263 new ParameterDefn("DefaultDensity", "Density for new objects" ,
264 10.000006836f, // Aluminum g/cm3
265 (s,cf,p,v) => { s.UnmanagedParams[0].defaultDensity = cf.GetFloat(p, v); },
266 (s) => { return s.UnmanagedParams[0].defaultDensity; },
267 (s,p,l,v) => { s.UnmanagedParams[0].defaultDensity = v; } ),
268 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
269 0f,
270 (s,cf,p,v) => { s.UnmanagedParams[0].defaultRestitution = cf.GetFloat(p, v); },
271 (s) => { return s.UnmanagedParams[0].defaultRestitution; },
272 (s,p,l,v) => { s.UnmanagedParams[0].defaultRestitution = v; } ),
273 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
274 0.04f,
275 (s,cf,p,v) => { s.UnmanagedParams[0].collisionMargin = cf.GetFloat(p, v); },
276 (s) => { return s.UnmanagedParams[0].collisionMargin; },
277 (s,p,l,v) => { s.UnmanagedParams[0].collisionMargin = v; } ),
278 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
279 -9.80665f,
280 (s,cf,p,v) => { s.UnmanagedParams[0].gravity = cf.GetFloat(p, v); },
281 (s) => { return s.UnmanagedParams[0].gravity; },
282 (s,p,l,v) => { s.UpdateParameterObject((x)=>{s.UnmanagedParams[0].gravity=x;}, p, PhysParameterEntry.APPLY_TO_NONE, v); },
283 (s,o,v) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,v)); } ),
284
285
286 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
287 0f,
288 (s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); },
289 (s) => { return LinearDamping; },
290 (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearDamping=x;}, p, l, v); },
291 (s,o,v) => { s.PE.SetDamping(o.PhysBody, v, AngularDamping); } ),
292 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
293 0f,
294 (s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); },
295 (s) => { return AngularDamping; },
296 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularDamping=x;}, p, l, v); },
297 (s,o,v) => { s.PE.SetDamping(o.PhysBody, LinearDamping, v); } ),
298 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
299 0.2f,
300 (s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); },
301 (s) => { return DeactivationTime; },
302 (s,p,l,v) => { s.UpdateParameterObject((x)=>{DeactivationTime=x;}, p, l, v); },
303 (s,o,v) => { s.PE.SetDeactivationTime(o.PhysBody, v); } ),
304 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
305 0.8f,
306 (s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); },
307 (s) => { return LinearSleepingThreshold; },
308 (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearSleepingThreshold=x;}, p, l, v); },
309 (s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ),
310 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
311 1.0f,
312 (s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); },
313 (s) => { return AngularSleepingThreshold; },
314 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularSleepingThreshold=x;}, p, l, v); },
315 (s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ),
316 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
317 0f, // set to zero to disable
318 (s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); },
319 (s) => { return CcdMotionThreshold; },
320 (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdMotionThreshold=x;}, p, l, v); },
321 (s,o,v) => { s.PE.SetCcdMotionThreshold(o.PhysBody, v); } ),
322 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
323 0f,
324 (s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); },
325 (s) => { return CcdSweptSphereRadius; },
326 (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdSweptSphereRadius=x;}, p, l, v); },
327 (s,o,v) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, v); } ),
328 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
329 0.1f,
330 (s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); },
331 (s) => { return ContactProcessingThreshold; },
332 (s,p,l,v) => { s.UpdateParameterObject((x)=>{ContactProcessingThreshold=x;}, p, l, v); },
333 (s,o,v) => { s.PE.SetContactProcessingThreshold(o.PhysBody, v); } ),
334
335 new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
336 (float)BSTerrainPhys.TerrainImplementation.Mesh,
337 (s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); },
338 (s) => { return TerrainImplementation; },
339 (s,p,l,v) => { TerrainImplementation = v; } ),
340 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
341 0.3f,
342 (s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); },
343 (s) => { return TerrainFriction; },
344 (s,p,l,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
345 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
346 0.8f,
347 (s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); },
348 (s) => { return TerrainHitFraction; },
349 (s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
350 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
351 0f,
352 (s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); },
353 (s) => { return TerrainRestitution; },
354 (s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
355 new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
356 0.04f,
357 (s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); },
358 (s) => { return TerrainCollisionMargin; },
359 (s,p,l,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
360
361 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
362 0.2f,
363 (s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); },
364 (s) => { return AvatarFriction; },
365 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarFriction=x;}, p, l, v); } ),
366 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
367 10.0f,
368 (s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); },
369 (s) => { return AvatarStandingFriction; },
370 (s,p,l,v) => { AvatarStandingFriction = v; } ),
371 new ParameterDefn("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
372 1.3f,
373 (s,cf,p,v) => { AvatarAlwaysRunFactor = cf.GetFloat(p, v); },
374 (s) => { return AvatarAlwaysRunFactor; },
375 (s,p,l,v) => { AvatarAlwaysRunFactor = v; } ),
376 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
377 3.5f,
378 (s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
379 (s) => { return AvatarDensity; },
380 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarDensity=x;}, p, l, v); } ),
381 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
382 0f,
383 (s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); },
384 (s) => { return AvatarRestitution; },
385 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarRestitution=x;}, p, l, v); } ),
386 new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
387 0.6f,
388 (s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); },
389 (s) => { return AvatarCapsuleWidth; },
390 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleWidth=x;}, p, l, v); } ),
391 new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
392 0.45f,
393 (s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); },
394 (s) => { return AvatarCapsuleDepth; },
395 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleDepth=x;}, p, l, v); } ),
396 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
397 1.5f,
398 (s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); },
399 (s) => { return AvatarCapsuleHeight; },
400 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleHeight=x;}, p, l, v); } ),
401 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
402 0.1f,
403 (s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); },
404 (s) => { return AvatarContactProcessingThreshold; },
405 (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarContactProcessingThreshold=x;}, p, l, v); } ),
406
407 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
408 0.95f,
409 (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
410 (s) => { return VehicleAngularDamping; },
411 (s,p,l,v) => { VehicleAngularDamping = v; } ),
412
413 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
414 0f,
415 (s,cf,p,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
416 (s) => { return s.UnmanagedParams[0].maxPersistantManifoldPoolSize; },
417 (s,p,l,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
418 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
419 0f,
420 (s,cf,p,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
421 (s) => { return s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize; },
422 (s,p,l,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
423 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
424 ConfigurationParameters.numericFalse,
425 (s,cf,p,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
426 (s) => { return s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation; },
427 (s,p,l,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ),
428 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
429 ConfigurationParameters.numericFalse,
430 (s,cf,p,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
431 (s) => { return s.UnmanagedParams[0].shouldForceUpdateAllAabbs; },
432 (s,p,l,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ),
433 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
434 ConfigurationParameters.numericTrue,
435 (s,cf,p,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
436 (s) => { return s.UnmanagedParams[0].shouldRandomizeSolverOrder; },
437 (s,p,l,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ),
438 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
439 ConfigurationParameters.numericTrue,
440 (s,cf,p,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
441 (s) => { return s.UnmanagedParams[0].shouldSplitSimulationIslands; },
442 (s,p,l,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ),
443 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
444 ConfigurationParameters.numericFalse,
445 (s,cf,p,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
446 (s) => { return s.UnmanagedParams[0].shouldEnableFrictionCaching; },
447 (s,p,l,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ),
448 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
449 0f, // zero says use Bullet default
450 (s,cf,p,v) => { s.UnmanagedParams[0].numberOfSolverIterations = cf.GetFloat(p, v); },
451 (s) => { return s.UnmanagedParams[0].numberOfSolverIterations; },
452 (s,p,l,v) => { s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
453
454 new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
455 (float)BSLinkset.LinksetImplementation.Compound,
456 (s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); },
457 (s) => { return LinksetImplementation; },
458 (s,p,l,v) => { LinksetImplementation = v; } ),
459 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
460 ConfigurationParameters.numericFalse,
461 (s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
462 (s) => { return LinkConstraintUseFrameOffset; },
463 (s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ),
464 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
465 ConfigurationParameters.numericTrue,
466 (s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
467 (s) => { return LinkConstraintEnableTransMotor; },
468 (s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ),
469 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
470 5.0f,
471 (s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
472 (s) => { return LinkConstraintTransMotorMaxVel; },
473 (s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ),
474 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
475 0.1f,
476 (s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
477 (s) => { return LinkConstraintTransMotorMaxForce; },
478 (s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ),
479 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
480 0.1f,
481 (s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); },
482 (s) => { return LinkConstraintCFM; },
483 (s,p,l,v) => { LinkConstraintCFM = v; } ),
484 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
485 0.1f,
486 (s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); },
487 (s) => { return LinkConstraintERP; },
488 (s,p,l,v) => { LinkConstraintERP = v; } ),
489 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
490 40,
491 (s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); },
492 (s) => { return LinkConstraintSolverIterations; },
493 (s,p,l,v) => { LinkConstraintSolverIterations = v; } ),
494
495 new ParameterDefn("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)",
496 0f,
497 (s,cf,p,v) => { s.PhysicsMetricDumpFrames = cf.GetFloat(p, (int)v); },
498 (s) => { return (float)s.PhysicsMetricDumpFrames; },
499 (s,p,l,v) => { s.PhysicsMetricDumpFrames = (int)v; } ),
500 };
501
502 // Convert a boolean to our numeric true and false values
503 public static float NumericBool(bool b)
504 {
505 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
506 }
507
508 // Convert numeric true and false values to a boolean
509 public static bool BoolNumeric(float b)
510 {
511 return (b == ConfigurationParameters.numericTrue ? true : false);
512 }
513
514 // Search through the parameter definitions and return the matching
515 // ParameterDefn structure.
516 // Case does not matter as names are compared after converting to lower case.
517 // Returns 'false' if the parameter is not found.
518 internal static bool TryGetParameter(string paramName, out ParameterDefn defn)
519 {
520 bool ret = false;
521 ParameterDefn foundDefn = new ParameterDefn();
522 string pName = paramName.ToLower();
523
524 foreach (ParameterDefn parm in ParameterDefinitions)
525 {
526 if (pName == parm.name.ToLower())
527 {
528 foundDefn = parm;
529 ret = true;
530 break;
531 }
532 }
533 defn = foundDefn;
534 return ret;
535 }
536
537 // Pass through the settable parameters and set the default values
538 internal static void SetParameterDefaultValues(BSScene physicsScene)
539 {
540 foreach (ParameterDefn parm in ParameterDefinitions)
541 {
542 parm.setter(physicsScene, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
543 }
544 }
545
546 // Get user set values out of the ini file.
547 internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg)
548 {
549 foreach (ParameterDefn parm in ParameterDefinitions)
550 {
551 parm.userParam(physicsScene, cfg, parm.name, parm.defaultValue);
552 }
553 }
554
555 internal static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
556
557 // This creates an array in the correct format for returning the list of
558 // parameters. This is used by the 'list' option of the 'physics' command.
559 internal static void BuildParameterTable()
560 {
561 if (SettableParameters.Length < ParameterDefinitions.Length)
562 {
563 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
564 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
565 {
566 ParameterDefn pd = ParameterDefinitions[ii];
567 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
568 }
569
570 // make the list in alphabetical order for estetic reasons
571 entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
572 {
573 return ppe1.name.CompareTo(ppe2.name);
574 });
575
576 SettableParameters = entries.ToArray();
577 }
578 }
579
580
581}
582}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
deleted file mode 100755
index e7cb3e0..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ /dev/null
@@ -1,386 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37/*
38 * Class to wrap all objects.
39 * The rest of BulletSim doesn't need to keep checking for avatars or prims
40 * unless the difference is significant.
41 *
42 * Variables in the physicsl objects are in three forms:
43 * VariableName: used by the simulator and performs taint operations, etc
44 * RawVariableName: direct reference to the BulletSim storage for the variable value
45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine.
46 * The last two (and certainly the last one) should be referenced only in taint-time.
47 */
48
49/*
50 * As of 20121221, the following are the call sequences (going down) for different script physical functions:
51 * llApplyImpulse llApplyRotImpulse llSetTorque llSetForce
52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce
53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse
54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v
55 * BS.ApplyCentralForce BS.ApplyTorque
56 */
57
58public abstract class BSPhysObject : PhysicsActor
59{
60 protected BSPhysObject()
61 {
62 }
63 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
64 {
65 PhysicsScene = parentScene;
66 LocalID = localID;
67 PhysObjectName = name;
68 TypeName = typeName;
69
70 // We don't have any physical representation yet.
71 PhysBody = new BulletBody(localID);
72 PhysShape = new BulletShape();
73
74 // A linkset of just me
75 Linkset = BSLinkset.Factory(PhysicsScene, this);
76 LastAssetBuildFailed = false;
77
78 // Default material type
79 Material = MaterialAttributes.Material.Wood;
80
81 CollisionCollection = new CollisionEventUpdate();
82 SubscribedEventsMs = 0;
83 CollidingStep = 0;
84 CollidingGroundStep = 0;
85 }
86
87 // Tell the object to clean up.
88 public virtual void Destroy()
89 {
90 UnRegisterAllPreStepActions();
91 }
92
93 public BSScene PhysicsScene { get; protected set; }
94 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
95 public string PhysObjectName { get; protected set; }
96 public string TypeName { get; protected set; }
97
98 public BSLinkset Linkset { get; set; }
99 public BSLinksetInfo LinksetInfo { get; set; }
100
101 // Return the object mass without calculating it or having side effects
102 public abstract float RawMass { get; }
103 // Set the raw mass but also update physical mass properties (inertia, ...)
104 // 'inWorld' true if the object has already been added to the dynamic world.
105 public abstract void UpdatePhysicalMassProperties(float mass, bool inWorld);
106
107 // The last value calculated for the prim's inertia
108 public OMV.Vector3 Inertia { get; set; }
109
110 // Reference to the physical body (btCollisionObject) of this object
111 public BulletBody PhysBody;
112 // Reference to the physical shape (btCollisionShape) of this object
113 public BulletShape PhysShape;
114
115 // 'true' if the mesh's underlying asset failed to build.
116 // This will keep us from looping after the first time the build failed.
117 public bool LastAssetBuildFailed { get; set; }
118
119 // The objects base shape information. Null if not a prim type shape.
120 public PrimitiveBaseShape BaseShape { get; protected set; }
121 // Some types of objects have preferred physical representations.
122 // Returns SHAPE_UNKNOWN if there is no preference.
123 public virtual BSPhysicsShapeType PreferredPhysicalShape
124 {
125 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
126 }
127
128 // When the physical properties are updated, an EntityProperty holds the update values.
129 // Keep the current and last EntityProperties to enable computation of differences
130 // between the current update and the previous values.
131 public EntityProperties CurrentEntityProperties { get; set; }
132 public EntityProperties LastEntityProperties { get; set; }
133
134 public virtual OMV.Vector3 Scale { get; set; }
135 public abstract bool IsSolid { get; }
136 public abstract bool IsStatic { get; }
137
138 // Materialness
139 public MaterialAttributes.Material Material { get; private set; }
140 public override void SetMaterial(int material)
141 {
142 Material = (MaterialAttributes.Material)material;
143 }
144
145 // Stop all physical motion.
146 public abstract void ZeroMotion(bool inTaintTime);
147 public abstract void ZeroAngularMotion(bool inTaintTime);
148
149 // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured.
150 public virtual void StepVehicle(float timeStep) { }
151
152 // Update the physical location and motion of the object. Called with data from Bullet.
153 public abstract void UpdateProperties(EntityProperties entprop);
154
155 public abstract OMV.Vector3 RawPosition { get; set; }
156 public abstract OMV.Vector3 ForcePosition { get; set; }
157
158 public abstract OMV.Quaternion RawOrientation { get; set; }
159 public abstract OMV.Quaternion ForceOrientation { get; set; }
160
161 // The system is telling us the velocity it wants to move at.
162 // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor
163 public override OMV.Vector3 TargetVelocity
164 {
165 get { return m_targetVelocity; }
166 set
167 {
168 m_targetVelocity = value;
169 Velocity = value;
170 }
171 }
172 public abstract OMV.Vector3 ForceVelocity { get; set; }
173
174 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
175
176 public abstract float ForceBuoyancy { get; set; }
177
178 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
179
180 #region Collisions
181
182 // Requested number of milliseconds between collision events. Zero means disabled.
183 protected int SubscribedEventsMs { get; set; }
184 // Given subscription, the time that a collision may be passed up
185 protected int NextCollisionOkTime { get; set; }
186 // The simulation step that last had a collision
187 protected long CollidingStep { get; set; }
188 // The simulation step that last had a collision with the ground
189 protected long CollidingGroundStep { get; set; }
190 // The simulation step that last collided with an object
191 protected long CollidingObjectStep { get; set; }
192 // The collision flags we think are set in Bullet
193 protected CollisionFlags CurrentCollisionFlags { get; set; }
194
195 public override bool IsColliding {
196 get { return (CollidingStep == PhysicsScene.SimulationStep); }
197 set {
198 if (value)
199 CollidingStep = PhysicsScene.SimulationStep;
200 else
201 CollidingStep = 0;
202 }
203 }
204 public override bool CollidingGround {
205 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
206 set
207 {
208 if (value)
209 CollidingGroundStep = PhysicsScene.SimulationStep;
210 else
211 CollidingGroundStep = 0;
212 }
213 }
214 public override bool CollidingObj {
215 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); }
216 set {
217 if (value)
218 CollidingObjectStep = PhysicsScene.SimulationStep;
219 else
220 CollidingObjectStep = 0;
221 }
222 }
223
224 // The collisions that have been collected this tick
225 protected CollisionEventUpdate CollisionCollection;
226
227 // The simulation step is telling this object about a collision.
228 // Return 'true' if a collision was processed and should be sent up.
229 // Called at taint time from within the Step() function
230 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
231 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
232 {
233 bool ret = false;
234
235 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
236 CollidingStep = PhysicsScene.SimulationStep;
237 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
238 {
239 CollidingGroundStep = PhysicsScene.SimulationStep;
240 }
241 else
242 {
243 CollidingObjectStep = PhysicsScene.SimulationStep;
244 }
245
246 // prims in the same linkset cannot collide with each other
247 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
248 {
249 return ret;
250 }
251
252 // if someone has subscribed for collision events....
253 if (SubscribedEvents()) {
254 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
255 DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
256 LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth);
257
258 ret = true;
259 }
260 return ret;
261 }
262
263 // Send the collected collisions into the simulator.
264 // Called at taint time from within the Step() function thus no locking problems
265 // with CollisionCollection and ObjectsWithNoMoreCollisions.
266 // Return 'true' if there were some actual collisions passed up
267 public virtual bool SendCollisions()
268 {
269 bool ret = true;
270 // If the 'no collision' call, force it to happen right now so quick collision_end
271 bool force = (CollisionCollection.Count == 0);
272
273 // throttle the collisions to the number of milliseconds specified in the subscription
274 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
275 {
276 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs;
277
278 // We are called if we previously had collisions. If there are no collisions
279 // this time, send up one last empty event so OpenSim can sense collision end.
280 if (CollisionCollection.Count == 0)
281 {
282 // If I have no collisions this time, remove me from the list of objects with collisions.
283 ret = false;
284 }
285
286 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
287 base.SendCollisionUpdate(CollisionCollection);
288
289 // The CollisionCollection instance is passed around in the simulator.
290 // Make sure we don't have a handle to that one and that a new one is used for next time.
291 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
292 // a race condition is created for the other users of this instance.
293 CollisionCollection = new CollisionEventUpdate();
294 }
295 return ret;
296 }
297
298 // Subscribe for collision events.
299 // Parameter is the millisecond rate the caller wishes collision events to occur.
300 public override void SubscribeEvents(int ms) {
301 // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms);
302 SubscribedEventsMs = ms;
303 if (ms > 0)
304 {
305 // make sure first collision happens
306 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
307
308 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
309 {
310 if (PhysBody.HasPhysicalBody)
311 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
312 });
313 }
314 else
315 {
316 // Subscribing for zero or less is the same as unsubscribing
317 UnSubscribeEvents();
318 }
319 }
320 public override void UnSubscribeEvents() {
321 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
322 SubscribedEventsMs = 0;
323 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
324 {
325 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
326 if (PhysBody.HasPhysicalBody)
327 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
328 });
329 }
330 // Return 'true' if the simulator wants collision events
331 public override bool SubscribedEvents() {
332 return (SubscribedEventsMs > 0);
333 }
334
335 #endregion // Collisions
336
337 #region Per Simulation Step actions
338 // There are some actions that must be performed for a physical object before each simulation step.
339 // These actions are optional so, rather than scanning all the physical objects and asking them
340 // if they have anything to do, a physical object registers for an event call before the step is performed.
341 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
342 private Dictionary<string, BSScene.PreStepAction> RegisteredActions = new Dictionary<string, BSScene.PreStepAction>();
343 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
344 {
345 string identifier = op + "-" + id.ToString();
346 RegisteredActions[identifier] = actn;
347 PhysicsScene.BeforeStep += actn;
348 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
349 }
350
351 // Unregister a pre step action. Safe to call if the action has not been registered.
352 protected void UnRegisterPreStepAction(string op, uint id)
353 {
354 string identifier = op + "-" + id.ToString();
355 bool removed = false;
356 if (RegisteredActions.ContainsKey(identifier))
357 {
358 PhysicsScene.BeforeStep -= RegisteredActions[identifier];
359 RegisteredActions.Remove(identifier);
360 removed = true;
361 }
362 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
363 }
364
365 protected void UnRegisterAllPreStepActions()
366 {
367 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredActions)
368 {
369 PhysicsScene.BeforeStep -= kvp.Value;
370 }
371 RegisteredActions.Clear();
372 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
373 }
374
375
376 #endregion // Per Simulation Step actions
377
378 // High performance detailed logging routine used by the physical objects.
379 protected void DetailLog(string msg, params Object[] args)
380 {
381 if (PhysicsScene.PhysicsLogging.Enabled)
382 PhysicsScene.DetailLog(msg, args);
383 }
384
385}
386}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
deleted file mode 100644
index 65be52a..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
+++ /dev/null
@@ -1,76 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using OpenSim.Framework;
30using OpenSim.Region.Physics.Manager;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35 /// <summary>
36 /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim.
37 /// This module interfaces to an unmanaged C++ library which makes the
38 /// actual calls into the Bullet physics engine.
39 /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/.
40 /// The unmanaged library is compiled and linked statically with Bullet
41 /// to create BulletSim.dll and libBulletSim.so (for both 32 and 64 bit).
42 /// </summary>
43public class BSPlugin : IPhysicsPlugin
44{
45 //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
46
47 private BSScene _mScene;
48
49 public BSPlugin()
50 {
51 }
52
53 public bool Init()
54 {
55 return true;
56 }
57
58 public PhysicsScene GetScene(String sceneIdentifier)
59 {
60 if (_mScene == null)
61 {
62 _mScene = new BSScene(sceneIdentifier);
63 }
64 return (_mScene);
65 }
66
67 public string GetName()
68 {
69 return ("BulletSim");
70 }
71
72 public void Dispose()
73 {
74 }
75}
76}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
deleted file mode 100644
index 826261c..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ /dev/null
@@ -1,1513 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Collections.Generic;
31using System.Xml;
32using log4net;
33using OMV = OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Physics.Manager;
36using OpenSim.Region.Physics.ConvexDecompositionDotNet;
37
38namespace OpenSim.Region.Physics.BulletSPlugin
39{
40
41 [Serializable]
42public sealed class BSPrim : BSPhysObject
43{
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 private static readonly string LogHeader = "[BULLETS PRIM]";
46
47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
48 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
49
50 private bool _grabbed;
51 private bool _isSelected;
52 private bool _isVolumeDetect;
53 private OMV.Vector3 _position;
54 private float _mass; // the mass of this object
55 private float _density;
56 private OMV.Vector3 _force;
57 private OMV.Vector3 _velocity;
58 private OMV.Vector3 _torque;
59 private float _collisionScore;
60 private OMV.Vector3 _acceleration;
61 private OMV.Quaternion _orientation;
62 private int _physicsActorType;
63 private bool _isPhysical;
64 private bool _flying;
65 private float _friction;
66 private float _restitution;
67 private bool _setAlwaysRun;
68 private bool _throttleUpdates;
69 private bool _isColliding;
70 private bool _collidingGround;
71 private bool _collidingObj;
72 private bool _floatOnWater;
73 private OMV.Vector3 _rotationalVelocity;
74 private bool _kinematic;
75 private float _buoyancy;
76
77 private BSDynamics _vehicle;
78
79 private OMV.Vector3 _PIDTarget;
80 private bool _usePID;
81 private float _PIDTau;
82 private bool _useHoverPID;
83 private float _PIDHoverHeight;
84 private PIDHoverType _PIDHoverType;
85 private float _PIDHoverTao;
86
87 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
88 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
89 : base(parent_scene, localID, primName, "BSPrim")
90 {
91 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
92 _physicsActorType = (int)ActorTypes.Prim;
93 _position = pos;
94 _size = size;
95 Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
96 _orientation = rotation;
97 _buoyancy = 0f;
98 _velocity = OMV.Vector3.Zero;
99 _rotationalVelocity = OMV.Vector3.Zero;
100 BaseShape = pbs;
101 _isPhysical = pisPhysical;
102 _isVolumeDetect = false;
103
104 // Someday set default attributes based on the material but, for now, we don't know the prim material yet.
105 // MaterialAttributes primMat = BSMaterials.GetAttributes(Material, pisPhysical);
106 _density = PhysicsScene.Params.defaultDensity;
107 _friction = PhysicsScene.Params.defaultFriction;
108 _restitution = PhysicsScene.Params.defaultRestitution;
109
110 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness
111
112 _mass = CalculateMass();
113
114 // Cause linkset variables to be initialized (like mass)
115 Linkset.Refresh(this);
116
117 DetailLog("{0},BSPrim.constructor,call", LocalID);
118 // do the actual object creation at taint time
119 PhysicsScene.TaintedObject("BSPrim.create", delegate()
120 {
121 CreateGeomAndObject(true);
122
123 CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody);
124 });
125 }
126
127 // called when this prim is being destroyed and we should free all the resources
128 public override void Destroy()
129 {
130 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
131 base.Destroy();
132
133 // Undo any links between me and any other object
134 BSPhysObject parentBefore = Linkset.LinksetRoot;
135 int childrenBefore = Linkset.NumberOfChildren;
136
137 Linkset = Linkset.RemoveMeFromLinkset(this);
138
139 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
140 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
141
142 // Undo any vehicle properties
143 this.VehicleType = (int)Vehicle.TYPE_NONE;
144
145 PhysicsScene.TaintedObject("BSPrim.destroy", delegate()
146 {
147 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
148 // If there are physical body and shape, release my use of same.
149 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
150 PhysBody.Clear();
151 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
152 PhysShape.Clear();
153 });
154 }
155
156 // No one uses this property.
157 public override bool Stopped {
158 get { return false; }
159 }
160 public override OMV.Vector3 Size {
161 get { return _size; }
162 set {
163 // We presume the scale and size are the same. If scale must be changed for
164 // the physical shape, that is done when the geometry is built.
165 _size = value;
166 Scale = _size;
167 ForceBodyShapeRebuild(false);
168 }
169 }
170
171 public override PrimitiveBaseShape Shape {
172 set {
173 BaseShape = value;
174 ForceBodyShapeRebuild(false);
175 }
176 }
177 // Whatever the linkset wants is what I want.
178 public override BSPhysicsShapeType PreferredPhysicalShape
179 { get { return Linkset.PreferredPhysicalShape(this); } }
180
181 public override bool ForceBodyShapeRebuild(bool inTaintTime)
182 {
183 LastAssetBuildFailed = false;
184 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
185 {
186 _mass = CalculateMass(); // changing the shape changes the mass
187 CreateGeomAndObject(true);
188 });
189 return true;
190 }
191 public override bool Grabbed {
192 set { _grabbed = value;
193 }
194 }
195 public override bool Selected {
196 set
197 {
198 if (value != _isSelected)
199 {
200 _isSelected = value;
201 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
202 {
203 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
204 SetObjectDynamic(false);
205 });
206 }
207 }
208 }
209 public override void CrossingFailure() { return; }
210
211 // link me to the specified parent
212 public override void link(PhysicsActor obj) {
213 BSPrim parent = obj as BSPrim;
214 if (parent != null)
215 {
216 BSPhysObject parentBefore = Linkset.LinksetRoot;
217 int childrenBefore = Linkset.NumberOfChildren;
218
219 Linkset = parent.Linkset.AddMeToLinkset(this);
220
221 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
222 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
223 }
224 return;
225 }
226
227 // delink me from my linkset
228 public override void delink() {
229 // TODO: decide if this parent checking needs to happen at taint time
230 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
231
232 BSPhysObject parentBefore = Linkset.LinksetRoot;
233 int childrenBefore = Linkset.NumberOfChildren;
234
235 Linkset = Linkset.RemoveMeFromLinkset(this);
236
237 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
238 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
239 return;
240 }
241
242 // Set motion values to zero.
243 // Do it to the properties so the values get set in the physics engine.
244 // Push the setting of the values to the viewer.
245 // Called at taint time!
246 public override void ZeroMotion(bool inTaintTime)
247 {
248 _velocity = OMV.Vector3.Zero;
249 _acceleration = OMV.Vector3.Zero;
250 _rotationalVelocity = OMV.Vector3.Zero;
251
252 // Zero some other properties in the physics engine
253 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
254 {
255 if (PhysBody.HasPhysicalBody)
256 PhysicsScene.PE.ClearAllForces(PhysBody);
257 });
258 }
259 public override void ZeroAngularMotion(bool inTaintTime)
260 {
261 _rotationalVelocity = OMV.Vector3.Zero;
262 // Zero some other properties in the physics engine
263 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
264 {
265 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
266 if (PhysBody.HasPhysicalBody)
267 {
268 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
269 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
270 }
271 });
272 }
273
274 public override void LockAngularMotion(OMV.Vector3 axis)
275 {
276 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
277 return;
278 }
279
280 public override OMV.Vector3 RawPosition
281 {
282 get { return _position; }
283 set { _position = value; }
284 }
285 public override OMV.Vector3 Position {
286 get {
287 /* NOTE: this refetch is not necessary. The simulator knows about linkset children
288 * and does not fetch this position info for children. Thus this is commented out.
289 // child prims move around based on their parent. Need to get the latest location
290 if (!Linkset.IsRoot(this))
291 _position = Linkset.PositionGet(this);
292 */
293
294 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
295 // _position = PhysicsScene.PE.GetObjectPosition2(PhysicsScene.World, BSBody);
296 return _position;
297 }
298 set {
299 // If the position must be forced into the physics engine, use ForcePosition.
300 // All positions are given in world positions.
301 if (_position == value)
302 {
303 DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation);
304 return;
305 }
306 _position = value;
307 PositionSanityCheck(false);
308
309 // A linkset might need to know if a component information changed.
310 Linkset.UpdateProperties(this, false);
311
312 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
313 {
314 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
315 ForcePosition = _position;
316 });
317 }
318 }
319 public override OMV.Vector3 ForcePosition {
320 get {
321 _position = PhysicsScene.PE.GetPosition(PhysBody);
322 return _position;
323 }
324 set {
325 _position = value;
326 if (PhysBody.HasPhysicalBody)
327 {
328 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
329 ActivateIfPhysical(false);
330 }
331 }
332 }
333
334 // Check that the current position is sane and, if not, modify the position to make it so.
335 // Check for being below terrain and being out of bounds.
336 // Returns 'true' of the position was made sane by some action.
337 private bool PositionSanityCheck(bool inTaintTime)
338 {
339 bool ret = false;
340
341 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position))
342 {
343 // The physical object is out of the known/simulated area.
344 // Upper levels of code will handle the transition to other areas so, for
345 // the time, we just ignore the position.
346 return ret;
347 }
348
349 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
350 OMV.Vector3 upForce = OMV.Vector3.Zero;
351 if (RawPosition.Z < terrainHeight)
352 {
353 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
354 float targetHeight = terrainHeight + (Size.Z / 2f);
355 // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec.
356 upForce.Z = (terrainHeight - RawPosition.Z) * 1f;
357 ret = true;
358 }
359
360 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
361 {
362 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
363 // TODO: a floating motor so object will bob in the water
364 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f)
365 {
366 // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
367 upForce.Z = (waterHeight - RawPosition.Z) * 1f;
368 ret = true;
369 }
370 }
371
372 // The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
373 // TODO: This should be intergrated with a geneal physics action mechanism.
374 // TODO: This should be moderated with PID'ness.
375 if (ret)
376 {
377 // Apply upforce and overcome gravity.
378 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity;
379 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
380 AddForce(correctionForce, false, inTaintTime);
381 }
382 return ret;
383 }
384
385 // Return the effective mass of the object.
386 // The definition of this call is to return the mass of the prim.
387 // If the simulator cares about the mass of the linkset, it will sum it itself.
388 public override float Mass
389 {
390 get
391 {
392 return _mass;
393 }
394 }
395
396 // used when we only want this prim's mass and not the linkset thing
397 public override float RawMass {
398 get { return _mass; }
399 }
400 // Set the physical mass to the passed mass.
401 // Note that this does not change _mass!
402 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
403 {
404 if (PhysBody.HasPhysicalBody)
405 {
406 if (IsStatic)
407 {
408 PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity);
409 Inertia = OMV.Vector3.Zero;
410 PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia);
411 PhysicsScene.PE.UpdateInertiaTensor(PhysBody);
412 }
413 else
414 {
415 OMV.Vector3 grav = ComputeGravity();
416
417 if (inWorld)
418 {
419 // Changing interesting properties doesn't change proxy and collision cache
420 // information. The Bullet solution is to re-add the object to the world
421 // after parameters are changed.
422 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody);
423 }
424
425 // The computation of mass props requires gravity to be set on the object.
426 PhysicsScene.PE.SetGravity(PhysBody, grav);
427
428 Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass);
429 PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia);
430 PhysicsScene.PE.UpdateInertiaTensor(PhysBody);
431
432 // center of mass is at the zero of the object
433 // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(PhysBody, ForcePosition, ForceOrientation);
434 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", LocalID, physMass, Inertia, grav, inWorld);
435
436 if (inWorld)
437 {
438 AddObjectToPhysicalWorld();
439 }
440
441 // Must set gravity after it has been added to the world because, for unknown reasons,
442 // adding the object resets the object's gravity to world gravity
443 PhysicsScene.PE.SetGravity(PhysBody, grav);
444
445 }
446 }
447 }
448
449 // Return what gravity should be set to this very moment
450 private OMV.Vector3 ComputeGravity()
451 {
452 OMV.Vector3 ret = PhysicsScene.DefaultGravity;
453
454 if (!IsStatic)
455 ret *= (1f - Buoyancy);
456
457 return ret;
458 }
459
460 // Is this used?
461 public override OMV.Vector3 CenterOfMass
462 {
463 get { return Linkset.CenterOfMass; }
464 }
465
466 // Is this used?
467 public override OMV.Vector3 GeometricCenter
468 {
469 get { return Linkset.GeometricCenter; }
470 }
471
472 public override OMV.Vector3 Force {
473 get { return _force; }
474 set {
475 _force = value;
476 if (_force != OMV.Vector3.Zero)
477 {
478 // If the force is non-zero, it must be reapplied each tick because
479 // Bullet clears the forces applied last frame.
480 RegisterPreStepAction("BSPrim.setForce", LocalID,
481 delegate(float timeStep)
482 {
483 DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force);
484 if (PhysBody.HasPhysicalBody)
485 {
486 PhysicsScene.PE.ApplyCentralForce(PhysBody, _force);
487 ActivateIfPhysical(false);
488 }
489 }
490 );
491 }
492 else
493 {
494 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
495 }
496 }
497 }
498
499 public override int VehicleType {
500 get {
501 return (int)_vehicle.Type; // if we are a vehicle, return that type
502 }
503 set {
504 Vehicle type = (Vehicle)value;
505
506 PhysicsScene.TaintedObject("setVehicleType", delegate()
507 {
508 // Done at taint time so we're sure the physics engine is not using the variables
509 // Vehicle code changes the parameters for this vehicle type.
510 _vehicle.ProcessTypeChange(type);
511 ActivateIfPhysical(false);
512
513 // If an active vehicle, register the vehicle code to be called before each step
514 if (_vehicle.Type == Vehicle.TYPE_NONE)
515 UnRegisterPreStepAction("BSPrim.Vehicle", LocalID);
516 else
517 RegisterPreStepAction("BSPrim.Vehicle", LocalID, _vehicle.Step);
518 });
519 }
520 }
521 public override void VehicleFloatParam(int param, float value)
522 {
523 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
524 {
525 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
526 ActivateIfPhysical(false);
527 });
528 }
529 public override void VehicleVectorParam(int param, OMV.Vector3 value)
530 {
531 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
532 {
533 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
534 ActivateIfPhysical(false);
535 });
536 }
537 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
538 {
539 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
540 {
541 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
542 ActivateIfPhysical(false);
543 });
544 }
545 public override void VehicleFlags(int param, bool remove)
546 {
547 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate()
548 {
549 _vehicle.ProcessVehicleFlags(param, remove);
550 });
551 }
552
553 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
554 public override void SetVolumeDetect(int param) {
555 bool newValue = (param != 0);
556 if (_isVolumeDetect != newValue)
557 {
558 _isVolumeDetect = newValue;
559 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
560 {
561 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
562 SetObjectDynamic(true);
563 });
564 }
565 return;
566 }
567 public override OMV.Vector3 Velocity {
568 get { return _velocity; }
569 set {
570 _velocity = value;
571 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
572 {
573 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
574 ForceVelocity = _velocity;
575 });
576 }
577 }
578 public override OMV.Vector3 ForceVelocity {
579 get { return _velocity; }
580 set {
581 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity");
582
583 _velocity = value;
584 if (PhysBody.HasPhysicalBody)
585 {
586 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity);
587 ActivateIfPhysical(false);
588 }
589 }
590 }
591 public override OMV.Vector3 Torque {
592 get { return _torque; }
593 set {
594 _torque = value;
595 if (_torque != OMV.Vector3.Zero)
596 {
597 // If the torque is non-zero, it must be reapplied each tick because
598 // Bullet clears the forces applied last frame.
599 RegisterPreStepAction("BSPrim.setTorque", LocalID,
600 delegate(float timeStep)
601 {
602 if (PhysBody.HasPhysicalBody)
603 AddAngularForce(_torque, false, true);
604 }
605 );
606 }
607 else
608 {
609 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
610 }
611 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
612 }
613 }
614 public override float CollisionScore {
615 get { return _collisionScore; }
616 set { _collisionScore = value;
617 }
618 }
619 public override OMV.Vector3 Acceleration {
620 get { return _acceleration; }
621 set { _acceleration = value; }
622 }
623 public override OMV.Quaternion RawOrientation
624 {
625 get { return _orientation; }
626 set { _orientation = value; }
627 }
628 public override OMV.Quaternion Orientation {
629 get {
630 /* NOTE: this refetch is not necessary. The simulator knows about linkset children
631 * and does not fetch this position info for children. Thus this is commented out.
632 // Children move around because tied to parent. Get a fresh value.
633 if (!Linkset.IsRoot(this))
634 {
635 _orientation = Linkset.OrientationGet(this);
636 }
637 */
638 return _orientation;
639 }
640 set {
641 if (_orientation == value)
642 return;
643 _orientation = value;
644
645 // A linkset might need to know if a component information changed.
646 Linkset.UpdateProperties(this, false);
647
648 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
649 {
650 if (PhysBody.HasPhysicalBody)
651 {
652 // _position = PhysicsScene.PE.GetObjectPosition(PhysicsScene.World, BSBody);
653 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
654 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
655 }
656 });
657 }
658 }
659 // Go directly to Bullet to get/set the value.
660 public override OMV.Quaternion ForceOrientation
661 {
662 get
663 {
664 _orientation = PhysicsScene.PE.GetOrientation(PhysBody);
665 return _orientation;
666 }
667 set
668 {
669 _orientation = value;
670 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
671 }
672 }
673 public override int PhysicsActorType {
674 get { return _physicsActorType; }
675 set { _physicsActorType = value; }
676 }
677 public override bool IsPhysical {
678 get { return _isPhysical; }
679 set {
680 if (_isPhysical != value)
681 {
682 _isPhysical = value;
683 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate()
684 {
685 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
686 SetObjectDynamic(true);
687 // whether phys-to-static or static-to-phys, the object is not moving.
688 ZeroMotion(true);
689 });
690 }
691 }
692 }
693
694 // An object is static (does not move) if selected or not physical
695 public override bool IsStatic
696 {
697 get { return _isSelected || !IsPhysical; }
698 }
699
700 // An object is solid if it's not phantom and if it's not doing VolumeDetect
701 public override bool IsSolid
702 {
703 get { return !IsPhantom && !_isVolumeDetect; }
704 }
705
706 // Make gravity work if the object is physical and not selected
707 // Called at taint-time!!
708 private void SetObjectDynamic(bool forceRebuild)
709 {
710 // Recreate the physical object if necessary
711 CreateGeomAndObject(forceRebuild);
712 }
713
714 // Convert the simulator's physical properties into settings on BulletSim objects.
715 // There are four flags we're interested in:
716 // IsStatic: Object does not move, otherwise the object has mass and moves
717 // isSolid: other objects bounce off of this object
718 // isVolumeDetect: other objects pass through but can generate collisions
719 // collisionEvents: whether this object returns collision events
720 private void UpdatePhysicalParameters()
721 {
722 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
723
724 // Mangling all the physical properties requires the object not be in the physical world.
725 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
726 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody);
727
728 // Set up the object physicalness (does gravity and collisions move this object)
729 MakeDynamic(IsStatic);
730
731 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
732 _vehicle.Refresh();
733
734 // Arrange for collision events if the simulator wants them
735 EnableCollisions(SubscribedEvents());
736
737 // Make solid or not (do things bounce off or pass through this object).
738 MakeSolid(IsSolid);
739
740 AddObjectToPhysicalWorld();
741
742 // Rebuild its shape
743 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody);
744
745 // Recompute any linkset parameters.
746 // When going from non-physical to physical, this re-enables the constraints that
747 // had been automatically disabled when the mass was set to zero.
748 // For compound based linksets, this enables and disables interactions of the children.
749 Linkset.Refresh(this);
750
751 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
752 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
753 }
754
755 // "Making dynamic" means changing to and from static.
756 // When static, gravity does not effect the object and it is fixed in space.
757 // When dynamic, the object can fall and be pushed by others.
758 // This is independent of its 'solidness' which controls what passes through
759 // this object and what interacts with it.
760 private void MakeDynamic(bool makeStatic)
761 {
762 if (makeStatic)
763 {
764 // Become a Bullet 'static' object type
765 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
766 // Stop all movement
767 ZeroMotion(true);
768
769 // Set various physical properties so other object interact properly
770 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
771 PhysicsScene.PE.SetFriction(PhysBody, matAttrib.friction);
772 PhysicsScene.PE.SetRestitution(PhysBody, matAttrib.restitution);
773
774 // Mass is zero which disables a bunch of physics stuff in Bullet
775 UpdatePhysicalMassProperties(0f, false);
776 // Set collision detection parameters
777 if (BSParam.CcdMotionThreshold > 0f)
778 {
779 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
780 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
781 }
782
783 // The activation state is 'disabled' so Bullet will not try to act on it.
784 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION);
785 // Start it out sleeping and physical actions could wake it up.
786 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING);
787
788 // This collides like a static object
789 PhysBody.collisionType = CollisionType.Static;
790
791 // There can be special things needed for implementing linksets
792 Linkset.MakeStatic(this);
793 }
794 else
795 {
796 // Not a Bullet static object
797 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
798
799 // Set various physical properties so other object interact properly
800 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, true);
801 PhysicsScene.PE.SetFriction(PhysBody, matAttrib.friction);
802 PhysicsScene.PE.SetRestitution(PhysBody, matAttrib.restitution);
803
804 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
805 // Since this can be called multiple times, only zero forces when becoming physical
806 // PhysicsScene.PE.ClearAllForces(BSBody);
807
808 // For good measure, make sure the transform is set through to the motion state
809 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
810
811 // Center of mass is at the center of the object
812 // DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation);
813
814 // A dynamic object has mass
815 UpdatePhysicalMassProperties(RawMass, false);
816
817 // Set collision detection parameters
818 if (BSParam.CcdMotionThreshold > 0f)
819 {
820 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
821 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
822 }
823
824 // Various values for simulation limits
825 PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping);
826 PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime);
827 PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold);
828 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
829
830 // This collides like an object.
831 PhysBody.collisionType = CollisionType.Dynamic;
832
833 // Force activation of the object so Bullet will act on it.
834 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
835 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
836
837 // There might be special things needed for implementing linksets.
838 Linkset.MakeDynamic(this);
839 }
840 }
841
842 // "Making solid" means that other object will not pass through this object.
843 // To make transparent, we create a Bullet ghost object.
844 // Note: This expects to be called from the UpdatePhysicalParameters() routine as
845 // the functions after this one set up the state of a possibly newly created collision body.
846 private void MakeSolid(bool makeSolid)
847 {
848 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody);
849 if (makeSolid)
850 {
851 // Verify the previous code created the correct shape for this type of thing.
852 if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0)
853 {
854 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
855 }
856 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
857 }
858 else
859 {
860 if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0)
861 {
862 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
863 }
864 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
865
866 // Change collision info from a static object to a ghosty collision object
867 PhysBody.collisionType = CollisionType.VolumeDetect;
868 }
869 }
870
871 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
872 // they need waking up when parameters are changed.
873 // Called in taint-time!!
874 private void ActivateIfPhysical(bool forceIt)
875 {
876 if (IsPhysical && PhysBody.HasPhysicalBody)
877 PhysicsScene.PE.Activate(PhysBody, forceIt);
878 }
879
880 // Turn on or off the flag controlling whether collision events are returned to the simulator.
881 private void EnableCollisions(bool wantsCollisionEvents)
882 {
883 if (wantsCollisionEvents)
884 {
885 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
886 }
887 else
888 {
889 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
890 }
891 }
892
893 // Add me to the physical world.
894 // Object MUST NOT already be in the world.
895 // This routine exists because some assorted properties get mangled by adding to the world.
896 internal void AddObjectToPhysicalWorld()
897 {
898 if (PhysBody.HasPhysicalBody)
899 {
900 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody);
901 }
902 else
903 {
904 m_log.ErrorFormat("{0} Attempt to add physical object without body. id={1}", LogHeader, LocalID);
905 DetailLog("{0},BSPrim.UpdatePhysicalParameters,addObjectWithoutBody,cType={1}", LocalID, PhysBody.collisionType);
906 }
907 }
908
909 // prims don't fly
910 public override bool Flying {
911 get { return _flying; }
912 set {
913 _flying = value;
914 }
915 }
916 public override bool SetAlwaysRun {
917 get { return _setAlwaysRun; }
918 set { _setAlwaysRun = value; }
919 }
920 public override bool ThrottleUpdates {
921 get { return _throttleUpdates; }
922 set { _throttleUpdates = value; }
923 }
924 public bool IsPhantom {
925 get {
926 // SceneObjectPart removes phantom objects from the physics scene
927 // so, although we could implement touching and such, we never
928 // are invoked as a phantom object
929 return false;
930 }
931 }
932 public override bool FloatOnWater {
933 set {
934 _floatOnWater = value;
935 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
936 {
937 if (_floatOnWater)
938 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
939 else
940 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
941 });
942 }
943 }
944 public override OMV.Vector3 RotationalVelocity {
945 get {
946 return _rotationalVelocity;
947 }
948 set {
949 _rotationalVelocity = value;
950 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
951 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
952 {
953 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
954 ForceRotationalVelocity = _rotationalVelocity;
955 });
956 }
957 }
958 public override OMV.Vector3 ForceRotationalVelocity {
959 get {
960 return _rotationalVelocity;
961 }
962 set {
963 _rotationalVelocity = value;
964 if (PhysBody.HasPhysicalBody)
965 {
966 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
967 ActivateIfPhysical(false);
968 }
969 }
970 }
971 public override bool Kinematic {
972 get { return _kinematic; }
973 set { _kinematic = value;
974 // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic);
975 }
976 }
977 public override float Buoyancy {
978 get { return _buoyancy; }
979 set {
980 _buoyancy = value;
981 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate()
982 {
983 ForceBuoyancy = _buoyancy;
984 });
985 }
986 }
987 public override float ForceBuoyancy {
988 get { return _buoyancy; }
989 set {
990 _buoyancy = value;
991 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
992 // Force the recalculation of the various inertia,etc variables in the object
993 DetailLog("{0},BSPrim.ForceBuoyancy,buoy={1},mass={2}", LocalID, _buoyancy, _mass);
994 UpdatePhysicalMassProperties(_mass, true);
995 ActivateIfPhysical(false);
996 }
997 }
998
999 // Used for MoveTo
1000 public override OMV.Vector3 PIDTarget {
1001 set { _PIDTarget = value; }
1002 }
1003 public override float PIDTau {
1004 set { _PIDTau = value; }
1005 }
1006 public override bool PIDActive {
1007 set { _usePID = value; }
1008 }
1009
1010 // Used for llSetHoverHeight and maybe vehicle height
1011 // Hover Height will override MoveTo target's Z
1012 public override bool PIDHoverActive {
1013 set { _useHoverPID = value; }
1014 }
1015 public override float PIDHoverHeight {
1016 set { _PIDHoverHeight = value; }
1017 }
1018 public override PIDHoverType PIDHoverType {
1019 set { _PIDHoverType = value; }
1020 }
1021 public override float PIDHoverTau {
1022 set { _PIDHoverTao = value; }
1023 }
1024
1025 // For RotLookAt
1026 public override OMV.Quaternion APIDTarget { set { return; } }
1027 public override bool APIDActive { set { return; } }
1028 public override float APIDStrength { set { return; } }
1029 public override float APIDDamping { set { return; } }
1030
1031 public override void AddForce(OMV.Vector3 force, bool pushforce) {
1032 // Since this force is being applied in only one step, make this a force per second.
1033 OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep;
1034 AddForce(addForce, pushforce, false);
1035 }
1036 // Applying a force just adds this to the total force on the object.
1037 // This added force will only last the next simulation tick.
1038 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
1039 // for an object, doesn't matter if force is a pushforce or not
1040 if (force.IsFinite())
1041 {
1042 float magnitude = force.Length();
1043 if (magnitude > BSParam.MaxAddForceMagnitude)
1044 {
1045 // Force has a limit
1046 force = force / magnitude * BSParam.MaxAddForceMagnitude;
1047 }
1048
1049 OMV.Vector3 addForce = force;
1050 DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
1051
1052 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
1053 {
1054 // Bullet adds this central force to the total force for this tick
1055 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1056 if (PhysBody.HasPhysicalBody)
1057 {
1058 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce);
1059 ActivateIfPhysical(false);
1060 }
1061 });
1062 }
1063 else
1064 {
1065 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
1066 return;
1067 }
1068 }
1069
1070 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
1071 AddAngularForce(force, pushforce, false);
1072 }
1073 public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1074 {
1075 if (force.IsFinite())
1076 {
1077 OMV.Vector3 angForce = force;
1078 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
1079 {
1080 if (PhysBody.HasPhysicalBody)
1081 {
1082 PhysicsScene.PE.ApplyTorque(PhysBody, angForce);
1083 ActivateIfPhysical(false);
1084 }
1085 });
1086 }
1087 else
1088 {
1089 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
1090 return;
1091 }
1092 }
1093
1094 // A torque impulse.
1095 // ApplyTorqueImpulse adds torque directly to the angularVelocity.
1096 // AddAngularForce accumulates the force and applied it to the angular velocity all at once.
1097 // Computed as: angularVelocity += impulse * inertia;
1098 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1099 {
1100 OMV.Vector3 applyImpulse = impulse;
1101 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1102 {
1103 if (PhysBody.HasPhysicalBody)
1104 {
1105 PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse);
1106 ActivateIfPhysical(false);
1107 }
1108 });
1109 }
1110
1111 public override void SetMomentum(OMV.Vector3 momentum) {
1112 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
1113 }
1114 #region Mass Calculation
1115
1116 private float CalculateMass()
1117 {
1118 float volume = _size.X * _size.Y * _size.Z; // default
1119 float tmp;
1120
1121 float returnMass = 0;
1122 float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f;
1123 float hollowVolume = hollowAmount * hollowAmount;
1124
1125 switch (BaseShape.ProfileShape)
1126 {
1127 case ProfileShape.Square:
1128 // default box
1129
1130 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
1131 {
1132 if (hollowAmount > 0.0)
1133 {
1134 switch (BaseShape.HollowShape)
1135 {
1136 case HollowShape.Square:
1137 case HollowShape.Same:
1138 break;
1139
1140 case HollowShape.Circle:
1141
1142 hollowVolume *= 0.78539816339f;
1143 break;
1144
1145 case HollowShape.Triangle:
1146
1147 hollowVolume *= (0.5f * .5f);
1148 break;
1149
1150 default:
1151 hollowVolume = 0;
1152 break;
1153 }
1154 volume *= (1.0f - hollowVolume);
1155 }
1156 }
1157
1158 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
1159 {
1160 //a tube
1161
1162 volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX);
1163 tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY);
1164 volume -= volume*tmp*tmp;
1165
1166 if (hollowAmount > 0.0)
1167 {
1168 hollowVolume *= hollowAmount;
1169
1170 switch (BaseShape.HollowShape)
1171 {
1172 case HollowShape.Square:
1173 case HollowShape.Same:
1174 break;
1175
1176 case HollowShape.Circle:
1177 hollowVolume *= 0.78539816339f;;
1178 break;
1179
1180 case HollowShape.Triangle:
1181 hollowVolume *= 0.5f * 0.5f;
1182 break;
1183 default:
1184 hollowVolume = 0;
1185 break;
1186 }
1187 volume *= (1.0f - hollowVolume);
1188 }
1189 }
1190
1191 break;
1192
1193 case ProfileShape.Circle:
1194
1195 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
1196 {
1197 volume *= 0.78539816339f; // elipse base
1198
1199 if (hollowAmount > 0.0)
1200 {
1201 switch (BaseShape.HollowShape)
1202 {
1203 case HollowShape.Same:
1204 case HollowShape.Circle:
1205 break;
1206
1207 case HollowShape.Square:
1208 hollowVolume *= 0.5f * 2.5984480504799f;
1209 break;
1210
1211 case HollowShape.Triangle:
1212 hollowVolume *= .5f * 1.27323954473516f;
1213 break;
1214
1215 default:
1216 hollowVolume = 0;
1217 break;
1218 }
1219 volume *= (1.0f - hollowVolume);
1220 }
1221 }
1222
1223 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
1224 {
1225 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX);
1226 tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
1227 volume *= (1.0f - tmp * tmp);
1228
1229 if (hollowAmount > 0.0)
1230 {
1231
1232 // calculate the hollow volume by it's shape compared to the prim shape
1233 hollowVolume *= hollowAmount;
1234
1235 switch (BaseShape.HollowShape)
1236 {
1237 case HollowShape.Same:
1238 case HollowShape.Circle:
1239 break;
1240
1241 case HollowShape.Square:
1242 hollowVolume *= 0.5f * 2.5984480504799f;
1243 break;
1244
1245 case HollowShape.Triangle:
1246 hollowVolume *= .5f * 1.27323954473516f;
1247 break;
1248
1249 default:
1250 hollowVolume = 0;
1251 break;
1252 }
1253 volume *= (1.0f - hollowVolume);
1254 }
1255 }
1256 break;
1257
1258 case ProfileShape.HalfCircle:
1259 if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
1260 {
1261 volume *= 0.52359877559829887307710723054658f;
1262 }
1263 break;
1264
1265 case ProfileShape.EquilateralTriangle:
1266
1267 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
1268 {
1269 volume *= 0.32475953f;
1270
1271 if (hollowAmount > 0.0)
1272 {
1273
1274 // calculate the hollow volume by it's shape compared to the prim shape
1275 switch (BaseShape.HollowShape)
1276 {
1277 case HollowShape.Same:
1278 case HollowShape.Triangle:
1279 hollowVolume *= .25f;
1280 break;
1281
1282 case HollowShape.Square:
1283 hollowVolume *= 0.499849f * 3.07920140172638f;
1284 break;
1285
1286 case HollowShape.Circle:
1287 // Hollow shape is a perfect cyllinder in respect to the cube's scale
1288 // Cyllinder hollow volume calculation
1289
1290 hollowVolume *= 0.1963495f * 3.07920140172638f;
1291 break;
1292
1293 default:
1294 hollowVolume = 0;
1295 break;
1296 }
1297 volume *= (1.0f - hollowVolume);
1298 }
1299 }
1300 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
1301 {
1302 volume *= 0.32475953f;
1303 volume *= 0.01f * (float)(200 - BaseShape.PathScaleX);
1304 tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
1305 volume *= (1.0f - tmp * tmp);
1306
1307 if (hollowAmount > 0.0)
1308 {
1309
1310 hollowVolume *= hollowAmount;
1311
1312 switch (BaseShape.HollowShape)
1313 {
1314 case HollowShape.Same:
1315 case HollowShape.Triangle:
1316 hollowVolume *= .25f;
1317 break;
1318
1319 case HollowShape.Square:
1320 hollowVolume *= 0.499849f * 3.07920140172638f;
1321 break;
1322
1323 case HollowShape.Circle:
1324
1325 hollowVolume *= 0.1963495f * 3.07920140172638f;
1326 break;
1327
1328 default:
1329 hollowVolume = 0;
1330 break;
1331 }
1332 volume *= (1.0f - hollowVolume);
1333 }
1334 }
1335 break;
1336
1337 default:
1338 break;
1339 }
1340
1341
1342
1343 float taperX1;
1344 float taperY1;
1345 float taperX;
1346 float taperY;
1347 float pathBegin;
1348 float pathEnd;
1349 float profileBegin;
1350 float profileEnd;
1351
1352 if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible)
1353 {
1354 taperX1 = BaseShape.PathScaleX * 0.01f;
1355 if (taperX1 > 1.0f)
1356 taperX1 = 2.0f - taperX1;
1357 taperX = 1.0f - taperX1;
1358
1359 taperY1 = BaseShape.PathScaleY * 0.01f;
1360 if (taperY1 > 1.0f)
1361 taperY1 = 2.0f - taperY1;
1362 taperY = 1.0f - taperY1;
1363 }
1364 else
1365 {
1366 taperX = BaseShape.PathTaperX * 0.01f;
1367 if (taperX < 0.0f)
1368 taperX = -taperX;
1369 taperX1 = 1.0f - taperX;
1370
1371 taperY = BaseShape.PathTaperY * 0.01f;
1372 if (taperY < 0.0f)
1373 taperY = -taperY;
1374 taperY1 = 1.0f - taperY;
1375
1376 }
1377
1378
1379 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
1380
1381 pathBegin = (float)BaseShape.PathBegin * 2.0e-5f;
1382 pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f;
1383 volume *= (pathEnd - pathBegin);
1384
1385 // this is crude aproximation
1386 profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f;
1387 profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f;
1388 volume *= (profileEnd - profileBegin);
1389
1390 returnMass = _density * volume;
1391
1392 /* Comment out code that computes the mass of the linkset. That is done in the Linkset class.
1393 if (IsRootOfLinkset)
1394 {
1395 foreach (BSPrim prim in _childrenPrims)
1396 {
1397 returnMass += prim.CalculateMass();
1398 }
1399 }
1400 */
1401
1402 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass);
1403
1404 return returnMass;
1405 }// end CalculateMass
1406 #endregion Mass Calculation
1407
1408 // Rebuild the geometry and object.
1409 // This is called when the shape changes so we need to recreate the mesh/hull.
1410 // Called at taint-time!!!
1411 public void CreateGeomAndObject(bool forceRebuild)
1412 {
1413 // If this prim is part of a linkset, we must remove and restore the physical
1414 // links if the body is rebuilt.
1415 bool needToRestoreLinkset = false;
1416 bool needToRestoreVehicle = false;
1417
1418 // Create the correct physical representation for this type of object.
1419 // Updates PhysBody and PhysShape with the new information.
1420 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
1421 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
1422 {
1423 // Called if the current prim body is about to be destroyed.
1424 // Remove all the physical dependencies on the old body.
1425 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
1426 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
1427 needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this);
1428 });
1429
1430 if (needToRestoreLinkset)
1431 {
1432 // If physical body dependencies were removed, restore them
1433 Linkset.RestoreBodyDependencies(this);
1434 }
1435 if (needToRestoreVehicle)
1436 {
1437 // If physical body dependencies were removed, restore them
1438 _vehicle.RestoreBodyDependencies(this);
1439 }
1440
1441 // Make sure the properties are set on the new object
1442 UpdatePhysicalParameters();
1443 return;
1444 }
1445
1446 // The physics engine says that properties have updated. Update same and inform
1447 // the world that things have changed.
1448 // TODO: do we really need to check for changed? Maybe just copy values and call RequestPhysicsterseUpdate()
1449 enum UpdatedProperties {
1450 Position = 1 << 0,
1451 Rotation = 1 << 1,
1452 Velocity = 1 << 2,
1453 Acceleration = 1 << 3,
1454 RotationalVel = 1 << 4
1455 }
1456
1457 const float ROTATION_TOLERANCE = 0.01f;
1458 const float VELOCITY_TOLERANCE = 0.001f;
1459 const float POSITION_TOLERANCE = 0.05f;
1460 const float ACCELERATION_TOLERANCE = 0.01f;
1461 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1462
1463 public override void UpdateProperties(EntityProperties entprop)
1464 {
1465 // Updates only for individual prims and for the root object of a linkset.
1466 if (Linkset.IsRoot(this))
1467 {
1468 // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
1469 // TODO: handle physics introduced by Bullet with computed vehicle physics.
1470 if (_vehicle.IsActive)
1471 {
1472 entprop.RotationalVelocity = OMV.Vector3.Zero;
1473 }
1474
1475 // Assign directly to the local variables so the normal set action does not happen
1476 _position = entprop.Position;
1477 _orientation = entprop.Rotation;
1478 _velocity = entprop.Velocity;
1479 _acceleration = entprop.Acceleration;
1480 _rotationalVelocity = entprop.RotationalVelocity;
1481
1482 // The sanity check can change the velocity and/or position.
1483 if (IsPhysical && PositionSanityCheck(true))
1484 {
1485 entprop.Position = _position;
1486 entprop.Velocity = _velocity;
1487 }
1488
1489 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG
1490 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1491 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
1492
1493 // remember the current and last set values
1494 LastEntityProperties = CurrentEntityProperties;
1495 CurrentEntityProperties = entprop;
1496
1497 base.RequestPhysicsterseUpdate();
1498 }
1499 /*
1500 else
1501 {
1502 // For debugging, report the movement of children
1503 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1504 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1505 entprop.Acceleration, entprop.RotationalVelocity);
1506 }
1507 */
1508
1509 // The linkset implimentation might want to know about this.
1510 Linkset.UpdateProperties(this, true);
1511 }
1512}
1513}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
deleted file mode 100644
index 7017194..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ /dev/null
@@ -1,946 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using System.Runtime.InteropServices;
31using System.Text;
32using System.Threading;
33using OpenSim.Framework;
34using OpenSim.Region.Framework;
35using OpenSim.Region.CoreModules;
36using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging;
37using OpenSim.Region.Physics.Manager;
38using Nini.Config;
39using log4net;
40using OpenMetaverse;
41
42namespace OpenSim.Region.Physics.BulletSPlugin
43{
44public sealed class BSScene : PhysicsScene, IPhysicsParameters
45{
46 internal static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
47 internal static readonly string LogHeader = "[BULLETS SCENE]";
48
49 // The name of the region we're working for.
50 public string RegionName { get; private set; }
51
52 public string BulletSimVersion = "?";
53
54 // The handle to the underlying managed or unmanaged version of Bullet being used.
55 public string BulletEngineName { get; private set; }
56 public BSAPITemplate PE;
57
58 public Dictionary<uint, BSPhysObject> PhysObjects;
59 public BSShapeCollection Shapes;
60
61 // Keeping track of the objects with collisions so we can report begin and end of a collision
62 public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>();
63 public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>();
64 // Keep track of all the avatars so we can send them a collision event
65 // every tick so OpenSim will update its animation.
66 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
67
68 // let my minuions use my logger
69 public ILog Logger { get { return m_log; } }
70
71 public IMesher mesher;
72 public uint WorldID { get; private set; }
73 public BulletWorld World { get; private set; }
74
75 // All the constraints that have been allocated in this instance.
76 public BSConstraintCollection Constraints { get; private set; }
77
78 // Simulation parameters
79 internal int m_maxSubSteps;
80 internal float m_fixedTimeStep;
81 internal long m_simulationStep = 0;
82 internal float NominalFrameRate { get; set; }
83 public long SimulationStep { get { return m_simulationStep; } }
84 internal int m_taintsToProcessPerStep;
85 internal float LastTimeStep { get; private set; }
86
87 // Physical objects can register for prestep or poststep events
88 public delegate void PreStepAction(float timeStep);
89 public delegate void PostStepAction(float timeStep);
90 public event PreStepAction BeforeStep;
91 public event PreStepAction AfterStep;
92
93 // A value of the time now so all the collision and update routines do not have to get their own
94 // Set to 'now' just before all the prims and actors are called for collisions and updates
95 public int SimulationNowTime { get; private set; }
96
97 // True if initialized and ready to do simulation steps
98 private bool m_initialized = false;
99
100 // Flag which is true when processing taints.
101 // Not guaranteed to be correct all the time (don't depend on this) but good for debugging.
102 public bool InTaintTime { get; private set; }
103
104 // Pinned memory used to pass step information between managed and unmanaged
105 internal int m_maxCollisionsPerFrame;
106 internal CollisionDesc[] m_collisionArray;
107
108 internal int m_maxUpdatesPerFrame;
109 internal EntityProperties[] m_updateArray;
110
111 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
112 public const uint GROUNDPLANE_ID = 1;
113 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
114
115 public float SimpleWaterLevel { get; set; }
116 public BSTerrainManager TerrainManager { get; private set; }
117
118 public ConfigurationParameters Params
119 {
120 get { return UnmanagedParams[0]; }
121 }
122 public Vector3 DefaultGravity
123 {
124 get { return new Vector3(0f, 0f, Params.gravity); }
125 }
126 // Just the Z value of the gravity
127 public float DefaultGravityZ
128 {
129 get { return Params.gravity; }
130 }
131
132 // When functions in the unmanaged code must be called, it is only
133 // done at a known time just before the simulation step. The taint
134 // system saves all these function calls and executes them in
135 // order before the simulation.
136 public delegate void TaintCallback();
137 private struct TaintCallbackEntry
138 {
139 public String ident;
140 public TaintCallback callback;
141 public TaintCallbackEntry(string i, TaintCallback c)
142 {
143 ident = i;
144 callback = c;
145 }
146 }
147 private Object _taintLock = new Object(); // lock for using the next object
148 private List<TaintCallbackEntry> _taintOperations;
149 private Dictionary<string, TaintCallbackEntry> _postTaintOperations;
150 private List<TaintCallbackEntry> _postStepOperations;
151
152 // A pointer to an instance if this structure is passed to the C++ code
153 // Used to pass basic configuration values to the unmanaged code.
154 internal ConfigurationParameters[] UnmanagedParams;
155
156 // Sometimes you just have to log everything.
157 public Logging.LogWriter PhysicsLogging;
158 private bool m_physicsLoggingEnabled;
159 private string m_physicsLoggingDir;
160 private string m_physicsLoggingPrefix;
161 private int m_physicsLoggingFileMinutes;
162 private bool m_physicsLoggingDoFlush;
163 private bool m_physicsPhysicalDumpEnabled;
164 public float PhysicsMetricDumpFrames { get; set; }
165 // 'true' of the vehicle code is to log lots of details
166 public bool VehicleLoggingEnabled { get; private set; }
167 public bool VehiclePhysicalLoggingEnabled { get; private set; }
168
169 #region Construction and Initialization
170 public BSScene(string identifier)
171 {
172 m_initialized = false;
173 // we are passed the name of the region we're working for.
174 RegionName = identifier;
175 }
176
177 public override void Initialise(IMesher meshmerizer, IConfigSource config)
178 {
179 mesher = meshmerizer;
180 _taintOperations = new List<TaintCallbackEntry>();
181 _postTaintOperations = new Dictionary<string, TaintCallbackEntry>();
182 _postStepOperations = new List<TaintCallbackEntry>();
183 PhysObjects = new Dictionary<uint, BSPhysObject>();
184 Shapes = new BSShapeCollection(this);
185
186 // Allocate pinned memory to pass parameters.
187 UnmanagedParams = new ConfigurationParameters[1];
188
189 // Set default values for physics parameters plus any overrides from the ini file
190 GetInitialParameterValues(config);
191
192 // Get the connection to the physics engine (could be native or one of many DLLs)
193 PE = SelectUnderlyingBulletEngine(BulletEngineName);
194
195 // Enable very detailed logging.
196 // By creating an empty logger when not logging, the log message invocation code
197 // can be left in and every call doesn't have to check for null.
198 if (m_physicsLoggingEnabled)
199 {
200 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
201 PhysicsLogging.ErrorLogger = m_log; // for DEBUG. Let's the logger output error messages.
202 }
203 else
204 {
205 PhysicsLogging = new Logging.LogWriter();
206 }
207
208 // Allocate memory for returning of the updates and collisions from the physics engine
209 m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame];
210 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
211
212 // The bounding box for the simulated world. The origin is 0,0,0 unless we're
213 // a child in a mega-region.
214 // Bullet actually doesn't care about the extents of the simulated
215 // area. It tracks active objects no matter where they are.
216 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
217
218 World = PE.Initialize(worldExtent, Params, m_maxCollisionsPerFrame, ref m_collisionArray, m_maxUpdatesPerFrame, ref m_updateArray);
219
220 Constraints = new BSConstraintCollection(World);
221
222 TerrainManager = new BSTerrainManager(this);
223 TerrainManager.CreateInitialGroundPlaneAndTerrain();
224
225 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation);
226
227 InTaintTime = false;
228 m_initialized = true;
229 }
230
231 // All default parameter values are set here. There should be no values set in the
232 // variable definitions.
233 private void GetInitialParameterValues(IConfigSource config)
234 {
235 ConfigurationParameters parms = new ConfigurationParameters();
236 UnmanagedParams[0] = parms;
237
238 BSParam.SetParameterDefaultValues(this);
239
240 if (config != null)
241 {
242 // If there are specifications in the ini file, use those values
243 IConfig pConfig = config.Configs["BulletSim"];
244 if (pConfig != null)
245 {
246 BSParam.SetParameterConfigurationValues(this, pConfig);
247
248 // There are two Bullet implementations to choose from
249 BulletEngineName = pConfig.GetString("BulletEngine", "BulletUnmanaged");
250
251 // Very detailed logging for physics debugging
252 // TODO: the boolean values can be moved to the normal parameter processing.
253 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
254 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
255 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
256 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
257 m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
258 m_physicsPhysicalDumpEnabled = pConfig.GetBoolean("PhysicsPhysicalDumpEnabled", false);
259 // Very detailed logging for vehicle debugging
260 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
261 VehiclePhysicalLoggingEnabled = pConfig.GetBoolean("VehiclePhysicalLoggingEnabled", false);
262
263 // Do any replacements in the parameters
264 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
265 }
266
267 // The material characteristics.
268 BSMaterials.InitializeFromDefaults(Params);
269 if (pConfig != null)
270 {
271 // Let the user add new and interesting material property values.
272 BSMaterials.InitializefromParameters(pConfig);
273 }
274 }
275 }
276
277 // A helper function that handles a true/false parameter and returns the proper float number encoding
278 float ParamBoolean(IConfig config, string parmName, float deflt)
279 {
280 float ret = deflt;
281 if (config.Contains(parmName))
282 {
283 ret = ConfigurationParameters.numericFalse;
284 if (config.GetBoolean(parmName, false))
285 {
286 ret = ConfigurationParameters.numericTrue;
287 }
288 }
289 return ret;
290 }
291
292 // Select the connection to the actual Bullet implementation.
293 // The main engine selection is the engineName up to the first hypen.
294 // So "Bullet-2.80-OpenCL-Intel" specifies the 'bullet' class here and the whole name
295 // is passed to the engine to do its special selection, etc.
296 private BSAPITemplate SelectUnderlyingBulletEngine(string engineName)
297 {
298 // For the moment, do a simple switch statement.
299 // Someday do fancyness with looking up the interfaces in the assembly.
300 BSAPITemplate ret = null;
301
302 string selectionName = engineName.ToLower();
303 int hyphenIndex = engineName.IndexOf("-");
304 if (hyphenIndex > 0)
305 selectionName = engineName.ToLower().Substring(0, hyphenIndex - 1);
306
307 switch (selectionName)
308 {
309 case "bulletunmanaged":
310 ret = new BSAPIUnman(engineName, this);
311 break;
312 case "bulletxna":
313 ret = new BSAPIXNA(engineName, this);
314 break;
315 }
316
317 if (ret == null)
318 {
319 m_log.ErrorFormat("{0) COULD NOT SELECT BULLET ENGINE: '[BulletSim]PhysicsEngine' must be either 'BulletUnmanaged-*' or 'BulletXNA-*'", LogHeader);
320 }
321 else
322 {
323 m_log.WarnFormat("{0} Selected bullet engine {1} -> {2}/{3}", LogHeader, engineName, ret.BulletEngineName, ret.BulletEngineVersion);
324 }
325
326 return ret;
327 }
328
329 public override void Dispose()
330 {
331 // m_log.DebugFormat("{0}: Dispose()", LogHeader);
332
333 // make sure no stepping happens while we're deleting stuff
334 m_initialized = false;
335
336 foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
337 {
338 kvp.Value.Destroy();
339 }
340 PhysObjects.Clear();
341
342 // Now that the prims are all cleaned up, there should be no constraints left
343 if (Constraints != null)
344 {
345 Constraints.Dispose();
346 Constraints = null;
347 }
348
349 if (Shapes != null)
350 {
351 Shapes.Dispose();
352 Shapes = null;
353 }
354
355 if (TerrainManager != null)
356 {
357 TerrainManager.ReleaseGroundPlaneAndTerrain();
358 TerrainManager.Dispose();
359 TerrainManager = null;
360 }
361
362 // Anything left in the unmanaged code should be cleaned out
363 PE.Shutdown(World);
364
365 // Not logging any more
366 PhysicsLogging.Close();
367 }
368 #endregion // Construction and Initialization
369
370 #region Prim and Avatar addition and removal
371
372 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
373 {
374 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
375 return null;
376 }
377
378 public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying)
379 {
380 // m_log.DebugFormat("{0}: AddAvatar: {1}", LogHeader, avName);
381
382 if (!m_initialized) return null;
383
384 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
385 lock (PhysObjects) PhysObjects.Add(localID, actor);
386
387 // TODO: Remove kludge someday.
388 // We must generate a collision for avatars whether they collide or not.
389 // This is required by OpenSim to update avatar animations, etc.
390 lock (m_avatars) m_avatars.Add(actor);
391
392 return actor;
393 }
394
395 public override void RemoveAvatar(PhysicsActor actor)
396 {
397 // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader);
398
399 if (!m_initialized) return;
400
401 BSCharacter bsactor = actor as BSCharacter;
402 if (bsactor != null)
403 {
404 try
405 {
406 lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
407 // Remove kludge someday
408 lock (m_avatars) m_avatars.Remove(bsactor);
409 }
410 catch (Exception e)
411 {
412 m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e);
413 }
414 bsactor.Destroy();
415 // bsactor.dispose();
416 }
417 }
418
419 public override void RemovePrim(PhysicsActor prim)
420 {
421 if (!m_initialized) return;
422
423 BSPrim bsprim = prim as BSPrim;
424 if (bsprim != null)
425 {
426 DetailLog("{0},RemovePrim,call", bsprim.LocalID);
427 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
428 try
429 {
430 lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID);
431 }
432 catch (Exception e)
433 {
434 m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e);
435 }
436 bsprim.Destroy();
437 // bsprim.dispose();
438 }
439 else
440 {
441 m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader);
442 }
443 }
444
445 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
446 Vector3 size, Quaternion rotation, bool isPhysical, uint localID)
447 {
448 // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName);
449
450 if (!m_initialized) return null;
451
452 DetailLog("{0},AddPrimShape,call", localID);
453
454 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
455 lock (PhysObjects) PhysObjects.Add(localID, prim);
456 return prim;
457 }
458
459 // This is a call from the simulator saying that some physical property has been updated.
460 // The BulletSim driver senses the changing of relevant properties so this taint
461 // information call is not needed.
462 public override void AddPhysicsActorTaint(PhysicsActor prim) { }
463
464 #endregion // Prim and Avatar addition and removal
465
466 #region Simulation
467 // Simulate one timestep
468 public override float Simulate(float timeStep)
469 {
470 // prevent simulation until we've been initialized
471 if (!m_initialized) return 5.0f;
472
473 LastTimeStep = timeStep;
474
475 int updatedEntityCount = 0;
476 int collidersCount = 0;
477
478 int beforeTime = 0;
479 int simTime = 0;
480
481 // update the prim states while we know the physics engine is not busy
482 int numTaints = _taintOperations.Count;
483
484 InTaintTime = true; // Only used for debugging so locking is not necessary.
485
486 ProcessTaints();
487
488 // Some of the physical objects requre individual, pre-step calls
489 TriggerPreStepEvent(timeStep);
490
491 // the prestep actions might have added taints
492 numTaints += _taintOperations.Count;
493 ProcessTaints();
494
495 InTaintTime = false; // Only used for debugging so locking is not necessary.
496
497 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
498 // Only enable this in a limited test world with few objects.
499 if (m_physicsPhysicalDumpEnabled)
500 PE.DumpAllInfo(World);
501
502 // step the physical world one interval
503 m_simulationStep++;
504 int numSubSteps = 0;
505 try
506 {
507 if (PhysicsLogging.Enabled)
508 beforeTime = Util.EnvironmentTickCount();
509
510 numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);
511
512 if (PhysicsLogging.Enabled)
513 {
514 simTime = Util.EnvironmentTickCountSubtract(beforeTime);
515 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
516 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
517 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
518 }
519 }
520 catch (Exception e)
521 {
522 m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
523 LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
524 DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
525 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
526 updatedEntityCount = 0;
527 collidersCount = 0;
528 }
529
530 if ((m_simulationStep % PhysicsMetricDumpFrames) == 0)
531 PE.DumpPhysicsStatistics(World);
532
533 // Get a value for 'now' so all the collision and update routines don't have to get their own.
534 SimulationNowTime = Util.EnvironmentTickCount();
535
536 // If there were collisions, process them by sending the event to the prim.
537 // Collisions must be processed before updates.
538 if (collidersCount > 0)
539 {
540 for (int ii = 0; ii < collidersCount; ii++)
541 {
542 uint cA = m_collisionArray[ii].aID;
543 uint cB = m_collisionArray[ii].bID;
544 Vector3 point = m_collisionArray[ii].point;
545 Vector3 normal = m_collisionArray[ii].normal;
546 SendCollision(cA, cB, point, normal, 0.01f);
547 SendCollision(cB, cA, point, -normal, 0.01f);
548 }
549 }
550
551 // The above SendCollision's batch up the collisions on the objects.
552 // Now push the collisions into the simulator.
553 if (ObjectsWithCollisions.Count > 0)
554 {
555 foreach (BSPhysObject bsp in ObjectsWithCollisions)
556 if (!bsp.SendCollisions())
557 {
558 // If the object is done colliding, see that it's removed from the colliding list
559 ObjectsWithNoMoreCollisions.Add(bsp);
560 }
561 }
562
563 // This is a kludge to get avatar movement updates.
564 // The simulator expects collisions for avatars even if there are have been no collisions.
565 // The event updates avatar animations and stuff.
566 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
567 foreach (BSPhysObject bsp in m_avatars)
568 if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
569 bsp.SendCollisions();
570
571 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
572 // Not done above because it is inside an iteration of ObjectWithCollisions.
573 // This complex collision processing is required to create an empty collision
574 // event call after all real collisions have happened on an object. This enables
575 // the simulator to generate the 'collision end' event.
576 if (ObjectsWithNoMoreCollisions.Count > 0)
577 {
578 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
579 ObjectsWithCollisions.Remove(po);
580 ObjectsWithNoMoreCollisions.Clear();
581 }
582 // Done with collisions.
583
584 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
585 if (updatedEntityCount > 0)
586 {
587 for (int ii = 0; ii < updatedEntityCount; ii++)
588 {
589 EntityProperties entprop = m_updateArray[ii];
590 BSPhysObject pobj;
591 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
592 {
593 pobj.UpdateProperties(entprop);
594 }
595 }
596 }
597
598 TriggerPostStepEvent(timeStep);
599
600 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
601 // Only enable this in a limited test world with few objects.
602 if (m_physicsPhysicalDumpEnabled)
603 PE.DumpAllInfo(World);
604
605 // The physics engine returns the number of milliseconds it simulated this call.
606 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
607 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55).
608 return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
609 }
610
611 // Something has collided
612 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration)
613 {
614 if (localID <= TerrainManager.HighestTerrainID)
615 {
616 return; // don't send collisions to the terrain
617 }
618
619 BSPhysObject collider;
620 if (!PhysObjects.TryGetValue(localID, out collider))
621 {
622 // If the object that is colliding cannot be found, just ignore the collision.
623 DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith);
624 return;
625 }
626
627 // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called.
628 BSPhysObject collidee = null;
629 PhysObjects.TryGetValue(collidingWith, out collidee);
630
631 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
632
633 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
634 {
635 // If a collision was posted, remember to send it to the simulator
636 ObjectsWithCollisions.Add(collider);
637 }
638
639 return;
640 }
641
642 #endregion // Simulation
643
644 public override void GetResults() { }
645
646 #region Terrain
647
648 public override void SetTerrain(float[] heightMap) {
649 TerrainManager.SetTerrain(heightMap);
650 }
651
652 public override void SetWaterLevel(float baseheight)
653 {
654 SimpleWaterLevel = baseheight;
655 }
656
657 public override void DeleteTerrain()
658 {
659 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
660 }
661
662 // Although no one seems to check this, I do support combining.
663 public override bool SupportsCombining()
664 {
665 return TerrainManager.SupportsCombining();
666 }
667 // This call says I am a child to region zero in a mega-region. 'pScene' is that
668 // of region zero, 'offset' is my offset from regions zero's origin, and
669 // 'extents' is the largest XY that is handled in my region.
670 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
671 {
672 TerrainManager.Combine(pScene, offset, extents);
673 }
674
675 // Unhook all the combining that I know about.
676 public override void UnCombine(PhysicsScene pScene)
677 {
678 TerrainManager.UnCombine(pScene);
679 }
680
681 #endregion // Terrain
682
683 public override Dictionary<uint, float> GetTopColliders()
684 {
685 return new Dictionary<uint, float>();
686 }
687
688 public override bool IsThreaded { get { return false; } }
689
690 #region Taints
691 // The simulation execution order is:
692 // Simulate()
693 // DoOneTimeTaints
694 // TriggerPreStepEvent
695 // DoOneTimeTaints
696 // Step()
697 // ProcessAndForwardCollisions
698 // ProcessAndForwardPropertyUpdates
699 // TriggerPostStepEvent
700
701 // Calls to the PhysicsActors can't directly call into the physics engine
702 // because it might be busy. We delay changes to a known time.
703 // We rely on C#'s closure to save and restore the context for the delegate.
704 public void TaintedObject(String ident, TaintCallback callback)
705 {
706 if (!m_initialized) return;
707
708 lock (_taintLock)
709 {
710 _taintOperations.Add(new TaintCallbackEntry(ident, callback));
711 }
712
713 return;
714 }
715
716 // Sometimes a potentially tainted operation can be used in and out of taint time.
717 // This routine executes the command immediately if in taint-time otherwise it is queued.
718 public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback)
719 {
720 if (inTaintTime)
721 callback();
722 else
723 TaintedObject(ident, callback);
724 }
725
726 private void TriggerPreStepEvent(float timeStep)
727 {
728 PreStepAction actions = BeforeStep;
729 if (actions != null)
730 actions(timeStep);
731
732 }
733
734 private void TriggerPostStepEvent(float timeStep)
735 {
736 PreStepAction actions = AfterStep;
737 if (actions != null)
738 actions(timeStep);
739
740 }
741
742 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues
743 // a callback into itself to do the actual property change. That callback is called
744 // here just before the physics engine is called to step the simulation.
745 public void ProcessTaints()
746 {
747 ProcessRegularTaints();
748 ProcessPostTaintTaints();
749 }
750
751 private void ProcessRegularTaints()
752 {
753 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process
754 {
755 // swizzle a new list into the list location so we can process what's there
756 List<TaintCallbackEntry> oldList;
757 lock (_taintLock)
758 {
759 oldList = _taintOperations;
760 _taintOperations = new List<TaintCallbackEntry>();
761 }
762
763 foreach (TaintCallbackEntry tcbe in oldList)
764 {
765 try
766 {
767 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
768 tcbe.callback();
769 }
770 catch (Exception e)
771 {
772 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
773 }
774 }
775 oldList.Clear();
776 }
777 }
778
779 // Schedule an update to happen after all the regular taints are processed.
780 // Note that new requests for the same operation ("ident") for the same object ("ID")
781 // will replace any previous operation by the same object.
782 public void PostTaintObject(String ident, uint ID, TaintCallback callback)
783 {
784 string uniqueIdent = ident + "-" + ID.ToString();
785 lock (_taintLock)
786 {
787 _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback);
788 }
789
790 return;
791 }
792
793 // Taints that happen after the normal taint processing but before the simulation step.
794 private void ProcessPostTaintTaints()
795 {
796 if (_postTaintOperations.Count > 0)
797 {
798 Dictionary<string, TaintCallbackEntry> oldList;
799 lock (_taintLock)
800 {
801 oldList = _postTaintOperations;
802 _postTaintOperations = new Dictionary<string, TaintCallbackEntry>();
803 }
804
805 foreach (KeyValuePair<string,TaintCallbackEntry> kvp in oldList)
806 {
807 try
808 {
809 DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG
810 kvp.Value.callback();
811 }
812 catch (Exception e)
813 {
814 m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e);
815 }
816 }
817 oldList.Clear();
818 }
819 }
820
821 // Only used for debugging. Does not change state of anything so locking is not necessary.
822 public bool AssertInTaintTime(string whereFrom)
823 {
824 if (!InTaintTime)
825 {
826 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
827 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
828 Util.PrintCallStack(DetailLog);
829 }
830 return InTaintTime;
831 }
832
833 #endregion // Taints
834
835 #region INI and command line parameter processing
836
837 #region IPhysicsParameters
838 // Get the list of parameters this physics engine supports
839 public PhysParameterEntry[] GetParameterList()
840 {
841 BSParam.BuildParameterTable();
842 return BSParam.SettableParameters;
843 }
844
845 // Set parameter on a specific or all instances.
846 // Return 'false' if not able to set the parameter.
847 // Setting the value in the m_params block will change the value the physics engine
848 // will use the next time since it's pinned and shared memory.
849 // Some of the values require calling into the physics engine to get the new
850 // value activated ('terrainFriction' for instance).
851 public bool SetPhysicsParameter(string parm, float val, uint localID)
852 {
853 bool ret = false;
854 BSParam.ParameterDefn theParam;
855 if (BSParam.TryGetParameter(parm, out theParam))
856 {
857 theParam.setter(this, parm, localID, val);
858 ret = true;
859 }
860 return ret;
861 }
862
863 // update all the localIDs specified
864 // If the local ID is APPLY_TO_NONE, just change the default value
865 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
866 // If the localID is a specific object, apply the parameter change to only that object
867 internal delegate void AssignVal(float x);
868 internal void UpdateParameterObject(AssignVal setDefault, string parm, uint localID, float val)
869 {
870 List<uint> objectIDs = new List<uint>();
871 switch (localID)
872 {
873 case PhysParameterEntry.APPLY_TO_NONE:
874 setDefault(val); // setting only the default value
875 // This will cause a call into the physical world if some operation is specified (SetOnObject).
876 objectIDs.Add(TERRAIN_ID);
877 TaintedUpdateParameter(parm, objectIDs, val);
878 break;
879 case PhysParameterEntry.APPLY_TO_ALL:
880 setDefault(val); // setting ALL also sets the default value
881 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
882 TaintedUpdateParameter(parm, objectIDs, val);
883 break;
884 default:
885 // setting only one localID
886 objectIDs.Add(localID);
887 TaintedUpdateParameter(parm, objectIDs, val);
888 break;
889 }
890 }
891
892 // schedule the actual updating of the paramter to when the phys engine is not busy
893 private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val)
894 {
895 float xval = val;
896 List<uint> xlIDs = lIDs;
897 string xparm = parm;
898 TaintedObject("BSScene.UpdateParameterSet", delegate() {
899 BSParam.ParameterDefn thisParam;
900 if (BSParam.TryGetParameter(xparm, out thisParam))
901 {
902 if (thisParam.onObject != null)
903 {
904 foreach (uint lID in xlIDs)
905 {
906 BSPhysObject theObject = null;
907 PhysObjects.TryGetValue(lID, out theObject);
908 thisParam.onObject(this, theObject, xval);
909 }
910 }
911 }
912 });
913 }
914
915 // Get parameter.
916 // Return 'false' if not able to get the parameter.
917 public bool GetPhysicsParameter(string parm, out float value)
918 {
919 float val = 0f;
920 bool ret = false;
921 BSParam.ParameterDefn theParam;
922 if (BSParam.TryGetParameter(parm, out theParam))
923 {
924 val = theParam.getter(this);
925 ret = true;
926 }
927 value = val;
928 return ret;
929 }
930
931 #endregion IPhysicsParameters
932
933 #endregion Runtime settable parameters
934
935 // Invoke the detailed logger and output something if it's enabled.
936 public void DetailLog(string msg, params Object[] args)
937 {
938 PhysicsLogging.Write(msg, args);
939 // Add the Flush() if debugging crashes. Gets all the messages written out.
940 if (m_physicsLoggingDoFlush) PhysicsLogging.Flush();
941 }
942 // Used to fill in the LocalID when there isn't one. It's the correct number of characters.
943 public const string DetailLogZero = "0000000000";
944
945}
946}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
deleted file mode 100755
index d361f18..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ /dev/null
@@ -1,1009 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OMV = OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Physics.Manager;
33using OpenSim.Region.Physics.ConvexDecompositionDotNet;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37public sealed class BSShapeCollection : IDisposable
38{
39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
40
41 private BSScene PhysicsScene { get; set; }
42
43 private Object m_collectionActivityLock = new Object();
44
45 // Description of a Mesh
46 private struct MeshDesc
47 {
48 public BulletShape shape;
49 public int referenceCount;
50 public DateTime lastReferenced;
51 public UInt64 shapeKey;
52 }
53
54 // Description of a hull.
55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
56 private struct HullDesc
57 {
58 public BulletShape shape;
59 public int referenceCount;
60 public DateTime lastReferenced;
61 public UInt64 shapeKey;
62 }
63
64 // The sharable set of meshes and hulls. Indexed by their shape hash.
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67
68 private bool DDetail = false;
69
70 public BSShapeCollection(BSScene physScene)
71 {
72 PhysicsScene = physScene;
73 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
74 // While detailed debugging is still active, this is better than commenting out all the
75 // DetailLog statements. When debugging slows down, this and the protected logging
76 // statements can be commented/removed.
77 DDetail = true;
78 }
79
80 public void Dispose()
81 {
82 // TODO!!!!!!!!!
83 }
84
85 // Callbacks called just before either the body or shape is destroyed.
86 // Mostly used for changing bodies out from under Linksets.
87 // Useful for other cases where parameters need saving.
88 // Passing 'null' says no callback.
89 public delegate void ShapeDestructionCallback(BulletShape shape);
90 public delegate void BodyDestructionCallback(BulletBody body);
91
92 // Called to update/change the body and shape for an object.
93 // First checks the shape and updates that if necessary then makes
94 // sure the body is of the right type.
95 // Return 'true' if either the body or the shape changed.
96 // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before
97 // the current shape or body is destroyed. This allows the caller to remove any
98 // higher level dependencies on the shape or body. Mostly used for LinkSets to
99 // remove the physical constraints before the body is destroyed.
100 // Called at taint-time!!
101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim,
102 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
103 {
104 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
105
106 bool ret = false;
107
108 // This lock could probably be pushed down lower but building shouldn't take long
109 lock (m_collectionActivityLock)
110 {
111 // Do we have the correct geometry for this type of object?
112 // Updates prim.BSShape with information/pointers to shape.
113 // Returns 'true' of BSShape is changed to a new shape.
114 bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback);
115 // If we had to select a new shape geometry for the object,
116 // rebuild the body around it.
117 // Updates prim.BSBody with information/pointers to requested body
118 // Returns 'true' if BSBody was changed.
119 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World,
120 prim.PhysShape, bodyCallback);
121 ret = newGeom || newBody;
122 }
123 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
124 prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape);
125
126 return ret;
127 }
128
129 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
130 {
131 return GetBodyAndShape(forceRebuild, sim, prim, null, null);
132 }
133
134 // Track another user of a body.
135 // We presume the caller has allocated the body.
136 // Bodies only have one user so the body is just put into the world if not already there.
137 public void ReferenceBody(BulletBody body, bool inTaintTime)
138 {
139 lock (m_collectionActivityLock)
140 {
141 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
142 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate()
143 {
144 if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
145 {
146 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body);
147 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
148 }
149 });
150 }
151 }
152
153 // Release the usage of a body.
154 // Called when releasing use of a BSBody. BSShape is handled separately.
155 public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback )
156 {
157 if (!body.HasPhysicalBody)
158 return;
159
160 lock (m_collectionActivityLock)
161 {
162 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate()
163 {
164 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}",
165 body.ID, body, inTaintTime);
166 // If the caller needs to know the old body is going away, pass the event up.
167 if (bodyCallback != null) bodyCallback(body);
168
169 if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
170 {
171 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
172 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
173 }
174
175 // Zero any reference to the shape so it is not freed when the body is deleted.
176 PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
177 PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
178 });
179 }
180 }
181
182 // Track the datastructures and use count for a shape.
183 // When creating a hull, this is called first to reference the mesh
184 // and then again to reference the hull.
185 // Meshes and hulls for the same shape have the same hash key.
186 // NOTE that native shapes are not added to the mesh list or removed.
187 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
188 public bool ReferenceShape(BulletShape shape)
189 {
190 bool ret = false;
191 switch (shape.type)
192 {
193 case BSPhysicsShapeType.SHAPE_MESH:
194 MeshDesc meshDesc;
195 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
196 {
197 // There is an existing instance of this mesh.
198 meshDesc.referenceCount++;
199 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
200 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
201 }
202 else
203 {
204 // This is a new reference to a mesh
205 meshDesc.shape = shape.Clone();
206 meshDesc.shapeKey = shape.shapeKey;
207 // We keep a reference to the underlying IMesh data so a hull can be built
208 meshDesc.referenceCount = 1;
209 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
210 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
211 ret = true;
212 }
213 meshDesc.lastReferenced = System.DateTime.Now;
214 Meshes[shape.shapeKey] = meshDesc;
215 break;
216 case BSPhysicsShapeType.SHAPE_HULL:
217 HullDesc hullDesc;
218 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
219 {
220 // There is an existing instance of this hull.
221 hullDesc.referenceCount++;
222 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
223 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
224 }
225 else
226 {
227 // This is a new reference to a hull
228 hullDesc.shape = shape.Clone();
229 hullDesc.shapeKey = shape.shapeKey;
230 hullDesc.referenceCount = 1;
231 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
232 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
233 ret = true;
234
235 }
236 hullDesc.lastReferenced = System.DateTime.Now;
237 Hulls[shape.shapeKey] = hullDesc;
238 break;
239 case BSPhysicsShapeType.SHAPE_UNKNOWN:
240 break;
241 default:
242 // Native shapes are not tracked and they don't go into any list
243 break;
244 }
245 return ret;
246 }
247
248 // Release the usage of a shape.
249 public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
250 {
251 if (!shape.HasPhysicalShape)
252 return;
253
254 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
255 {
256 if (shape.HasPhysicalShape)
257 {
258 if (shape.isNativeShape)
259 {
260 // Native shapes are not tracked and are released immediately
261 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
262 BSScene.DetailLogZero, shape.AddrString, inTaintTime);
263 if (shapeCallback != null) shapeCallback(shape);
264 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
265 }
266 else
267 {
268 switch (shape.type)
269 {
270 case BSPhysicsShapeType.SHAPE_HULL:
271 DereferenceHull(shape, shapeCallback);
272 break;
273 case BSPhysicsShapeType.SHAPE_MESH:
274 DereferenceMesh(shape, shapeCallback);
275 break;
276 case BSPhysicsShapeType.SHAPE_COMPOUND:
277 DereferenceCompound(shape, shapeCallback);
278 break;
279 case BSPhysicsShapeType.SHAPE_UNKNOWN:
280 break;
281 default:
282 break;
283 }
284 }
285 }
286 });
287 }
288
289 // Count down the reference count for a mesh shape
290 // Called at taint-time.
291 private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback)
292 {
293 MeshDesc meshDesc;
294 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
295 {
296 meshDesc.referenceCount--;
297 // TODO: release the Bullet storage
298 if (shapeCallback != null) shapeCallback(shape);
299 meshDesc.lastReferenced = System.DateTime.Now;
300 Meshes[shape.shapeKey] = meshDesc;
301 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
302 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
303
304 }
305 }
306
307 // Count down the reference count for a hull shape
308 // Called at taint-time.
309 private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
310 {
311 HullDesc hullDesc;
312 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
313 {
314 hullDesc.referenceCount--;
315 // TODO: release the Bullet storage (aging old entries?)
316
317 // Tell upper layers that, if they have dependencies on this shape, this link is going away
318 if (shapeCallback != null) shapeCallback(shape);
319
320 hullDesc.lastReferenced = System.DateTime.Now;
321 Hulls[shape.shapeKey] = hullDesc;
322 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
323 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
324 }
325 }
326
327 // Remove a reference to a compound shape.
328 // Taking a compound shape apart is a little tricky because if you just delete the
329 // physical shape, it will free all the underlying children. We can't do that because
330 // they could be shared. So, this removes each of the children from the compound and
331 // dereferences them separately before destroying the compound collision object itself.
332 // Called at taint-time.
333 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
334 {
335 if (!PhysicsScene.PE.IsCompound(shape))
336 {
337 // Failed the sanity check!!
338 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
339 LogHeader, shape.type, shape.AddrString);
340 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
341 BSScene.DetailLogZero, shape.type, shape.AddrString);
342 return;
343 }
344
345 int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape);
346 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
347
348 for (int ii = numChildren - 1; ii >= 0; ii--)
349 {
350 BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii);
351 DereferenceAnonCollisionShape(childShape);
352 }
353 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
354 }
355
356 // Sometimes we have a pointer to a collision shape but don't know what type it is.
357 // Figure out type and call the correct dereference routine.
358 // Called at taint-time.
359 private void DereferenceAnonCollisionShape(BulletShape shapeInfo)
360 {
361 MeshDesc meshDesc;
362 HullDesc hullDesc;
363
364 if (TryGetMeshByPtr(shapeInfo, out meshDesc))
365 {
366 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
367 shapeInfo.shapeKey = meshDesc.shapeKey;
368 }
369 else
370 {
371 if (TryGetHullByPtr(shapeInfo, out hullDesc))
372 {
373 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
374 shapeInfo.shapeKey = hullDesc.shapeKey;
375 }
376 else
377 {
378 if (PhysicsScene.PE.IsCompound(shapeInfo))
379 {
380 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
381 }
382 else
383 {
384 if (PhysicsScene.PE.IsNativeShape(shapeInfo))
385 {
386 shapeInfo.isNativeShape = true;
387 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
388 }
389 }
390 }
391 }
392
393 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
394
395 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
396 {
397 DereferenceShape(shapeInfo, true, null);
398 }
399 else
400 {
401 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}",
402 LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString);
403 }
404 }
405
406 // Create the geometry information in Bullet for later use.
407 // The objects needs a hull if it's physical otherwise a mesh is enough.
408 // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls,
409 // shared geometries will be used. If the parameters of the existing shape are the same
410 // as this request, the shape is not rebuilt.
411 // Info in prim.BSShape is updated to the new shape.
412 // Returns 'true' if the geometry was rebuilt.
413 // Called at taint-time!
414 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
415 {
416 bool ret = false;
417 bool haveShape = false;
418
419 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
420 {
421 // an avatar capsule is close to a native shape (it is not shared)
422 GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback);
423 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
424 ret = true;
425 haveShape = true;
426 }
427
428 // Compound shapes are handled special as they are rebuilt from scratch.
429 // This isn't too great a hardship since most of the child shapes will have already been created.
430 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
431 {
432 ret = GetReferenceToCompoundShape(prim, shapeCallback);
433 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
434 haveShape = true;
435 }
436
437 if (!haveShape)
438 {
439 ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback);
440 }
441
442 return ret;
443 }
444
445 // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'.
446 public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
447 {
448 bool ret = false;
449 bool haveShape = false;
450 bool nativeShapePossible = true;
451 PrimitiveBaseShape pbs = prim.BaseShape;
452
453 // If the prim attributes are simple, this could be a simple Bullet native shape
454 if (!haveShape
455 && pbs != null
456 && nativeShapePossible
457 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim)
458 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
459 && pbs.ProfileHollow == 0
460 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
461 && pbs.PathBegin == 0 && pbs.PathEnd == 0
462 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
463 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
464 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
465 {
466 // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
467 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
468 if (prim.PhysShape.HasPhysicalShape)
469 scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape);
470
471 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
472 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type);
473
474 // It doesn't look like Bullet scales spheres so make sure the scales are all equal
475 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
476 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
477 {
478 haveShape = true;
479 if (forceRebuild
480 || prim.Scale != scaleOfExistingShape
481 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
482 )
483 {
484 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
485 FixedShapeKey.KEY_SPHERE, shapeCallback);
486 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
487 prim.LocalID, forceRebuild, prim.PhysShape);
488 }
489 }
490 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
491 {
492 haveShape = true;
493 if (forceRebuild
494 || prim.Scale != scaleOfExistingShape
495 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
496 )
497 {
498 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
499 FixedShapeKey.KEY_BOX, shapeCallback);
500 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
501 prim.LocalID, forceRebuild, prim.PhysShape);
502 }
503 }
504 }
505
506 // If a simple shape is not happening, create a mesh and possibly a hull.
507 if (!haveShape && pbs != null)
508 {
509 ret = CreateGeomMeshOrHull(prim, shapeCallback);
510 }
511
512 return ret;
513 }
514
515 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
516 {
517
518 bool ret = false;
519 // Note that if it's a native shape, the check for physical/non-physical is not
520 // made. Native shapes work in either case.
521 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
522 {
523 // Update prim.BSShape to reference a hull of this shape.
524 ret = GetReferenceToHull(prim,shapeCallback);
525 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
526 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
527 }
528 else
529 {
530 ret = GetReferenceToMesh(prim, shapeCallback);
531 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
532 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
533 }
534 return ret;
535 }
536
537 // Creates a native shape and assignes it to prim.BSShape.
538 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
539 private bool GetReferenceToNativeShape(BSPhysObject prim,
540 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey,
541 ShapeDestructionCallback shapeCallback)
542 {
543 // release any previous shape
544 DereferenceShape(prim.PhysShape, true, shapeCallback);
545
546 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
547
548 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
549 if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
550 prim.LocalID, newShape, prim.Scale);
551
552 // native shapes are scaled by Bullet
553 prim.PhysShape = newShape;
554 return true;
555 }
556
557 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType,
558 FixedShapeKey shapeKey)
559 {
560 BulletShape newShape;
561 // Need to make sure the passed shape information is for the native type.
562 ShapeData nativeShapeData = new ShapeData();
563 nativeShapeData.Type = shapeType;
564 nativeShapeData.ID = prim.LocalID;
565 nativeShapeData.Scale = prim.Scale;
566 nativeShapeData.Size = prim.Scale; // unneeded, I think.
567 nativeShapeData.MeshKey = (ulong)shapeKey;
568 nativeShapeData.HullKey = (ulong)shapeKey;
569
570 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
571 {
572
573 newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale);
574 if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
575 }
576 else
577 {
578 // Native shapes are scaled in Bullet so set the scaling to the size
579 newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData);
580
581 }
582 if (!newShape.HasPhysicalShape)
583 {
584 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
585 LogHeader, prim.LocalID, shapeType);
586 }
587 newShape.shapeKey = (System.UInt64)shapeKey;
588 newShape.isNativeShape = true;
589
590 return newShape;
591 }
592
593 // Builds a mesh shape in the physical world and updates prim.BSShape.
594 // Dereferences previous shape in BSShape and adds a reference for this new shape.
595 // Returns 'true' of a mesh was actually built. Otherwise .
596 // Called at taint-time!
597 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
598 {
599 BulletShape newShape = new BulletShape();
600
601 float lod;
602 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
603
604 // if this new shape is the same as last time, don't recreate the mesh
605 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
606 return false;
607
608 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
609 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
610
611 // Since we're recreating new, get rid of the reference to the previous shape
612 DereferenceShape(prim.PhysShape, true, shapeCallback);
613
614 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod);
615 // Take evasive action if the mesh was not constructed.
616 newShape = VerifyMeshCreated(newShape, prim);
617
618 ReferenceShape(newShape);
619
620 prim.PhysShape = newShape;
621
622 return true; // 'true' means a new shape has been added to this prim
623 }
624
625 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
626 {
627 BulletShape newShape = new BulletShape();
628 IMesh meshData = null;
629
630 MeshDesc meshDesc;
631 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
632 {
633 // If the mesh has already been built just use it.
634 newShape = meshDesc.shape.Clone();
635 }
636 else
637 {
638 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false);
639
640 if (meshData != null)
641 {
642 int[] indices = meshData.getIndexListAsInt();
643 List<OMV.Vector3> vertices = meshData.getVertexList();
644
645 float[] verticesAsFloats = new float[vertices.Count * 3];
646 int vi = 0;
647 foreach (OMV.Vector3 vv in vertices)
648 {
649 verticesAsFloats[vi++] = vv.X;
650 verticesAsFloats[vi++] = vv.Y;
651 verticesAsFloats[vi++] = vv.Z;
652 }
653
654 // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
655 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
656
657 newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World,
658 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
659 }
660 }
661 newShape.shapeKey = newMeshKey;
662
663 return newShape;
664 }
665
666 // See that hull shape exists in the physical world and update prim.BSShape.
667 // We could be creating the hull because scale changed or whatever.
668 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
669 {
670 BulletShape newShape;
671
672 float lod;
673 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
674
675 // if the hull hasn't changed, don't rebuild it
676 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
677 return false;
678
679 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
680 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
681
682 // Remove usage of the previous shape.
683 DereferenceShape(prim.PhysShape, true, shapeCallback);
684
685 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
686 newShape = VerifyMeshCreated(newShape, prim);
687
688 ReferenceShape(newShape);
689
690 prim.PhysShape = newShape;
691 return true; // 'true' means a new shape has been added to this prim
692 }
693
694 List<ConvexResult> m_hulls;
695 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
696 {
697
698 BulletShape newShape = new BulletShape();
699 IntPtr hullPtr = IntPtr.Zero;
700
701 HullDesc hullDesc;
702 if (Hulls.TryGetValue(newHullKey, out hullDesc))
703 {
704 // If the hull shape already is created, just use it.
705 newShape = hullDesc.shape.Clone();
706 }
707 else
708 {
709 // Build a new hull in the physical world
710 // Pass true for physicalness as this creates some sort of bounding box which we don't need
711 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false);
712 if (meshData != null)
713 {
714
715 int[] indices = meshData.getIndexListAsInt();
716 List<OMV.Vector3> vertices = meshData.getVertexList();
717
718 //format conversion from IMesh format to DecompDesc format
719 List<int> convIndices = new List<int>();
720 List<float3> convVertices = new List<float3>();
721 for (int ii = 0; ii < indices.GetLength(0); ii++)
722 {
723 convIndices.Add(indices[ii]);
724 }
725 foreach (OMV.Vector3 vv in vertices)
726 {
727 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
728 }
729
730 // setup and do convex hull conversion
731 m_hulls = new List<ConvexResult>();
732 DecompDesc dcomp = new DecompDesc();
733 dcomp.mIndices = convIndices;
734 dcomp.mVertices = convVertices;
735 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
736 // create the hull into the _hulls variable
737 convexBuilder.process(dcomp);
738
739 // Convert the vertices and indices for passing to unmanaged.
740 // The hull information is passed as a large floating point array.
741 // The format is:
742 // convHulls[0] = number of hulls
743 // convHulls[1] = number of vertices in first hull
744 // convHulls[2] = hull centroid X coordinate
745 // convHulls[3] = hull centroid Y coordinate
746 // convHulls[4] = hull centroid Z coordinate
747 // convHulls[5] = first hull vertex X
748 // convHulls[6] = first hull vertex Y
749 // convHulls[7] = first hull vertex Z
750 // convHulls[8] = second hull vertex X
751 // ...
752 // convHulls[n] = number of vertices in second hull
753 // convHulls[n+1] = second hull centroid X coordinate
754 // ...
755 //
756 // TODO: is is very inefficient. Someday change the convex hull generator to return
757 // data structures that do not need to be converted in order to pass to Bullet.
758 // And maybe put the values directly into pinned memory rather than marshaling.
759 int hullCount = m_hulls.Count;
760 int totalVertices = 1; // include one for the count of the hulls
761 foreach (ConvexResult cr in m_hulls)
762 {
763 totalVertices += 4; // add four for the vertex count and centroid
764 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
765 }
766 float[] convHulls = new float[totalVertices];
767
768 convHulls[0] = (float)hullCount;
769 int jj = 1;
770 foreach (ConvexResult cr in m_hulls)
771 {
772 // copy vertices for index access
773 float3[] verts = new float3[cr.HullVertices.Count];
774 int kk = 0;
775 foreach (float3 ff in cr.HullVertices)
776 {
777 verts[kk++] = ff;
778 }
779
780 // add to the array one hull's worth of data
781 convHulls[jj++] = cr.HullIndices.Count;
782 convHulls[jj++] = 0f; // centroid x,y,z
783 convHulls[jj++] = 0f;
784 convHulls[jj++] = 0f;
785 foreach (int ind in cr.HullIndices)
786 {
787 convHulls[jj++] = verts[ind].x;
788 convHulls[jj++] = verts[ind].y;
789 convHulls[jj++] = verts[ind].z;
790 }
791 }
792 // create the hull data structure in Bullet
793 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
794 }
795 }
796
797 newShape.shapeKey = newHullKey;
798
799 return newShape;
800 }
801
802 // Callback from convex hull creater with a newly created hull.
803 // Just add it to our collection of hulls for this shape.
804 private void HullReturn(ConvexResult result)
805 {
806 m_hulls.Add(result);
807 return;
808 }
809
810 // Compound shapes are always built from scratch.
811 // This shouldn't be to bad since most of the parts will be meshes that had been built previously.
812 private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
813 {
814 // Remove reference to the old shape
815 // Don't need to do this as the shape is freed when the new root shape is created below.
816 // DereferenceShape(prim.PhysShape, true, shapeCallback);
817
818
819 BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false);
820
821 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
822 CreateGeomMeshOrHull(prim, shapeCallback);
823 PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity);
824 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
825 prim.LocalID, cShape, prim.PhysShape);
826
827 prim.PhysShape = cShape;
828
829 return true;
830 }
831
832 // Create a hash of all the shape parameters to be used as a key
833 // for this particular shape.
834 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
835 {
836 // level of detail based on size and type of the object
837 float lod = BSParam.MeshLOD;
838 if (pbs.SculptEntry)
839 lod = BSParam.SculptLOD;
840
841 // Mega prims usually get more detail because one can interact with shape approximations at this size.
842 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
843 if (maxAxis > BSParam.MeshMegaPrimThreshold)
844 lod = BSParam.MeshMegaPrimLOD;
845
846 retLod = lod;
847 return pbs.GetMeshKey(size, lod);
848 }
849 // For those who don't want the LOD
850 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
851 {
852 float lod;
853 return ComputeShapeKey(size, pbs, out lod);
854 }
855
856 // The creation of a mesh or hull can fail if an underlying asset is not available.
857 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
858 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
859 // The first case causes the asset to be fetched. The second case requires
860 // us to not loop forever.
861 // Called after creating a physical mesh or hull. If the physical shape was created,
862 // just return.
863 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
864 {
865 // If the shape was successfully created, nothing more to do
866 if (newShape.HasPhysicalShape)
867 return newShape;
868
869 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
870 if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero)
871 {
872 prim.LastAssetBuildFailed = true;
873 BSPhysObject xprim = prim;
874 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}",
875 LogHeader, prim.LocalID, prim.LastAssetBuildFailed);
876 Util.FireAndForget(delegate
877 {
878 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
879 if (assetProvider != null)
880 {
881 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
882 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
883 {
884 if (!yprim.BaseShape.SculptEntry)
885 return;
886 if (yprim.BaseShape.SculptTexture.ToString() != asset.ID)
887 return;
888
889 yprim.BaseShape.SculptData = asset.Data;
890 // This will cause the prim to see that the filler shape is not the right
891 // one and try again to build the object.
892 // No race condition with the normal shape setting since the rebuild is at taint time.
893 yprim.ForceBodyShapeRebuild(false);
894
895 });
896 }
897 });
898 }
899 else
900 {
901 if (prim.LastAssetBuildFailed)
902 {
903 PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}",
904 LogHeader, prim.LocalID, prim.BaseShape.SculptTexture);
905 }
906 }
907
908 // While we figure out the real problem, stick a simple native shape on the object.
909 BulletShape fillinShape =
910 BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
911
912 return fillinShape;
913 }
914
915 // Create a body object in Bullet.
916 // Updates prim.BSBody with the information about the new body if one is created.
917 // Returns 'true' if an object was actually created.
918 // Called at taint-time.
919 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BulletShape shape,
920 BodyDestructionCallback bodyCallback)
921 {
922 bool ret = false;
923
924 // the mesh, hull or native shape must have already been created in Bullet
925 bool mustRebuild = !prim.PhysBody.HasPhysicalBody;
926
927 // If there is an existing body, verify it's of an acceptable type.
928 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
929 if (!mustRebuild)
930 {
931 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody);
932 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
933 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
934 {
935 // If the collisionObject is not the correct type for solidness, rebuild what's there
936 mustRebuild = true;
937 }
938 }
939
940 if (mustRebuild || forceRebuild)
941 {
942 // Free any old body
943 DereferenceBody(prim.PhysBody, true, bodyCallback);
944
945 BulletBody aBody;
946 if (prim.IsSolid)
947 {
948 aBody = PhysicsScene.PE.CreateBodyFromShape(sim, shape, prim.LocalID, prim.RawPosition, prim.RawOrientation);
949 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody);
950 }
951 else
952 {
953 aBody = PhysicsScene.PE.CreateGhostFromShape(sim, shape, prim.LocalID, prim.RawPosition, prim.RawOrientation);
954 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
955 }
956
957 ReferenceBody(aBody, true);
958
959 prim.PhysBody = aBody;
960
961 ret = true;
962 }
963
964 return ret;
965 }
966
967 private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc)
968 {
969 bool ret = false;
970 MeshDesc foundDesc = new MeshDesc();
971 foreach (MeshDesc md in Meshes.Values)
972 {
973 if (md.shape.ReferenceSame(shape))
974 {
975 foundDesc = md;
976 ret = true;
977 break;
978 }
979
980 }
981 outDesc = foundDesc;
982 return ret;
983 }
984
985 private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc)
986 {
987 bool ret = false;
988 HullDesc foundDesc = new HullDesc();
989 foreach (HullDesc hd in Hulls.Values)
990 {
991 if (hd.shape.ReferenceSame(shape))
992 {
993 foundDesc = hd;
994 ret = true;
995 break;
996 }
997
998 }
999 outDesc = foundDesc;
1000 return ret;
1001 }
1002
1003 private void DetailLog(string msg, params Object[] args)
1004 {
1005 if (PhysicsScene.PhysicsLogging.Enabled)
1006 PhysicsScene.DetailLog(msg, args);
1007 }
1008}
1009}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
deleted file mode 100755
index c75eb9b..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ /dev/null
@@ -1,232 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public abstract class BSShape
36{
37 public IntPtr ptr { get; set; }
38 public BSPhysicsShapeType type { get; set; }
39 public System.UInt64 key { get; set; }
40 public int referenceCount { get; set; }
41 public DateTime lastReferenced { get; set; }
42
43 public BSShape()
44 {
45 ptr = IntPtr.Zero;
46 type = BSPhysicsShapeType.SHAPE_UNKNOWN;
47 key = 0;
48 referenceCount = 0;
49 lastReferenced = DateTime.Now;
50 }
51
52 // Get a reference to a physical shape. Create if it doesn't exist
53 public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
54 {
55 BSShape ret = null;
56
57 if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
58 {
59 // an avatar capsule is close to a native shape (it is not shared)
60 ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
61 FixedShapeKey.KEY_CAPSULE);
62 physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
63 }
64
65 // Compound shapes are handled special as they are rebuilt from scratch.
66 // This isn't too great a hardship since most of the child shapes will already been created.
67 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
68 {
69 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
70 ret = BSShapeCompound.GetReference(prim);
71 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
72 }
73
74 if (ret == null)
75 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
76
77 return ret;
78 }
79 public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
80 {
81 return null;
82 }
83 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
84 {
85 return null;
86 }
87
88 // Release the use of a physical shape.
89 public abstract void Dereference(BSScene physicsScene);
90
91 // All shapes have a static call to get a reference to the physical shape
92 // protected abstract static BSShape GetReference();
93
94 // Returns a string for debugging that uniquily identifies the memory used by this instance
95 public string AddrString
96 {
97 get { return ptr.ToString("X"); }
98 }
99
100 public override string ToString()
101 {
102 StringBuilder buff = new StringBuilder();
103 buff.Append("<p=");
104 buff.Append(AddrString);
105 buff.Append(",s=");
106 buff.Append(type.ToString());
107 buff.Append(",k=");
108 buff.Append(key.ToString("X"));
109 buff.Append(",c=");
110 buff.Append(referenceCount.ToString());
111 buff.Append(">");
112 return buff.ToString();
113 }
114}
115
116public class BSShapeNull : BSShape
117{
118 public BSShapeNull() : base()
119 {
120 }
121 public static BSShape GetReference() { return new BSShapeNull(); }
122 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
123}
124
125public class BSShapeNative : BSShape
126{
127 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
128 public BSShapeNative() : base()
129 {
130 }
131 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
132 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
133 {
134 // Native shapes are not shared and are always built anew.
135 //return new BSShapeNative(physicsScene, prim, shapeType, shapeKey);
136 return null;
137 }
138
139 private BSShapeNative(BSScene physicsScene, BSPhysObject prim,
140 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
141 {
142 ShapeData nativeShapeData = new ShapeData();
143 nativeShapeData.Type = shapeType;
144 nativeShapeData.ID = prim.LocalID;
145 nativeShapeData.Scale = prim.Scale;
146 nativeShapeData.Size = prim.Scale;
147 nativeShapeData.MeshKey = (ulong)shapeKey;
148 nativeShapeData.HullKey = (ulong)shapeKey;
149
150
151 /*
152 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
153 {
154 ptr = PhysicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale);
155 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
156 }
157 else
158 {
159 ptr = PhysicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData);
160 }
161 if (ptr == IntPtr.Zero)
162 {
163 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
164 LogHeader, prim.LocalID, shapeType);
165 }
166 type = shapeType;
167 key = (UInt64)shapeKey;
168 */
169 }
170 // Make this reference to the physical shape go away since native shapes are not shared.
171 public override void Dereference(BSScene physicsScene)
172 {
173 /*
174 // Native shapes are not tracked and are released immediately
175 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
176 PhysicsScene.PE.DeleteCollisionShape(physicsScene.World, this);
177 ptr = IntPtr.Zero;
178 // Garbage collection will free up this instance.
179 */
180 }
181}
182
183public class BSShapeMesh : BSShape
184{
185 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
186 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
187
188 public BSShapeMesh() : base()
189 {
190 }
191 public static BSShape GetReference() { return new BSShapeNull(); }
192 public override void Dereference(BSScene physicsScene) { }
193}
194
195public class BSShapeHull : BSShape
196{
197 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
198 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
199
200 public BSShapeHull() : base()
201 {
202 }
203 public static BSShape GetReference() { return new BSShapeNull(); }
204 public override void Dereference(BSScene physicsScene) { }
205}
206
207public class BSShapeCompound : BSShape
208{
209 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
210 public BSShapeCompound() : base()
211 {
212 }
213 public static BSShape GetReference(BSPhysObject prim)
214 {
215 return new BSShapeNull();
216 }
217 public override void Dereference(BSScene physicsScene) { }
218}
219
220public class BSShapeAvatar : BSShape
221{
222 private static string LogHeader = "[BULLETSIM SHAPE AVATAR]";
223 public BSShapeAvatar() : base()
224 {
225 }
226 public static BSShape GetReference(BSPhysObject prim)
227 {
228 return new BSShapeNull();
229 }
230 public override void Dereference(BSScene physicsScene) { }
231}
232}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
deleted file mode 100755
index e4fecc3..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
+++ /dev/null
@@ -1,171 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public sealed class BSTerrainHeightmap : BSTerrainPhys
44{
45 static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]";
46
47 BulletHMapInfo m_mapInfo = null;
48
49 // Constructor to build a default, flat heightmap terrain.
50 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
51 : base(physicsScene, regionBase, id)
52 {
53 Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE);
54 Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION);
55 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
56 float[] initialMap = new float[totalHeights];
57 for (int ii = 0; ii < totalHeights; ii++)
58 {
59 initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION;
60 }
61 m_mapInfo = new BulletHMapInfo(id, initialMap);
62 m_mapInfo.minCoords = minTerrainCoords;
63 m_mapInfo.maxCoords = maxTerrainCoords;
64 m_mapInfo.terrainRegionBase = TerrainBase;
65 // Don't have to free any previous since we just got here.
66 BuildHeightmapTerrain();
67 }
68
69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z
70 // are the high and low points of the heightmap).
71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
72 Vector3 minCoords, Vector3 maxCoords)
73 : base(physicsScene, regionBase, id)
74 {
75 m_mapInfo = new BulletHMapInfo(id, initialMap);
76 m_mapInfo.minCoords = minCoords;
77 m_mapInfo.maxCoords = maxCoords;
78 m_mapInfo.minZ = minCoords.Z;
79 m_mapInfo.maxZ = maxCoords.Z;
80 m_mapInfo.terrainRegionBase = TerrainBase;
81
82 // Don't have to free any previous since we just got here.
83 BuildHeightmapTerrain();
84 }
85
86 public override void Dispose()
87 {
88 ReleaseHeightMapTerrain();
89 }
90
91 // Using the information in m_mapInfo, create the physical representation of the heightmap.
92 private void BuildHeightmapTerrain()
93 {
94 // Create the terrain shape from the mapInfo
95 m_mapInfo.terrainShape = PhysicsScene.PE.CreateTerrainShape( m_mapInfo.ID,
96 new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ,
97 m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin);
98
99
100 // The terrain object initial position is at the center of the object
101 Vector3 centerPos;
102 centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f);
103 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
104 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f);
105
106 m_mapInfo.terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape,
107 m_mapInfo.ID, centerPos, Quaternion.Identity);
108
109 // Set current terrain attributes
110 PhysicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction);
111 PhysicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction);
112 PhysicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution);
113 PhysicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT);
114
115 // Return the new terrain to the world of physical objects
116 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_mapInfo.terrainBody);
117
118 // redo its bounding box now that it is in the world
119 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_mapInfo.terrainBody);
120
121 m_mapInfo.terrainBody.collisionType = CollisionType.Terrain;
122 m_mapInfo.terrainBody.ApplyCollisionMask(PhysicsScene);
123
124 // Make it so the terrain will not move or be considered for movement.
125 PhysicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION);
126
127 return;
128 }
129
130 // If there is information in m_mapInfo pointing to physical structures, release same.
131 private void ReleaseHeightMapTerrain()
132 {
133 if (m_mapInfo != null)
134 {
135 if (m_mapInfo.terrainBody.HasPhysicalBody)
136 {
137 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_mapInfo.terrainBody);
138 // Frees both the body and the shape.
139 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_mapInfo.terrainBody);
140 }
141 }
142 m_mapInfo = null;
143 }
144
145 // The passed position is relative to the base of the region.
146 public override float GetTerrainHeightAtXYZ(Vector3 pos)
147 {
148 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
149
150 int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X;
151 try
152 {
153 ret = m_mapInfo.heightMap[mapIndex];
154 }
155 catch
156 {
157 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
158 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
159 LogHeader, m_mapInfo.terrainRegionBase, pos);
160 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
161 }
162 return ret;
163 }
164
165 // The passed position is relative to the base of the region.
166 public override float GetWaterLevelAtXYZ(Vector3 pos)
167 {
168 return PhysicsScene.SimpleWaterLevel;
169 }
170}
171}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
deleted file mode 100755
index 2e9db39..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ /dev/null
@@ -1,458 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43
44// The physical implementation of the terrain is wrapped in this class.
45public abstract class BSTerrainPhys : IDisposable
46{
47 public enum TerrainImplementation
48 {
49 Heightmap = 0,
50 Mesh = 1
51 }
52
53 public BSScene PhysicsScene { get; private set; }
54 // Base of the region in world coordinates. Coordinates inside the region are relative to this.
55 public Vector3 TerrainBase { get; private set; }
56 public uint ID { get; private set; }
57
58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id)
59 {
60 PhysicsScene = physicsScene;
61 TerrainBase = regionBase;
62 ID = id;
63 }
64 public abstract void Dispose();
65 public abstract float GetTerrainHeightAtXYZ(Vector3 pos);
66 public abstract float GetWaterLevelAtXYZ(Vector3 pos);
67}
68
69// ==========================================================================================
70public sealed class BSTerrainManager : IDisposable
71{
72 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
73
74 // These height values are fractional so the odd values will be
75 // noticable when debugging.
76 public const float HEIGHT_INITIALIZATION = 24.987f;
77 public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
78 public const float HEIGHT_GETHEIGHT_RET = 24.765f;
79 public const float WATER_HEIGHT_GETHEIGHT_RET = 19.998f;
80
81 // If the min and max height are equal, we reduce the min by this
82 // amount to make sure that a bounding box is built for the terrain.
83 public const float HEIGHT_EQUAL_FUDGE = 0.2f;
84
85 // Until the whole simulator is changed to pass us the region size, we rely on constants.
86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
87
88 // The scene that I am part of
89 private BSScene PhysicsScene { get; set; }
90
91 // The ground plane created to keep thing from falling to infinity.
92 private BulletBody m_groundPlane;
93
94 // If doing mega-regions, if we're region zero we will be managing multiple
95 // region terrains since region zero does the physics for the whole mega-region.
96 private Dictionary<Vector3, BSTerrainPhys> m_terrains;
97
98 // Flags used to know when to recalculate the height.
99 private bool m_terrainModified = false;
100
101 // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
102 // This is incremented before assigning to new region so it is the last ID allocated.
103 private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1;
104 public uint HighestTerrainID { get {return m_terrainCount; } }
105
106 // If doing mega-regions, this holds our offset from region zero of
107 // the mega-regions. "parentScene" points to the PhysicsScene of region zero.
108 private Vector3 m_worldOffset;
109 // If the parent region (region 0), this is the extent of the combined regions
110 // relative to the origin of region zero
111 private Vector3 m_worldMax;
112 private PhysicsScene MegaRegionParentPhysicsScene { get; set; }
113
114 public BSTerrainManager(BSScene physicsScene)
115 {
116 PhysicsScene = physicsScene;
117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
118
119 // Assume one region of default size
120 m_worldOffset = Vector3.Zero;
121 m_worldMax = new Vector3(DefaultRegionSize);
122 MegaRegionParentPhysicsScene = null;
123 }
124
125 public void Dispose()
126 {
127 ReleaseGroundPlaneAndTerrain();
128 }
129
130 // Create the initial instance of terrain and the underlying ground plane.
131 // This is called from the initialization routine so we presume it is
132 // safe to call Bullet in real time. We hope no one is moving prims around yet.
133 public void CreateInitialGroundPlaneAndTerrain()
134 {
135 // The ground plane is here to catch things that are trying to drop to negative infinity
136 BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
137 m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
138 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity);
139
140 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane);
141 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane);
142 // Ground plane does not move
143 PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
144 // Everything collides with the ground plane.
145 m_groundPlane.collisionType = CollisionType.Groundplane;
146 m_groundPlane.ApplyCollisionMask(PhysicsScene);
147
148 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
150 m_terrains.Add(Vector3.Zero, initialTerrain);
151 }
152
153 // Release all the terrain structures we might have allocated
154 public void ReleaseGroundPlaneAndTerrain()
155 {
156 if (m_groundPlane.HasPhysicalBody)
157 {
158 if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane))
159 {
160 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_groundPlane);
161 }
162 m_groundPlane.Clear();
163 }
164
165 ReleaseTerrain();
166 }
167
168 // Release all the terrain we have allocated
169 public void ReleaseTerrain()
170 {
171 lock (m_terrains)
172 {
173 foreach (KeyValuePair<Vector3, BSTerrainPhys> kvp in m_terrains)
174 {
175 kvp.Value.Dispose();
176 }
177 m_terrains.Clear();
178 }
179 }
180
181 // The simulator wants to set a new heightmap for the terrain.
182 public void SetTerrain(float[] heightMap) {
183 float[] localHeightMap = heightMap;
184 // If there are multiple requests for changes to the same terrain between ticks,
185 // only do that last one.
186 PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate()
187 {
188 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
189 {
190 // If a child of a mega-region, we shouldn't have any terrain allocated for us
191 ReleaseGroundPlaneAndTerrain();
192 // If doing the mega-prim stuff and we are the child of the zero region,
193 // the terrain is added to our parent
194 if (MegaRegionParentPhysicsScene is BSScene)
195 {
196 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
197 BSScene.DetailLogZero, m_worldOffset, m_worldMax);
198 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain(
199 BSScene.CHILDTERRAIN_ID, localHeightMap,
200 m_worldOffset, m_worldOffset + DefaultRegionSize, true);
201 }
202 }
203 else
204 {
205 // If not doing the mega-prim thing, just change the terrain
206 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
207
208 UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap,
209 m_worldOffset, m_worldOffset + DefaultRegionSize, true);
210 }
211 });
212 }
213
214 // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
215 // based on the passed information. The 'id' should be either the terrain id or
216 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
217 // The latter feature is for creating child terrains for mega-regions.
218 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
219 // terrain shape is created and added to the body.
220 // This call is most often used to update the heightMap and parameters of the terrain.
221 // (The above does suggest that some simplification/refactoring is in order.)
222 // Called during taint-time.
223 private void UpdateTerrain(uint id, float[] heightMap,
224 Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
225 {
226 DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}",
227 BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime);
228
229 // Find high and low points of passed heightmap.
230 // The min and max passed in is usually the area objects can be in (maximum
231 // object height, for instance). The terrain wants the bounding box for the
232 // terrain so replace passed min and max Z with the actual terrain min/max Z.
233 float minZ = float.MaxValue;
234 float maxZ = float.MinValue;
235 foreach (float height in heightMap)
236 {
237 if (height < minZ) minZ = height;
238 if (height > maxZ) maxZ = height;
239 }
240 if (minZ == maxZ)
241 {
242 // If min and max are the same, reduce min a little bit so a good bounding box is created.
243 minZ -= BSTerrainManager.HEIGHT_EQUAL_FUDGE;
244 }
245 minCoords.Z = minZ;
246 maxCoords.Z = maxZ;
247
248 Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f);
249
250 lock (m_terrains)
251 {
252 BSTerrainPhys terrainPhys;
253 if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys))
254 {
255 // There is already a terrain in this spot. Free the old and build the new.
256 DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
257 BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords);
258
259 // Remove old terrain from the collection
260 m_terrains.Remove(terrainRegionBase);
261 // Release any physical memory it may be using.
262 terrainPhys.Dispose();
263
264 if (MegaRegionParentPhysicsScene == null)
265 {
266 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
267 m_terrains.Add(terrainRegionBase, newTerrainPhys);
268
269 m_terrainModified = true;
270 }
271 else
272 {
273 // It's possible that Combine() was called after this code was queued.
274 // If we are a child of combined regions, we don't create any terrain for us.
275 DetailLog("{0},BSTerrainManager.UpdateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
276
277 // Get rid of any terrain that may have been allocated for us.
278 ReleaseGroundPlaneAndTerrain();
279
280 // I hate doing this, but just bail
281 return;
282 }
283 }
284 else
285 {
286 // We don't know about this terrain so either we are creating a new terrain or
287 // our mega-prim child is giving us a new terrain to add to the phys world
288
289 // if this is a child terrain, calculate a unique terrain id
290 uint newTerrainID = id;
291 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
292 newTerrainID = ++m_terrainCount;
293
294 DetailLog("{0},UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
295 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
296 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
297 m_terrains.Add(terrainRegionBase, newTerrainPhys);
298
299 m_terrainModified = true;
300 }
301 }
302 }
303
304 // TODO: redo terrain implementation selection to allow other base types than heightMap.
305 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
306 {
307 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
308 LogHeader, PhysicsScene.RegionName, terrainRegionBase,
309 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation);
310 BSTerrainPhys newTerrainPhys = null;
311 switch ((int)BSParam.TerrainImplementation)
312 {
313 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
314 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id,
315 heightMap, minCoords, maxCoords);
316 break;
317 case (int)BSTerrainPhys.TerrainImplementation.Mesh:
318 newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id,
319 heightMap, minCoords, maxCoords);
320 break;
321 default:
322 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
323 LogHeader,
324 (int)BSParam.TerrainImplementation,
325 BSParam.TerrainImplementation,
326 PhysicsScene.RegionName, terrainRegionBase);
327 break;
328 }
329 return newTerrainPhys;
330 }
331
332 // Return 'true' of this position is somewhere in known physical terrain space
333 public bool IsWithinKnownTerrain(Vector3 pos)
334 {
335 Vector3 terrainBaseXYZ;
336 BSTerrainPhys physTerrain;
337 return GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ);
338 }
339
340 // Given an X and Y, find the height of the terrain.
341 // Since we could be handling multiple terrains for a mega-region,
342 // the base of the region is calcuated assuming all regions are
343 // the same size and that is the default.
344 // Once the heightMapInfo is found, we have all the information to
345 // compute the offset into the array.
346 private float lastHeightTX = 999999f;
347 private float lastHeightTY = 999999f;
348 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
349 public float GetTerrainHeightAtXYZ(Vector3 pos)
350 {
351 float tX = pos.X;
352 float tY = pos.Y;
353 // You'd be surprized at the number of times this routine is called
354 // with the same parameters as last time.
355 if (!m_terrainModified && (lastHeightTX == tX) && (lastHeightTY == tY))
356 return lastHeight;
357 m_terrainModified = false;
358
359 lastHeightTX = tX;
360 lastHeightTY = tY;
361 float ret = HEIGHT_GETHEIGHT_RET;
362
363 Vector3 terrainBaseXYZ;
364 BSTerrainPhys physTerrain;
365 if (GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ))
366 {
367 ret = physTerrain.GetTerrainHeightAtXYZ(pos - terrainBaseXYZ);
368 }
369 else
370 {
371 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
372 LogHeader, PhysicsScene.RegionName, tX, tY);
373 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}",
374 BSScene.DetailLogZero, pos, terrainBaseXYZ);
375 }
376
377 lastHeight = ret;
378 return ret;
379 }
380
381 public float GetWaterLevelAtXYZ(Vector3 pos)
382 {
383 float ret = WATER_HEIGHT_GETHEIGHT_RET;
384
385 Vector3 terrainBaseXYZ;
386 BSTerrainPhys physTerrain;
387 if (GetTerrainPhysicalAtXYZ(pos, out physTerrain, out terrainBaseXYZ))
388 {
389 ret = physTerrain.GetWaterLevelAtXYZ(pos);
390 }
391 else
392 {
393 PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}",
394 LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret);
395 }
396 return ret;
397 }
398
399 // Given an address, return 'true' of there is a description of that terrain and output
400 // the descriptor class and the 'base' fo the addresses therein.
401 private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase)
402 {
403 int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
404 int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
405 Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);
406
407 BSTerrainPhys physTerrain = null;
408 lock (m_terrains)
409 {
410 m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain);
411 }
412 outTerrainBase = terrainBaseXYZ;
413 outPhysTerrain = physTerrain;
414 return (physTerrain != null);
415 }
416
417 // Although no one seems to check this, I do support combining.
418 public bool SupportsCombining()
419 {
420 return true;
421 }
422
423 // This routine is called two ways:
424 // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
425 // extent of the combined regions. This is to inform the parent of the size
426 // of the combined regions.
427 // and one with 'offset' as the offset of the child region to the base region,
428 // 'pScene' pointing to the parent and 'extents' of zero. This informs the
429 // child of its relative base and new parent.
430 public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
431 {
432 m_worldOffset = offset;
433 m_worldMax = extents;
434 MegaRegionParentPhysicsScene = pScene;
435 if (pScene != null)
436 {
437 // We are a child.
438 // We want m_worldMax to be the highest coordinate of our piece of terrain.
439 m_worldMax = offset + DefaultRegionSize;
440 }
441 DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
442 BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
443 }
444
445 // Unhook all the combining that I know about.
446 public void UnCombine(PhysicsScene pScene)
447 {
448 // Just like ODE, we don't do anything yet.
449 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
450 }
451
452
453 private void DetailLog(string msg, params Object[] args)
454 {
455 PhysicsScene.PhysicsLogging.Write(msg, args);
456 }
457}
458}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
deleted file mode 100755
index 1d55ce3..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
+++ /dev/null
@@ -1,265 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public sealed class BSTerrainMesh : BSTerrainPhys
44{
45 static string LogHeader = "[BULLETSIM TERRAIN MESH]";
46
47 private float[] m_savedHeightMap;
48 int m_sizeX;
49 int m_sizeY;
50
51 BulletShape m_terrainShape;
52 BulletBody m_terrainBody;
53
54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
55 : base(physicsScene, regionBase, id)
56 {
57 }
58
59 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */)
60 : base(physicsScene, regionBase, id)
61 {
62 }
63
64 // Create terrain mesh from a heightmap.
65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
66 Vector3 minCoords, Vector3 maxCoords)
67 : base(physicsScene, regionBase, id)
68 {
69 int indicesCount;
70 int[] indices;
71 int verticesCount;
72 float[] vertices;
73
74 m_savedHeightMap = initialMap;
75
76 m_sizeX = (int)(maxCoords.X - minCoords.X);
77 m_sizeY = (int)(maxCoords.Y - minCoords.Y);
78
79 if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap,
80 m_sizeX, m_sizeY,
81 (float)m_sizeX, (float)m_sizeY,
82 Vector3.Zero, 1.0f,
83 out indicesCount, out indices, out verticesCount, out vertices))
84 {
85 // DISASTER!!
86 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID);
87 PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
88 // Something is very messed up and a crash is in our future.
89 return;
90 }
91 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}",
92 ID, indicesCount, indices.Length, verticesCount, vertices.Length);
93
94 m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices);
95 if (!m_terrainShape.HasPhysicalShape)
96 {
97 // DISASTER!!
98 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID);
99 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
100 // Something is very messed up and a crash is in our future.
101 return;
102 }
103
104 Vector3 pos = regionBase;
105 Quaternion rot = Quaternion.Identity;
106
107 m_terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot);
108 if (!m_terrainBody.HasPhysicalBody)
109 {
110 // DISASTER!!
111 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
112 // Something is very messed up and a crash is in our future.
113 return;
114 }
115
116 // Set current terrain attributes
117 PhysicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
118 PhysicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
119 PhysicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
120 PhysicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);
121
122 // Static objects are not very massive.
123 PhysicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero);
124
125 // Put the new terrain to the world of physical objects
126 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_terrainBody);
127
128 // Redo its bounding box now that it is in the world
129 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_terrainBody);
130
131 m_terrainBody.collisionType = CollisionType.Terrain;
132 m_terrainBody.ApplyCollisionMask(PhysicsScene);
133
134 // Make it so the terrain will not move or be considered for movement.
135 PhysicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION);
136 }
137
138 public override void Dispose()
139 {
140 if (m_terrainBody.HasPhysicalBody)
141 {
142 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_terrainBody);
143 // Frees both the body and the shape.
144 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_terrainBody);
145 }
146 }
147
148 public override float GetTerrainHeightAtXYZ(Vector3 pos)
149 {
150 // For the moment use the saved heightmap to get the terrain height.
151 // TODO: raycast downward to find the true terrain below the position.
152 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
153
154 int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X;
155 try
156 {
157 ret = m_savedHeightMap[mapIndex];
158 }
159 catch
160 {
161 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
162 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
163 LogHeader, TerrainBase, pos);
164 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
165 }
166 return ret;
167 }
168
169 // The passed position is relative to the base of the region.
170 public override float GetWaterLevelAtXYZ(Vector3 pos)
171 {
172 return PhysicsScene.SimpleWaterLevel;
173 }
174
175 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
176 // Return 'true' if successfully created.
177 public static bool ConvertHeightmapToMesh(
178 BSScene physicsScene,
179 float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap
180 float extentX, float extentY, // zero based range for output vertices
181 Vector3 extentBase, // base to be added to all vertices
182 float magnification, // number of vertices to create between heightMap coords
183 out int indicesCountO, out int[] indicesO,
184 out int verticesCountO, out float[] verticesO)
185 {
186 bool ret = false;
187
188 int indicesCount = 0;
189 int verticesCount = 0;
190 int[] indices = new int[0];
191 float[] vertices = new float[0];
192
193 // Simple mesh creation which assumes magnification == 1.
194 // TODO: do a more general solution that scales, adds new vertices and smoothes the result.
195
196 // Create an array of vertices that is sizeX+1 by sizeY+1 (note the loop
197 // from zero to <= sizeX). The triangle indices are then generated as two triangles
198 // per heightmap point. There are sizeX by sizeY of these squares. The extra row and
199 // column of vertices are used to complete the triangles of the last row and column
200 // of the heightmap.
201 try
202 {
203 // One vertice per heightmap value plus the vertices off the top and bottom edge.
204 int totalVertices = (sizeX + 1) * (sizeY + 1);
205 vertices = new float[totalVertices * 3];
206 int totalIndices = sizeX * sizeY * 6;
207 indices = new int[totalIndices];
208
209 float magX = (float)sizeX / extentX;
210 float magY = (float)sizeY / extentY;
211 physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}",
212 BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY);
213 float minHeight = float.MaxValue;
214 // Note that sizeX+1 vertices are created since there is land between this and the next region.
215 for (int yy = 0; yy <= sizeY; yy++)
216 {
217 for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we go around sizeX + 1 times
218 {
219 int offset = yy * sizeX + xx;
220 // Extend the height with the height from the last row or column
221 if (yy == sizeY) offset -= sizeX;
222 if (xx == sizeX) offset -= 1;
223 float height = heightMap[offset];
224 minHeight = Math.Min(minHeight, height);
225 vertices[verticesCount + 0] = (float)xx * magX + extentBase.X;
226 vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y;
227 vertices[verticesCount + 2] = height + extentBase.Z;
228 verticesCount += 3;
229 }
230 }
231 verticesCount = verticesCount / 3;
232
233 for (int yy = 0; yy < sizeY; yy++)
234 {
235 for (int xx = 0; xx < sizeX; xx++)
236 {
237 int offset = yy * (sizeX + 1) + xx;
238 // Each vertices is presumed to be the upper left corner of a box of two triangles
239 indices[indicesCount + 0] = offset;
240 indices[indicesCount + 1] = offset + 1;
241 indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column
242 indices[indicesCount + 3] = offset + 1;
243 indices[indicesCount + 4] = offset + sizeX + 2;
244 indices[indicesCount + 5] = offset + sizeX + 1;
245 indicesCount += 6;
246 }
247 }
248
249 ret = true;
250 }
251 catch (Exception e)
252 {
253 physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
254 LogHeader, physicsScene.RegionName, extentBase, e);
255 }
256
257 indicesCountO = indicesCount;
258 indicesO = indices;
259 verticesCountO = verticesCount;
260 verticesO = vertices;
261
262 return ret;
263 }
264}
265}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
deleted file mode 100755
index 662dd68..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
+++ /dev/null
@@ -1,263 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OMV = OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34// Classes to allow some type checking for the API
35// These hold pointers to allocated objects in the unmanaged space.
36// These classes are subclassed by the various physical implementations of
37// objects. In particular, there is a version for physical instances in
38// unmanaged memory ("unman") and one for in managed memory ("XNA").
39
40// Currently, the instances of these classes are a reference to a
41// physical representation and this has no releationship to other
42// instances. Someday, refarb the usage of these classes so each instance
43// refers to a particular physical instance and this class controls reference
44// counts and such. This should be done along with adding BSShapes.
45
46public class BulletWorld
47{
48 public BulletWorld(uint worldId, BSScene bss)
49 {
50 worldID = worldId;
51 physicsScene = bss;
52 }
53 public uint worldID;
54 // The scene is only in here so very low level routines have a handle to print debug/error messages
55 public BSScene physicsScene;
56}
57
58// An allocated Bullet btRigidBody
59public class BulletBody
60{
61 public BulletBody(uint id)
62 {
63 ID = id;
64 collisionType = CollisionType.Static;
65 }
66 public uint ID;
67 public CollisionType collisionType;
68
69 public virtual void Clear() { }
70 public virtual bool HasPhysicalBody { get { return false; } }
71
72 // Apply the specificed collision mask into the physical world
73 public virtual bool ApplyCollisionMask(BSScene physicsScene)
74 {
75 // Should assert the body has been added to the physical world.
76 // (The collision masks are stored in the collision proxy cache which only exists for
77 // a collision body that is in the world.)
78 return physicsScene.PE.SetCollisionGroupMask(this,
79 BulletSimData.CollisionTypeMasks[collisionType].group,
80 BulletSimData.CollisionTypeMasks[collisionType].mask);
81 }
82
83 // Used for log messages for a unique display of the memory/object allocated to this instance
84 public virtual string AddrString
85 {
86 get { return "unknown"; }
87 }
88
89 public override string ToString()
90 {
91 StringBuilder buff = new StringBuilder();
92 buff.Append("<id=");
93 buff.Append(ID.ToString());
94 buff.Append(",p=");
95 buff.Append(AddrString);
96 buff.Append(",c=");
97 buff.Append(collisionType);
98 buff.Append(">");
99 return buff.ToString();
100 }
101}
102
103public class BulletShape
104{
105 public BulletShape()
106 {
107 type = BSPhysicsShapeType.SHAPE_UNKNOWN;
108 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
109 isNativeShape = false;
110 }
111 public BSPhysicsShapeType type;
112 public System.UInt64 shapeKey;
113 public bool isNativeShape;
114
115 public virtual void Clear() { }
116 public virtual bool HasPhysicalShape { get { return false; } }
117 // Make another reference to this physical object.
118 public virtual BulletShape Clone() { return new BulletShape(); }
119 // Return 'true' if this and other refer to the same physical object
120 public virtual bool ReferenceSame(BulletShape xx) { return false; }
121
122 // Used for log messages for a unique display of the memory/object allocated to this instance
123 public virtual string AddrString
124 {
125 get { return "unknown"; }
126 }
127
128 public override string ToString()
129 {
130 StringBuilder buff = new StringBuilder();
131 buff.Append("<p=");
132 buff.Append(AddrString);
133 buff.Append(",s=");
134 buff.Append(type.ToString());
135 buff.Append(",k=");
136 buff.Append(shapeKey.ToString("X"));
137 buff.Append(",n=");
138 buff.Append(isNativeShape.ToString());
139 buff.Append(">");
140 return buff.ToString();
141 }
142}
143
144// An allocated Bullet btConstraint
145public class BulletConstraint
146{
147 public BulletConstraint()
148 {
149 }
150 public virtual void Clear() { }
151 public virtual bool HasPhysicalConstraint { get { return false; } }
152
153 // Used for log messages for a unique display of the memory/object allocated to this instance
154 public virtual string AddrString
155 {
156 get { return "unknown"; }
157 }
158}
159
160// An allocated HeightMapThing which holds various heightmap info.
161// Made a class rather than a struct so there would be only one
162// instance of this and C# will pass around pointers rather
163// than making copies.
164public class BulletHMapInfo
165{
166 public BulletHMapInfo(uint id, float[] hm) {
167 ID = id;
168 heightMap = hm;
169 terrainRegionBase = OMV.Vector3.Zero;
170 minCoords = new OMV.Vector3(100f, 100f, 25f);
171 maxCoords = new OMV.Vector3(101f, 101f, 26f);
172 minZ = maxZ = 0f;
173 sizeX = sizeY = 256f;
174 }
175 public uint ID;
176 public float[] heightMap;
177 public OMV.Vector3 terrainRegionBase;
178 public OMV.Vector3 minCoords;
179 public OMV.Vector3 maxCoords;
180 public float sizeX, sizeY;
181 public float minZ, maxZ;
182 public BulletShape terrainShape;
183 public BulletBody terrainBody;
184}
185
186// The general class of collsion object.
187public enum CollisionType
188{
189 Avatar,
190 Groundplane,
191 Terrain,
192 Static,
193 Dynamic,
194 VolumeDetect,
195 // Linkset, // A linkset should be either Static or Dynamic
196 LinksetChild,
197 Unknown
198};
199
200// Hold specification of group and mask collision flags for a CollisionType
201public struct CollisionTypeFilterGroup
202{
203 public CollisionTypeFilterGroup(CollisionType t, uint g, uint m)
204 {
205 type = t;
206 group = g;
207 mask = m;
208 }
209 public CollisionType type;
210 public uint group;
211 public uint mask;
212};
213
214public static class BulletSimData
215{
216
217// Map of collisionTypes to flags for collision groups and masks.
218// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code
219// but, instead, use references to this dictionary. Finding and debugging
220// collision flag problems will be made easier.
221public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks
222 = new Dictionary<CollisionType, CollisionTypeFilterGroup>()
223{
224 { CollisionType.Avatar,
225 new CollisionTypeFilterGroup(CollisionType.Avatar,
226 (uint)CollisionFilterGroups.BCharacterGroup,
227 (uint)CollisionFilterGroups.BAllGroup)
228 },
229 { CollisionType.Groundplane,
230 new CollisionTypeFilterGroup(CollisionType.Groundplane,
231 (uint)CollisionFilterGroups.BGroundPlaneGroup,
232 (uint)CollisionFilterGroups.BAllGroup)
233 },
234 { CollisionType.Terrain,
235 new CollisionTypeFilterGroup(CollisionType.Terrain,
236 (uint)CollisionFilterGroups.BTerrainGroup,
237 (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup))
238 },
239 { CollisionType.Static,
240 new CollisionTypeFilterGroup(CollisionType.Static,
241 (uint)CollisionFilterGroups.BStaticGroup,
242 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
243 },
244 { CollisionType.Dynamic,
245 new CollisionTypeFilterGroup(CollisionType.Dynamic,
246 (uint)CollisionFilterGroups.BSolidGroup,
247 (uint)(CollisionFilterGroups.BAllGroup))
248 },
249 { CollisionType.VolumeDetect,
250 new CollisionTypeFilterGroup(CollisionType.VolumeDetect,
251 (uint)CollisionFilterGroups.BSensorTrigger,
252 (uint)(~CollisionFilterGroups.BSensorTrigger))
253 },
254 { CollisionType.LinksetChild,
255 new CollisionTypeFilterGroup(CollisionType.LinksetChild,
256 (uint)CollisionFilterGroups.BLinksetChildGroup,
257 (uint)(CollisionFilterGroups.BNoneGroup))
258 // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
259 },
260};
261
262}
263}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
deleted file mode 100755
index a8a4ff5..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ /dev/null
@@ -1,272 +0,0 @@
1CURRENT PRIORITIES
2=================================================
3Redo BulletSimAPI to allow native C# implementation of Bullet option.
4Avatar movement
5 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle
6 walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
7 avatar capsule rotation completed
8llMoveToTarget
9Enable vehicle border crossings (at least as poorly as ODE)
10 Terrain skirts
11 Avatar created in previous region and not new region when crossing border
12 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
13Vehicle movement on terrain smoothness
14Vehicle script tuning/debugging
15 Avanti speed script
16 Weapon shooter script
17limitMotorUp calibration (more down?)
18Boats float low in the water
19Add material densities to the material types.
20
21CRASHES
22=================================================
2320121129.1411: editting/moving phys object across region boundries causes crash
24 getPos-> btRigidBody::upcast -> getBodyType -> BOOM
2520121128.1600: mesh object not rezzing (no physics mesh).
26 Causes many errors. Doesn't stop after first error with box shape.
27 Eventually crashes when deleting the object.
2820121206.1434: rez Sam-pan into OSGrid BulletSim11 region
29 Immediate simulator crash. Mono does not output any stacktrace and
30 log just stops after reporting taint-time linking of the linkset.
31
32VEHICLES TODO LIST:
33=================================================
34Angular motor direction is global coordinates rather than local coordinates
35Border crossing with linked vehicle causes crash
36Vehicles (Move smoothly)
37Add vehicle collisions so IsColliding is properly reported.
38 Needed for banking, limitMotorUp, movementLimiting, ...
39VehicleAddForce is not scaled by the simulation step but it is only
40 applied for one step. Should it be scaled?
41Some vehicles should not be able to turn if no speed or off ground.
42Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
43Neb car jiggling left and right
44 Happens on terrain and any other mesh object. Flat cubes are much smoother.
45 This has been reduced but not eliminated.
46Implement referenceFrame for all the motion routines.
47Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
48 Verify that angular motion specified around Z moves in the vehicle coordinates.
49Verify llGetVel() is returning a smooth and good value for vehicle movement.
50llGetVel() should return the root's velocity if requested in a child prim.
51Implement function efficiency for lineaar and angular motion.
52After getting off a vehicle, the root prim is phantom (can be walked through)
53 Need to force a position update for the root prim after compound shape destruction
54Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
55For limitMotorUp, use raycast down to find if vehicle is in the air.
56Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties().
57 A kludge that isn't fixing the real problem of Bullet adding extra motion.
58Incorporate inter-relationship of angular corrections. For instance, angularDeflection
59 and angularMotorUp will compute same X or Y correction. When added together
60 creates over-correction and over-shoot and wabbling.
61
62BULLETSIM TODO LIST:
63=================================================
64Implement an avatar mesh shape. The Bullet capsule is way too limited.
65 Consider just hand creating a vertex/index array in a new BSShapeAvatar.
66Revisit CollisionMargin. Builders notice the 0.04 spacing between prims.
67Duplicating a physical prim causes old prim to jump away
68 Dup a phys prim and the original become unselected and thus interacts w/ selected prim.
69Scenes with hundred of thousands of static objects take a lot of physics CPU time.
70BSPrim.Force should set a continious force on the prim. The force should be
71 applied each tick. Some limits?
72Gun sending shooter flying.
73Collision margin (gap between physical objects lying on each other)
74Boundry checking (crashes related to crossing boundry)
75 Add check for border edge position for avatars and objects.
76 Verify the events are created for border crossings.
77Avatar rotation (check out changes to ScenePresence for physical rotation)
78Avatar running (what does phys engine need to do?)
79Small physical objects do not interact correctly
80 Create chain of .5x.5x.1 torui and make all but top physical so to hang.
81 The chain will fall apart and pairs will dance around on ground
82 Chains of 1x1x.2 will stay connected but will dance.
83 Chains above 2x2x.4 are more stable and get stablier as torui get larger.
84Add PID motor for avatar movement (slow to stop, ...)
85setForce should set a constant force. Different than AddImpulse.
86Implement raycast.
87Implement ShapeCollection.Dispose()
88Implement water as a plain so raycasting and collisions can happen with same.
89Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
90 Also osGetPhysicsEngineVerion() maybe.
91Linkset.Position and Linkset.Orientation requre rewrite to properly return
92 child position. LinksetConstraint acts like it's at taint time!!
93Implement LockAngularMotion -- implements llSetStatus(ROTATE_AXIS_*, T/F)
94Should the different PID factors have non-equal contributions for different
95 values of Efficiency?
96Selecting and deselecting physical objects causes CPU processing time to jump
97 http://www.youtube.com/watch?v=Hjg57fWg8yI&hd=1
98 put thousand physical objects, select and deselect same. CPU time will be large.
99Re-implement buoyancy as a separate force on the object rather than diddling gravity.
100 Register a pre-step event to add the force.
101More efficient memory usage when passing hull information from BSPrim to BulletSim
102Avatar movement motor check for zero or small movement. Somehow suppress small movements
103 when avatar has stopped and is just standing. Simple test for near zero has
104 the problem of preventing starting up (increase from zero) especially when falling.
105Physical and phantom will drop through the terrain
106
107
108LINKSETS
109======================================================
110Offset the center of the linkset to be the geometric center of all the prims
111 Not quite the same as the center-of-gravity
112Linksets should allow collisions to individual children
113 Add LocalID to children shapes in LinksetCompound and create events for individuals
114LinksetCompound: when one of the children changes orientation (like tires
115 turning on a vehicle, the whole compound object is rebuilt. Optimize this
116 so orientation/position of individual children can change without a rebuild.
117Verify/think through scripts in children of linksets. What do they reference
118 and return when getting position, velocity, ...
119Confirm constraint linksets still work after making all the changes for compound linksets.
120Add 'changed' flag or similar to reduce the number of times a linkset is rebuilt.
121 For compound linksets, add ability to remove or reposition individual child shapes.
122Disable activity of passive linkset children.
123 Since the linkset is a compound object, the old prims are left lying
124 around and need to be phantomized so they don't collide, ...
125Speed up creation of large physical linksets
126 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical.
127 REALLY bad for very large physical linksets (freezes the sim for many seconds).
128Eliminate collisions between objects in a linkset. (LinksetConstraint)
129 Have UserPointer point to struct with localID and linksetID?
130 Objects in original linkset still collide with each other?
131
132MORE
133======================================================
134Test avatar walking up stairs. How does compare with SL.
135 Radius of the capsule affects ability to climb edges.
136Debounce avatar contact so legs don't keep folding up when standing.
137Implement LSL physics controls. Like STATUS_ROTATE_X.
138Add border extensions to terrain to help region crossings and objects leaving region.
139Use a different capsule shape for avatar when sitting
140 LL uses a pyrimidal shape scaled by the avatar's bounding box
141 http://wiki.secondlife.com/wiki/File:Avmeshforms.png
142
143Performance test with lots of avatars. Can BulletSim support a thousand?
144Optimize collisions in C++: only send up to the object subscribed to collisions.
145 Use collision subscription and remove the collsion(A,B) and collision(B,A)
146Check whether SimMotionState needs large if statement (see TODO).
147
148Implement 'top colliders' info.
149Avatar jump
150Performance measurement and changes to make quicker.
151Implement detailed physics stats (GetStats()).
152
153Measure performance improvement from hulls
154Test not using ghost objects for volume detect implementation.
155Performance of closures and delegates for taint processing
156 Are there faster ways?
157 Is any slowdown introduced by the existing implementation significant?
158Is there are more efficient method of implementing pre and post step actions?
159 See http://www.codeproject.com/Articles/29922/Weak-Events-in-C
160
161Physics Arena central pyramid: why is one side permiable?
162
163In SL, perfect spheres don't seem to have rolling friction. Add special case.
164Enforce physical parameter min/max:
165 Gravity: [-1, 28]
166 Friction: [0, 255]
167 Density: [1, 22587]
168 Restitution [0, 1]
169 http://wiki.secondlife.com/wiki/Physics_Material_Settings_test
170Avatar attachments have no mass? http://forums-archive.secondlife.com/54/f0/31796/1.html
171
172INTERNAL IMPROVEMENT/CLEANUP
173=================================================
174Create the physical wrapper classes (BulletBody, BulletShape) by methods on
175 BSAPITemplate and make their actual implementation Bullet engine specific.
176 For the short term, just call the existing functions in ShapeCollection.
177Consider moving prim/character body and shape destruction in destroy()
178 to postTimeTime rather than protecting all the potential sets that
179 might have been queued up.
180Remove unused fields from ShapeData (not used in API2)
181Remove unused fields from pinned memory shared parameter block
182 Create parameter variables in BSScene to replace same.
183Breakout code for mesh/hull/compound/native into separate BSShape* classes
184 Standardize access to building and reference code.
185 The skeleton classes are in the sources but are not complete or linked in.
186Make BSBody and BSShape real classes to centralize creation/changin/destruction
187 Convert state and parameter calls from BulletSimAPI direct calls to
188 calls on BSBody and BSShape
189Generalize Dynamics and PID with standardized motors.
190Generalize Linkset and vehicles into PropertyManagers
191 Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
192 Potentially add events for shape destruction, etc.
193Complete implemention of preStepActions
194 Replace vehicle step call with prestep event.
195 Is there a need for postStepActions? postStepTaints?
196Implement linkset by setting position of children when root updated. (LinksetManual)
197 Linkset implementation using manual prim movement.
198LinkablePrim class? Would that simplify/centralize the linkset logic?
199BSScene.UpdateParameterSet() is broken. How to set params on objects?
200Remove HeightmapInfo from terrain specification
201 Since C++ code does not need terrain height, this structure et al are not needed.
202Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
203 bob at the water level. BSPrim.PositionSanityCheck().
204Should taints check for existance or activeness of target?
205 When destroying linksets/etc, taints can be generated for objects that are
206 actually gone when the taint happens. Crashes don't happen because the taint closure
207 keeps the object from being freed, but that is just an accident.
208 Possibly have and 'active' flag that is checked by the taint processor?
209Parameters for physics logging should be moved from BSScene to BSParam (at least boolean ones)
210Can some of the physical wrapper classes (BulletBody, BulletWorld, BulletShape) be 'sealed'?
211There are TOO MANY interfaces from BulletSim core to Bullet itself
212 Think of something to eliminate one or more of the layers
213
214THREADING
215=================================================
216Do taint action immediately if not actually executing Bullet.
217 Add lock around Bullet execution and just do taint actions if simulation is not happening.
218
219DONE DONE DONE DONE
220=================================================
221Cleanup code in BSDynamics by using motors. (Resolution: started)
222Consider implementing terrain with a mesh rather than heightmap. (Resolution: done)
223 Would have better and adjustable resolution.
224Build terrain mesh so heighmap is height of the center of the square meter.
225 Resolution: NOT DONE: SL and ODE define meter square as being at one corner with one diagional.
226Terrain as mesh. (Resolution: done)
227How are static linksets seen by the physics engine?
228 Resolution: they are not linked in physics. When moved, all the children are repositioned.
229Convert BSCharacter to use all API2 (Resolution: done)
230Avatar pushing difficult (too heavy?)
231Use asset service passed to BulletSim to get sculptie bodies, etc. (Resolution: done)
232Remove old code in DLL (all non-API2 stuff). (Resolution: done)
233Measurements of mega-physical prim performance (with graph) (Resolution: done, email)
234Debug Bullet internal stats output (why is timing all wrong?)
235 Resolution: Bullet stats logging only works with a single instance of Bullet (one region).
236Implement meshes or just verify that they work. (Resolution: they do!)
237Do prim hash codes work for sculpties and meshes? (Resolution: yes)
238Linkset implementation using compound shapes. (Resolution: implemented LinksetCompound)
239 Compound shapes will need the LocalID in the shapes and collision
240 processing to get it from there.
241Light cycle not banking (Resolution: It doesn't. Banking is roll adding yaw.)
242Package Bullet source mods for Bullet internal stats output
243 (Resolution: move code into WorldData.h rather than relying on patches)
244Single prim vehicles don't seem to properly vehiclize.
245 (Resolution: mass was not getting set properly for single prim linksets)
246Add material type linkage and input all the material property definitions.
247 Skeleton classes and table are in the sources but are not filled or used.
248 (Resolution:
249Neb vehicle taking > 25ms of physics time!!
250 (Resolution: compound linksets were being rebuild WAY too often)
251Avatar height off after unsitting (floats off ground)
252 Editting appearance then moving restores.
253 Must not be initializing height when recreating capsule after unsit.
254 (Resolution: confusion of scale vs size for native objects removed)
255Light cycle falling over when driving (Resolution: implemented angularMotorUp)
256Should vehicle angular/linear movement friction happen after all the components
257 or does it only apply to the basic movement?
258 (Resolution: friction added before returning newly computed motor value.
259 What is expected by some vehicles (turning up friction to moderate speed))
260Tune terrain/object friction to be closer to SL.
261 (Resolution: added material type with friction and resolution)
262Smooth avatar movement with motor (DONE)
263 Should motor update be all at taint-time? (Yes, DONE)
264 Fix avatar slowly sliding when standing (zero motion when stopped) (DONE)
265 (Resolution: added BSVMotor for avatar starting and stopping)
266llApplyImpulse()
267 Compare mass/movement in OS and SL. Calibrate actions. (DONE)
268 (Resolution: tested on SL and OS. AddForce scales the force for timestep)
269llSetBuoyancy() (DONE)
270 (Resolution: Bullet resets object gravity when added to world. Moved set gravity)
271Avatar density is WAY off. Compare and calibrate with what's in SL. (DONE)
272 (Resolution: set default density to 3.5 (from 60) which is closer to SL)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
deleted file mode 100644
index 0d1db3b..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,33 +0,0 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.Physics.BulletSPlugin")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("520ea11b-20cb-449d-ba05-c01015fed841")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]