OdePlugin.cs 80 KB

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