OdePlugin.cs 88 KB

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