BulletDotNETScene.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  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. using System;
  28. using System.Collections.Generic;
  29. using System.Reflection;
  30. using System.IO;
  31. using System.Diagnostics;
  32. using System.Threading;
  33. using log4net;
  34. using Nini.Config;
  35. using OpenSim.Framework;
  36. using OpenSim.Region.Physics.Manager;
  37. using OpenMetaverse;
  38. using BulletDotNET;
  39. namespace OpenSim.Region.Physics.BulletDotNETPlugin
  40. {
  41. public class BulletDotNETScene : PhysicsScene
  42. {
  43. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  44. // private string m_sceneIdentifier = string.Empty;
  45. private List<BulletDotNETCharacter> m_characters = new List<BulletDotNETCharacter>();
  46. private List<BulletDotNETPrim> m_prims = new List<BulletDotNETPrim>();
  47. private List<BulletDotNETPrim> m_activePrims = new List<BulletDotNETPrim>();
  48. private List<PhysicsActor> m_taintedActors = new List<PhysicsActor>();
  49. private btDiscreteDynamicsWorld m_world;
  50. private btAxisSweep3 m_broadphase;
  51. private btCollisionConfiguration m_collisionConfiguration;
  52. private btConstraintSolver m_solver;
  53. private btCollisionDispatcher m_dispatcher;
  54. private btHeightfieldTerrainShape m_terrainShape;
  55. public btRigidBody TerrainBody;
  56. private btVector3 m_terrainPosition;
  57. private btVector3 m_gravity;
  58. public btMotionState m_terrainMotionState;
  59. public btTransform m_terrainTransform;
  60. public btVector3 VectorZero;
  61. public btQuaternion QuatIdentity;
  62. public btTransform TransZero;
  63. public float geomDefaultDensity = 10.000006836f;
  64. private float avPIDD = 65f;
  65. private float avPIDP = 21f;
  66. private float avCapRadius = 0.37f;
  67. private float avStandupTensor = 2000000f;
  68. private float avDensity = 80f;
  69. private float avHeightFudgeFactor = 0.52f;
  70. private float avMovementDivisorWalk = 1.8f;
  71. private float avMovementDivisorRun = 0.8f;
  72. // private float minimumGroundFlightOffset = 3f;
  73. public bool meshSculptedPrim = true;
  74. public float meshSculptLOD = 32;
  75. public float MeshSculptphysicalLOD = 16;
  76. public float bodyPIDD = 35f;
  77. public float bodyPIDG = 25;
  78. internal int geomCrossingFailuresBeforeOutofbounds = 4;
  79. public float bodyMotorJointMaxforceTensor = 2;
  80. public int bodyFramesAutoDisable = 20;
  81. public float WorldTimeStep = 10f/60f;
  82. public const float WorldTimeComp = 1/60f;
  83. public float gravityz = -9.8f;
  84. private float[] _origheightmap; // Used for Fly height. Kitto Flora
  85. private bool usingGImpactAlgorithm = false;
  86. // private IConfigSource m_config;
  87. private readonly btVector3 worldAabbMin = new btVector3(-10f, -10f, 0);
  88. private readonly btVector3 worldAabbMax = new btVector3((int)Constants.RegionSize + 10f, (int)Constants.RegionSize + 10f, 9000);
  89. public IMesher mesher;
  90. private ContactAddedCallbackHandler m_CollisionInterface;
  91. public BulletDotNETScene(string sceneIdentifier)
  92. {
  93. // m_sceneIdentifier = sceneIdentifier;
  94. VectorZero = new btVector3(0, 0, 0);
  95. QuatIdentity = new btQuaternion(0, 0, 0, 1);
  96. TransZero = new btTransform(QuatIdentity, VectorZero);
  97. m_gravity = new btVector3(0, 0, gravityz);
  98. _origheightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize];
  99. }
  100. public override void Initialise(IMesher meshmerizer, IConfigSource config)
  101. {
  102. mesher = meshmerizer;
  103. // m_config = config;
  104. /*
  105. if (Environment.OSVersion.Platform == PlatformID.Unix)
  106. {
  107. m_log.Fatal("[BulletDotNET]: This configuration is not supported on *nix currently");
  108. Thread.Sleep(5000);
  109. Environment.Exit(0);
  110. }
  111. */
  112. m_broadphase = new btAxisSweep3(worldAabbMin, worldAabbMax, 16000);
  113. m_collisionConfiguration = new btDefaultCollisionConfiguration();
  114. m_solver = new btSequentialImpulseConstraintSolver();
  115. m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
  116. m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
  117. m_world.setGravity(m_gravity);
  118. //EnableCollisionInterface();
  119. }
  120. public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size, bool isFlying)
  121. {
  122. BulletDotNETCharacter chr = new BulletDotNETCharacter(avName, this, position, size, avPIDD, avPIDP,
  123. avCapRadius, avStandupTensor, avDensity,
  124. avHeightFudgeFactor, avMovementDivisorWalk,
  125. avMovementDivisorRun);
  126. m_characters.Add(chr);
  127. AddPhysicsActorTaint(chr);
  128. return chr;
  129. }
  130. public override void RemoveAvatar(PhysicsActor actor)
  131. {
  132. BulletDotNETCharacter chr = (BulletDotNETCharacter) actor;
  133. m_characters.Remove(chr);
  134. m_world.removeRigidBody(chr.Body);
  135. m_world.removeCollisionObject(chr.Body);
  136. chr.Remove();
  137. AddPhysicsActorTaint(chr);
  138. //chr = null;
  139. }
  140. public override void RemovePrim(PhysicsActor prim)
  141. {
  142. if (prim is BulletDotNETPrim)
  143. {
  144. BulletDotNETPrim p = (BulletDotNETPrim)prim;
  145. p.setPrimForRemoval();
  146. AddPhysicsActorTaint(prim);
  147. //RemovePrimThreadLocked(p);
  148. }
  149. }
  150. private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation,
  151. IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
  152. {
  153. PhysicsVector pos = new PhysicsVector(position.X, position.Y, position.Z);
  154. //pos.X = position.X;
  155. //pos.Y = position.Y;
  156. //pos.Z = position.Z;
  157. PhysicsVector siz = new PhysicsVector();
  158. siz.X = size.X;
  159. siz.Y = size.Y;
  160. siz.Z = size.Z;
  161. Quaternion rot = rotation;
  162. BulletDotNETPrim newPrim;
  163. newPrim = new BulletDotNETPrim(name, this, pos, siz, rot, mesh, pbs, isphysical);
  164. //lock (m_prims)
  165. // m_prims.Add(newPrim);
  166. return newPrim;
  167. }
  168. public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quaternion rotation)
  169. {
  170. return AddPrimShape(primName, pbs, position, size, rotation, false);
  171. }
  172. public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, PhysicsVector size, Quaternion rotation, bool isPhysical)
  173. {
  174. PhysicsActor result;
  175. IMesh mesh = null;
  176. //switch (pbs.ProfileShape)
  177. //{
  178. // case ProfileShape.Square:
  179. // //support simple box & hollow box now; later, more shapes
  180. // if (needsMeshing(pbs))
  181. // {
  182. // mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
  183. // }
  184. // break;
  185. //}
  186. if (needsMeshing(pbs))
  187. mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
  188. result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
  189. return result;
  190. }
  191. public override void AddPhysicsActorTaint(PhysicsActor prim)
  192. {
  193. lock (m_taintedActors)
  194. {
  195. if (!m_taintedActors.Contains(prim))
  196. {
  197. m_taintedActors.Add(prim);
  198. }
  199. }
  200. }
  201. internal void SetUsingGImpact()
  202. {
  203. if (!usingGImpactAlgorithm)
  204. btGImpactCollisionAlgorithm.registerAlgorithm(m_dispatcher);
  205. usingGImpactAlgorithm = true;
  206. }
  207. public override float Simulate(float timeStep)
  208. {
  209. lock (m_taintedActors)
  210. {
  211. foreach (PhysicsActor act in m_taintedActors)
  212. {
  213. if (act is BulletDotNETCharacter)
  214. ((BulletDotNETCharacter) act).ProcessTaints(timeStep);
  215. if (act is BulletDotNETPrim)
  216. ((BulletDotNETPrim)act).ProcessTaints(timeStep);
  217. }
  218. m_taintedActors.Clear();
  219. }
  220. lock (m_characters)
  221. {
  222. foreach (BulletDotNETCharacter chr in m_characters)
  223. {
  224. chr.Move(timeStep);
  225. }
  226. }
  227. lock (m_prims)
  228. {
  229. foreach (BulletDotNETPrim prim in m_prims)
  230. {
  231. if (prim != null)
  232. prim.Move(timeStep);
  233. }
  234. }
  235. float steps = m_world.stepSimulation(timeStep * 1000, 10, WorldTimeComp);
  236. foreach (BulletDotNETCharacter chr in m_characters)
  237. {
  238. chr.UpdatePositionAndVelocity();
  239. }
  240. foreach (BulletDotNETPrim prm in m_activePrims)
  241. {
  242. /*
  243. if (prm != null)
  244. if (prm.Body != null)
  245. */
  246. prm.UpdatePositionAndVelocity();
  247. }
  248. if (m_CollisionInterface != null)
  249. {
  250. List<int> collisions = m_CollisionInterface.GetContactList();
  251. lock (collisions)
  252. {
  253. foreach (int pvalue in collisions)
  254. {
  255. System.Console.Write(string.Format("{0} ", pvalue));
  256. }
  257. }
  258. m_CollisionInterface.Clear();
  259. }
  260. return steps;
  261. }
  262. public override void GetResults()
  263. {
  264. }
  265. public override void SetTerrain(float[] heightMap)
  266. {
  267. if (m_terrainShape != null)
  268. DeleteTerrain();
  269. float hfmax = -9000;
  270. float hfmin = 90000;
  271. for (int i = 0; i <heightMap.Length;i++)
  272. {
  273. if (Single.IsNaN(heightMap[i]) || Single.IsInfinity(heightMap[i]))
  274. {
  275. heightMap[i] = 0f;
  276. }
  277. hfmin = (heightMap[i] < hfmin) ? heightMap[i] : hfmin;
  278. hfmax = (heightMap[i] > hfmax) ? heightMap[i] : hfmax;
  279. }
  280. // store this for later reference.
  281. // Note, we're storing it after we check it for anomolies above
  282. _origheightmap = heightMap;
  283. hfmin = 0;
  284. hfmax = 256;
  285. m_terrainShape = new btHeightfieldTerrainShape((int)Constants.RegionSize, (int)Constants.RegionSize, heightMap,
  286. 1.0f, hfmin, hfmax, (int)btHeightfieldTerrainShape.UPAxis.Z,
  287. (int)btHeightfieldTerrainShape.PHY_ScalarType.PHY_FLOAT, false);
  288. float AabbCenterX = Constants.RegionSize/2f;
  289. float AabbCenterY = Constants.RegionSize/2f;
  290. float AabbCenterZ = 0;
  291. float temphfmin, temphfmax;
  292. temphfmin = hfmin;
  293. temphfmax = hfmax;
  294. if (temphfmin < 0)
  295. {
  296. temphfmax = 0 - temphfmin;
  297. temphfmin = 0 - temphfmin;
  298. }
  299. else if (temphfmin > 0)
  300. {
  301. temphfmax = temphfmax + (0 - temphfmin);
  302. //temphfmin = temphfmin + (0 - temphfmin);
  303. }
  304. AabbCenterZ = temphfmax/2f;
  305. if (m_terrainPosition == null)
  306. {
  307. m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
  308. }
  309. else
  310. {
  311. try
  312. {
  313. m_terrainPosition.setValue(AabbCenterX, AabbCenterY, AabbCenterZ);
  314. }
  315. catch (ObjectDisposedException)
  316. {
  317. m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
  318. }
  319. }
  320. if (m_terrainMotionState != null)
  321. {
  322. m_terrainMotionState.Dispose();
  323. m_terrainMotionState = null;
  324. }
  325. m_terrainTransform = new btTransform(QuatIdentity, m_terrainPosition);
  326. m_terrainMotionState = new btDefaultMotionState(m_terrainTransform);
  327. TerrainBody = new btRigidBody(0, m_terrainMotionState, m_terrainShape);
  328. m_world.addRigidBody(TerrainBody);
  329. }
  330. public override void SetWaterLevel(float baseheight)
  331. {
  332. }
  333. public override void DeleteTerrain()
  334. {
  335. if (TerrainBody != null)
  336. {
  337. m_world.removeRigidBody(TerrainBody);
  338. }
  339. if (m_terrainShape != null)
  340. {
  341. m_terrainShape.Dispose();
  342. m_terrainShape = null;
  343. }
  344. if (m_terrainMotionState != null)
  345. {
  346. m_terrainMotionState.Dispose();
  347. m_terrainMotionState = null;
  348. }
  349. if (m_terrainTransform != null)
  350. {
  351. m_terrainTransform.Dispose();
  352. m_terrainTransform = null;
  353. }
  354. if (m_terrainPosition != null)
  355. {
  356. m_terrainPosition.Dispose();
  357. m_terrainPosition = null;
  358. }
  359. }
  360. public override void Dispose()
  361. {
  362. disposeAllBodies();
  363. m_world.Dispose();
  364. m_broadphase.Dispose();
  365. ((btDefaultCollisionConfiguration) m_collisionConfiguration).Dispose();
  366. ((btSequentialImpulseConstraintSolver) m_solver).Dispose();
  367. worldAabbMax.Dispose();
  368. worldAabbMin.Dispose();
  369. VectorZero.Dispose();
  370. QuatIdentity.Dispose();
  371. m_gravity.Dispose();
  372. VectorZero = null;
  373. QuatIdentity = null;
  374. }
  375. public override Dictionary<uint, float> GetTopColliders()
  376. {
  377. return new Dictionary<uint, float>();
  378. }
  379. public btDiscreteDynamicsWorld getBulletWorld()
  380. {
  381. return m_world;
  382. }
  383. private void disposeAllBodies()
  384. {
  385. lock (m_prims)
  386. {
  387. foreach (BulletDotNETPrim prim in m_prims)
  388. {
  389. if (prim.Body != null)
  390. m_world.removeRigidBody(prim.Body);
  391. prim.Dispose();
  392. }
  393. m_prims.Clear();
  394. foreach (BulletDotNETCharacter chr in m_characters)
  395. {
  396. if (chr.Body != null)
  397. m_world.removeRigidBody(chr.Body);
  398. chr.Dispose();
  399. }
  400. m_characters.Clear();
  401. }
  402. }
  403. public override bool IsThreaded
  404. {
  405. get { return false; }
  406. }
  407. internal void addCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
  408. {
  409. //TODO: FIXME:
  410. }
  411. internal void remCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
  412. {
  413. //TODO: FIXME:
  414. }
  415. internal void AddRigidBody(btRigidBody Body)
  416. {
  417. m_world.addRigidBody(Body);
  418. }
  419. [Obsolete("bad!")]
  420. internal void removeFromWorld(btRigidBody body)
  421. {
  422. m_world.removeRigidBody(body);
  423. }
  424. internal void removeFromWorld(BulletDotNETPrim prm ,btRigidBody body)
  425. {
  426. lock (m_prims)
  427. {
  428. if (m_prims.Contains(prm))
  429. {
  430. m_world.removeRigidBody(body);
  431. }
  432. remActivePrim(prm);
  433. m_prims.Remove(prm);
  434. }
  435. }
  436. internal float GetWaterLevel()
  437. {
  438. throw new NotImplementedException();
  439. }
  440. // Recovered for use by fly height. Kitto Flora
  441. public float GetTerrainHeightAtXY(float x, float y)
  442. {
  443. // Teravus: Kitto, this code causes recurring errors that stall physics permenantly unless
  444. // the values are checked, so checking below.
  445. // Is there any reason that we don't do this in ScenePresence?
  446. // The only physics engine that benefits from it in the physics plugin is this one
  447. if (x > (int)Constants.RegionSize || y > (int)Constants.RegionSize ||
  448. x < 0.001f || y < 0.001f)
  449. return 0;
  450. return _origheightmap[(int)y * Constants.RegionSize + (int)x];
  451. }
  452. // End recovered. Kitto Flora
  453. /// <summary>
  454. /// Routine to figure out if we need to mesh this prim with our mesher
  455. /// </summary>
  456. /// <param name="pbs"></param>
  457. /// <returns></returns>
  458. public bool needsMeshing(PrimitiveBaseShape pbs)
  459. {
  460. // most of this is redundant now as the mesher will return null if it cant mesh a prim
  461. // but we still need to check for sculptie meshing being enabled so this is the most
  462. // convenient place to do it for now...
  463. // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
  464. // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
  465. int iPropertiesNotSupportedDefault = 0;
  466. if (pbs.SculptEntry && !meshSculptedPrim)
  467. {
  468. #if SPAM
  469. m_log.Warn("NonMesh");
  470. #endif
  471. return false;
  472. }
  473. // 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
  474. if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
  475. || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
  476. && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
  477. {
  478. if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
  479. && pbs.ProfileHollow == 0
  480. && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
  481. && pbs.PathBegin == 0 && pbs.PathEnd == 0
  482. && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
  483. && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
  484. && pbs.PathShearX == 0 && pbs.PathShearY == 0)
  485. {
  486. #if SPAM
  487. m_log.Warn("NonMesh");
  488. #endif
  489. return false;
  490. }
  491. }
  492. if (pbs.ProfileHollow != 0)
  493. iPropertiesNotSupportedDefault++;
  494. if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
  495. iPropertiesNotSupportedDefault++;
  496. if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
  497. iPropertiesNotSupportedDefault++;
  498. if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
  499. iPropertiesNotSupportedDefault++;
  500. if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
  501. iPropertiesNotSupportedDefault++;
  502. if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
  503. iPropertiesNotSupportedDefault++;
  504. 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))
  505. iPropertiesNotSupportedDefault++;
  506. if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
  507. iPropertiesNotSupportedDefault++;
  508. // test for torus
  509. if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
  510. {
  511. if (pbs.PathCurve == (byte)Extrusion.Curve1)
  512. {
  513. iPropertiesNotSupportedDefault++;
  514. }
  515. }
  516. else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
  517. {
  518. if (pbs.PathCurve == (byte)Extrusion.Straight)
  519. {
  520. iPropertiesNotSupportedDefault++;
  521. }
  522. // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
  523. else if (pbs.PathCurve == (byte)Extrusion.Curve1)
  524. {
  525. iPropertiesNotSupportedDefault++;
  526. }
  527. }
  528. else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
  529. {
  530. if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
  531. {
  532. iPropertiesNotSupportedDefault++;
  533. }
  534. }
  535. else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
  536. {
  537. if (pbs.PathCurve == (byte)Extrusion.Straight)
  538. {
  539. iPropertiesNotSupportedDefault++;
  540. }
  541. else if (pbs.PathCurve == (byte)Extrusion.Curve1)
  542. {
  543. iPropertiesNotSupportedDefault++;
  544. }
  545. }
  546. if (iPropertiesNotSupportedDefault == 0)
  547. {
  548. #if SPAM
  549. m_log.Warn("NonMesh");
  550. #endif
  551. return false;
  552. }
  553. #if SPAM
  554. m_log.Debug("Mesh");
  555. #endif
  556. return true;
  557. }
  558. internal void addActivePrim(BulletDotNETPrim pPrim)
  559. {
  560. lock (m_activePrims)
  561. {
  562. if (!m_activePrims.Contains(pPrim))
  563. {
  564. m_activePrims.Add(pPrim);
  565. }
  566. }
  567. }
  568. public void remActivePrim(BulletDotNETPrim pDeactivatePrim)
  569. {
  570. lock (m_activePrims)
  571. {
  572. m_activePrims.Remove(pDeactivatePrim);
  573. }
  574. }
  575. internal void AddPrimToScene(BulletDotNETPrim pPrim)
  576. {
  577. lock (m_prims)
  578. {
  579. if (!m_prims.Contains(pPrim))
  580. {
  581. m_prims.Add(pPrim);
  582. m_world.addRigidBody(pPrim.Body);
  583. m_log.Debug("ADDED");
  584. }
  585. }
  586. }
  587. internal void EnableCollisionInterface()
  588. {
  589. if (m_CollisionInterface == null)
  590. {
  591. m_CollisionInterface = new ContactAddedCallbackHandler();
  592. m_world.SetCollisionAddedCallback(m_CollisionInterface);
  593. }
  594. }
  595. }
  596. }