OdePlugin.cs 90 KB

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