BulletDotNETScene.cs 28 KB

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