aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs')
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs776
1 files changed, 0 insertions, 776 deletions
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
deleted file mode 100644
index 0d1bd82..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETScene.cs
+++ /dev/null
@@ -1,776 +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.Reflection;
31using System.IO;
32using System.Diagnostics;
33using System.Threading;
34using log4net;
35using Nini.Config;
36using OpenSim.Framework;
37using OpenSim.Region.Physics.Manager;
38using OpenMetaverse;
39using BulletDotNET;
40
41namespace OpenSim.Region.Physics.BulletDotNETPlugin
42{
43 public class BulletDotNETScene : PhysicsScene
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 // private string m_sceneIdentifier = string.Empty;
48
49 private List<BulletDotNETCharacter> m_characters = new List<BulletDotNETCharacter>();
50 private Dictionary<uint, BulletDotNETCharacter> m_charactersLocalID = new Dictionary<uint, BulletDotNETCharacter>();
51 private List<BulletDotNETPrim> m_prims = new List<BulletDotNETPrim>();
52 private Dictionary<uint, BulletDotNETPrim> m_primsLocalID = new Dictionary<uint, BulletDotNETPrim>();
53 private List<BulletDotNETPrim> m_activePrims = new List<BulletDotNETPrim>();
54 private List<PhysicsActor> m_taintedActors = new List<PhysicsActor>();
55 private btDiscreteDynamicsWorld m_world;
56 private btAxisSweep3 m_broadphase;
57 private btCollisionConfiguration m_collisionConfiguration;
58 private btConstraintSolver m_solver;
59 private btCollisionDispatcher m_dispatcher;
60 private btHeightfieldTerrainShape m_terrainShape;
61 public btRigidBody TerrainBody;
62 private btVector3 m_terrainPosition;
63 private btVector3 m_gravity;
64 public btMotionState m_terrainMotionState;
65 public btTransform m_terrainTransform;
66 public btVector3 VectorZero;
67 public btQuaternion QuatIdentity;
68 public btTransform TransZero;
69
70 public float geomDefaultDensity = 10.000006836f;
71
72 private float avPIDD = 65f;
73 private float avPIDP = 21f;
74 private float avCapRadius = 0.37f;
75 private float avStandupTensor = 2000000f;
76 private float avDensity = 80f;
77 private float avHeightFudgeFactor = 0.52f;
78 private float avMovementDivisorWalk = 1.8f;
79 private float avMovementDivisorRun = 0.8f;
80
81 // private float minimumGroundFlightOffset = 3f;
82
83 public bool meshSculptedPrim = true;
84
85 public float meshSculptLOD = 32;
86 public float MeshSculptphysicalLOD = 16;
87
88 public float bodyPIDD = 35f;
89 public float bodyPIDG = 25;
90 internal int geomCrossingFailuresBeforeOutofbounds = 4;
91
92 public float bodyMotorJointMaxforceTensor = 2;
93
94 public int bodyFramesAutoDisable = 20;
95
96 public float WorldTimeStep = 10f/60f;
97 public const float WorldTimeComp = 1/60f;
98 public float gravityz = -9.8f;
99
100 private float[] _origheightmap; // Used for Fly height. Kitto Flora
101 private bool usingGImpactAlgorithm = false;
102
103 // private IConfigSource m_config;
104 private readonly btVector3 worldAabbMin = new btVector3(-10f, -10f, 0);
105 private readonly btVector3 worldAabbMax = new btVector3((int)Constants.RegionSize + 10f, (int)Constants.RegionSize + 10f, 9000);
106
107 public IMesher mesher;
108 private ContactAddedCallbackHandler m_CollisionInterface;
109
110 public BulletDotNETScene(string sceneIdentifier)
111 {
112 // m_sceneIdentifier = sceneIdentifier;
113 VectorZero = new btVector3(0, 0, 0);
114 QuatIdentity = new btQuaternion(0, 0, 0, 1);
115 TransZero = new btTransform(QuatIdentity, VectorZero);
116 m_gravity = new btVector3(0, 0, gravityz);
117 _origheightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize];
118
119 }
120
121 public override void Initialise(IMesher meshmerizer, IConfigSource config)
122 {
123 mesher = meshmerizer;
124 // m_config = config;
125 /*
126 if (Environment.OSVersion.Platform == PlatformID.Unix)
127 {
128 m_log.Fatal("[BulletDotNET]: This configuration is not supported on *nix currently");
129 Thread.Sleep(5000);
130 Environment.Exit(0);
131 }
132 */
133 m_broadphase = new btAxisSweep3(worldAabbMin, worldAabbMax, 16000);
134 m_collisionConfiguration = new btDefaultCollisionConfiguration();
135 m_solver = new btSequentialImpulseConstraintSolver();
136 m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
137 m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
138 m_world.setGravity(m_gravity);
139 EnableCollisionInterface();
140
141
142 }
143
144 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
145 {
146 BulletDotNETCharacter chr = new BulletDotNETCharacter(avName, this, position, size, avPIDD, avPIDP,
147 avCapRadius, avStandupTensor, avDensity,
148 avHeightFudgeFactor, avMovementDivisorWalk,
149 avMovementDivisorRun);
150 try
151 {
152 m_characters.Add(chr);
153 m_charactersLocalID.Add(chr.m_localID, chr);
154 }
155 catch
156 {
157 // noop if it's already there
158 m_log.Debug("[PHYSICS] BulletDotNet: adding duplicate avatar localID");
159 }
160 AddPhysicsActorTaint(chr);
161 return chr;
162 }
163
164 public override void RemoveAvatar(PhysicsActor actor)
165 {
166 BulletDotNETCharacter chr = (BulletDotNETCharacter) actor;
167
168 m_charactersLocalID.Remove(chr.m_localID);
169 m_characters.Remove(chr);
170 m_world.removeRigidBody(chr.Body);
171 m_world.removeCollisionObject(chr.Body);
172
173 chr.Remove();
174 AddPhysicsActorTaint(chr);
175 //chr = null;
176 }
177
178 public override void RemovePrim(PhysicsActor prim)
179 {
180 if (prim is BulletDotNETPrim)
181 {
182
183 BulletDotNETPrim p = (BulletDotNETPrim)prim;
184
185 p.setPrimForRemoval();
186 AddPhysicsActorTaint(prim);
187 //RemovePrimThreadLocked(p);
188
189 }
190 }
191
192 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
193 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
194 {
195 Vector3 pos = position;
196 //pos.X = position.X;
197 //pos.Y = position.Y;
198 //pos.Z = position.Z;
199 Vector3 siz = Vector3.Zero;
200 siz.X = size.X;
201 siz.Y = size.Y;
202 siz.Z = size.Z;
203 Quaternion rot = rotation;
204
205 BulletDotNETPrim newPrim;
206
207 newPrim = new BulletDotNETPrim(name, this, pos, siz, rot, mesh, pbs, isphysical);
208
209 //lock (m_prims)
210 // m_prims.Add(newPrim);
211
212
213 return newPrim;
214 }
215
216 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
217 {
218 PhysicsActor result;
219 IMesh mesh = null;
220
221 //switch (pbs.ProfileShape)
222 //{
223 // case ProfileShape.Square:
224 // //support simple box & hollow box now; later, more shapes
225 // if (needsMeshing(pbs))
226 // {
227 // mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
228 // }
229
230 // break;
231 //}
232
233 if (needsMeshing(pbs))
234 mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
235
236 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
237
238 return result;
239 }
240
241 public override void AddPhysicsActorTaint(PhysicsActor prim)
242 {
243 lock (m_taintedActors)
244 {
245 if (!m_taintedActors.Contains(prim))
246 {
247 m_taintedActors.Add(prim);
248 }
249 }
250 }
251 internal void SetUsingGImpact()
252 {
253 if (!usingGImpactAlgorithm)
254 btGImpactCollisionAlgorithm.registerAlgorithm(m_dispatcher);
255 usingGImpactAlgorithm = true;
256 }
257
258 public override float Simulate(float timeStep)
259 {
260
261 lock (m_taintedActors)
262 {
263 foreach (PhysicsActor act in m_taintedActors)
264 {
265 if (act is BulletDotNETCharacter)
266 ((BulletDotNETCharacter) act).ProcessTaints(timeStep);
267 if (act is BulletDotNETPrim)
268 ((BulletDotNETPrim)act).ProcessTaints(timeStep);
269 }
270 m_taintedActors.Clear();
271 }
272
273 lock (m_characters)
274 {
275 foreach (BulletDotNETCharacter chr in m_characters)
276 {
277 chr.Move(timeStep);
278 }
279 }
280
281 lock (m_prims)
282 {
283 foreach (BulletDotNETPrim prim in m_prims)
284 {
285 if (prim != null)
286 prim.Move(timeStep);
287 }
288 }
289 float steps = m_world.stepSimulation(timeStep, 10, WorldTimeComp);
290
291 foreach (BulletDotNETCharacter chr in m_characters)
292 {
293 chr.UpdatePositionAndVelocity();
294 }
295
296 foreach (BulletDotNETPrim prm in m_activePrims)
297 {
298 /*
299 if (prm != null)
300 if (prm.Body != null)
301 */
302 prm.UpdatePositionAndVelocity();
303 }
304 if (m_CollisionInterface != null)
305 {
306 List<BulletDotNETPrim> primsWithCollisions = new List<BulletDotNETPrim>();
307 List<BulletDotNETCharacter> charactersWithCollisions = new List<BulletDotNETCharacter>();
308
309 // get the collisions that happened this tick
310 List<BulletDotNET.ContactAddedCallbackHandler.ContactInfo> collisions = m_CollisionInterface.GetContactList();
311 // passed back the localID of the prim so we can associate the prim
312 foreach (BulletDotNET.ContactAddedCallbackHandler.ContactInfo ci in collisions)
313 {
314 // ContactPoint = { contactPoint, contactNormal, penetrationDepth }
315 ContactPoint contact = new ContactPoint(new Vector3(ci.pX, ci.pY, ci.pZ),
316 new Vector3(ci.nX, ci.nY, ci.nZ), ci.depth);
317
318 ProcessContact(ci.contact, ci.contactWith, contact, ref primsWithCollisions, ref charactersWithCollisions);
319 ProcessContact(ci.contactWith, ci.contact, contact, ref primsWithCollisions, ref charactersWithCollisions);
320
321 }
322 m_CollisionInterface.Clear();
323 // for those prims and characters that had collisions cause collision events
324 foreach (BulletDotNETPrim bdnp in primsWithCollisions)
325 {
326 bdnp.SendCollisions();
327 }
328 foreach (BulletDotNETCharacter bdnc in charactersWithCollisions)
329 {
330 bdnc.SendCollisions();
331 }
332 }
333 return steps;
334 }
335
336 private void ProcessContact(uint cont, uint contWith, ContactPoint contact,
337 ref List<BulletDotNETPrim> primsWithCollisions,
338 ref List<BulletDotNETCharacter> charactersWithCollisions)
339 {
340 BulletDotNETPrim bdnp;
341 // collisions with a normal prim?
342 if (m_primsLocalID.TryGetValue(cont, out bdnp))
343 {
344 // Added collision event to the prim. This creates a pile of events
345 // that will be sent to any subscribed listeners.
346 bdnp.AddCollision(contWith, contact);
347 if (!primsWithCollisions.Contains(bdnp))
348 {
349 primsWithCollisions.Add(bdnp);
350 }
351 }
352 else
353 {
354 BulletDotNETCharacter bdnc;
355 // if not a prim, maybe it's one of the characters
356 if (m_charactersLocalID.TryGetValue(cont, out bdnc))
357 {
358 bdnc.AddCollision(contWith, contact);
359 if (!charactersWithCollisions.Contains(bdnc))
360 {
361 charactersWithCollisions.Add(bdnc);
362 }
363 }
364 }
365 }
366
367 public override void GetResults()
368 {
369
370 }
371
372 public override void SetTerrain(float[] heightMap)
373 {
374 if (m_terrainShape != null)
375 DeleteTerrain();
376
377 float hfmax = -9000;
378 float hfmin = 90000;
379
380 for (int i = 0; i <heightMap.Length;i++)
381 {
382 if (Single.IsNaN(heightMap[i]) || Single.IsInfinity(heightMap[i]))
383 {
384 heightMap[i] = 0f;
385 }
386
387 hfmin = (heightMap[i] < hfmin) ? heightMap[i] : hfmin;
388 hfmax = (heightMap[i] > hfmax) ? heightMap[i] : hfmax;
389 }
390 // store this for later reference.
391 // Note, we're storing it after we check it for anomolies above
392 _origheightmap = heightMap;
393
394 hfmin = 0;
395 hfmax = 256;
396
397 m_terrainShape = new btHeightfieldTerrainShape((int)Constants.RegionSize, (int)Constants.RegionSize, heightMap,
398 1.0f, hfmin, hfmax, (int)btHeightfieldTerrainShape.UPAxis.Z,
399 (int)btHeightfieldTerrainShape.PHY_ScalarType.PHY_FLOAT, false);
400 float AabbCenterX = Constants.RegionSize/2f;
401 float AabbCenterY = Constants.RegionSize/2f;
402
403 float AabbCenterZ = 0;
404 float temphfmin, temphfmax;
405
406 temphfmin = hfmin;
407 temphfmax = hfmax;
408
409 if (temphfmin < 0)
410 {
411 temphfmax = 0 - temphfmin;
412 temphfmin = 0 - temphfmin;
413 }
414 else if (temphfmin > 0)
415 {
416 temphfmax = temphfmax + (0 - temphfmin);
417 //temphfmin = temphfmin + (0 - temphfmin);
418 }
419 AabbCenterZ = temphfmax/2f;
420
421 if (m_terrainPosition == null)
422 {
423 m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
424 }
425 else
426 {
427 try
428 {
429 m_terrainPosition.setValue(AabbCenterX, AabbCenterY, AabbCenterZ);
430 }
431 catch (ObjectDisposedException)
432 {
433 m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
434 }
435 }
436 if (m_terrainMotionState != null)
437 {
438 m_terrainMotionState.Dispose();
439 m_terrainMotionState = null;
440 }
441 m_terrainTransform = new btTransform(QuatIdentity, m_terrainPosition);
442 m_terrainMotionState = new btDefaultMotionState(m_terrainTransform);
443 TerrainBody = new btRigidBody(0, m_terrainMotionState, m_terrainShape);
444 TerrainBody.setUserPointer((IntPtr)0);
445 m_world.addRigidBody(TerrainBody);
446
447
448 }
449
450 public override void SetWaterLevel(float baseheight)
451 {
452
453 }
454
455 public override void DeleteTerrain()
456 {
457 if (TerrainBody != null)
458 {
459 m_world.removeRigidBody(TerrainBody);
460 }
461
462 if (m_terrainShape != null)
463 {
464 m_terrainShape.Dispose();
465 m_terrainShape = null;
466 }
467
468 if (m_terrainMotionState != null)
469 {
470 m_terrainMotionState.Dispose();
471 m_terrainMotionState = null;
472 }
473
474 if (m_terrainTransform != null)
475 {
476 m_terrainTransform.Dispose();
477 m_terrainTransform = null;
478 }
479
480 if (m_terrainPosition != null)
481 {
482 m_terrainPosition.Dispose();
483 m_terrainPosition = null;
484 }
485 }
486
487 public override void Dispose()
488 {
489 disposeAllBodies();
490 m_world.Dispose();
491 m_broadphase.Dispose();
492 ((btDefaultCollisionConfiguration) m_collisionConfiguration).Dispose();
493 ((btSequentialImpulseConstraintSolver) m_solver).Dispose();
494 worldAabbMax.Dispose();
495 worldAabbMin.Dispose();
496 VectorZero.Dispose();
497 QuatIdentity.Dispose();
498 m_gravity.Dispose();
499 VectorZero = null;
500 QuatIdentity = null;
501 }
502
503 public override Dictionary<uint, float> GetTopColliders()
504 {
505 return new Dictionary<uint, float>();
506 }
507
508 public btDiscreteDynamicsWorld getBulletWorld()
509 {
510 return m_world;
511 }
512
513 private void disposeAllBodies()
514 {
515 lock (m_prims)
516 {
517 m_primsLocalID.Clear();
518 foreach (BulletDotNETPrim prim in m_prims)
519 {
520 if (prim.Body != null)
521 m_world.removeRigidBody(prim.Body);
522
523 prim.Dispose();
524 }
525 m_prims.Clear();
526
527 foreach (BulletDotNETCharacter chr in m_characters)
528 {
529 if (chr.Body != null)
530 m_world.removeRigidBody(chr.Body);
531 chr.Dispose();
532 }
533 m_characters.Clear();
534 }
535 }
536
537 public override bool IsThreaded
538 {
539 get { return false; }
540 }
541
542 internal void addCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
543 {
544 //TODO: FIXME:
545 }
546
547 internal void remCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
548 {
549 //TODO: FIXME:
550 }
551
552 internal void AddRigidBody(btRigidBody Body)
553 {
554 m_world.addRigidBody(Body);
555 }
556 [Obsolete("bad!")]
557 internal void removeFromWorld(btRigidBody body)
558 {
559
560 m_world.removeRigidBody(body);
561 }
562
563 internal void removeFromWorld(BulletDotNETPrim prm ,btRigidBody body)
564 {
565 lock (m_prims)
566 {
567 if (m_prims.Contains(prm))
568 {
569 m_world.removeRigidBody(body);
570 }
571 remActivePrim(prm);
572 m_primsLocalID.Remove(prm.m_localID);
573 m_prims.Remove(prm);
574 }
575
576 }
577
578 internal float GetWaterLevel()
579 {
580 throw new NotImplementedException();
581 }
582
583 // Recovered for use by fly height. Kitto Flora
584 public float GetTerrainHeightAtXY(float x, float y)
585 {
586 // Teravus: Kitto, this code causes recurring errors that stall physics permenantly unless
587 // the values are checked, so checking below.
588 // Is there any reason that we don't do this in ScenePresence?
589 // The only physics engine that benefits from it in the physics plugin is this one
590
591 if (x > (int)Constants.RegionSize || y > (int)Constants.RegionSize ||
592 x < 0.001f || y < 0.001f)
593 return 0;
594
595 return _origheightmap[(int)y * Constants.RegionSize + (int)x];
596 }
597 // End recovered. Kitto Flora
598
599 /// <summary>
600 /// Routine to figure out if we need to mesh this prim with our mesher
601 /// </summary>
602 /// <param name="pbs"></param>
603 /// <returns></returns>
604 public bool needsMeshing(PrimitiveBaseShape pbs)
605 {
606 // most of this is redundant now as the mesher will return null if it cant mesh a prim
607 // but we still need to check for sculptie meshing being enabled so this is the most
608 // convenient place to do it for now...
609
610 // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
611 // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
612 int iPropertiesNotSupportedDefault = 0;
613
614 if (pbs.SculptEntry && !meshSculptedPrim)
615 {
616#if SPAM
617 m_log.Warn("NonMesh");
618#endif
619 return false;
620 }
621
622 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
623 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
624 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
625 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
626 {
627
628 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
629 && pbs.ProfileHollow == 0
630 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
631 && pbs.PathBegin == 0 && pbs.PathEnd == 0
632 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
633 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
634 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
635 {
636#if SPAM
637 m_log.Warn("NonMesh");
638#endif
639 return false;
640 }
641 }
642
643 if (pbs.ProfileHollow != 0)
644 iPropertiesNotSupportedDefault++;
645
646 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
647 iPropertiesNotSupportedDefault++;
648
649 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
650 iPropertiesNotSupportedDefault++;
651
652 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
653 iPropertiesNotSupportedDefault++;
654
655 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
656 iPropertiesNotSupportedDefault++;
657
658 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
659 iPropertiesNotSupportedDefault++;
660
661 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
662 iPropertiesNotSupportedDefault++;
663
664 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
665 iPropertiesNotSupportedDefault++;
666
667 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
668 iPropertiesNotSupportedDefault++;
669
670 // test for torus
671 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
672 {
673 if (pbs.PathCurve == (byte)Extrusion.Curve1)
674 {
675 iPropertiesNotSupportedDefault++;
676 }
677 }
678 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
679 {
680 if (pbs.PathCurve == (byte)Extrusion.Straight)
681 {
682 iPropertiesNotSupportedDefault++;
683 }
684
685 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
686 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
687 {
688 iPropertiesNotSupportedDefault++;
689 }
690 }
691 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
692 {
693 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
694 {
695 iPropertiesNotSupportedDefault++;
696 }
697 }
698 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
699 {
700 if (pbs.PathCurve == (byte)Extrusion.Straight)
701 {
702 iPropertiesNotSupportedDefault++;
703 }
704 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
705 {
706 iPropertiesNotSupportedDefault++;
707 }
708 }
709
710
711 if (iPropertiesNotSupportedDefault == 0)
712 {
713#if SPAM
714 m_log.Warn("NonMesh");
715#endif
716 return false;
717 }
718#if SPAM
719 m_log.Debug("Mesh");
720#endif
721 return true;
722 }
723
724 internal void addActivePrim(BulletDotNETPrim pPrim)
725 {
726 lock (m_activePrims)
727 {
728 if (!m_activePrims.Contains(pPrim))
729 {
730 m_activePrims.Add(pPrim);
731 }
732 }
733 }
734
735 public void remActivePrim(BulletDotNETPrim pDeactivatePrim)
736 {
737 lock (m_activePrims)
738 {
739 m_activePrims.Remove(pDeactivatePrim);
740 }
741 }
742
743 internal void AddPrimToScene(BulletDotNETPrim pPrim)
744 {
745 lock (m_prims)
746 {
747 if (!m_prims.Contains(pPrim))
748 {
749 try
750 {
751 m_prims.Add(pPrim);
752 m_primsLocalID.Add(pPrim.m_localID, pPrim);
753 }
754 catch
755 {
756 // noop if it's already there
757 m_log.Debug("[PHYSICS] BulletDotNet: adding duplicate prim localID");
758 }
759 m_world.addRigidBody(pPrim.Body);
760 // m_log.Debug("[PHYSICS] added prim to scene");
761 }
762 }
763 }
764 internal void EnableCollisionInterface()
765 {
766 if (m_CollisionInterface == null)
767 {
768 m_CollisionInterface = new ContactAddedCallbackHandler(m_world);
769 // m_world.SetCollisionAddedCallback(m_CollisionInterface);
770 }
771 }
772
773
774
775 }
776}