BSParam.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  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 copyrightD
  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 OpenSimulator 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.Text;
  30. using OpenSim.Region.Physics.Manager;
  31. using OpenMetaverse;
  32. using Nini.Config;
  33. namespace OpenSim.Region.Physics.BulletSNPlugin
  34. {
  35. public static class BSParam
  36. {
  37. // Level of Detail values kept as float because that's what the Meshmerizer wants
  38. public static float MeshLOD { get; private set; }
  39. public static float MeshMegaPrimLOD { get; private set; }
  40. public static float MeshMegaPrimThreshold { get; private set; }
  41. public static float SculptLOD { get; private set; }
  42. public static float MinimumObjectMass { get; private set; }
  43. public static float MaximumObjectMass { get; private set; }
  44. public static float LinearDamping { get; private set; }
  45. public static float AngularDamping { get; private set; }
  46. public static float DeactivationTime { get; private set; }
  47. public static float LinearSleepingThreshold { get; private set; }
  48. public static float AngularSleepingThreshold { get; private set; }
  49. public static float CcdMotionThreshold { get; private set; }
  50. public static float CcdSweptSphereRadius { get; private set; }
  51. public static float ContactProcessingThreshold { get; private set; }
  52. public static bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
  53. public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
  54. public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
  55. public static float TerrainImplementation { get; private set; }
  56. public static float TerrainFriction { get; private set; }
  57. public static float TerrainHitFraction { get; private set; }
  58. public static float TerrainRestitution { get; private set; }
  59. public static float TerrainCollisionMargin { get; private set; }
  60. // Avatar parameters
  61. public static float AvatarFriction { get; private set; }
  62. public static float AvatarStandingFriction { get; private set; }
  63. public static float AvatarDensity { get; private set; }
  64. public static float AvatarRestitution { get; private set; }
  65. public static float AvatarCapsuleWidth { get; private set; }
  66. public static float AvatarCapsuleDepth { get; private set; }
  67. public static float AvatarCapsuleHeight { get; private set; }
  68. public static float AvatarContactProcessingThreshold { get; private set; }
  69. public static float VehicleAngularDamping { get; private set; }
  70. public static float LinksetImplementation { get; private set; }
  71. public static float LinkConstraintUseFrameOffset { get; private set; }
  72. public static float LinkConstraintEnableTransMotor { get; private set; }
  73. public static float LinkConstraintTransMotorMaxVel { get; private set; }
  74. public static float LinkConstraintTransMotorMaxForce { get; private set; }
  75. public static float LinkConstraintERP { get; private set; }
  76. public static float LinkConstraintCFM { get; private set; }
  77. public static float LinkConstraintSolverIterations { get; private set; }
  78. public static float PID_D { get; private set; } // derivative
  79. public static float PID_P { get; private set; } // proportional
  80. public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
  81. public delegate float ParamGet(BSScene scene);
  82. public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
  83. public delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
  84. public struct ParameterDefn
  85. {
  86. public string name; // string name of the parameter
  87. public string desc; // a short description of what the parameter means
  88. public float defaultValue; // default value if not specified anywhere else
  89. public ParamUser userParam; // get the value from the configuration file
  90. public ParamGet getter; // return the current value stored for this parameter
  91. public ParamSet setter; // set the current value for this parameter
  92. public SetOnObject onObject; // set the value on an object in the physical domain
  93. public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
  94. {
  95. name = n;
  96. desc = d;
  97. defaultValue = v;
  98. userParam = u;
  99. getter = g;
  100. setter = s;
  101. onObject = null;
  102. }
  103. public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
  104. {
  105. name = n;
  106. desc = d;
  107. defaultValue = v;
  108. userParam = u;
  109. getter = g;
  110. setter = s;
  111. onObject = o;
  112. }
  113. }
  114. // List of all of the externally visible parameters.
  115. // For each parameter, this table maps a text name to getter and setters.
  116. // To add a new externally referencable/settable parameter, add the paramter storage
  117. // location somewhere in the program and make an entry in this table with the
  118. // getters and setters.
  119. // It is easiest to find an existing definition and copy it.
  120. // Parameter values are floats. Booleans are converted to a floating value.
  121. //
  122. // A ParameterDefn() takes the following parameters:
  123. // -- the text name of the parameter. This is used for console input and ini file.
  124. // -- a short text description of the parameter. This shows up in the console listing.
  125. // -- a default value (float)
  126. // -- a delegate for fetching the parameter from the ini file.
  127. // Should handle fetching the right type from the ini file and converting it.
  128. // -- a delegate for getting the value as a float
  129. // -- a delegate for setting the value from a float
  130. // -- an optional delegate to update the value in the world. Most often used to
  131. // push the new value to an in-world object.
  132. //
  133. // The single letter parameters for the delegates are:
  134. // s = BSScene
  135. // o = BSPhysObject
  136. // p = string parameter name
  137. // l = localID of referenced object
  138. // v = value (float)
  139. // cf = parameter configuration class (for fetching values from ini file)
  140. private static ParameterDefn[] ParameterDefinitions =
  141. {
  142. new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
  143. ConfigurationParameters.numericTrue,
  144. (s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
  145. (s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); },
  146. (s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ),
  147. new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
  148. ConfigurationParameters.numericFalse,
  149. (s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
  150. (s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); },
  151. (s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ),
  152. new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
  153. ConfigurationParameters.numericTrue,
  154. (s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); },
  155. (s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); },
  156. (s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ),
  157. new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
  158. 8f,
  159. (s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); },
  160. (s) => { return MeshLOD; },
  161. (s,p,l,v) => { MeshLOD = v; } ),
  162. new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
  163. 16f,
  164. (s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
  165. (s) => { return MeshMegaPrimLOD; },
  166. (s,p,l,v) => { MeshMegaPrimLOD = v; } ),
  167. new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
  168. 10f,
  169. (s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
  170. (s) => { return MeshMegaPrimThreshold; },
  171. (s,p,l,v) => { MeshMegaPrimThreshold = v; } ),
  172. new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
  173. 32f,
  174. (s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); },
  175. (s) => { return SculptLOD; },
  176. (s,p,l,v) => { SculptLOD = v; } ),
  177. new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
  178. 10f,
  179. (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
  180. (s) => { return (float)s.m_maxSubSteps; },
  181. (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
  182. new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
  183. 1f / 60f,
  184. (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
  185. (s) => { return (float)s.m_fixedTimeStep; },
  186. (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
  187. new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
  188. 2048f,
  189. (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
  190. (s) => { return (float)s.m_maxCollisionsPerFrame; },
  191. (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
  192. new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
  193. 8000f,
  194. (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
  195. (s) => { return (float)s.m_maxUpdatesPerFrame; },
  196. (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
  197. new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
  198. 500f,
  199. (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
  200. (s) => { return (float)s.m_taintsToProcessPerStep; },
  201. (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
  202. new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)",
  203. 0.0001f,
  204. (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
  205. (s) => { return (float)MinimumObjectMass; },
  206. (s,p,l,v) => { MinimumObjectMass = v; } ),
  207. new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
  208. 10000.01f,
  209. (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
  210. (s) => { return (float)MaximumObjectMass; },
  211. (s,p,l,v) => { MaximumObjectMass = v; } ),
  212. new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
  213. 2200f,
  214. (s,cf,p,v) => { PID_D = cf.GetFloat(p, v); },
  215. (s) => { return (float)PID_D; },
  216. (s,p,l,v) => { PID_D = v; } ),
  217. new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
  218. 900f,
  219. (s,cf,p,v) => { PID_P = cf.GetFloat(p, v); },
  220. (s) => { return (float)PID_P; },
  221. (s,p,l,v) => { PID_P = v; } ),
  222. new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
  223. 0.2f,
  224. (s,cf,p,v) => { s.UnmanagedParams[0].defaultFriction = cf.GetFloat(p, v); },
  225. (s) => { return s.UnmanagedParams[0].defaultFriction; },
  226. (s,p,l,v) => { s.UnmanagedParams[0].defaultFriction = v; } ),
  227. new ParameterDefn("DefaultDensity", "Density for new objects" ,
  228. 10.000006836f, // Aluminum g/cm3
  229. (s,cf,p,v) => { s.UnmanagedParams[0].defaultDensity = cf.GetFloat(p, v); },
  230. (s) => { return s.UnmanagedParams[0].defaultDensity; },
  231. (s,p,l,v) => { s.UnmanagedParams[0].defaultDensity = v; } ),
  232. new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
  233. 0f,
  234. (s,cf,p,v) => { s.UnmanagedParams[0].defaultRestitution = cf.GetFloat(p, v); },
  235. (s) => { return s.UnmanagedParams[0].defaultRestitution; },
  236. (s,p,l,v) => { s.UnmanagedParams[0].defaultRestitution = v; } ),
  237. new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
  238. 0.04f,
  239. (s,cf,p,v) => { s.UnmanagedParams[0].collisionMargin = cf.GetFloat(p, v); },
  240. (s) => { return s.UnmanagedParams[0].collisionMargin; },
  241. (s,p,l,v) => { s.UnmanagedParams[0].collisionMargin = v; } ),
  242. new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
  243. -9.80665f,
  244. (s,cf,p,v) => { s.UnmanagedParams[0].gravity = cf.GetFloat(p, v); },
  245. (s) => { return s.UnmanagedParams[0].gravity; },
  246. (s,p,l,v) => { s.UpdateParameterObject((x)=>{s.UnmanagedParams[0].gravity=x;}, p, PhysParameterEntry.APPLY_TO_NONE, v); },
  247. (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ),
  248. new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
  249. 0f,
  250. (s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); },
  251. (s) => { return LinearDamping; },
  252. (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearDamping=x;}, p, l, v); },
  253. (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, AngularDamping); } ),
  254. new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
  255. 0f,
  256. (s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); },
  257. (s) => { return AngularDamping; },
  258. (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularDamping=x;}, p, l, v); },
  259. (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, LinearDamping, v); } ),
  260. new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
  261. 0.2f,
  262. (s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); },
  263. (s) => { return DeactivationTime; },
  264. (s,p,l,v) => { s.UpdateParameterObject((x)=>{DeactivationTime=x;}, p, l, v); },
  265. (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ),
  266. new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
  267. 0.8f,
  268. (s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); },
  269. (s) => { return LinearSleepingThreshold; },
  270. (s,p,l,v) => { s.UpdateParameterObject((x)=>{LinearSleepingThreshold=x;}, p, l, v); },
  271. (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
  272. new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
  273. 1.0f,
  274. (s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); },
  275. (s) => { return AngularSleepingThreshold; },
  276. (s,p,l,v) => { s.UpdateParameterObject((x)=>{AngularSleepingThreshold=x;}, p, l, v); },
  277. (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
  278. new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
  279. 0f, // set to zero to disable
  280. (s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); },
  281. (s) => { return CcdMotionThreshold; },
  282. (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdMotionThreshold=x;}, p, l, v); },
  283. (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ),
  284. new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
  285. 0f,
  286. (s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); },
  287. (s) => { return CcdSweptSphereRadius; },
  288. (s,p,l,v) => { s.UpdateParameterObject((x)=>{CcdSweptSphereRadius=x;}, p, l, v); },
  289. (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ),
  290. new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
  291. 0.1f,
  292. (s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); },
  293. (s) => { return ContactProcessingThreshold; },
  294. (s,p,l,v) => { s.UpdateParameterObject((x)=>{ContactProcessingThreshold=x;}, p, l, v); },
  295. (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ),
  296. new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
  297. (float)BSTerrainPhys.TerrainImplementation.Heightmap,
  298. (s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); },
  299. (s) => { return TerrainImplementation; },
  300. (s,p,l,v) => { TerrainImplementation = v; } ),
  301. new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
  302. 0.3f,
  303. (s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); },
  304. (s) => { return TerrainFriction; },
  305. (s,p,l,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
  306. new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
  307. 0.8f,
  308. (s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); },
  309. (s) => { return TerrainHitFraction; },
  310. (s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
  311. new ParameterDefn("TerrainRestitution", "Bouncyness" ,
  312. 0f,
  313. (s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); },
  314. (s) => { return TerrainRestitution; },
  315. (s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
  316. new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
  317. 0.04f,
  318. (s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); },
  319. (s) => { return TerrainCollisionMargin; },
  320. (s,p,l,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
  321. new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
  322. 0.2f,
  323. (s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); },
  324. (s) => { return AvatarFriction; },
  325. (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarFriction=x;}, p, l, v); } ),
  326. new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
  327. 10.0f,
  328. (s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); },
  329. (s) => { return AvatarStandingFriction; },
  330. (s,p,l,v) => { AvatarStandingFriction = v; } ),
  331. new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
  332. 3.5f,
  333. (s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
  334. (s) => { return AvatarDensity; },
  335. (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarDensity=x;}, p, l, v); } ),
  336. new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
  337. 0f,
  338. (s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); },
  339. (s) => { return AvatarRestitution; },
  340. (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarRestitution=x;}, p, l, v); } ),
  341. new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
  342. 0.6f,
  343. (s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); },
  344. (s) => { return AvatarCapsuleWidth; },
  345. (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleWidth=x;}, p, l, v); } ),
  346. new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
  347. 0.45f,
  348. (s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); },
  349. (s) => { return AvatarCapsuleDepth; },
  350. (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleDepth=x;}, p, l, v); } ),
  351. new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
  352. 1.5f,
  353. (s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); },
  354. (s) => { return AvatarCapsuleHeight; },
  355. (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarCapsuleHeight=x;}, p, l, v); } ),
  356. new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
  357. 0.1f,
  358. (s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); },
  359. (s) => { return AvatarContactProcessingThreshold; },
  360. (s,p,l,v) => { s.UpdateParameterObject((x)=>{AvatarContactProcessingThreshold=x;}, p, l, v); } ),
  361. new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
  362. 0.95f,
  363. (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
  364. (s) => { return VehicleAngularDamping; },
  365. (s,p,l,v) => { VehicleAngularDamping = v; } ),
  366. new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
  367. 0f,
  368. (s,cf,p,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
  369. (s) => { return s.UnmanagedParams[0].maxPersistantManifoldPoolSize; },
  370. (s,p,l,v) => { s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
  371. new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
  372. 0f,
  373. (s,cf,p,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
  374. (s) => { return s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize; },
  375. (s,p,l,v) => { s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
  376. new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
  377. ConfigurationParameters.numericFalse,
  378. (s,cf,p,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
  379. (s) => { return s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation; },
  380. (s,p,l,v) => { s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ),
  381. new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
  382. ConfigurationParameters.numericFalse,
  383. (s,cf,p,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
  384. (s) => { return s.UnmanagedParams[0].shouldForceUpdateAllAabbs; },
  385. (s,p,l,v) => { s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ),
  386. new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
  387. ConfigurationParameters.numericTrue,
  388. (s,cf,p,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
  389. (s) => { return s.UnmanagedParams[0].shouldRandomizeSolverOrder; },
  390. (s,p,l,v) => { s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ),
  391. new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
  392. ConfigurationParameters.numericTrue,
  393. (s,cf,p,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
  394. (s) => { return s.UnmanagedParams[0].shouldSplitSimulationIslands; },
  395. (s,p,l,v) => { s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ),
  396. new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
  397. ConfigurationParameters.numericFalse,
  398. (s,cf,p,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
  399. (s) => { return s.UnmanagedParams[0].shouldEnableFrictionCaching; },
  400. (s,p,l,v) => { s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ),
  401. new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
  402. 0f, // zero says use Bullet default
  403. (s,cf,p,v) => { s.UnmanagedParams[0].numberOfSolverIterations = cf.GetFloat(p, v); },
  404. (s) => { return s.UnmanagedParams[0].numberOfSolverIterations; },
  405. (s,p,l,v) => { s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
  406. new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
  407. (float)BSLinkset.LinksetImplementation.Compound,
  408. (s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); },
  409. (s) => { return LinksetImplementation; },
  410. (s,p,l,v) => { LinksetImplementation = v; } ),
  411. new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
  412. ConfigurationParameters.numericFalse,
  413. (s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
  414. (s) => { return LinkConstraintUseFrameOffset; },
  415. (s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ),
  416. new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
  417. ConfigurationParameters.numericTrue,
  418. (s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
  419. (s) => { return LinkConstraintEnableTransMotor; },
  420. (s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ),
  421. new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
  422. 5.0f,
  423. (s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
  424. (s) => { return LinkConstraintTransMotorMaxVel; },
  425. (s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ),
  426. new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
  427. 0.1f,
  428. (s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
  429. (s) => { return LinkConstraintTransMotorMaxForce; },
  430. (s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ),
  431. new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
  432. 0.1f,
  433. (s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); },
  434. (s) => { return LinkConstraintCFM; },
  435. (s,p,l,v) => { LinkConstraintCFM = v; } ),
  436. new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
  437. 0.1f,
  438. (s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); },
  439. (s) => { return LinkConstraintERP; },
  440. (s,p,l,v) => { LinkConstraintERP = v; } ),
  441. new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
  442. 40,
  443. (s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); },
  444. (s) => { return LinkConstraintSolverIterations; },
  445. (s,p,l,v) => { LinkConstraintSolverIterations = v; } ),
  446. new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)",
  447. 0f,
  448. (s,cf,p,v) => { s.UnmanagedParams[0].physicsLoggingFrames = cf.GetInt(p, (int)v); },
  449. (s) => { return (float)s.UnmanagedParams[0].physicsLoggingFrames; },
  450. (s,p,l,v) => { s.UnmanagedParams[0].physicsLoggingFrames = (int)v; } ),
  451. };
  452. // Convert a boolean to our numeric true and false values
  453. public static float NumericBool(bool b)
  454. {
  455. return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
  456. }
  457. // Convert numeric true and false values to a boolean
  458. public static bool BoolNumeric(float b)
  459. {
  460. return (b == ConfigurationParameters.numericTrue ? true : false);
  461. }
  462. // Search through the parameter definitions and return the matching
  463. // ParameterDefn structure.
  464. // Case does not matter as names are compared after converting to lower case.
  465. // Returns 'false' if the parameter is not found.
  466. internal static bool TryGetParameter(string paramName, out ParameterDefn defn)
  467. {
  468. bool ret = false;
  469. ParameterDefn foundDefn = new ParameterDefn();
  470. string pName = paramName.ToLower();
  471. foreach (ParameterDefn parm in ParameterDefinitions)
  472. {
  473. if (pName == parm.name.ToLower())
  474. {
  475. foundDefn = parm;
  476. ret = true;
  477. break;
  478. }
  479. }
  480. defn = foundDefn;
  481. return ret;
  482. }
  483. // Pass through the settable parameters and set the default values
  484. internal static void SetParameterDefaultValues(BSScene physicsScene)
  485. {
  486. foreach (ParameterDefn parm in ParameterDefinitions)
  487. {
  488. parm.setter(physicsScene, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
  489. }
  490. }
  491. // Get user set values out of the ini file.
  492. internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg)
  493. {
  494. foreach (ParameterDefn parm in ParameterDefinitions)
  495. {
  496. parm.userParam(physicsScene, cfg, parm.name, parm.defaultValue);
  497. }
  498. }
  499. internal static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
  500. // This creates an array in the correct format for returning the list of
  501. // parameters. This is used by the 'list' option of the 'physics' command.
  502. internal static void BuildParameterTable()
  503. {
  504. if (SettableParameters.Length < ParameterDefinitions.Length)
  505. {
  506. List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
  507. for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
  508. {
  509. ParameterDefn pd = ParameterDefinitions[ii];
  510. entries.Add(new PhysParameterEntry(pd.name, pd.desc));
  511. }
  512. // make the list in alphabetical order for estetic reasons
  513. entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
  514. {
  515. return ppe1.name.CompareTo(ppe2.name);
  516. });
  517. SettableParameters = entries.ToArray();
  518. }
  519. }
  520. }
  521. }