ODEPrim.cs 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  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 OpenSim 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. */
  28. using System;
  29. using Axiom.Math;
  30. using Ode.NET;
  31. using OpenSim.Framework;
  32. using OpenSim.Region.Physics.Manager;
  33. using System.Collections.Generic; // rex
  34. using System.Runtime.InteropServices; // rex
  35. using RexDotMeshLoader; // rex
  36. using OpenSim.Framework.Console; // rex
  37. using libsecondlife; // rex
  38. namespace OpenSim.Region.Physics.OdePlugin
  39. {
  40. // rex, new class
  41. public class OdeCollisionMesh : IMesh
  42. {
  43. public float[] vertexListOrig;
  44. public int[] indexListOrig;
  45. public float[] vertexList;
  46. public int[] indexList;
  47. public GCHandle gchVertexList;
  48. public GCHandle gchIndexList;
  49. public LLVector3 BoundsMin = new LLVector3();
  50. public LLVector3 BoundsMax = new LLVector3();
  51. public bool m_BoundsScaling;
  52. public OdeCollisionMesh(int vVertexCount, int vIndexCount)
  53. {
  54. vertexList = new float[vVertexCount];
  55. gchVertexList = GCHandle.Alloc(vertexList, GCHandleType.Pinned);
  56. vertexListOrig = new float[vVertexCount];
  57. indexList = new int[vIndexCount];
  58. gchIndexList = GCHandle.Alloc(indexList, GCHandleType.Pinned);
  59. indexListOrig = new int[vIndexCount];
  60. }
  61. public void FreeLists()
  62. {
  63. gchVertexList.Free();
  64. gchIndexList.Free();
  65. }
  66. public List<PhysicsVector> getVertexList()
  67. {
  68. return null;
  69. }
  70. public int[] getIndexListAsInt()
  71. {
  72. return indexList;
  73. }
  74. public int[] getIndexListAsIntLocked()
  75. {
  76. return indexList;
  77. }
  78. public float[] getVertexListAsFloatLocked()
  79. {
  80. return vertexList;
  81. }
  82. }
  83. public class OdePrim : PhysicsActor
  84. {
  85. public PhysicsVector _position;
  86. private PhysicsVector _velocity;
  87. private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f, 0.0f, 0.0f);
  88. private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f);
  89. private PhysicsVector m_rotationalVelocity;
  90. private PhysicsVector _size;
  91. private PhysicsVector _acceleration;
  92. private Quaternion _orientation;
  93. private PhysicsVector m_taintposition;
  94. private PhysicsVector m_taintsize;
  95. private Quaternion m_taintrot;
  96. private bool m_taintshape = false;
  97. private bool m_taintPhysics = false;
  98. public bool m_taintremove = false;
  99. private IMesh _mesh;
  100. private PrimitiveBaseShape _pbs;
  101. private OdeScene _parent_scene;
  102. public IntPtr m_targetSpace = (IntPtr) 0;
  103. public IntPtr prim_geom;
  104. public IntPtr _triMeshData;
  105. private bool iscolliding = false;
  106. private bool m_isphysical = false;
  107. private bool m_throttleUpdates = false;
  108. private int throttleCounter = 0;
  109. public bool outofBounds = false;
  110. private float m_density = 10.000006836f; // Aluminum g/cm3;
  111. public bool _zeroFlag = false;
  112. private bool m_lastUpdateSent = false;
  113. public IntPtr Body = (IntPtr) 0;
  114. private String m_primName;
  115. private PhysicsVector _target_velocity;
  116. public d.Mass pMass;
  117. private int debugcounter = 0;
  118. private bool m_DotMeshCollision = false; // rex
  119. public bool m_BoundsScalingUpdate = false; // rex
  120. private bool m_PrimVolume = false; // rex
  121. public OdePrim(String primName, OdeScene parent_scene, IntPtr targetSpace, PhysicsVector pos, PhysicsVector size,
  122. Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, uint localID)
  123. {
  124. m_localID = localID; // rex
  125. _velocity = new PhysicsVector();
  126. _position = pos;
  127. m_taintposition = pos;
  128. if (_position.X > 257)
  129. {
  130. _position.X = 257;
  131. }
  132. if (_position.X < 0)
  133. {
  134. _position.X = 0;
  135. }
  136. if (_position.Y > 257)
  137. {
  138. _position.Y = 257;
  139. }
  140. if (_position.Y < 0)
  141. {
  142. _position.Y = 0;
  143. }
  144. _size = size;
  145. m_taintsize = _size;
  146. _acceleration = new PhysicsVector();
  147. m_rotationalVelocity = PhysicsVector.Zero;
  148. _orientation = rotation;
  149. m_taintrot = _orientation;
  150. _mesh = mesh;
  151. _pbs = pbs;
  152. _parent_scene = parent_scene;
  153. m_targetSpace = targetSpace;
  154. if (pos.Z < 0)
  155. m_isphysical = false;
  156. else
  157. {
  158. m_isphysical = pisPhysical;
  159. // If we're physical, we need to be in the master space for now.
  160. // linksets *should* be in a space together.. but are not currently
  161. if (m_isphysical)
  162. m_targetSpace = _parent_scene.space;
  163. }
  164. m_primName = primName;
  165. lock (OdeScene.OdeLock)
  166. {
  167. if (mesh != null)
  168. {
  169. setMesh(parent_scene, mesh);
  170. }
  171. else
  172. {
  173. prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  174. }
  175. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  176. d.Quaternion myrot = new d.Quaternion();
  177. myrot.W = rotation.w;
  178. myrot.X = rotation.x;
  179. myrot.Y = rotation.y;
  180. myrot.Z = rotation.z;
  181. d.GeomSetQuaternion(prim_geom, ref myrot);
  182. if (m_isphysical && Body == (IntPtr) 0)
  183. {
  184. enableBody();
  185. }
  186. parent_scene.geom_name_map[prim_geom] = primName;
  187. parent_scene.actor_name_map[prim_geom] = (PhysicsActor) this;
  188. // don't do .add() here; old geoms get recycled with the same hash
  189. }
  190. }
  191. // rex, modified function, m_PrimVolume added
  192. public override int PhysicsActorType
  193. {
  194. get
  195. {
  196. if (m_PrimVolume)
  197. return (int)ActorTypes.PrimVolume;
  198. else
  199. return (int)ActorTypes.Prim;
  200. }
  201. set
  202. {
  203. if (value == (int)ActorTypes.PrimVolume)
  204. m_PrimVolume = true;
  205. else
  206. m_PrimVolume = false;
  207. }
  208. }
  209. public override bool SetAlwaysRun
  210. {
  211. get { return false; }
  212. set { return; }
  213. }
  214. public void enableBody()
  215. {
  216. // Sets the geom to a body
  217. Body = d.BodyCreate(_parent_scene.world);
  218. setMass();
  219. d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
  220. d.Quaternion myrot = new d.Quaternion();
  221. myrot.W = _orientation.w;
  222. myrot.X = _orientation.x;
  223. myrot.Y = _orientation.y;
  224. myrot.Z = _orientation.z;
  225. d.BodySetQuaternion(Body, ref myrot);
  226. d.GeomSetBody(prim_geom, Body);
  227. d.BodySetAutoDisableFlag(Body, true);
  228. d.BodySetAutoDisableSteps(Body, 20);
  229. _parent_scene.addActivePrim(this);
  230. }
  231. private float CalculateMass()
  232. {
  233. float volume = 0;
  234. // No material is passed to the physics engines yet.. soo..
  235. // we're using the m_density constant in the class definition
  236. float returnMass = 0;
  237. switch (_pbs.ProfileShape)
  238. {
  239. case ProfileShape.Square:
  240. // Profile Volume
  241. volume = _size.X*_size.Y*_size.Z;
  242. // If the user has 'hollowed out'
  243. // ProfileHollow is one of those 0 to 50000 values :P
  244. // we like percentages better.. so turning into a percentage
  245. if (((float) _pbs.ProfileHollow/50000f) > 0.0)
  246. {
  247. float hollowAmount = (float) _pbs.ProfileHollow/50000f;
  248. // calculate the hollow volume by it's shape compared to the prim shape
  249. float hollowVolume = 0;
  250. switch (_pbs.HollowShape)
  251. {
  252. case HollowShape.Square:
  253. case HollowShape.Same:
  254. // Cube Hollow volume calculation
  255. float hollowsizex = _size.X*hollowAmount;
  256. float hollowsizey = _size.Y*hollowAmount;
  257. float hollowsizez = _size.Z*hollowAmount;
  258. hollowVolume = hollowsizex*hollowsizey*hollowsizez;
  259. break;
  260. case HollowShape.Circle:
  261. // Hollow shape is a perfect cyllinder in respect to the cube's scale
  262. // Cyllinder hollow volume calculation
  263. float hRadius = _size.X/2;
  264. float hLength = _size.Z;
  265. // pi * r2 * h
  266. hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount);
  267. break;
  268. case HollowShape.Triangle:
  269. // Equilateral Triangular Prism volume hollow calculation
  270. // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y
  271. float aLength = _size.Y;
  272. // 1/2 abh
  273. hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount);
  274. break;
  275. default:
  276. hollowVolume = 0;
  277. break;
  278. }
  279. volume = volume - hollowVolume;
  280. }
  281. break;
  282. default:
  283. // we don't have all of the volume formulas yet so
  284. // use the common volume formula for all
  285. volume = _size.X*_size.Y*_size.Z;
  286. break;
  287. }
  288. // Calculate Path cut effect on volume
  289. // Not exact, in the triangle hollow example
  290. // They should never be zero or less then zero..
  291. // we'll ignore it if it's less then zero
  292. // ProfileEnd and ProfileBegin are values
  293. // from 0 to 50000
  294. // Turning them back into percentages so that I can cut that percentage off the volume
  295. float PathCutEndAmount = _pbs.ProfileEnd;
  296. float PathCutStartAmount = _pbs.ProfileBegin;
  297. if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f)
  298. {
  299. float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f);
  300. // Check the return amount for sanity
  301. if (pathCutAmount >= 0.99f)
  302. pathCutAmount = 0.99f;
  303. volume = volume - (volume*pathCutAmount);
  304. }
  305. // Mass = density * volume
  306. returnMass = m_density*volume;
  307. return returnMass;
  308. }
  309. public void setMass()
  310. {
  311. if (Body != (IntPtr) 0)
  312. {
  313. d.MassSetBoxTotal(out pMass, CalculateMass(), _size.X, _size.Y, _size.Z);
  314. d.BodySetMass(Body, ref pMass);
  315. }
  316. }
  317. public void disableBody()
  318. {
  319. //this kills the body so things like 'mesh' can re-create it.
  320. if (Body != (IntPtr) 0)
  321. {
  322. _parent_scene.remActivePrim(this);
  323. d.BodyDestroy(Body);
  324. Body = (IntPtr) 0;
  325. }
  326. }
  327. public void setMesh(OdeScene parent_scene, IMesh mesh)
  328. {
  329. //Kill Body so that mesh can re-make the geom
  330. if (IsPhysical && Body != (IntPtr) 0)
  331. {
  332. disableBody();
  333. }
  334. float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
  335. int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
  336. int VertexCount = vertexList.GetLength(0)/3;
  337. int IndexCount = indexList.GetLength(0);
  338. // rex, del old trimeshdata
  339. if (_triMeshData != (IntPtr)0)
  340. d.GeomTriMeshDataDestroy(_triMeshData);
  341. _mesh = mesh; // rex, end
  342. _triMeshData = d.GeomTriMeshDataCreate();
  343. d.GeomTriMeshDataBuildSimple(_triMeshData, vertexList, 3*sizeof (float), VertexCount, indexList, IndexCount,
  344. 3*sizeof (int));
  345. d.GeomTriMeshDataPreprocess(_triMeshData);
  346. prim_geom = d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null);
  347. if (IsPhysical && Body == (IntPtr) 0)
  348. {
  349. // Recreate the body
  350. enableBody();
  351. }
  352. }
  353. public void ProcessTaints(float timestep)
  354. {
  355. if (m_taintposition != _position)
  356. Move(timestep);
  357. if (m_taintrot != _orientation)
  358. rotate(timestep);
  359. //
  360. if (m_taintPhysics != m_isphysical)
  361. changePhysicsStatus(timestep);
  362. //
  363. if (m_taintsize != _size)
  364. changesize(timestep);
  365. if (m_BoundsScalingUpdate) // rex
  366. changesize(timestep);
  367. //
  368. if (m_taintshape)
  369. changeshape(timestep);
  370. //
  371. }
  372. public void Move(float timestep)
  373. {
  374. if (m_isphysical)
  375. {
  376. // This is a fallback.. May no longer be necessary.
  377. if (Body == (IntPtr) 0)
  378. enableBody();
  379. //Prim auto disable after 20 frames,
  380. ///if you move it, re-enable the prim manually.
  381. d.BodyEnable(Body);
  382. d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
  383. }
  384. else
  385. {
  386. string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
  387. int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
  388. m_targetSpace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
  389. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  390. d.SpaceAdd(m_targetSpace, prim_geom);
  391. }
  392. m_taintposition = _position;
  393. }
  394. // rex, function changed
  395. public void rotate(float timestep)
  396. {
  397. d.Quaternion myrot = new d.Quaternion();
  398. if (m_DotMeshCollision && _mesh != null) // rex, setting rot for collision 3d model
  399. {
  400. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  401. Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0));
  402. Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0));
  403. Quaternion mytemprot = _orientation * meshRotA * meshRotB;
  404. myrot.W = mytemprot.w;
  405. myrot.X = mytemprot.x;
  406. myrot.Y = mytemprot.y;
  407. myrot.Z = mytemprot.z;
  408. d.GeomSetQuaternion(prim_geom, ref myrot);
  409. }
  410. else
  411. {
  412. myrot.W = _orientation.w;
  413. myrot.X = _orientation.x;
  414. myrot.Y = _orientation.y;
  415. myrot.Z = _orientation.z;
  416. d.GeomSetQuaternion(prim_geom, ref myrot);
  417. }
  418. if (m_isphysical && Body != (IntPtr) 0)
  419. {
  420. d.BodySetQuaternion(Body, ref myrot);
  421. }
  422. m_taintrot = _orientation;
  423. }
  424. public void changePhysicsStatus(float timestap)
  425. {
  426. if (m_isphysical == true)
  427. {
  428. if (Body == (IntPtr) 0)
  429. {
  430. enableBody();
  431. }
  432. }
  433. else
  434. {
  435. if (Body != (IntPtr) 0)
  436. {
  437. disableBody();
  438. }
  439. }
  440. m_taintPhysics = m_isphysical;
  441. }
  442. // rex, function changed
  443. public void changesize(float timestamp)
  444. {
  445. string oldname = _parent_scene.geom_name_map[prim_geom];
  446. // Cleanup of old prim geometry
  447. if (_mesh != null)
  448. {
  449. // Cleanup meshing here
  450. }
  451. //kill body to rebuild
  452. if (IsPhysical && Body != (IntPtr) 0)
  453. {
  454. disableBody();
  455. }
  456. if (d.SpaceQuery(m_targetSpace, prim_geom))
  457. {
  458. d.SpaceRemove(m_targetSpace, prim_geom);
  459. }
  460. d.GeomDestroy(prim_geom);
  461. // we don't need to do space calculation because the client sends a position update also.
  462. if (m_DotMeshCollision && _mesh != null) // rex, scaling dotmesh models
  463. {
  464. float[] scalefactor = new float[3];
  465. int vertindex = 0;
  466. OdeCollisionMesh mesh = _mesh as OdeCollisionMesh;
  467. LLVector3 scalingvector = new LLVector3(_size.X, _size.Y, _size.Z);
  468. if (mesh.m_BoundsScaling)
  469. {
  470. LLVector3 boundssize = mesh.BoundsMax - mesh.BoundsMin;
  471. if (boundssize.X != 0)
  472. scalingvector.X /= boundssize.X;
  473. if (boundssize.Y != 0)
  474. scalingvector.Z /= boundssize.Y;
  475. if (boundssize.Z != 0)
  476. scalingvector.Y /= boundssize.Z;
  477. }
  478. scalefactor[0] = scalingvector.X;
  479. scalefactor[1] = scalingvector.Z;
  480. scalefactor[2] = scalingvector.Y;
  481. for (int i = 0; i < mesh.vertexList.GetLength(0); i++)
  482. {
  483. mesh.vertexList[i] = mesh.vertexListOrig[i] * scalefactor[vertindex];
  484. vertindex++;
  485. if (vertindex > 2)
  486. vertindex = 0;
  487. }
  488. for (int i = 0; i < mesh.indexList.GetLength(0); i++)
  489. mesh.indexList[i] = mesh.indexListOrig[i];
  490. setMesh(_parent_scene, mesh);
  491. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  492. Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0));
  493. Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0));
  494. Quaternion mytemprot = _orientation * meshRotA * meshRotB;
  495. d.Quaternion myrot = new d.Quaternion();
  496. myrot.W = mytemprot.w;
  497. myrot.X = mytemprot.x;
  498. myrot.Y = mytemprot.y;
  499. myrot.Z = mytemprot.z;
  500. d.GeomSetQuaternion(prim_geom, ref myrot);
  501. if (IsPhysical && Body == (IntPtr)0)
  502. {
  503. // Re creates body on size.
  504. // EnableBody also does setMass()
  505. enableBody();
  506. d.BodyEnable(Body);
  507. }
  508. } // rex, end scaling
  509. // Construction of new prim
  510. else if (_parent_scene.needsMeshing(_pbs))
  511. {
  512. // Don't need to re-enable body.. it's done in SetMesh
  513. IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
  514. // createmesh returns null when it's a shape that isn't a cube.
  515. if (mesh != null)
  516. {
  517. setMesh(_parent_scene, mesh);
  518. }
  519. else
  520. {
  521. prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  522. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  523. d.Quaternion myrot = new d.Quaternion();
  524. myrot.W = _orientation.w;
  525. myrot.X = _orientation.x;
  526. myrot.Y = _orientation.y;
  527. myrot.Z = _orientation.z;
  528. d.GeomSetQuaternion(prim_geom, ref myrot);
  529. }
  530. }
  531. else
  532. {
  533. prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  534. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  535. d.Quaternion myrot = new d.Quaternion();
  536. myrot.W = _orientation.w;
  537. myrot.X = _orientation.x;
  538. myrot.Y = _orientation.y;
  539. myrot.Z = _orientation.z;
  540. d.GeomSetQuaternion(prim_geom, ref myrot);
  541. //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  542. if (IsPhysical && Body == (IntPtr) 0)
  543. {
  544. // Re creates body on size.
  545. // EnableBody also does setMass()
  546. enableBody();
  547. d.BodyEnable(Body);
  548. }
  549. }
  550. _parent_scene.geom_name_map[prim_geom] = oldname;
  551. m_taintsize = _size;
  552. m_BoundsScalingUpdate = false; // rex
  553. }
  554. public void changeshape(float timestamp)
  555. {
  556. string oldname = _parent_scene.geom_name_map[prim_geom];
  557. // Cleanup of old prim geometry and Bodies
  558. if (IsPhysical && Body != (IntPtr) 0)
  559. {
  560. disableBody();
  561. }
  562. d.GeomDestroy(prim_geom);
  563. if (_mesh != null)
  564. {
  565. d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  566. }
  567. // Construction of new prim
  568. if (_parent_scene.needsMeshing(_pbs))
  569. {
  570. IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
  571. if (mesh != null)
  572. {
  573. setMesh(_parent_scene, mesh);
  574. }
  575. else
  576. {
  577. prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  578. }
  579. }
  580. else
  581. {
  582. prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  583. }
  584. if (IsPhysical && Body == (IntPtr) 0)
  585. {
  586. //re-create new body
  587. enableBody();
  588. }
  589. else
  590. {
  591. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  592. d.Quaternion myrot = new d.Quaternion();
  593. myrot.W = _orientation.w;
  594. myrot.X = _orientation.x;
  595. myrot.Y = _orientation.y;
  596. myrot.Z = _orientation.z;
  597. d.GeomSetQuaternion(prim_geom, ref myrot);
  598. }
  599. _parent_scene.geom_name_map[prim_geom] = oldname;
  600. m_taintshape = false;
  601. }
  602. public override bool IsPhysical
  603. {
  604. get { return m_isphysical; }
  605. set { m_isphysical = value; }
  606. }
  607. public void setPrimForRemoval()
  608. {
  609. m_taintremove = true;
  610. }
  611. public override bool Flying
  612. {
  613. get { return false; //no flying prims for you
  614. }
  615. set { }
  616. }
  617. public override bool IsColliding
  618. {
  619. get { return iscolliding; }
  620. set { iscolliding = value; }
  621. }
  622. public override bool CollidingGround
  623. {
  624. get { return false; }
  625. set { return; }
  626. }
  627. public override bool CollidingObj
  628. {
  629. get { return false; }
  630. set { return; }
  631. }
  632. public override bool ThrottleUpdates
  633. {
  634. get { return m_throttleUpdates; }
  635. set { m_throttleUpdates = value; }
  636. }
  637. public override PhysicsVector Position
  638. {
  639. get { return _position; }
  640. set { _position = value; }
  641. }
  642. public override PhysicsVector Size
  643. {
  644. get { return _size; }
  645. set { _size = value; }
  646. }
  647. public override float Mass
  648. {
  649. get { return CalculateMass(); }
  650. }
  651. public override PhysicsVector Force
  652. {
  653. get { return PhysicsVector.Zero; }
  654. }
  655. public override PhysicsVector CenterOfMass
  656. {
  657. get { return PhysicsVector.Zero; }
  658. }
  659. public override PhysicsVector GeometricCenter
  660. {
  661. get { return PhysicsVector.Zero; }
  662. }
  663. public override PrimitiveBaseShape Shape
  664. {
  665. set { _pbs = value; }
  666. }
  667. public override PhysicsVector Velocity
  668. {
  669. get
  670. {
  671. // Averate previous velocity with the new one so
  672. // client object interpolation works a 'little' better
  673. PhysicsVector returnVelocity = new PhysicsVector();
  674. returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2;
  675. returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2;
  676. returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2;
  677. return returnVelocity;
  678. }
  679. set { _velocity = value; }
  680. }
  681. public override bool Kinematic
  682. {
  683. get { return false; }
  684. set { }
  685. }
  686. public override Quaternion Orientation
  687. {
  688. get { return _orientation; }
  689. set { _orientation = value; }
  690. }
  691. public override PhysicsVector Acceleration
  692. {
  693. get { return _acceleration; }
  694. }
  695. public void SetAcceleration(PhysicsVector accel)
  696. {
  697. _acceleration = accel;
  698. }
  699. public override void AddForce(PhysicsVector force)
  700. {
  701. }
  702. public override PhysicsVector RotationalVelocity
  703. {
  704. get { return m_rotationalVelocity; }
  705. set { m_rotationalVelocity = value; }
  706. }
  707. public void UpdatePositionAndVelocity()
  708. {
  709. // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
  710. if (Body != (IntPtr) 0)
  711. {
  712. d.Vector3 vec = d.BodyGetPosition(Body);
  713. d.Quaternion ori = d.BodyGetQuaternion(Body);
  714. d.Vector3 vel = d.BodyGetLinearVel(Body);
  715. d.Vector3 rotvel = d.BodyGetAngularVel(Body);
  716. PhysicsVector l_position = new PhysicsVector();
  717. // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
  718. if (vec.X < 0.0f) vec.X = 0.0f;
  719. if (vec.Y < 0.0f) vec.Y = 0.0f;
  720. if (vec.X > 255.95f) vec.X = 255.95f;
  721. if (vec.Y > 255.95f) vec.Y = 255.95f;
  722. m_lastposition = _position;
  723. l_position.X = vec.X;
  724. l_position.Y = vec.Y;
  725. l_position.Z = vec.Z;
  726. if (l_position.Z < 0)
  727. {
  728. // This is so prim that get lost underground don't fall forever and suck up
  729. //
  730. // Sim resources and memory.
  731. // Disables the prim's movement physics....
  732. // It's a hack and will generate a console message if it fails.
  733. //IsPhysical = false;
  734. base.RaiseOutOfBounds(_position);
  735. _velocity.X = 0;
  736. _velocity.Y = 0;
  737. _velocity.Z = 0;
  738. m_rotationalVelocity.X = 0;
  739. m_rotationalVelocity.Y = 0;
  740. m_rotationalVelocity.Z = 0;
  741. base.RequestPhysicsterseUpdate();
  742. m_throttleUpdates = false;
  743. throttleCounter = 0;
  744. _zeroFlag = true;
  745. //outofBounds = true;
  746. }
  747. if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
  748. && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
  749. && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02))
  750. {
  751. _zeroFlag = true;
  752. }
  753. else
  754. {
  755. //System.Console.WriteLine(Math.Abs(m_lastposition.X - l_position.X).ToString());
  756. _zeroFlag = false;
  757. }
  758. if (_zeroFlag)
  759. {
  760. // Supposedly this is supposed to tell SceneObjectGroup that
  761. // no more updates need to be sent..
  762. // but it seems broken.
  763. _velocity.X = 0.0f;
  764. _velocity.Y = 0.0f;
  765. _velocity.Z = 0.0f;
  766. //_orientation.w = 0f;
  767. //_orientation.x = 0f;
  768. //_orientation.y = 0f;
  769. //_orientation.z = 0f;
  770. m_rotationalVelocity.X = 0;
  771. m_rotationalVelocity.Y = 0;
  772. m_rotationalVelocity.Z = 0;
  773. if (!m_lastUpdateSent)
  774. {
  775. m_throttleUpdates = false;
  776. throttleCounter = 0;
  777. base.RequestPhysicsterseUpdate();
  778. m_lastUpdateSent = true;
  779. }
  780. }
  781. else
  782. {
  783. m_lastVelocity = _velocity;
  784. _position = l_position;
  785. _velocity.X = vel.X;
  786. _velocity.Y = vel.Y;
  787. _velocity.Z = vel.Z;
  788. m_rotationalVelocity.X = rotvel.X;
  789. m_rotationalVelocity.Y = rotvel.Y;
  790. m_rotationalVelocity.Z = rotvel.Z;
  791. //System.Console.WriteLine("ODE: " + m_rotationalVelocity.ToString());
  792. _orientation.w = ori.W;
  793. _orientation.x = ori.X;
  794. _orientation.y = ori.Y;
  795. _orientation.z = ori.Z;
  796. m_lastUpdateSent = false;
  797. if (!m_throttleUpdates || throttleCounter > 15)
  798. {
  799. base.RequestPhysicsterseUpdate();
  800. }
  801. else
  802. {
  803. throttleCounter++;
  804. }
  805. }
  806. m_lastposition = l_position;
  807. }
  808. else
  809. {
  810. // Not a body.. so Make sure the client isn't interpolating
  811. _velocity.X = 0;
  812. _velocity.Y = 0;
  813. _velocity.Z = 0;
  814. m_rotationalVelocity.X = 0;
  815. m_rotationalVelocity.Y = 0;
  816. m_rotationalVelocity.Z = 0;
  817. _zeroFlag = true;
  818. }
  819. }
  820. public override void SetMomentum(PhysicsVector momentum)
  821. {
  822. }
  823. // rex, new function.
  824. // This function should be called only outside of simulation loop -> OdeLock used.
  825. public override void SetCollisionMesh(byte[] vData, string MeshName, bool vbScaleMesh)
  826. {
  827. float[] tempVertexList;
  828. float[] tempBounds;
  829. int[] tempIndexList;
  830. string errorMessage;
  831. float[] scalefactor = new float[3];
  832. int vertindex = 0;
  833. lock (OdeScene.OdeLock)
  834. {
  835. // 1. Get rid of old mesh
  836. m_DotMeshCollision = false;
  837. if (_mesh != null)
  838. {
  839. if ((OdeCollisionMesh)_mesh != null)
  840. (_mesh as OdeCollisionMesh).FreeLists();
  841. _mesh = null;
  842. }
  843. // 2. Try to load new colmesh
  844. OdeCollisionMesh mesh = null;
  845. if (vData != null)
  846. {
  847. DotMeshLoader.ReadDotMeshModel(vData, out tempVertexList, out tempIndexList, out tempBounds, out errorMessage);
  848. if (tempVertexList != null && tempIndexList != null)
  849. {
  850. mesh = new OdeCollisionMesh(tempVertexList.GetLength(0), tempIndexList.GetLength(0));
  851. mesh.m_BoundsScaling = vbScaleMesh;
  852. mesh.BoundsMin.X = tempBounds[0];
  853. mesh.BoundsMin.Y = tempBounds[1];
  854. mesh.BoundsMin.Z = tempBounds[2];
  855. mesh.BoundsMax.X = tempBounds[3];
  856. mesh.BoundsMax.Y = tempBounds[4];
  857. mesh.BoundsMax.Z = tempBounds[5];
  858. LLVector3 scalingvector = new LLVector3(_size.X, _size.Y, _size.Z);
  859. if (vbScaleMesh)
  860. {
  861. LLVector3 boundssize = mesh.BoundsMax - mesh.BoundsMin;
  862. if (boundssize.X != 0)
  863. scalingvector.X /= boundssize.X;
  864. if (boundssize.Y != 0)
  865. scalingvector.Z /= boundssize.Y;
  866. if (boundssize.Z != 0)
  867. scalingvector.Y /= boundssize.Z;
  868. }
  869. scalefactor[0] = scalingvector.X;
  870. scalefactor[1] = scalingvector.Z;
  871. scalefactor[2] = scalingvector.Y;
  872. for (int i = 0; i < tempVertexList.GetLength(0); i++)
  873. {
  874. mesh.vertexListOrig[i] = tempVertexList[i];
  875. mesh.vertexList[i] = tempVertexList[i] * scalefactor[vertindex];
  876. vertindex++;
  877. if (vertindex > 2)
  878. vertindex = 0;
  879. }
  880. for (int i = 0; i < tempIndexList.GetLength(0); i++)
  881. {
  882. mesh.indexListOrig[i] = tempIndexList[i];
  883. mesh.indexList[i] = tempIndexList[i];
  884. }
  885. }
  886. else
  887. MainLog.Instance.Error("PHYSICS", "Error importing mesh:" + MeshName + ", " + errorMessage);
  888. }
  889. // 3. If mesh is null, must create the default collisionbox
  890. if (mesh == null)
  891. {
  892. CreateDefaultCollision();
  893. return;
  894. }
  895. // 4. If mesh loaded, use it
  896. string oldname = _parent_scene.geom_name_map[prim_geom];
  897. m_DotMeshCollision = true;
  898. if (IsPhysical && Body != (IntPtr)0)
  899. disableBody();
  900. if (prim_geom != (IntPtr)0)
  901. {
  902. if (d.SpaceQuery(m_targetSpace, prim_geom))
  903. {
  904. d.SpaceRemove(m_targetSpace, prim_geom);
  905. }
  906. d.GeomDestroy(prim_geom);
  907. }
  908. setMesh(_parent_scene, mesh);
  909. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  910. Quaternion meshRotA = Quaternion.FromAngleAxis((float)(Math.PI * 0.5), new Vector3(1, 0, 0));
  911. Quaternion meshRotB = Quaternion.FromAngleAxis((float)(Math.PI), new Vector3(0, 1, 0));
  912. Quaternion mytemprot = _orientation * meshRotA * meshRotB;
  913. d.Quaternion myrot = new d.Quaternion();
  914. myrot.W = mytemprot.w;
  915. myrot.X = mytemprot.x;
  916. myrot.Y = mytemprot.y;
  917. myrot.Z = mytemprot.z;
  918. d.GeomSetQuaternion(prim_geom, ref myrot);
  919. _parent_scene.geom_name_map[prim_geom] = oldname;
  920. }
  921. }
  922. // rex, function added
  923. private void CreateDefaultCollision()
  924. {
  925. string oldname = _parent_scene.geom_name_map[prim_geom];
  926. // Cleanup of old prim geometry
  927. if (_mesh != null)
  928. {
  929. // Cleanup meshing here
  930. }
  931. //kill body to rebuild
  932. if (IsPhysical && Body != (IntPtr)0)
  933. {
  934. disableBody();
  935. }
  936. if (d.SpaceQuery(m_targetSpace, prim_geom))
  937. {
  938. d.SpaceRemove(m_targetSpace, prim_geom);
  939. }
  940. d.GeomDestroy(prim_geom);
  941. // we don't need to do space calculation because the client sends a position update also.
  942. // Construction of new prim
  943. if (_parent_scene.needsMeshing(_pbs))
  944. {
  945. // Don't need to re-enable body.. it's done in SetMesh
  946. IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size);
  947. // createmesh returns null when it's a shape that isn't a cube.
  948. if (mesh != null)
  949. {
  950. setMesh(_parent_scene, mesh);
  951. }
  952. else
  953. {
  954. prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  955. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  956. d.Quaternion myrot = new d.Quaternion();
  957. myrot.W = _orientation.w;
  958. myrot.X = _orientation.x;
  959. myrot.Y = _orientation.y;
  960. myrot.Z = _orientation.z;
  961. d.GeomSetQuaternion(prim_geom, ref myrot);
  962. }
  963. }
  964. else
  965. {
  966. prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
  967. d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
  968. d.Quaternion myrot = new d.Quaternion();
  969. myrot.W = _orientation.w;
  970. myrot.X = _orientation.x;
  971. myrot.Y = _orientation.y;
  972. myrot.Z = _orientation.z;
  973. d.GeomSetQuaternion(prim_geom, ref myrot);
  974. //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
  975. if (IsPhysical && Body == (IntPtr)0)
  976. {
  977. // Re creates body on size.
  978. // EnableBody also does setMass()
  979. enableBody();
  980. d.BodyEnable(Body);
  981. }
  982. }
  983. _parent_scene.geom_name_map[prim_geom] = oldname;
  984. }
  985. // rex, new function
  986. public override void SetBoundsScaling(bool vbScaleMesh)
  987. {
  988. if (m_DotMeshCollision && _mesh != null)
  989. {
  990. (_mesh as OdeCollisionMesh).m_BoundsScaling = vbScaleMesh;
  991. m_BoundsScalingUpdate = true;
  992. }
  993. }
  994. }
  995. }