OdePlugin.cs 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030
  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. using System;
  28. using System.Collections.Generic;
  29. using System.Reflection;
  30. using System.Runtime.InteropServices;
  31. using System.Threading;
  32. using Axiom.Math;
  33. using log4net;
  34. using Ode.NET;
  35. using OpenSim.Framework;
  36. using OpenSim.Region.Physics.Manager;
  37. //using OpenSim.Region.Physics.OdePlugin.Meshing;
  38. namespace OpenSim.Region.Physics.OdePlugin
  39. {
  40. /// <summary>
  41. /// ODE plugin
  42. /// </summary>
  43. public class OdePlugin : IPhysicsPlugin
  44. {
  45. //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  46. private CollisionLocker ode;
  47. private OdeScene _mScene;
  48. public OdePlugin()
  49. {
  50. ode = new CollisionLocker();
  51. }
  52. public bool Init()
  53. {
  54. return true;
  55. }
  56. public PhysicsScene GetScene()
  57. {
  58. if (_mScene == null)
  59. {
  60. _mScene = new OdeScene(ode);
  61. }
  62. return (_mScene);
  63. }
  64. public string GetName()
  65. {
  66. return ("OpenDynamicsEngine");
  67. }
  68. public void Dispose()
  69. {
  70. }
  71. }
  72. public enum StatusIndicators : int
  73. {
  74. Generic = 0,
  75. Start = 1,
  76. End = 2
  77. }
  78. public struct sCollisionData
  79. {
  80. public uint ColliderLocalId;
  81. public uint CollidedWithLocalId;
  82. public int NumberOfCollisions;
  83. public int CollisionType;
  84. public int StatusIndicator;
  85. public int lastframe;
  86. }
  87. [Flags]
  88. public enum CollisionCategories : int
  89. {
  90. Disabled = 0,
  91. Geom = 0x00000001,
  92. Body = 0x00000002,
  93. Space = 0x00000004,
  94. Character = 0x00000008,
  95. Land = 0x00000010,
  96. Water = 0x00000020,
  97. Wind = 0x00000040,
  98. Sensor = 0x00000080,
  99. Selected = 0x00000100
  100. }
  101. public class OdeScene : PhysicsScene
  102. {
  103. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  104. private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
  105. CollisionLocker ode;
  106. protected Random fluidRandomizer = new Random(Environment.TickCount);
  107. private const uint m_regionWidth = Constants.RegionSize;
  108. private const uint m_regionHeight = Constants.RegionSize;
  109. private static float ODE_STEPSIZE = 0.020f;
  110. private static float metersInSpace = 29.9f;
  111. private float waterlevel = 0f;
  112. private int framecount = 0;
  113. private int m_returncollisions = 10;
  114. private IntPtr contactgroup;
  115. private IntPtr LandGeom = (IntPtr) 0;
  116. private IntPtr WaterGeom = (IntPtr)0;
  117. private float[] _heightmap;
  118. private float[] _watermap;
  119. private float[] _origheightmap;
  120. private d.NearCallback nearCallback;
  121. public d.TriCallback triCallback;
  122. public d.TriArrayCallback triArrayCallback;
  123. private List<OdeCharacter> _characters = new List<OdeCharacter>();
  124. private List<OdePrim> _prims = new List<OdePrim>();
  125. private List<OdePrim> _activeprims = new List<OdePrim>();
  126. private List<OdePrim> _taintedPrim = new List<OdePrim>();
  127. public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
  128. public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
  129. private d.ContactGeom[] contacts = new d.ContactGeom[80];
  130. private d.Contact contact;
  131. private d.Contact TerrainContact;
  132. private d.Contact AvatarMovementprimContact;
  133. private d.Contact AvatarMovementTerrainContact;
  134. private d.Contact WaterContact;
  135. //Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
  136. //Ckrinke private int m_randomizeWater = 200;
  137. private int m_physicsiterations = 10;
  138. private float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
  139. private PhysicsActor PANull = new NullPhysicsActor();
  140. private float step_time = 0.0f;
  141. //Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
  142. //Ckrinke private int ms = 0;
  143. public IntPtr world;
  144. private bool returncollisions = false;
  145. private uint obj1LocalID = 0;
  146. private uint obj2LocalID = 0;
  147. private int ctype = 0;
  148. private OdeCharacter cc1;
  149. private OdePrim cp1;
  150. private OdeCharacter cc2;
  151. private OdePrim cp2;
  152. private int cStartStop = 0;
  153. private string cDictKey = "";
  154. public IntPtr space;
  155. //private IntPtr tmpSpace;
  156. // split static geometry collision handling into spaces of 30 meters
  157. public IntPtr[,] staticPrimspace = new IntPtr[(int) (300/metersInSpace),(int) (300/metersInSpace)];
  158. public static Object OdeLock = new Object();
  159. public IMesher mesher;
  160. /// <summary>
  161. /// Initiailizes the scene
  162. /// Sets many properties that ODE requires to be stable
  163. /// These settings need to be tweaked 'exactly' right or weird stuff happens.
  164. /// </summary>
  165. public OdeScene(CollisionLocker dode)
  166. {
  167. ode = dode;
  168. nearCallback = near;
  169. triCallback = TriCallback;
  170. triArrayCallback = TriArrayCallback;
  171. /*
  172. contact.surface.mode |= d.ContactFlags.Approx1 | d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP;
  173. contact.surface.mu = 10.0f;
  174. contact.surface.bounce = 0.9f;
  175. contact.surface.soft_erp = 0.005f;
  176. contact.surface.soft_cfm = 0.00003f;
  177. */
  178. // Centeral contact friction and bounce
  179. contact.surface.mu = 250.0f;
  180. contact.surface.bounce = 0.2f;
  181. // Terrain contact friction and Bounce
  182. // This is the *non* moving version. Use this when an avatar
  183. // isn't moving to keep it in place better
  184. TerrainContact.surface.mode |= d.ContactFlags.SoftERP;
  185. TerrainContact.surface.mu = 255.0f;
  186. TerrainContact.surface.bounce = 0.1f;
  187. TerrainContact.surface.soft_erp = 0.1025f;
  188. WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM);
  189. WaterContact.surface.mu = 0f; // No friction
  190. WaterContact.surface.bounce = 0.0f; // No bounce
  191. WaterContact.surface.soft_cfm = 0.01f;
  192. WaterContact.surface.soft_erp = 0.010f;
  193. // Prim contact friction and bounce
  194. // THis is the *non* moving version of friction and bounce
  195. // Use this when an avatar comes in contact with a prim
  196. // and is moving
  197. AvatarMovementprimContact.surface.mu = 75.0f;
  198. AvatarMovementprimContact.surface.bounce = 0.1f;
  199. // Terrain contact friction bounce and various error correcting calculations
  200. // Use this when an avatar is in contact with the terrain and moving.
  201. AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP;
  202. AvatarMovementTerrainContact.surface.mu = 75.0f;
  203. AvatarMovementTerrainContact.surface.bounce = 0.05f;
  204. AvatarMovementTerrainContact.surface.soft_erp = 0.05025f;
  205. lock (OdeLock)
  206. {
  207. // Creat the world and the first space
  208. world = d.WorldCreate();
  209. space = d.HashSpaceCreate(IntPtr.Zero);
  210. d.HashSpaceSetLevels(space, -4, 128);
  211. contactgroup = d.JointGroupCreate(0);
  212. //contactgroup
  213. // Set the gravity,, don't disable things automatically (we set it explicitly on some things)
  214. d.WorldSetGravity(world, 0.0f, 0.0f, -9.8f);
  215. d.WorldSetAutoDisableFlag(world, false);
  216. d.WorldSetContactSurfaceLayer(world, 0.001f);
  217. // Set how many steps we go without running collision testing
  218. // This is in addition to the step size.
  219. // Essentially Steps * m_physicsiterations
  220. d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
  221. ///d.WorldSetContactMaxCorrectingVel(world, 1000.0f);
  222. }
  223. // zero out a heightmap array float array (single dimention [flattened]))
  224. _heightmap = new float[514*514];
  225. _watermap = new float[258 * 258];
  226. // Zero out the prim spaces array (we split our space into smaller spaces so
  227. // we can hit test less.
  228. for (int i = 0; i < staticPrimspace.GetLength(0); i++)
  229. {
  230. for (int j = 0; j < staticPrimspace.GetLength(1); j++)
  231. {
  232. staticPrimspace[i, j] = IntPtr.Zero;
  233. }
  234. }
  235. }
  236. // Initialize the mesh plugin
  237. public override void Initialise(IMesher meshmerizer)
  238. {
  239. mesher = meshmerizer;
  240. }
  241. internal void waitForSpaceUnlock(IntPtr space)
  242. {
  243. //if (space != (IntPtr)0)
  244. //while (d.SpaceLockQuery(space)){ } // Wait and do nothing
  245. }
  246. /// <summary>
  247. /// Debug space message for printing the space that a prim/avatar is in.
  248. /// </summary>
  249. /// <param name="pos"></param>
  250. /// <returns>Returns which split up space the given position is in.</returns>
  251. public string whichspaceamIin(PhysicsVector pos)
  252. {
  253. return calculateSpaceForGeom(pos).ToString();
  254. }
  255. #region Collision Detection
  256. /// <summary>
  257. /// This is our near callback. A geometry is near a body
  258. /// </summary>
  259. /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
  260. /// <param name="g1">a geometry or space</param>
  261. /// <param name="g2">another geometry or space</param>
  262. private void near(IntPtr space, IntPtr g1, IntPtr g2)
  263. {
  264. // no lock here! It's invoked from within Simulate(), which is thread-locked
  265. // Test if we're collidng a geom with a space.
  266. // If so we have to drill down into the space recursively
  267. if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
  268. {
  269. if (g1 == (IntPtr)0 || g2 == (IntPtr)0)
  270. return;
  271. // Separating static prim geometry spaces.
  272. // We'll be calling near recursivly if one
  273. // of them is a space to find all of the
  274. // contact points in the space
  275. try
  276. {
  277. d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
  278. }
  279. catch (AccessViolationException)
  280. {
  281. m_log.Warn("[PHYSICS]: Unable to collide test a space");
  282. return;
  283. }
  284. //Colliding a space or a geom with a space or a geom. so drill down
  285. //Collide all geoms in each space..
  286. //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
  287. //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
  288. return;
  289. }
  290. if (g1 == (IntPtr)0 || g2 == (IntPtr)0)
  291. return;
  292. IntPtr b1 = d.GeomGetBody(g1);
  293. IntPtr b2 = d.GeomGetBody(g2);
  294. d.GeomClassID id = d.GeomGetClass(g1);
  295. String name1 = null;
  296. String name2 = null;
  297. if (!geom_name_map.TryGetValue(g1, out name1))
  298. {
  299. name1 = "null";
  300. }
  301. if (!geom_name_map.TryGetValue(g2, out name2))
  302. {
  303. name2 = "null";
  304. }
  305. //if (id == d.GeomClassId.TriMeshClass)
  306. //{
  307. // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2);
  308. //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
  309. //}
  310. // Figure out how many contact points we have
  311. int count = 0;
  312. try
  313. {
  314. // Colliding Geom To Geom
  315. // This portion of the function 'was' blatantly ripped off from BoxStack.cs
  316. if (g1 == g2)
  317. return; // Can't collide with yourself
  318. if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
  319. return;
  320. lock (contacts)
  321. {
  322. count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
  323. }
  324. }
  325. catch (SEHException)
  326. {
  327. m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
  328. ode.drelease(world);
  329. base.TriggerPhysicsBasedRestart();
  330. }
  331. catch (AccessViolationException)
  332. {
  333. m_log.Warn("[PHYSICS]: Unable to collide test an object");
  334. return;
  335. }
  336. PhysicsActor p1;
  337. PhysicsActor p2;
  338. for (int i = 0; i < count; i++)
  339. {
  340. //m_log.Warn("[CCOUNT]: " + count);
  341. IntPtr joint;
  342. // If we're colliding with terrain, use 'TerrainContact' instead of contact.
  343. // allows us to have different settings
  344. if (!actor_name_map.TryGetValue(g1, out p1))
  345. {
  346. p1 = PANull;
  347. }
  348. if (!actor_name_map.TryGetValue(g2, out p2))
  349. {
  350. p2 = PANull;
  351. }
  352. // We only need to test p2 for 'jump crouch purposes'
  353. p2.IsColliding = true;
  354. //if ((framecount % m_returncollisions) == 0)
  355. //collision_accounting_events(p1, p2);
  356. switch (p1.PhysicsActorType)
  357. {
  358. case (int)ActorTypes.Agent:
  359. p2.CollidingObj = true;
  360. break;
  361. case (int)ActorTypes.Prim:
  362. if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0)
  363. p2.CollidingObj = true;
  364. break;
  365. case (int)ActorTypes.Unknown:
  366. p2.CollidingGround = true;
  367. break;
  368. default:
  369. p2.CollidingGround = true;
  370. break;
  371. }
  372. // we don't want prim or avatar to explode
  373. #region InterPenetration Handling - Unintended physics explosions
  374. if (contacts[i].depth >= 0.08f)
  375. {
  376. //This is disabled at the moment only because it needs more tweaking
  377. //It will eventually be uncommented
  378. if (contacts[i].depth >= 1.00f)
  379. {
  380. //m_log.Debug("[PHYSICS]: " + contacts[i].depth.ToString());
  381. }
  382. //If you interpenetrate a prim with an agent
  383. if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
  384. p1.PhysicsActorType == (int) ActorTypes.Prim) ||
  385. (p1.PhysicsActorType == (int) ActorTypes.Agent &&
  386. p2.PhysicsActorType == (int) ActorTypes.Prim))
  387. {
  388. # region disabled code1
  389. //contacts[i].depth = contacts[i].depth * 4.15f;
  390. /*
  391. if (p2.PhysicsActorType == (int) ActorTypes.Agent)
  392. {
  393. p2.CollidingObj = true;
  394. contacts[i].depth = 0.003f;
  395. p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f);
  396. OdeCharacter character = (OdeCharacter) p2;
  397. character.SetPidStatus(true);
  398. contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2));
  399. }
  400. else
  401. {
  402. //contacts[i].depth = 0.0000000f;
  403. }
  404. if (p1.PhysicsActorType == (int) ActorTypes.Agent)
  405. {
  406. p1.CollidingObj = true;
  407. contacts[i].depth = 0.003f;
  408. p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f);
  409. contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2));
  410. OdeCharacter character = (OdeCharacter)p1;
  411. character.SetPidStatus(true);
  412. }
  413. else
  414. {
  415. //contacts[i].depth = 0.0000000f;
  416. }
  417. */
  418. #endregion
  419. }
  420. // If you interpenetrate a prim with another prim
  421. if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim)
  422. {
  423. #region disabledcode2
  424. //OdePrim op1 = (OdePrim)p1;
  425. //OdePrim op2 = (OdePrim)p2;
  426. //op1.m_collisionscore++;
  427. //op2.m_collisionscore++;
  428. //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000)
  429. //{
  430. //op1.m_taintdisable = true;
  431. //AddPhysicsActorTaint(p1);
  432. //op2.m_taintdisable = true;
  433. //AddPhysicsActorTaint(p2);
  434. //}
  435. //if (contacts[i].depth >= 0.25f)
  436. //{
  437. // Don't collide, one or both prim will expld.
  438. //op1.m_interpenetrationcount++;
  439. //op2.m_interpenetrationcount++;
  440. //interpenetrations_before_disable = 200;
  441. //if (op1.m_interpenetrationcount >= interpenetrations_before_disable)
  442. //{
  443. //op1.m_taintdisable = true;
  444. //AddPhysicsActorTaint(p1);
  445. //}
  446. //if (op2.m_interpenetrationcount >= interpenetrations_before_disable)
  447. //{
  448. // op2.m_taintdisable = true;
  449. //AddPhysicsActorTaint(p2);
  450. //}
  451. //contacts[i].depth = contacts[i].depth / 8f;
  452. //contacts[i].normal = new d.Vector3(0, 0, 1);
  453. //}
  454. //if (op1.m_disabled || op2.m_disabled)
  455. //{
  456. //Manually disabled objects stay disabled
  457. //contacts[i].depth = 0f;
  458. //}
  459. #endregion
  460. }
  461. if (contacts[i].depth >= 1.00f)
  462. {
  463. //m_log.Info("[P]: " + contacts[i].depth.ToString());
  464. if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
  465. p1.PhysicsActorType == (int) ActorTypes.Unknown) ||
  466. (p1.PhysicsActorType == (int) ActorTypes.Agent &&
  467. p2.PhysicsActorType == (int) ActorTypes.Unknown))
  468. {
  469. if (p2.PhysicsActorType == (int) ActorTypes.Agent)
  470. {
  471. OdeCharacter character = (OdeCharacter) p2;
  472. //p2.CollidingObj = true;
  473. contacts[i].depth = 0.00000003f;
  474. p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f);
  475. contacts[i].pos =
  476. new d.Vector3(contacts[i].pos.X + (p1.Size.X/2),
  477. contacts[i].pos.Y + (p1.Size.Y/2),
  478. contacts[i].pos.Z + (p1.Size.Z/2));
  479. character.SetPidStatus(true);
  480. }
  481. else
  482. {
  483. }
  484. if (p1.PhysicsActorType == (int) ActorTypes.Agent)
  485. {
  486. OdeCharacter character = (OdeCharacter)p1;
  487. //p2.CollidingObj = true;
  488. contacts[i].depth = 0.00000003f;
  489. p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f);
  490. contacts[i].pos =
  491. new d.Vector3(contacts[i].pos.X + (p1.Size.X/2),
  492. contacts[i].pos.Y + (p1.Size.Y/2),
  493. contacts[i].pos.Z + (p1.Size.Z/2));
  494. character.SetPidStatus(true);
  495. }
  496. else
  497. {
  498. //contacts[i].depth = 0.0000000f;
  499. }
  500. }
  501. }
  502. }
  503. #endregion
  504. if (contacts[i].depth >= 0f)
  505. {
  506. // If we're collidng against terrain
  507. if (name1 == "Terrain" || name2 == "Terrain")
  508. {
  509. // If we're moving
  510. if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
  511. (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
  512. {
  513. // Use the movement terrain contact
  514. AvatarMovementTerrainContact.geom = contacts[i];
  515. joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
  516. }
  517. else
  518. {
  519. // Use the non moving terrain contact
  520. TerrainContact.geom = contacts[i];
  521. joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
  522. }
  523. }
  524. else if (name1 == "Water" || name2 == "Water")
  525. {
  526. if ((p2.PhysicsActorType == (int)ActorTypes.Prim))
  527. {
  528. }
  529. else
  530. {
  531. }
  532. WaterContact.surface.soft_cfm = 0.0000f;
  533. WaterContact.surface.soft_erp = 0.00000f;
  534. if (contacts[i].depth > 0.1f)
  535. {
  536. contacts[i].depth *= 52;
  537. //contacts[i].normal = new d.Vector3(0, 0, 1);
  538. //contacts[i].pos = new d.Vector3(0, 0, contacts[i].pos.Z - 5f);
  539. }
  540. WaterContact.geom = contacts[i];
  541. joint = d.JointCreateContact(world, contactgroup, ref WaterContact);
  542. //m_log.Info("[PHYSICS]: Prim Water Contact" + contacts[i].depth);
  543. }
  544. else
  545. {
  546. // we're colliding with prim or avatar
  547. // check if we're moving
  548. if ((p2.PhysicsActorType == (int)ActorTypes.Agent) &&
  549. (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
  550. {
  551. // Use the Movement prim contact
  552. AvatarMovementprimContact.geom = contacts[i];
  553. joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
  554. }
  555. else
  556. {
  557. // Use the non movement contact
  558. contact.geom = contacts[i];
  559. joint = d.JointCreateContact(world, contactgroup, ref contact);
  560. }
  561. }
  562. d.JointAttach(joint, b1, b2);
  563. }
  564. if (count > 3)
  565. {
  566. // If there are more then 3 contact points, it's likely
  567. // that we've got a pile of objects
  568. //
  569. // We don't want to send out hundreds of terse updates over and over again
  570. // so lets throttle them and send them again after it's somewhat sorted out.
  571. p2.ThrottleUpdates = true;
  572. }
  573. //System.Console.WriteLine(count.ToString());
  574. //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
  575. }
  576. }
  577. private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2)
  578. {
  579. obj1LocalID = 0;
  580. returncollisions = false;
  581. obj2LocalID = 0;
  582. ctype = 0;
  583. cStartStop = 0;
  584. switch ((ActorTypes)p2.PhysicsActorType)
  585. {
  586. case ActorTypes.Agent:
  587. cc2 = (OdeCharacter)p2;
  588. if (cc2.m_returnCollisions)
  589. {
  590. obj1LocalID = cc2.m_localID;
  591. switch ((ActorTypes)p1.PhysicsActorType)
  592. {
  593. case ActorTypes.Agent:
  594. cc1 = (OdeCharacter)p1;
  595. obj2LocalID = cc1.m_localID;
  596. ctype = (int)CollisionCategories.Character;
  597. if (cc1.CollidingObj)
  598. cStartStop = (int)StatusIndicators.Generic;
  599. else
  600. cStartStop = (int)StatusIndicators.Start;
  601. returncollisions = true;
  602. break;
  603. case ActorTypes.Prim:
  604. cp1 = (OdePrim)p1;
  605. obj2LocalID = cp1.m_localID;
  606. ctype = (int)CollisionCategories.Geom;
  607. if (cp1.CollidingObj)
  608. cStartStop = (int)StatusIndicators.Generic;
  609. else
  610. cStartStop = (int)StatusIndicators.Start;
  611. returncollisions = true;
  612. break;
  613. case ActorTypes.Ground:
  614. case ActorTypes.Unknown:
  615. obj2LocalID = 0;
  616. ctype = (int)CollisionCategories.Land;
  617. returncollisions = true;
  618. break;
  619. }
  620. }
  621. break;
  622. case ActorTypes.Prim:
  623. cp2 = (OdePrim)p2;
  624. if (cp2.m_returnCollisions)
  625. {
  626. obj1LocalID = cp2.m_localID;
  627. switch ((ActorTypes)p1.PhysicsActorType)
  628. {
  629. case ActorTypes.Agent:
  630. cc1 = (OdeCharacter)p1;
  631. obj2LocalID = cc1.m_localID;
  632. ctype = (int)CollisionCategories.Character;
  633. if (cc1.CollidingObj)
  634. cStartStop = (int)StatusIndicators.Generic;
  635. else
  636. cStartStop = (int)StatusIndicators.Start;
  637. returncollisions = true;
  638. break;
  639. case ActorTypes.Prim:
  640. cp1 = (OdePrim)p1;
  641. obj2LocalID = cp1.m_localID;
  642. ctype = (int)CollisionCategories.Geom;
  643. if (cp1.CollidingObj)
  644. cStartStop = (int)StatusIndicators.Generic;
  645. else
  646. cStartStop = (int)StatusIndicators.Start;
  647. returncollisions = true;
  648. break;
  649. case ActorTypes.Ground:
  650. case ActorTypes.Unknown:
  651. obj2LocalID = 0;
  652. ctype = (int)CollisionCategories.Land;
  653. returncollisions = true;
  654. break;
  655. }
  656. }
  657. break;
  658. }
  659. if (returncollisions)
  660. {
  661. lock (m_storedCollisions)
  662. {
  663. cDictKey = obj1LocalID.ToString() + obj2LocalID.ToString() + cStartStop.ToString() + ctype.ToString();
  664. if (m_storedCollisions.ContainsKey(cDictKey))
  665. {
  666. sCollisionData objd = m_storedCollisions[cDictKey];
  667. objd.NumberOfCollisions += 1;
  668. objd.lastframe = framecount;
  669. m_storedCollisions[cDictKey] = objd;
  670. }
  671. else
  672. {
  673. sCollisionData objd = new sCollisionData();
  674. objd.ColliderLocalId = obj1LocalID;
  675. objd.CollidedWithLocalId = obj2LocalID;
  676. objd.CollisionType = ctype;
  677. objd.NumberOfCollisions = 1;
  678. objd.lastframe = framecount;
  679. objd.StatusIndicator = cStartStop;
  680. m_storedCollisions.Add(cDictKey, objd);
  681. }
  682. }
  683. }
  684. }
  685. public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount)
  686. {
  687. /* String name1 = null;
  688. String name2 = null;
  689. if (!geom_name_map.TryGetValue(trimesh, out name1))
  690. {
  691. name1 = "null";
  692. }
  693. if (!geom_name_map.TryGetValue(refObject, out name2))
  694. {
  695. name2 = "null";
  696. }
  697. m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2);
  698. */
  699. return 1;
  700. }
  701. public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
  702. {
  703. String name1 = null;
  704. String name2 = null;
  705. if (!geom_name_map.TryGetValue(trimesh, out name1))
  706. {
  707. name1 = "null";
  708. }
  709. if (!geom_name_map.TryGetValue(refObject, out name2))
  710. {
  711. name2 = "null";
  712. }
  713. // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex);
  714. d.Vector3 v0 = new d.Vector3();
  715. d.Vector3 v1 = new d.Vector3();
  716. d.Vector3 v2 = new d.Vector3();
  717. d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
  718. // m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z);
  719. return 1;
  720. }
  721. /// <summary>
  722. /// This is our collision testing routine in ODE
  723. /// </summary>
  724. /// <param name="timeStep"></param>
  725. private void collision_optimized(float timeStep)
  726. {
  727. foreach (OdeCharacter chr in _characters)
  728. {
  729. // Reset the collision values to false
  730. // since we don't know if we're colliding yet
  731. chr.IsColliding = false;
  732. chr.CollidingGround = false;
  733. chr.CollidingObj = false;
  734. // test the avatar's geometry for collision with the space
  735. // This will return near and the space that they are the closest to
  736. // And we'll run this again against the avatar and the space segment
  737. // This will return with a bunch of possible objects in the space segment
  738. // and we'll run it again on all of them.
  739. try
  740. {
  741. d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
  742. }
  743. catch (AccessViolationException)
  744. {
  745. m_log.Warn("[PHYSICS]: Unable to space collide");
  746. }
  747. //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
  748. //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10)
  749. //{
  750. //chr.Position.Z = terrainheight + 10.0f;
  751. //forcedZ = true;
  752. //}
  753. }
  754. lock (_activeprims)
  755. {
  756. foreach (OdePrim chr in _activeprims)
  757. {
  758. if (d.BodyIsEnabled(chr.Body) && (!chr.m_disabled))
  759. {
  760. try
  761. {
  762. lock (chr)
  763. {
  764. if (space != (IntPtr)0 && chr.prim_geom != (IntPtr)0 && chr.m_taintremove == false)
  765. d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback);
  766. else
  767. m_log.Debug("[PHYSICS]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed");
  768. }
  769. }
  770. catch (AccessViolationException)
  771. {
  772. m_log.Warn("[PHYSICS]: Unable to space collide");
  773. }
  774. }
  775. }
  776. }
  777. }
  778. #endregion
  779. // TODO: unused
  780. // private float GetTerrainHeightAtXY(float x, float y)
  781. // {
  782. // return (float)_origheightmap[(int)y * Constants.RegionSize + (int)x];
  783. // }
  784. #region Add/Remove Entities
  785. public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size)
  786. {
  787. PhysicsVector pos = new PhysicsVector();
  788. pos.X = position.X;
  789. pos.Y = position.Y;
  790. pos.Z = position.Z;
  791. OdeCharacter newAv = new OdeCharacter(avName, this, pos, ode, size);
  792. _characters.Add(newAv);
  793. return newAv;
  794. }
  795. public override void RemoveAvatar(PhysicsActor actor)
  796. {
  797. lock (OdeLock)
  798. {
  799. m_log.Debug("[PHYSICS]:ODELOCK");
  800. ((OdeCharacter) actor).Destroy();
  801. _characters.Remove((OdeCharacter) actor);
  802. }
  803. }
  804. private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation,
  805. IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
  806. {
  807. PhysicsVector pos = new PhysicsVector();
  808. pos.X = position.X;
  809. pos.Y = position.Y;
  810. pos.Z = position.Z;
  811. PhysicsVector siz = new PhysicsVector();
  812. siz.X = size.X;
  813. siz.Y = size.Y;
  814. siz.Z = size.Z;
  815. Quaternion rot = new Quaternion();
  816. rot.w = rotation.w;
  817. rot.x = rotation.x;
  818. rot.y = rotation.y;
  819. rot.z = rotation.z;
  820. OdePrim newPrim;
  821. lock (OdeLock)
  822. {
  823. newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode);
  824. _prims.Add(newPrim);
  825. }
  826. return newPrim;
  827. }
  828. public void addActivePrim(OdePrim activatePrim)
  829. {
  830. // adds active prim.. (ones that should be iterated over in collisions_optimized
  831. _activeprims.Add(activatePrim);
  832. }
  833. public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
  834. PhysicsVector size, Quaternion rotation) //To be removed
  835. {
  836. return AddPrimShape(primName, pbs, position, size, rotation, false);
  837. }
  838. public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
  839. PhysicsVector size, Quaternion rotation, bool isPhysical)
  840. {
  841. PhysicsActor result;
  842. IMesh mesh = null;
  843. switch (pbs.ProfileShape)
  844. {
  845. case ProfileShape.Square:
  846. /// support simple box & hollow box now; later, more shapes
  847. if (needsMeshing(pbs))
  848. {
  849. mesh = mesher.CreateMesh(primName, pbs, size);
  850. }
  851. break;
  852. }
  853. result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
  854. return result;
  855. }
  856. public void remActivePrim(OdePrim deactivatePrim)
  857. {
  858. lock (_activeprims)
  859. {
  860. _activeprims.Remove(deactivatePrim);
  861. }
  862. }
  863. public override void RemovePrim(PhysicsActor prim)
  864. {
  865. if (prim is OdePrim)
  866. {
  867. lock (OdeLock)
  868. {
  869. OdePrim p = (OdePrim) prim;
  870. p.setPrimForRemoval();
  871. AddPhysicsActorTaint(prim);
  872. //RemovePrimThreadLocked(p);
  873. }
  874. }
  875. }
  876. /// <summary>
  877. /// This is called from within simulate but outside the locked portion
  878. /// We need to do our own locking here
  879. /// Essentially, we need to remove the prim from our space segment, whatever segment it's in.
  880. ///
  881. /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory
  882. /// that the space was using.
  883. /// </summary>
  884. /// <param name="prim"></param>
  885. public void RemovePrimThreadLocked(OdePrim prim)
  886. {
  887. lock (prim)
  888. {
  889. lock (ode)
  890. {
  891. if (prim.prim_geom != (IntPtr)0)
  892. {
  893. //System.Threading.Thread.Sleep(20);
  894. prim.ResetTaints();
  895. if (prim.IsPhysical)
  896. {
  897. prim.disableBody();
  898. }
  899. // we don't want to remove the main space
  900. // If the geometry is in the targetspace, remove it from the target space
  901. //m_log.Warn(prim.m_targetSpace);
  902. //if (prim.m_targetSpace != (IntPtr)0)
  903. //{
  904. //if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom))
  905. //{
  906. //if (d.GeomIsSpace(prim.m_targetSpace))
  907. //{
  908. //waitForSpaceUnlock(prim.m_targetSpace);
  909. //d.SpaceRemove(prim.m_targetSpace, prim.prim_geom);
  910. prim.m_targetSpace = (IntPtr)0;
  911. //}
  912. //else
  913. //{
  914. // m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
  915. //((OdePrim)prim).m_targetSpace.ToString());
  916. //}
  917. //}
  918. //}
  919. //m_log.Warn(prim.prim_geom);
  920. try
  921. {
  922. if (prim.prim_geom != (IntPtr)0)
  923. {
  924. d.GeomDestroy(prim.prim_geom);
  925. prim.prim_geom = (IntPtr)0;
  926. }
  927. else
  928. {
  929. m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene");
  930. }
  931. }
  932. catch (AccessViolationException)
  933. {
  934. m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed.");
  935. }
  936. _prims.Remove(prim);
  937. //If there are no more geometries in the sub-space, we don't need it in the main space anymore
  938. //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0)
  939. //{
  940. //if (!(prim.m_targetSpace.Equals(null)))
  941. //{
  942. //if (d.GeomIsSpace(prim.m_targetSpace))
  943. //{
  944. //waitForSpaceUnlock(prim.m_targetSpace);
  945. //d.SpaceRemove(space, prim.m_targetSpace);
  946. // free up memory used by the space.
  947. //d.SpaceDestroy(prim.m_targetSpace);
  948. //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position);
  949. //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]);
  950. //}
  951. //else
  952. //{
  953. //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
  954. //((OdePrim) prim).m_targetSpace.ToString());
  955. //}
  956. //}
  957. //}
  958. }
  959. }
  960. }
  961. }
  962. #endregion
  963. #region Space Separation Calculation
  964. /// <summary>
  965. /// Takes a space pointer and zeros out the array we're using to hold the spaces
  966. /// </summary>
  967. /// <param name="space"></param>
  968. public void resetSpaceArrayItemToZero(IntPtr space)
  969. {
  970. for (int x = 0; x < staticPrimspace.GetLength(0); x++)
  971. {
  972. for (int y = 0; y < staticPrimspace.GetLength(1); y++)
  973. {
  974. if (staticPrimspace[x, y] == space)
  975. staticPrimspace[x, y] = IntPtr.Zero;
  976. }
  977. }
  978. }
  979. public void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY)
  980. {
  981. staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero;
  982. }
  983. /// <summary>
  984. /// Called when a static prim moves. Allocates a space for the prim based on it's position
  985. /// </summary>
  986. /// <param name="geom">the pointer to the geom that moved</param>
  987. /// <param name="pos">the position that the geom moved to</param>
  988. /// <param name="currentspace">a pointer to the space it was in before it was moved.</param>
  989. /// <returns>a pointer to the new space it's in</returns>
  990. public IntPtr recalculateSpaceForGeom(IntPtr geom, PhysicsVector pos, IntPtr currentspace)
  991. {
  992. // Called from setting the Position and Size of an ODEPrim so
  993. // it's already in locked space.
  994. // we don't want to remove the main space
  995. // we don't need to test physical here because this function should
  996. // never be called if the prim is physical(active)
  997. // All physical prim end up in the root space
  998. Thread.Sleep(20);
  999. if (currentspace != space)
  1000. {
  1001. //m_log.Info("[SPACE]: C:" + currentspace.ToString() + " g:" + geom.ToString());
  1002. //if (currentspace == (IntPtr) 0)
  1003. //{
  1004. //int adfadf = 0;
  1005. //}
  1006. if (d.SpaceQuery(currentspace, geom) && currentspace != (IntPtr) 0)
  1007. {
  1008. if (d.GeomIsSpace(currentspace))
  1009. {
  1010. waitForSpaceUnlock(currentspace);
  1011. d.SpaceRemove(currentspace, geom);
  1012. }
  1013. else
  1014. {
  1015. m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace.ToString() +
  1016. " Geom:" + geom.ToString());
  1017. }
  1018. }
  1019. else
  1020. {
  1021. IntPtr sGeomIsIn = d.GeomGetSpace(geom);
  1022. if (!(sGeomIsIn.Equals(null)))
  1023. {
  1024. if (sGeomIsIn != (IntPtr) 0)
  1025. {
  1026. if (d.GeomIsSpace(currentspace))
  1027. {
  1028. waitForSpaceUnlock(sGeomIsIn);
  1029. d.SpaceRemove(sGeomIsIn, geom);
  1030. }
  1031. else
  1032. {
  1033. m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
  1034. sGeomIsIn.ToString() + " Geom:" + geom.ToString());
  1035. }
  1036. }
  1037. }
  1038. }
  1039. //If there are no more geometries in the sub-space, we don't need it in the main space anymore
  1040. if (d.SpaceGetNumGeoms(currentspace) == 0)
  1041. {
  1042. if (currentspace != (IntPtr) 0)
  1043. {
  1044. if (d.GeomIsSpace(currentspace))
  1045. {
  1046. waitForSpaceUnlock(currentspace);
  1047. waitForSpaceUnlock(space);
  1048. d.SpaceRemove(space, currentspace);
  1049. // free up memory used by the space.
  1050. //d.SpaceDestroy(currentspace);
  1051. resetSpaceArrayItemToZero(currentspace);
  1052. }
  1053. else
  1054. {
  1055. m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
  1056. currentspace.ToString() + " Geom:" + geom.ToString());
  1057. }
  1058. }
  1059. }
  1060. }
  1061. else
  1062. {
  1063. // this is a physical object that got disabled. ;.;
  1064. if (currentspace != (IntPtr)0 && geom != (IntPtr)0)
  1065. {
  1066. if (d.SpaceQuery(currentspace, geom))
  1067. {
  1068. if (d.GeomIsSpace(currentspace))
  1069. {
  1070. waitForSpaceUnlock(currentspace);
  1071. d.SpaceRemove(currentspace, geom);
  1072. }
  1073. else
  1074. {
  1075. m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
  1076. currentspace.ToString() + " Geom:" + geom.ToString());
  1077. }
  1078. }
  1079. else
  1080. {
  1081. IntPtr sGeomIsIn = d.GeomGetSpace(geom);
  1082. if (!(sGeomIsIn.Equals(null)))
  1083. {
  1084. if (sGeomIsIn != (IntPtr)0)
  1085. {
  1086. if (d.GeomIsSpace(sGeomIsIn))
  1087. {
  1088. waitForSpaceUnlock(sGeomIsIn);
  1089. d.SpaceRemove(sGeomIsIn, geom);
  1090. }
  1091. else
  1092. {
  1093. m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
  1094. sGeomIsIn.ToString() + " Geom:" + geom.ToString());
  1095. }
  1096. }
  1097. }
  1098. }
  1099. }
  1100. }
  1101. // The routines in the Position and Size sections do the 'inserting' into the space,
  1102. // so all we have to do is make sure that the space that we're putting the prim into
  1103. // is in the 'main' space.
  1104. int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos);
  1105. IntPtr newspace = calculateSpaceForGeom(pos);
  1106. if (newspace == IntPtr.Zero)
  1107. {
  1108. newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
  1109. d.HashSpaceSetLevels(newspace, -4, 66);
  1110. }
  1111. return newspace;
  1112. }
  1113. /// <summary>
  1114. /// Creates a new space at X Y
  1115. /// </summary>
  1116. /// <param name="iprimspaceArrItemX"></param>
  1117. /// <param name="iprimspaceArrItemY"></param>
  1118. /// <returns>A pointer to the created space</returns>
  1119. public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY)
  1120. {
  1121. // creating a new space for prim and inserting it into main space.
  1122. staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero);
  1123. d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space);
  1124. waitForSpaceUnlock(space);
  1125. d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]);
  1126. return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY];
  1127. }
  1128. /// <summary>
  1129. /// Calculates the space the prim should be in by it's position
  1130. /// </summary>
  1131. /// <param name="pos"></param>
  1132. /// <returns>a pointer to the space. This could be a new space or reused space.</returns>
  1133. public IntPtr calculateSpaceForGeom(PhysicsVector pos)
  1134. {
  1135. IntPtr locationbasedspace =IntPtr.Zero;
  1136. int[] xyspace = calculateSpaceArrayItemFromPos(pos);
  1137. //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString());
  1138. locationbasedspace = staticPrimspace[xyspace[0], xyspace[1]];
  1139. //locationbasedspace = space;
  1140. return locationbasedspace;
  1141. }
  1142. /// <summary>
  1143. /// Holds the space allocation logic
  1144. /// </summary>
  1145. /// <param name="pos"></param>
  1146. /// <returns>an array item based on the position</returns>
  1147. public int[] calculateSpaceArrayItemFromPos(PhysicsVector pos)
  1148. {
  1149. int[] returnint = new int[2];
  1150. returnint[0] = (int) (pos.X/metersInSpace);
  1151. if (returnint[0] > ((int) (259f/metersInSpace)))
  1152. returnint[0] = ((int) (259f/metersInSpace));
  1153. if (returnint[0] < 0)
  1154. returnint[0] = 0;
  1155. returnint[1] = (int) (pos.Y/metersInSpace);
  1156. if (returnint[1] > ((int) (259f/metersInSpace)))
  1157. returnint[1] = ((int) (259f/metersInSpace));
  1158. if (returnint[1] < 0)
  1159. returnint[1] = 0;
  1160. return returnint;
  1161. }
  1162. #endregion
  1163. /// <summary>
  1164. /// Routine to figure out if we need to mesh this prim with our mesher
  1165. /// </summary>
  1166. /// <param name="pbs"></param>
  1167. /// <returns></returns>
  1168. public bool needsMeshing(PrimitiveBaseShape pbs)
  1169. {
  1170. if (pbs.ProfileHollow != 0)
  1171. return true;
  1172. if (((Int16)pbs.PathTwistBegin != 0) || ((Int16)pbs.PathTwist != 0))
  1173. return true;
  1174. if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
  1175. return true;
  1176. if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
  1177. return true;
  1178. if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
  1179. return true;
  1180. if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
  1181. return true;
  1182. 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))
  1183. return true;
  1184. if (pbs.ProfileShape == ProfileShape.EquilateralTriangle)
  1185. return true;
  1186. return false;
  1187. }
  1188. /// <summary>
  1189. /// Called after our prim properties are set Scale, position etc.
  1190. /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
  1191. /// This assures us that we have no race conditions
  1192. /// </summary>
  1193. /// <param name="prim"></param>
  1194. public override void AddPhysicsActorTaint(PhysicsActor prim)
  1195. {
  1196. if (prim is OdePrim)
  1197. {
  1198. OdePrim taintedprim = ((OdePrim) prim);
  1199. lock (_taintedPrim)
  1200. {
  1201. if (!(_taintedPrim.Contains(taintedprim)))
  1202. _taintedPrim.Add(taintedprim);
  1203. }
  1204. }
  1205. }
  1206. /// <summary>
  1207. /// This is our main simulate loop
  1208. /// It's thread locked by a Mutex in the scene.
  1209. /// It holds Collisions, it instructs ODE to step through the physical reactions
  1210. /// It moves the objects around in memory
  1211. /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
  1212. /// </summary>
  1213. /// <param name="timeStep"></param>
  1214. /// <returns></returns>
  1215. public override float Simulate(float timeStep)
  1216. {
  1217. if (framecount >= int.MaxValue)
  1218. framecount = 0;
  1219. framecount++;
  1220. float fps = 0;
  1221. //m_log.Info(timeStep.ToString());
  1222. step_time += timeStep;
  1223. // If We're loaded down by something else,
  1224. // or debugging with the Visual Studio project on pause
  1225. // skip a few frames to catch up gracefully.
  1226. // without shooting the physicsactors all over the place
  1227. if (step_time >= m_SkipFramesAtms)
  1228. {
  1229. // Instead of trying to catch up, it'll do 5 physics frames only
  1230. step_time = ODE_STEPSIZE;
  1231. m_physicsiterations = 5;
  1232. }
  1233. else
  1234. {
  1235. m_physicsiterations = 10;
  1236. }
  1237. lock (OdeLock)
  1238. {
  1239. // Process 10 frames if the sim is running normal..
  1240. // process 5 frames if the sim is running slow
  1241. //try
  1242. //{
  1243. //d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
  1244. //}
  1245. //catch (StackOverflowException)
  1246. //{
  1247. // m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim.");
  1248. // ode.drelease(world);
  1249. //base.TriggerPhysicsBasedRestart();
  1250. //}
  1251. int i = 0;
  1252. // Figure out the Frames Per Second we're going at.
  1253. //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size
  1254. step_time = 0.09375f;
  1255. fps = (step_time/ODE_STEPSIZE) * 1000;
  1256. while (step_time > 0.0f)
  1257. {
  1258. //lock (ode)
  1259. //{
  1260. //if (!ode.lockquery())
  1261. //{
  1262. // ode.dlock(world);
  1263. try
  1264. {
  1265. lock (_characters)
  1266. {
  1267. foreach (OdeCharacter actor in _characters)
  1268. {
  1269. if (actor != null)
  1270. actor.Move(timeStep);
  1271. }
  1272. }
  1273. bool processedtaints = false;
  1274. lock (_taintedPrim)
  1275. {
  1276. foreach (OdePrim prim in _taintedPrim)
  1277. {
  1278. if (prim.m_taintremove)
  1279. {
  1280. RemovePrimThreadLocked(prim);
  1281. }
  1282. else
  1283. {
  1284. prim.ProcessTaints(timeStep);
  1285. }
  1286. processedtaints = true;
  1287. prim.m_collisionscore = 0;
  1288. }
  1289. if (processedtaints)
  1290. _taintedPrim = new List<OdePrim>();
  1291. }
  1292. lock (_activeprims)
  1293. {
  1294. foreach (OdePrim prim in _activeprims)
  1295. {
  1296. prim.m_collisionscore = 0;
  1297. prim.Move(timeStep);
  1298. }
  1299. }
  1300. //if ((framecount % m_randomizeWater) == 0)
  1301. // randomizeWater(waterlevel);
  1302. collision_optimized(timeStep);
  1303. d.WorldQuickStep(world, ODE_STEPSIZE);
  1304. d.JointGroupEmpty(contactgroup);
  1305. //ode.dunlock(world);
  1306. }
  1307. catch (Exception e)
  1308. {
  1309. m_log.Error("[PHYSICS]: " + e.Message.ToString() + e.TargetSite.ToString());
  1310. ode.dunlock(world);
  1311. }
  1312. step_time -= ODE_STEPSIZE;
  1313. i++;
  1314. //}
  1315. //else
  1316. //{
  1317. //fps = 0;
  1318. //}
  1319. //}
  1320. }
  1321. lock (_characters)
  1322. {
  1323. foreach (OdeCharacter actor in _characters)
  1324. {
  1325. if (actor != null)
  1326. actor.UpdatePositionAndVelocity();
  1327. }
  1328. }
  1329. lock (_activeprims)
  1330. {
  1331. if (timeStep < 0.2f)
  1332. {
  1333. foreach (OdePrim actor in _activeprims)
  1334. {
  1335. if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag))
  1336. {
  1337. actor.UpdatePositionAndVelocity();
  1338. }
  1339. }
  1340. }
  1341. }
  1342. }
  1343. return fps;
  1344. }
  1345. public override void GetResults()
  1346. {
  1347. }
  1348. public override bool IsThreaded
  1349. {
  1350. // for now we won't be multithreaded
  1351. get { return (false); }
  1352. }
  1353. #region ODE Specific Terrain Fixes
  1354. public float[] ResizeTerrain512NearestNeighbour(float[] heightMap)
  1355. {
  1356. float[] returnarr = new float[262144];
  1357. float[,] resultarr = new float[m_regionWidth, m_regionHeight];
  1358. // Filling out the array into it's multi-dimentional components
  1359. for (int y = 0; y < m_regionHeight; y++)
  1360. {
  1361. for (int x = 0; x < m_regionWidth; x++)
  1362. {
  1363. resultarr[y, x] = heightMap[y * m_regionWidth + x];
  1364. }
  1365. }
  1366. // Resize using Nearest Neighbour
  1367. // This particular way is quick but it only works on a multiple of the original
  1368. // The idea behind this method can be described with the following diagrams
  1369. // second pass and third pass happen in the same loop really.. just separated
  1370. // them to show what this does.
  1371. // First Pass
  1372. // ResultArr:
  1373. // 1,1,1,1,1,1
  1374. // 1,1,1,1,1,1
  1375. // 1,1,1,1,1,1
  1376. // 1,1,1,1,1,1
  1377. // 1,1,1,1,1,1
  1378. // 1,1,1,1,1,1
  1379. // Second Pass
  1380. // ResultArr2:
  1381. // 1,,1,,1,,1,,1,,1,
  1382. // ,,,,,,,,,,
  1383. // 1,,1,,1,,1,,1,,1,
  1384. // ,,,,,,,,,,
  1385. // 1,,1,,1,,1,,1,,1,
  1386. // ,,,,,,,,,,
  1387. // 1,,1,,1,,1,,1,,1,
  1388. // ,,,,,,,,,,
  1389. // 1,,1,,1,,1,,1,,1,
  1390. // ,,,,,,,,,,
  1391. // 1,,1,,1,,1,,1,,1,
  1392. // Third pass fills in the blanks
  1393. // ResultArr2:
  1394. // 1,1,1,1,1,1,1,1,1,1,1,1
  1395. // 1,1,1,1,1,1,1,1,1,1,1,1
  1396. // 1,1,1,1,1,1,1,1,1,1,1,1
  1397. // 1,1,1,1,1,1,1,1,1,1,1,1
  1398. // 1,1,1,1,1,1,1,1,1,1,1,1
  1399. // 1,1,1,1,1,1,1,1,1,1,1,1
  1400. // 1,1,1,1,1,1,1,1,1,1,1,1
  1401. // 1,1,1,1,1,1,1,1,1,1,1,1
  1402. // 1,1,1,1,1,1,1,1,1,1,1,1
  1403. // 1,1,1,1,1,1,1,1,1,1,1,1
  1404. // 1,1,1,1,1,1,1,1,1,1,1,1
  1405. // X,Y = .
  1406. // X+1,y = ^
  1407. // X,Y+1 = *
  1408. // X+1,Y+1 = #
  1409. // Filling in like this;
  1410. // .*
  1411. // ^#
  1412. // 1st .
  1413. // 2nd *
  1414. // 3rd ^
  1415. // 4th #
  1416. // on single loop.
  1417. float[,] resultarr2 = new float[512, 512];
  1418. for (int y = 0; y < m_regionHeight; y++)
  1419. {
  1420. for (int x = 0; x < m_regionWidth; x++)
  1421. {
  1422. resultarr2[y * 2, x * 2] = resultarr[y, x];
  1423. if (y < m_regionHeight)
  1424. {
  1425. resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x];
  1426. }
  1427. if (x < m_regionWidth)
  1428. {
  1429. resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x];
  1430. }
  1431. if (x < m_regionWidth && y < m_regionHeight)
  1432. {
  1433. resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x];
  1434. }
  1435. }
  1436. }
  1437. //Flatten out the array
  1438. int i = 0;
  1439. for (int y = 0; y < 512; y++)
  1440. {
  1441. for (int x = 0; x < 512; x++)
  1442. {
  1443. if (resultarr2[y, x] <= 0)
  1444. returnarr[i] = 0.0000001f;
  1445. else
  1446. returnarr[i] = resultarr2[y, x];
  1447. i++;
  1448. }
  1449. }
  1450. return returnarr;
  1451. }
  1452. public float[] ResizeTerrain512Interpolation(float[] heightMap)
  1453. {
  1454. float[] returnarr = new float[262144];
  1455. float[,] resultarr = new float[m_regionWidth,m_regionHeight];
  1456. // Filling out the array into it's multi-dimentional components
  1457. for (int y = 0; y < m_regionHeight; y++)
  1458. {
  1459. for (int x = 0; x < m_regionWidth; x++)
  1460. {
  1461. resultarr[y, x] = heightMap[y*m_regionWidth + x];
  1462. }
  1463. }
  1464. // Resize using interpolation
  1465. // This particular way is quick but it only works on a multiple of the original
  1466. // The idea behind this method can be described with the following diagrams
  1467. // second pass and third pass happen in the same loop really.. just separated
  1468. // them to show what this does.
  1469. // First Pass
  1470. // ResultArr:
  1471. // 1,1,1,1,1,1
  1472. // 1,1,1,1,1,1
  1473. // 1,1,1,1,1,1
  1474. // 1,1,1,1,1,1
  1475. // 1,1,1,1,1,1
  1476. // 1,1,1,1,1,1
  1477. // Second Pass
  1478. // ResultArr2:
  1479. // 1,,1,,1,,1,,1,,1,
  1480. // ,,,,,,,,,,
  1481. // 1,,1,,1,,1,,1,,1,
  1482. // ,,,,,,,,,,
  1483. // 1,,1,,1,,1,,1,,1,
  1484. // ,,,,,,,,,,
  1485. // 1,,1,,1,,1,,1,,1,
  1486. // ,,,,,,,,,,
  1487. // 1,,1,,1,,1,,1,,1,
  1488. // ,,,,,,,,,,
  1489. // 1,,1,,1,,1,,1,,1,
  1490. // Third pass fills in the blanks
  1491. // ResultArr2:
  1492. // 1,1,1,1,1,1,1,1,1,1,1,1
  1493. // 1,1,1,1,1,1,1,1,1,1,1,1
  1494. // 1,1,1,1,1,1,1,1,1,1,1,1
  1495. // 1,1,1,1,1,1,1,1,1,1,1,1
  1496. // 1,1,1,1,1,1,1,1,1,1,1,1
  1497. // 1,1,1,1,1,1,1,1,1,1,1,1
  1498. // 1,1,1,1,1,1,1,1,1,1,1,1
  1499. // 1,1,1,1,1,1,1,1,1,1,1,1
  1500. // 1,1,1,1,1,1,1,1,1,1,1,1
  1501. // 1,1,1,1,1,1,1,1,1,1,1,1
  1502. // 1,1,1,1,1,1,1,1,1,1,1,1
  1503. // X,Y = .
  1504. // X+1,y = ^
  1505. // X,Y+1 = *
  1506. // X+1,Y+1 = #
  1507. // Filling in like this;
  1508. // .*
  1509. // ^#
  1510. // 1st .
  1511. // 2nd *
  1512. // 3rd ^
  1513. // 4th #
  1514. // on single loop.
  1515. float[,] resultarr2 = new float[512,512];
  1516. for (int y = 0; y < m_regionHeight; y++)
  1517. {
  1518. for (int x = 0; x < m_regionWidth; x++)
  1519. {
  1520. resultarr2[y*2, x*2] = resultarr[y, x];
  1521. if (y < m_regionHeight)
  1522. {
  1523. if (y + 1 < m_regionHeight)
  1524. {
  1525. if (x + 1 < m_regionWidth)
  1526. {
  1527. resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] +
  1528. resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
  1529. }
  1530. else
  1531. {
  1532. resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2);
  1533. }
  1534. }
  1535. else
  1536. {
  1537. resultarr2[(y*2) + 1, x*2] = resultarr[y, x];
  1538. }
  1539. }
  1540. if (x < m_regionWidth)
  1541. {
  1542. if (x + 1 < m_regionWidth)
  1543. {
  1544. if (y + 1 < m_regionHeight)
  1545. {
  1546. resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
  1547. resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
  1548. }
  1549. else
  1550. {
  1551. resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2);
  1552. }
  1553. }
  1554. else
  1555. {
  1556. resultarr2[y*2, (x*2) + 1] = resultarr[y, x];
  1557. }
  1558. }
  1559. if (x < m_regionWidth && y < m_regionHeight)
  1560. {
  1561. if ((x + 1 < m_regionWidth) && (y + 1 < m_regionHeight))
  1562. {
  1563. resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] +
  1564. resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4);
  1565. }
  1566. else
  1567. {
  1568. resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x];
  1569. }
  1570. }
  1571. }
  1572. }
  1573. //Flatten out the array
  1574. int i = 0;
  1575. for (int y = 0; y < 512; y++)
  1576. {
  1577. for (int x = 0; x < 512; x++)
  1578. {
  1579. if (resultarr2[y, x] <= 0)
  1580. returnarr[i] = 0.0000001f;
  1581. else
  1582. returnarr[i] = resultarr2[y, x];
  1583. i++;
  1584. }
  1585. }
  1586. return returnarr;
  1587. }
  1588. #endregion
  1589. public override void SetTerrain(float[] heightMap)
  1590. {
  1591. // this._heightmap[i] = (double)heightMap[i];
  1592. // dbm (danx0r) -- creating a buffer zone of one extra sample all around
  1593. _origheightmap = heightMap;
  1594. const uint heightmapWidth = m_regionWidth + 2;
  1595. const uint heightmapHeight = m_regionHeight + 2;
  1596. const uint heightmapWidthSamples = 2*m_regionWidth + 2;
  1597. const uint heightmapHeightSamples = 2*m_regionHeight + 2;
  1598. const float scale = 1.0f;
  1599. const float offset = 0.0f;
  1600. const float thickness = 0.2f;
  1601. const int wrap = 0;
  1602. //Double resolution
  1603. heightMap = ResizeTerrain512Interpolation(heightMap);
  1604. for (int x = 0; x < heightmapWidthSamples; x++)
  1605. {
  1606. for (int y = 0; y < heightmapHeightSamples; y++)
  1607. {
  1608. int xx = Util.Clip(x - 1, 0, 511);
  1609. int yy = Util.Clip(y - 1, 0, 511);
  1610. float val = heightMap[yy*512 + xx];
  1611. _heightmap[x*heightmapHeightSamples + y] = val;
  1612. }
  1613. }
  1614. lock (OdeLock)
  1615. {
  1616. if (!(LandGeom == (IntPtr) 0))
  1617. {
  1618. d.SpaceRemove(space, LandGeom);
  1619. }
  1620. IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
  1621. d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth, heightmapHeight,
  1622. (int) heightmapWidthSamples, (int) heightmapHeightSamples, scale,
  1623. offset, thickness, wrap);
  1624. d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight);
  1625. LandGeom = d.CreateHeightfield(space, HeightmapData, 1);
  1626. if (LandGeom != (IntPtr)0)
  1627. {
  1628. d.GeomSetCategoryBits(LandGeom, (int)(CollisionCategories.Land));
  1629. d.GeomSetCollideBits(LandGeom, (int)(CollisionCategories.Space));
  1630. }
  1631. geom_name_map[LandGeom] = "Terrain";
  1632. d.Matrix3 R = new d.Matrix3();
  1633. Quaternion q1 = Quaternion.FromAngleAxis(1.5707f, new Vector3(1, 0, 0));
  1634. Quaternion q2 = Quaternion.FromAngleAxis(1.5707f, new Vector3(0, 1, 0));
  1635. //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
  1636. q1 = q1*q2;
  1637. //q1 = q1 * q3;
  1638. Vector3 v3 = new Vector3();
  1639. float angle = 0;
  1640. q1.ToAngleAxis(ref angle, ref v3);
  1641. d.RFromAxisAndAngle(out R, v3.x, v3.y, v3.z, angle);
  1642. d.GeomSetRotation(LandGeom, ref R);
  1643. d.GeomSetPosition(LandGeom, 128, 128, 0);
  1644. }
  1645. }
  1646. public override void DeleteTerrain()
  1647. {
  1648. }
  1649. public override void SetWaterLevel(float baseheight)
  1650. {
  1651. waterlevel = baseheight;
  1652. randomizeWater(waterlevel);
  1653. }
  1654. public void randomizeWater(float baseheight)
  1655. {
  1656. const uint heightmapWidth = m_regionWidth + 2;
  1657. const uint heightmapHeight = m_regionHeight + 2;
  1658. const uint heightmapWidthSamples = m_regionWidth + 2;
  1659. const uint heightmapHeightSamples = m_regionHeight + 2;
  1660. const float scale = 1.0f;
  1661. const float offset = 0.0f;
  1662. const float thickness = 2.9f;
  1663. const int wrap = 0;
  1664. for (int i = 0; i < (258 * 258); i++)
  1665. {
  1666. _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f);
  1667. // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f));
  1668. }
  1669. lock (OdeLock)
  1670. {
  1671. if (!(WaterGeom == (IntPtr)0))
  1672. {
  1673. d.SpaceRemove(space, WaterGeom);
  1674. }
  1675. IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
  1676. d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight,
  1677. (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
  1678. offset, thickness, wrap);
  1679. d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight);
  1680. WaterGeom = d.CreateHeightfield(space, HeightmapData, 1);
  1681. if (WaterGeom != (IntPtr)0)
  1682. {
  1683. d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water));
  1684. d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space));
  1685. }
  1686. geom_name_map[WaterGeom] = "Water";
  1687. d.Matrix3 R = new d.Matrix3();
  1688. Quaternion q1 = Quaternion.FromAngleAxis(1.5707f, new Vector3(1, 0, 0));
  1689. Quaternion q2 = Quaternion.FromAngleAxis(1.5707f, new Vector3(0, 1, 0));
  1690. //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
  1691. q1 = q1 * q2;
  1692. //q1 = q1 * q3;
  1693. Vector3 v3 = new Vector3();
  1694. float angle = 0;
  1695. q1.ToAngleAxis(ref angle, ref v3);
  1696. d.RFromAxisAndAngle(out R, v3.x, v3.y, v3.z, angle);
  1697. d.GeomSetRotation(WaterGeom, ref R);
  1698. d.GeomSetPosition(WaterGeom, 128, 128, 0);
  1699. }
  1700. }
  1701. public override void Dispose()
  1702. {
  1703. lock (OdeLock)
  1704. {
  1705. foreach (OdePrim prm in _prims)
  1706. {
  1707. RemovePrim(prm);
  1708. }
  1709. //foreach (OdeCharacter act in _characters)
  1710. //{
  1711. //RemoveAvatar(act);
  1712. //}
  1713. d.WorldDestroy(world);
  1714. //d.CloseODE();
  1715. }
  1716. }
  1717. }
  1718. }