BulletDotNETScene.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  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)
  181. {
  182. return AddPrimShape(primName, pbs, position, size, rotation, false);
  183. }
  184. public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, Vector3 size, Quaternion rotation, bool isPhysical)
  185. {
  186. PhysicsActor result;
  187. IMesh mesh = null;
  188. //switch (pbs.ProfileShape)
  189. //{
  190. // case ProfileShape.Square:
  191. // //support simple box & hollow box now; later, more shapes
  192. // if (needsMeshing(pbs))
  193. // {
  194. // mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
  195. // }
  196. // break;
  197. //}
  198. if (needsMeshing(pbs))
  199. mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
  200. result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
  201. return result;
  202. }
  203. public override void AddPhysicsActorTaint(PhysicsActor prim)
  204. {
  205. lock (m_taintedActors)
  206. {
  207. if (!m_taintedActors.Contains(prim))
  208. {
  209. m_taintedActors.Add(prim);
  210. }
  211. }
  212. }
  213. internal void SetUsingGImpact()
  214. {
  215. if (!usingGImpactAlgorithm)
  216. btGImpactCollisionAlgorithm.registerAlgorithm(m_dispatcher);
  217. usingGImpactAlgorithm = true;
  218. }
  219. public override float Simulate(float timeStep)
  220. {
  221. lock (m_taintedActors)
  222. {
  223. foreach (PhysicsActor act in m_taintedActors)
  224. {
  225. if (act is BulletDotNETCharacter)
  226. ((BulletDotNETCharacter) act).ProcessTaints(timeStep);
  227. if (act is BulletDotNETPrim)
  228. ((BulletDotNETPrim)act).ProcessTaints(timeStep);
  229. }
  230. m_taintedActors.Clear();
  231. }
  232. lock (m_characters)
  233. {
  234. foreach (BulletDotNETCharacter chr in m_characters)
  235. {
  236. chr.Move(timeStep);
  237. }
  238. }
  239. lock (m_prims)
  240. {
  241. foreach (BulletDotNETPrim prim in m_prims)
  242. {
  243. if (prim != null)
  244. prim.Move(timeStep);
  245. }
  246. }
  247. float steps = m_world.stepSimulation(timeStep, 10, WorldTimeComp);
  248. foreach (BulletDotNETCharacter chr in m_characters)
  249. {
  250. chr.UpdatePositionAndVelocity();
  251. }
  252. foreach (BulletDotNETPrim prm in m_activePrims)
  253. {
  254. /*
  255. if (prm != null)
  256. if (prm.Body != null)
  257. */
  258. prm.UpdatePositionAndVelocity();
  259. }
  260. if (m_CollisionInterface != null)
  261. {
  262. List<BulletDotNETPrim> primsWithCollisions = new List<BulletDotNETPrim>();
  263. List<BulletDotNETCharacter> charactersWithCollisions = new List<BulletDotNETCharacter>();
  264. // get the collisions that happened this tick
  265. List<BulletDotNET.ContactAddedCallbackHandler.ContactInfo> collisions = m_CollisionInterface.GetContactList();
  266. // passed back the localID of the prim so we can associate the prim
  267. foreach (BulletDotNET.ContactAddedCallbackHandler.ContactInfo ci in collisions)
  268. {
  269. // ContactPoint = { contactPoint, contactNormal, penetrationDepth }
  270. ContactPoint contact = new ContactPoint(new Vector3(ci.pX, ci.pY, ci.pZ),
  271. new Vector3(ci.nX, ci.nY, ci.nZ), ci.depth);
  272. ProcessContact(ci.contact, ci.contactWith, contact, ref primsWithCollisions, ref charactersWithCollisions);
  273. ProcessContact(ci.contactWith, ci.contact, contact, ref primsWithCollisions, ref charactersWithCollisions);
  274. }
  275. m_CollisionInterface.Clear();
  276. // for those prims and characters that had collisions cause collision events
  277. foreach (BulletDotNETPrim bdnp in primsWithCollisions)
  278. {
  279. bdnp.SendCollisions();
  280. }
  281. foreach (BulletDotNETCharacter bdnc in charactersWithCollisions)
  282. {
  283. bdnc.SendCollisions();
  284. }
  285. }
  286. return steps;
  287. }
  288. private void ProcessContact(uint cont, uint contWith, ContactPoint contact,
  289. ref List<BulletDotNETPrim> primsWithCollisions,
  290. ref List<BulletDotNETCharacter> charactersWithCollisions)
  291. {
  292. BulletDotNETPrim bdnp;
  293. // collisions with a normal prim?
  294. if (m_primsLocalID.TryGetValue(cont, out bdnp))
  295. {
  296. // Added collision event to the prim. This creates a pile of events
  297. // that will be sent to any subscribed listeners.
  298. bdnp.AddCollision(contWith, contact);
  299. if (!primsWithCollisions.Contains(bdnp))
  300. {
  301. primsWithCollisions.Add(bdnp);
  302. }
  303. }
  304. else
  305. {
  306. BulletDotNETCharacter bdnc;
  307. // if not a prim, maybe it's one of the characters
  308. if (m_charactersLocalID.TryGetValue(cont, out bdnc))
  309. {
  310. bdnc.AddCollision(contWith, contact);
  311. if (!charactersWithCollisions.Contains(bdnc))
  312. {
  313. charactersWithCollisions.Add(bdnc);
  314. }
  315. }
  316. }
  317. }
  318. public override void GetResults()
  319. {
  320. }
  321. public override void SetTerrain(float[] heightMap)
  322. {
  323. if (m_terrainShape != null)
  324. DeleteTerrain();
  325. float hfmax = -9000;
  326. float hfmin = 90000;
  327. for (int i = 0; i <heightMap.Length;i++)
  328. {
  329. if (Single.IsNaN(heightMap[i]) || Single.IsInfinity(heightMap[i]))
  330. {
  331. heightMap[i] = 0f;
  332. }
  333. hfmin = (heightMap[i] < hfmin) ? heightMap[i] : hfmin;
  334. hfmax = (heightMap[i] > hfmax) ? heightMap[i] : hfmax;
  335. }
  336. // store this for later reference.
  337. // Note, we're storing it after we check it for anomolies above
  338. _origheightmap = heightMap;
  339. hfmin = 0;
  340. hfmax = 256;
  341. m_terrainShape = new btHeightfieldTerrainShape((int)Constants.RegionSize, (int)Constants.RegionSize, heightMap,
  342. 1.0f, hfmin, hfmax, (int)btHeightfieldTerrainShape.UPAxis.Z,
  343. (int)btHeightfieldTerrainShape.PHY_ScalarType.PHY_FLOAT, false);
  344. float AabbCenterX = Constants.RegionSize/2f;
  345. float AabbCenterY = Constants.RegionSize/2f;
  346. float AabbCenterZ = 0;
  347. float temphfmin, temphfmax;
  348. temphfmin = hfmin;
  349. temphfmax = hfmax;
  350. if (temphfmin < 0)
  351. {
  352. temphfmax = 0 - temphfmin;
  353. temphfmin = 0 - temphfmin;
  354. }
  355. else if (temphfmin > 0)
  356. {
  357. temphfmax = temphfmax + (0 - temphfmin);
  358. //temphfmin = temphfmin + (0 - temphfmin);
  359. }
  360. AabbCenterZ = temphfmax/2f;
  361. if (m_terrainPosition == null)
  362. {
  363. m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
  364. }
  365. else
  366. {
  367. try
  368. {
  369. m_terrainPosition.setValue(AabbCenterX, AabbCenterY, AabbCenterZ);
  370. }
  371. catch (ObjectDisposedException)
  372. {
  373. m_terrainPosition = new btVector3(AabbCenterX, AabbCenterY, AabbCenterZ);
  374. }
  375. }
  376. if (m_terrainMotionState != null)
  377. {
  378. m_terrainMotionState.Dispose();
  379. m_terrainMotionState = null;
  380. }
  381. m_terrainTransform = new btTransform(QuatIdentity, m_terrainPosition);
  382. m_terrainMotionState = new btDefaultMotionState(m_terrainTransform);
  383. TerrainBody = new btRigidBody(0, m_terrainMotionState, m_terrainShape);
  384. TerrainBody.setUserPointer((IntPtr)0);
  385. m_world.addRigidBody(TerrainBody);
  386. }
  387. public override void SetWaterLevel(float baseheight)
  388. {
  389. }
  390. public override void DeleteTerrain()
  391. {
  392. if (TerrainBody != null)
  393. {
  394. m_world.removeRigidBody(TerrainBody);
  395. }
  396. if (m_terrainShape != null)
  397. {
  398. m_terrainShape.Dispose();
  399. m_terrainShape = null;
  400. }
  401. if (m_terrainMotionState != null)
  402. {
  403. m_terrainMotionState.Dispose();
  404. m_terrainMotionState = null;
  405. }
  406. if (m_terrainTransform != null)
  407. {
  408. m_terrainTransform.Dispose();
  409. m_terrainTransform = null;
  410. }
  411. if (m_terrainPosition != null)
  412. {
  413. m_terrainPosition.Dispose();
  414. m_terrainPosition = null;
  415. }
  416. }
  417. public override void Dispose()
  418. {
  419. disposeAllBodies();
  420. m_world.Dispose();
  421. m_broadphase.Dispose();
  422. ((btDefaultCollisionConfiguration) m_collisionConfiguration).Dispose();
  423. ((btSequentialImpulseConstraintSolver) m_solver).Dispose();
  424. worldAabbMax.Dispose();
  425. worldAabbMin.Dispose();
  426. VectorZero.Dispose();
  427. QuatIdentity.Dispose();
  428. m_gravity.Dispose();
  429. VectorZero = null;
  430. QuatIdentity = null;
  431. }
  432. public override Dictionary<uint, float> GetTopColliders()
  433. {
  434. return new Dictionary<uint, float>();
  435. }
  436. public btDiscreteDynamicsWorld getBulletWorld()
  437. {
  438. return m_world;
  439. }
  440. private void disposeAllBodies()
  441. {
  442. lock (m_prims)
  443. {
  444. m_primsLocalID.Clear();
  445. foreach (BulletDotNETPrim prim in m_prims)
  446. {
  447. if (prim.Body != null)
  448. m_world.removeRigidBody(prim.Body);
  449. prim.Dispose();
  450. }
  451. m_prims.Clear();
  452. foreach (BulletDotNETCharacter chr in m_characters)
  453. {
  454. if (chr.Body != null)
  455. m_world.removeRigidBody(chr.Body);
  456. chr.Dispose();
  457. }
  458. m_characters.Clear();
  459. }
  460. }
  461. public override bool IsThreaded
  462. {
  463. get { return false; }
  464. }
  465. internal void addCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
  466. {
  467. //TODO: FIXME:
  468. }
  469. internal void remCollisionEventReporting(PhysicsActor bulletDotNETCharacter)
  470. {
  471. //TODO: FIXME:
  472. }
  473. internal void AddRigidBody(btRigidBody Body)
  474. {
  475. m_world.addRigidBody(Body);
  476. }
  477. [Obsolete("bad!")]
  478. internal void removeFromWorld(btRigidBody body)
  479. {
  480. m_world.removeRigidBody(body);
  481. }
  482. internal void removeFromWorld(BulletDotNETPrim prm ,btRigidBody body)
  483. {
  484. lock (m_prims)
  485. {
  486. if (m_prims.Contains(prm))
  487. {
  488. m_world.removeRigidBody(body);
  489. }
  490. remActivePrim(prm);
  491. m_primsLocalID.Remove(prm.m_localID);
  492. m_prims.Remove(prm);
  493. }
  494. }
  495. internal float GetWaterLevel()
  496. {
  497. throw new NotImplementedException();
  498. }
  499. // Recovered for use by fly height. Kitto Flora
  500. public float GetTerrainHeightAtXY(float x, float y)
  501. {
  502. // Teravus: Kitto, this code causes recurring errors that stall physics permenantly unless
  503. // the values are checked, so checking below.
  504. // Is there any reason that we don't do this in ScenePresence?
  505. // The only physics engine that benefits from it in the physics plugin is this one
  506. if (x > (int)Constants.RegionSize || y > (int)Constants.RegionSize ||
  507. x < 0.001f || y < 0.001f)
  508. return 0;
  509. return _origheightmap[(int)y * Constants.RegionSize + (int)x];
  510. }
  511. // End recovered. Kitto Flora
  512. /// <summary>
  513. /// Routine to figure out if we need to mesh this prim with our mesher
  514. /// </summary>
  515. /// <param name="pbs"></param>
  516. /// <returns></returns>
  517. public bool needsMeshing(PrimitiveBaseShape pbs)
  518. {
  519. // most of this is redundant now as the mesher will return null if it cant mesh a prim
  520. // but we still need to check for sculptie meshing being enabled so this is the most
  521. // convenient place to do it for now...
  522. // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f)
  523. // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString());
  524. int iPropertiesNotSupportedDefault = 0;
  525. if (pbs.SculptEntry && !meshSculptedPrim)
  526. {
  527. #if SPAM
  528. m_log.Warn("NonMesh");
  529. #endif
  530. return false;
  531. }
  532. // 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
  533. if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
  534. || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
  535. && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
  536. {
  537. if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
  538. && pbs.ProfileHollow == 0
  539. && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
  540. && pbs.PathBegin == 0 && pbs.PathEnd == 0
  541. && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
  542. && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
  543. && pbs.PathShearX == 0 && pbs.PathShearY == 0)
  544. {
  545. #if SPAM
  546. m_log.Warn("NonMesh");
  547. #endif
  548. return false;
  549. }
  550. }
  551. if (pbs.ProfileHollow != 0)
  552. iPropertiesNotSupportedDefault++;
  553. if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
  554. iPropertiesNotSupportedDefault++;
  555. if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
  556. iPropertiesNotSupportedDefault++;
  557. if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
  558. iPropertiesNotSupportedDefault++;
  559. if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
  560. iPropertiesNotSupportedDefault++;
  561. if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
  562. iPropertiesNotSupportedDefault++;
  563. if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
  564. iPropertiesNotSupportedDefault++;
  565. 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))
  566. iPropertiesNotSupportedDefault++;
  567. if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
  568. iPropertiesNotSupportedDefault++;
  569. // test for torus
  570. if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
  571. {
  572. if (pbs.PathCurve == (byte)Extrusion.Curve1)
  573. {
  574. iPropertiesNotSupportedDefault++;
  575. }
  576. }
  577. else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
  578. {
  579. if (pbs.PathCurve == (byte)Extrusion.Straight)
  580. {
  581. iPropertiesNotSupportedDefault++;
  582. }
  583. // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
  584. else if (pbs.PathCurve == (byte)Extrusion.Curve1)
  585. {
  586. iPropertiesNotSupportedDefault++;
  587. }
  588. }
  589. else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
  590. {
  591. if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
  592. {
  593. iPropertiesNotSupportedDefault++;
  594. }
  595. }
  596. else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
  597. {
  598. if (pbs.PathCurve == (byte)Extrusion.Straight)
  599. {
  600. iPropertiesNotSupportedDefault++;
  601. }
  602. else if (pbs.PathCurve == (byte)Extrusion.Curve1)
  603. {
  604. iPropertiesNotSupportedDefault++;
  605. }
  606. }
  607. if (iPropertiesNotSupportedDefault == 0)
  608. {
  609. #if SPAM
  610. m_log.Warn("NonMesh");
  611. #endif
  612. return false;
  613. }
  614. #if SPAM
  615. m_log.Debug("Mesh");
  616. #endif
  617. return true;
  618. }
  619. internal void addActivePrim(BulletDotNETPrim pPrim)
  620. {
  621. lock (m_activePrims)
  622. {
  623. if (!m_activePrims.Contains(pPrim))
  624. {
  625. m_activePrims.Add(pPrim);
  626. }
  627. }
  628. }
  629. public void remActivePrim(BulletDotNETPrim pDeactivatePrim)
  630. {
  631. lock (m_activePrims)
  632. {
  633. m_activePrims.Remove(pDeactivatePrim);
  634. }
  635. }
  636. internal void AddPrimToScene(BulletDotNETPrim pPrim)
  637. {
  638. lock (m_prims)
  639. {
  640. if (!m_prims.Contains(pPrim))
  641. {
  642. try
  643. {
  644. m_prims.Add(pPrim);
  645. m_primsLocalID.Add(pPrim.m_localID, pPrim);
  646. }
  647. catch
  648. {
  649. // noop if it's already there
  650. m_log.Debug("[PHYSICS] BulletDotNet: adding duplicate prim localID");
  651. }
  652. m_world.addRigidBody(pPrim.Body);
  653. // m_log.Debug("[PHYSICS] added prim to scene");
  654. }
  655. }
  656. }
  657. internal void EnableCollisionInterface()
  658. {
  659. if (m_CollisionInterface == null)
  660. {
  661. m_CollisionInterface = new ContactAddedCallbackHandler(m_world);
  662. // m_world.SetCollisionAddedCallback(m_CollisionInterface);
  663. }
  664. }
  665. }
  666. }