Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

BulletSim: Changes to terrain storage and management so mega-regions …

…work.

Moved all terrain code out of BSScene and into new BSTerrainManager.
Added logic to manage multiple terrains for mega-regions.
Added new functions to BulletSimAPI to match the library.
Moved all of the terrain creation and setup logic from C++ code to C# code.
    The unused code has not yet been removed from either place. Soon.
Moved checks for avatar above ground and in bounds into BSCharacter.
  • Loading branch information...
commit 7c140570db3b01eb83efc0d42a47715d3047e376 1 parent 7b6987c
@radams1 radams1 authored
View
37 OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -226,16 +226,37 @@ private bool PositionSanityCheck()
bool ret = false;
// If below the ground, move the avatar up
- float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
- if (_position.Z < terrainHeight)
+ float terrainHeight = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position);
+ if (Position.Z < terrainHeight)
{
- DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation);
- _position.Z = terrainHeight + 2.0f;
+ DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
+ Vector3 newPos = _position;
+ newPos.Z = terrainHeight + 2.0f;
+ _position = newPos;
ret = true;
}
// TODO: check for out of bounds
+ return ret;
+ }
+ // A version of the sanity check that also makes sure a new position value is
+ // pushed back to the physics engine. This routine would be used by anyone
+ // who is not already pushing the value.
+ private bool PositionSanityCheck2()
+ {
+ bool ret = false;
+ if (PositionSanityCheck())
+ {
+ // The new position value must be pushed into the physics engine but we can't
+ // just assign to "Position" because of potential call loops.
+ _scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
+ {
+ DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
+ BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
+ });
+ ret = true;
+ }
return ret;
}
@@ -500,9 +521,13 @@ public override void UpdateProperties(EntityProperties entprop)
// Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
// base.RequestPhysicsterseUpdate();
- DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
+ // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
+ PositionSanityCheck2();
+
+ float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // just for debug
+ DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
- entprop.Acceleration, entprop.RotationalVelocity);
+ entprop.Acceleration, entprop.RotationalVelocity, heightHere);
}
// Called by the scene when a collision with this object is reported
View
3  OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -48,11 +48,10 @@ public virtual void Dispose()
{
if (m_enabled)
{
- // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
+ m_enabled = false;
bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
m_constraint.Ptr = System.IntPtr.Zero;
- m_enabled = false;
}
}
View
9 OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -465,6 +465,7 @@ internal void ProcessTypeChange(Vehicle pType, float stepSize)
}
}//end SetDefaultsForType
+ // One step of the vehicle properties for the next 'pTimestep' seconds.
internal void Step(float pTimestep)
{
if (m_type == Vehicle.TYPE_NONE) return;
@@ -592,9 +593,9 @@ private void MoveLinear(float pTimestep)
}
// If below the terrain, move us above the ground a little.
- if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos))
+ if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos))
{
- pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2;
+ pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2;
m_prim.Position = pos;
VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
}
@@ -609,7 +610,7 @@ private void MoveLinear(float pTimestep)
}
if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
{
- m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
+ m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
}
if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
{
@@ -673,7 +674,7 @@ private void MoveLinear(float pTimestep)
{
grav.Z = (float)(grav.Z * 1.125);
}
- float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
+ float terraintemp = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
float postemp = (pos.Z - terraintemp);
if (postemp > 2.5f)
{
View
118 OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -1,58 +1,60 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyrightD
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using OMV = OpenMetaverse;
-using OpenSim.Framework;
-using OpenSim.Region.Physics.Manager;
-
-namespace OpenSim.Region.Physics.BulletSPlugin
-{
-// Class to wrap all objects.
-// The rest of BulletSim doesn't need to keep checking for avatars or prims
-// unless the difference is significant.
-public abstract class BSPhysObject : PhysicsActor
-{
- public abstract BSLinkset Linkset { get; set; }
-
- public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type,
- OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
- public abstract void SendCollisions();
-
- // Return the object mass without calculating it or side effects
- public abstract float MassRaw { get; }
-
- public abstract BulletBody Body { get; set; }
- public abstract void ZeroMotion();
-
- public abstract void UpdateProperties(EntityProperties entprop);
-
- public abstract void Destroy();
-}
-}
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyrightD
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using OMV = OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Region.Physics.Manager;
+
+namespace OpenSim.Region.Physics.BulletSPlugin
+{
+// Class to wrap all objects.
+// The rest of BulletSim doesn't need to keep checking for avatars or prims
+// unless the difference is significant.
+public abstract class BSPhysObject : PhysicsActor
+{
+ public abstract BSLinkset Linkset { get; set; }
+
+ public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type,
+ OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
+ public abstract void SendCollisions();
+
+ // Return the object mass without calculating it or side effects
+ public abstract float MassRaw { get; }
+
+ public abstract BulletBody Body { get; set; }
+ public abstract void ZeroMotion();
+
+ public virtual void StepVehicle(float timeStep) { }
+
+ public abstract void UpdateProperties(EntityProperties entprop);
+
+ public abstract void Destroy();
+}
+}
View
2  OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -377,7 +377,7 @@ public override void VehicleFlags(int param, bool remove)
// Called each simulation step to advance vehicle characteristics.
// Called from Scene when doing simulation step so we're in taint processing time.
- public void StepVehicle(float timeStep)
+ public override void StepVehicle(float timeStep)
{
if (IsPhysical)
_vehicle.Step(timeStep);
View
245 OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,8 +39,6 @@
using OpenMetaverse;
// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
-// Debug linkset
-// Test with multiple regions in one simulator
// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
// Test sculpties
// Compute physics FPS reasonably
@@ -54,10 +52,8 @@
// Use collision masks for collision with terrain and phantom objects
// Check out llVolumeDetect. Must do something for that.
// Should prim.link() and prim.delink() membership checking happen at taint time?
-// changing the position and orientation of a linked prim must rebuild the constraint with the root.
// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
-// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
// Implement LockAngularMotion
// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
// Does NeedsMeshing() really need to exclude all the different shapes?
@@ -85,18 +81,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// moved to a better place.
private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
- private List<BSPrim> m_vehicles = new List<BSPrim>();
-
- private float[] m_heightMap;
- private float m_waterLevel;
- private uint m_worldID;
- public uint WorldID { get { return m_worldID; } }
+ // List of all the objects that have vehicle properties and should be called
+ // to update each physics step.
+ private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
// let my minuions use my logger
public ILog Logger { get { return m_log; } }
- private bool m_initialized = false;
-
+ // If non-zero, the number of simulation steps between calls to the physics
+ // engine to output detailed physics stats. Debug logging level must be on also.
private int m_detailedStatsStep = 0;
public IMesher mesher;
@@ -106,29 +99,31 @@ public class BSScene : PhysicsScene, IPhysicsParameters
public float MeshMegaPrimThreshold { get; private set; }
public float SculptLOD { get; private set; }
- private BulletSim m_worldSim;
- public BulletSim World
- {
- get { return m_worldSim; }
- }
- private BSConstraintCollection m_constraintCollection;
- public BSConstraintCollection Constraints
- {
- get { return m_constraintCollection; }
- }
+ public uint WorldID { get; private set; }
+ public BulletSim World { get; private set; }
+
+ // All the constraints that have been allocated in this instance.
+ public BSConstraintCollection Constraints { get; private set; }
+ // Simulation parameters
private int m_maxSubSteps;
private float m_fixedTimeStep;
private long m_simulationStep = 0;
public long SimulationStep { get { return m_simulationStep; } }
+ // The length of the last timestep we were asked to simulate.
+ // This is used by the vehicle code. Since the vehicle code is called
+ // once per simulation step, its constants need to be scaled by this.
public float LastSimulatedTimestep { get; private set; }
// A value of the time now so all the collision and update routines do not have to get their own
- // Set to 'now' just before all the prims and actors are called for collisions and updates
- private int m_simulationNowTime;
- public int SimulationNowTime { get { return m_simulationNowTime; } }
+ // Set to 'now' just before all the prims and actors are called for collisions and updates
+ public int SimulationNowTime { get; private set; }
+
+ // True if initialized and ready to do simulation steps
+ private bool m_initialized = false;
+ // Pinned memory used to pass step information between managed and unmanaged
private int m_maxCollisionsPerFrame;
private CollisionDesc[] m_collisionArray;
private GCHandle m_collisionArrayPinnedHandle;
@@ -145,6 +140,10 @@ public BSConstraintCollection Constraints
public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
public const uint GROUNDPLANE_ID = 1;
+ public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
+
+ private float m_waterLevel;
+ public BSTerrainManager TerrainManager { get; private set; }
public ConfigurationParameters Params
{
@@ -155,12 +154,12 @@ public Vector3 DefaultGravity
get { return new Vector3(0f, 0f, Params.gravity); }
}
- private float m_maximumObjectMass;
- public float MaximumObjectMass
- {
- get { return m_maximumObjectMass; }
- }
+ public float MaximumObjectMass { get; private set; }
+ // When functions in the unmanaged code must be called, it is only
+ // done at a known time just before the simulation step. The taint
+ // system saves all these function calls and executes them in
+ // order before the simulation.
public delegate void TaintCallback();
private struct TaintCallbackEntry
{
@@ -176,6 +175,7 @@ public TaintCallbackEntry(string i, TaintCallback c)
private Object _taintLock = new Object();
// A pointer to an instance if this structure is passed to the C++ code
+ // Used to pass basic configuration values to the unmanaged code.
ConfigurationParameters[] m_params;
GCHandle m_paramsHandle;
@@ -189,11 +189,11 @@ public TaintCallbackEntry(string i, TaintCallback c)
private bool m_physicsLoggingEnabled;
private string m_physicsLoggingDir;
private string m_physicsLoggingPrefix;
- private int m_physicsLoggingFileMinutes;
-
- private bool m_vehicleLoggingEnabled;
- public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
+ private int m_physicsLoggingFileMinutes;
+ // 'true' of the vehicle code is to log lots of details
+ public bool VehicleLoggingEnabled { get; private set; }
+ #region Construction and Initialization
public BSScene(string identifier)
{
m_initialized = false;
@@ -216,6 +216,9 @@ public override void Initialise(IMesher meshmerizer, IConfigSource config)
m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
+ mesher = meshmerizer;
+ _taintedObjects = new List<TaintCallbackEntry>();
+
// Enable very detailed logging.
// By creating an empty logger when not logging, the log message invocation code
// can be left in and every call doesn't have to check for null.
@@ -228,11 +231,6 @@ public override void Initialise(IMesher meshmerizer, IConfigSource config)
PhysicsLogging = new Logging.LogWriter();
}
- // Get the version of the DLL
- // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
- // BulletSimVersion = BulletSimAPI.GetVersion();
- // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
-
// If Debug logging level, enable logging from the unmanaged code
if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
{
@@ -245,22 +243,32 @@ public override void Initialise(IMesher meshmerizer, IConfigSource config)
BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
}
- _taintedObjects = new List<TaintCallbackEntry>();
-
- mesher = meshmerizer;
+ // Get the version of the DLL
+ // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
+ // BulletSimVersion = BulletSimAPI.GetVersion();
+ // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
- // The bounding box for the simulated world
+ // The bounding box for the simulated world. The origin is 0,0,0 unless we're
+ // a child in a mega-region.
+ // Turns out that Bullet really doesn't care about the extents of the simulated
+ // area. It tracks active objects no matter where they are.
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f);
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
- m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
+ WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
// Initialization to support the transition to a new API which puts most of the logic
// into the C# code so it is easier to modify and add to.
- m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID));
- m_constraintCollection = new BSConstraintCollection(World);
+ World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID));
+
+ Constraints = new BSConstraintCollection(World);
+
+ // Note: choose one of the two following lines
+ // BulletSimAPI.CreateInitialGroundPlaneAndTerrain(WorldID);
+ TerrainManager = new BSTerrainManager(this);
+ TerrainManager.CreateInitialGroundPlaneAndTerrain();
m_initialized = true;
}
@@ -288,7 +296,7 @@ private void GetInitialParameterValues(IConfigSource config)
m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
// Very detailed logging for vehicle debugging
- m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
+ VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
// Do any replacements in the parameters
m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
@@ -323,6 +331,38 @@ private void BulletLoggerPhysLog(string msg)
PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
}
+ public override void Dispose()
+ {
+ // m_log.DebugFormat("{0}: Dispose()", LogHeader);
+
+ // make sure no stepping happens while we're deleting stuff
+ m_initialized = false;
+
+ TerrainManager.ReleaseGroundPlaneAndTerrain();
+
+ foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
+ {
+ kvp.Value.Destroy();
+ }
+ PhysObjects.Clear();
+
+ // Now that the prims are all cleaned up, there should be no constraints left
+ if (Constraints != null)
+ {
+ Constraints.Dispose();
+ Constraints = null;
+ }
+
+ // Anything left in the unmanaged code should be cleaned out
+ BulletSimAPI.Shutdown(WorldID);
+
+ // Not logging any more
+ PhysicsLogging.Close();
+ }
+ #endregion // Construction and Initialization
+
+ #region Prim and Avatar addition and removal
+
public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
{
m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
@@ -413,6 +453,9 @@ public override void RemovePrim(PhysicsActor prim)
// information call is not needed.
public override void AddPhysicsActorTaint(PhysicsActor prim) { }
+ #endregion // Prim and Avatar addition and removal
+
+ #region Simulation
// Simulate one timestep
public override float Simulate(float timeStep)
{
@@ -428,7 +471,8 @@ public override float Simulate(float timeStep)
int simulateStartTime = Util.EnvironmentTickCount();
- // update the prim states while we know the physics engine is not busy
+ // update the prim states while we know the physics engine is not busy
+ int numTaints = _taintedObjects.Count;
ProcessTaints();
// Some of the prims operate with special vehicle properties
@@ -440,14 +484,17 @@ public override float Simulate(float timeStep)
int numSubSteps = 0;
try
{
- numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
+ numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
- DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
+ DetailLog("{0},Simulate,call, nTaints= {1}, substeps={2}, updates={3}, colliders={4}",
+ DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
}
catch (Exception e)
{
- m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e);
- // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
+ m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
+ LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
+ DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
+ DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
updatedEntityCount = 0;
collidersCount = 0;
}
@@ -456,7 +503,7 @@ public override float Simulate(float timeStep)
// Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
// Get a value for 'now' so all the collision and update routines don't have to get their own
- m_simulationNowTime = Util.EnvironmentTickCount();
+ SimulationNowTime = Util.EnvironmentTickCount();
// If there were collisions, process them by sending the event to the prim.
// Collisions must be processed before updates.
@@ -527,7 +574,7 @@ public override float Simulate(float timeStep)
// Something has collided
private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration)
{
- if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID)
+ if (localID <= TerrainManager.HighestTerrainID)
{
return; // don't send collisions to the terrain
}
@@ -539,7 +586,7 @@ private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoin
BSPhysObject collidee = null;
ActorTypes type = ActorTypes.Prim;
- if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID)
+ if (collidingWith <= TerrainManager.HighestTerrainID)
{
type = ActorTypes.Ground;
}
@@ -558,28 +605,14 @@ private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoin
return;
}
+ #endregion // Simulation
+
public override void GetResults() { }
- public override void SetTerrain(float[] heightMap) {
- m_heightMap = heightMap;
- this.TaintedObject("BSScene.SetTerrain", delegate()
- {
- BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
- });
- }
+ #region Terrain
- // Someday we will have complex terrain with caves and tunnels
- // For the moment, it's flat and convex
- public float GetTerrainHeightAtXYZ(Vector3 loc)
- {
- return GetTerrainHeightAtXY(loc.X, loc.Y);
- }
-
- public float GetTerrainHeightAtXY(float tX, float tY)
- {
- if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
- return 30;
- return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
+ public override void SetTerrain(float[] heightMap) {
+ TerrainManager.SetTerrain(heightMap);
}
public override void SetWaterLevel(float baseheight)
@@ -595,35 +628,29 @@ public float GetWaterLevel()
public override void DeleteTerrain()
{
// m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
+ }
+
+ // Although no one seems to check this, I do support combining.
+ public override bool SupportsCombining()
+ {
+ return TerrainManager.SupportsCombining();
}
-
- public override void Dispose()
- {
- // m_log.DebugFormat("{0}: Dispose()", LogHeader);
-
- // make sure no stepping happens while we're deleting stuff
- m_initialized = false;
-
- foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
- {
- kvp.Value.Destroy();
- }
- PhysObjects.Clear();
-
- // Now that the prims are all cleaned up, there should be no constraints left
- if (m_constraintCollection != null)
- {
- m_constraintCollection.Dispose();
- m_constraintCollection = null;
- }
-
- // Anything left in the unmanaged code should be cleaned out
- BulletSimAPI.Shutdown(WorldID);
-
- // Not logging any more
- PhysicsLogging.Close();
+ // This call says I am a child to region zero in a mega-region. 'pScene' is that
+ // of region zero, 'offset' is my offset from regions zero's origin, and
+ // 'extents' is the largest XY that is handled in my region.
+ public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
+ {
+ TerrainManager.Combine(pScene, offset, extents);
+ }
+
+ // Unhook all the combining that I know about.
+ public override void UnCombine(PhysicsScene pScene)
+ {
+ TerrainManager.UnCombine(pScene);
}
+ #endregion // Terrain
+
public override Dictionary<uint, float> GetTopColliders()
{
return new Dictionary<uint, float>();
@@ -833,14 +860,14 @@ public void RemoveVehiclePrim(BSPrim vehicle)
// no locking because only called when physics engine is not busy
private void ProcessVehicles(float timeStep)
{
- foreach (BSPrim prim in m_vehicles)
+ foreach (BSPhysObject pobj in m_vehicles)
{
- prim.StepVehicle(timeStep);
+ pobj.StepVehicle(timeStep);
}
}
#endregion Vehicles
- #region Parameters
+ #region INI and command line parameter processing
delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
delegate float ParamGet(BSScene scene);
@@ -943,9 +970,9 @@ public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, Param
(s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
10000.01f,
- (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
- (s) => { return (float)s.m_maximumObjectMass; },
- (s,p,l,v) => { s.m_maximumObjectMass = v; } ),
+ (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
+ (s) => { return (float)s.MaximumObjectMass; },
+ (s,p,l,v) => { s.MaximumObjectMass = v; } ),
new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
2200f,
@@ -1207,6 +1234,8 @@ private void SetParameterConfigurationValues(IConfig cfg)
private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
+ // This creates an array in the correct format for returning the list of
+ // parameters. This is used by the 'list' option of the 'physics' command.
private void BuildParameterTable()
{
if (SettableParameters.Length < ParameterDefinitions.Length)
@@ -1283,7 +1312,7 @@ protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string
TaintedObject("BSScene.UpdateParameterSet", delegate() {
foreach (uint lID in objectIDs)
{
- BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
+ BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval);
}
});
break;
@@ -1301,7 +1330,7 @@ protected void TaintedUpdateParameter(string parm, uint localID, float val)
string xparm = parm.ToLower();
float xval = val;
TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
- BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval);
+ BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval);
});
}
View
307 OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyrightD
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using OpenSim.Framework;
+using OpenSim.Region.Framework;
+using OpenSim.Region.CoreModules;
+using OpenSim.Region.Physics.Manager;
+
+using Nini.Config;
+using log4net;
+
+using OpenMetaverse;
+
+namespace OpenSim.Region.Physics.BulletSPlugin
+{
+public class BSTerrainManager
+{
+ static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
+
+ BSScene m_physicsScene;
+
+ private BulletBody m_groundPlane;
+
+ // If doing mega-regions, if we're region zero we will be managing multiple
+ // region terrains since region zero does the physics for the whole mega-region.
+ private Dictionary<Vector2, BulletBody> m_terrains;
+ private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps;
+
+ // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
+ // This is incremented before assigning to new region so it is the last ID allocated.
+ private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1;
+ public uint HighestTerrainID { get {return m_terrainCount; } }
+
+ // If doing mega-regions, this holds our offset from region zero of
+ // the mega-regions. "parentScene" points to the PhysicsScene of region zero.
+ private Vector3 m_worldOffset = Vector3.Zero;
+ public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
+ private PhysicsScene m_parentScene = null;
+
+ public BSTerrainManager(BSScene physicsScene)
+ {
+ m_physicsScene = physicsScene;
+ m_terrains = new Dictionary<Vector2,BulletBody>();
+ m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>();
+ }
+
+ // Create the initial instance of terrain and the underlying ground plane.
+ // The objects are allocated in the unmanaged space and the pointers are tracked
+ // by the managed code.
+ // The terrains and the groundPlane are not added to the list of PhysObjects.
+ // This is called from the initialization routine so we presume it is
+ // safe to call Bullet in real time. We hope no one is moving around prim yet.
+ public void CreateInitialGroundPlaneAndTerrain()
+ {
+ // The ground plane is here to catch things that are trying to drop to negative infinity
+ m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
+ BulletSimAPI.CreateGroundPlaneBody2(BSScene.GROUNDPLANE_ID, 1f, 0.4f));
+ BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
+
+ Vector3 minTerrainCoords = new Vector3(0f, 0f, 24f);
+ Vector3 maxTerrainCoords = new Vector3(Constants.RegionSize, Constants.RegionSize, 25f);
+ int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
+ float[] initialMap = new float[totalHeights];
+ for (int ii = 0; ii < totalHeights; ii++)
+ {
+ initialMap[ii] = 25f;
+ }
+ CreateNewTerrainSegment(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords);
+ }
+
+ public void ReleaseGroundPlaneAndTerrain()
+ {
+ if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr))
+ {
+ BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
+ }
+ m_groundPlane.Ptr = IntPtr.Zero;
+
+ foreach (KeyValuePair<Vector2, BulletBody> kvp in m_terrains)
+ {
+ if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.Ptr))
+ {
+ BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.Ptr);
+ BulletSimAPI.ReleaseHeightmapInfo2(m_heightMaps[kvp.Key].Ptr);
+ }
+ }
+ m_terrains.Clear();
+ m_heightMaps.Clear();
+ }
+
+ // Create a new terrain description. This is used for mega-regions where
+ // the children of region zero give region zero all of the terrain
+ // segments since region zero does all the physics for the mega-region.
+ // Call at taint time!!
+ public void CreateNewTerrainSegment(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
+ {
+ // The Z coordinates are recalculated to be the min and max height of the terrain
+ // itself. The caller may have passed us the real region extent.
+ float minZ = float.MaxValue;
+ float maxZ = float.MinValue;
+ int hSize = heightMap.Length;
+ for (int ii = 0; ii < hSize; ii++)
+ {
+ minZ = heightMap[ii] < minZ ? heightMap[ii] : minZ;
+ maxZ = heightMap[ii] > maxZ ? heightMap[ii] : maxZ;
+ }
+ minCoords.Z = minZ;
+ maxCoords.Z = maxZ;
+ // If the terrain is flat, make a difference so we get a good bounding box
+ if (minZ == maxZ)
+ minZ -= 0.2f;
+ Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
+
+ // Create the heightmap data structure in the unmanaged space
+ BulletHeightMapInfo mapInfo = new BulletHeightMapInfo(
+ BulletSimAPI.CreateHeightmap2(minCoords, maxCoords, heightMap), heightMap);
+ mapInfo.terrainRegionBase = terrainRegionBase;
+ mapInfo.maxRegionExtent = maxCoords;
+ mapInfo.minZ = minZ;
+ mapInfo.maxZ = maxZ;
+ mapInfo.sizeX = maxCoords.X - minCoords.X;
+ mapInfo.sizeY = maxCoords.Y - minCoords.Y;
+
+ DetailLog("{0},BSScene.CreateNewTerrainSegment,call,minZ={1},maxZ={2},hMapPtr={3},minC={4},maxC={5}",
+ BSScene.DetailLogZero, minZ, maxZ, mapInfo.Ptr, minCoords, maxCoords);
+ // Create the terrain body from that heightmap
+ BulletBody terrainBody = new BulletBody(id, BulletSimAPI.CreateTerrainBody2(id, mapInfo.Ptr, 0.01f));
+
+ BulletSimAPI.SetFriction2(terrainBody.Ptr, m_physicsScene.Params.terrainFriction);
+ BulletSimAPI.SetHitFraction2(terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction);
+ BulletSimAPI.SetRestitution2(terrainBody.Ptr, m_physicsScene.Params.terrainRestitution);
+ BulletSimAPI.SetCollisionFlags2(terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
+ BulletSimAPI.Activate2(terrainBody.Ptr, true);
+
+ // Add the new terrain to the dynamics world
+ BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, terrainBody.Ptr);
+ BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, terrainBody.Ptr);
+
+
+ // Add the created terrain to the management set. If we are doing mega-regions,
+ // the terrains of our children will be added.
+ m_terrains.Add(terrainRegionBase, terrainBody);
+ m_heightMaps.Add(terrainRegionBase, mapInfo);
+ }
+
+ public void SetTerrain(float[] heightMap) {
+ if (m_worldOffset != Vector3.Zero && m_parentScene != null)
+ {
+ // If doing the mega-prim stuff and we are the child of the zero region,
+ // the terrain is really added to our parent
+ if (m_parentScene is BSScene)
+ {
+ ((BSScene)m_parentScene).TerrainManager.SetTerrain(heightMap, m_worldOffset);
+ }
+ }
+ else
+ {
+ // if not doing the mega-prim thing, just change the terrain
+ SetTerrain(heightMap, m_worldOffset);
+ }
+ }
+
+ private void SetTerrain(float[] heightMap, Vector3 tOffset)
+ {
+ float minZ = float.MaxValue;
+ float maxZ = float.MinValue;
+
+ // Copy heightMap local and compute some statistics.
+ // Not really sure if we need to do this deep copy but, given
+ // the magic that happens to make the closure for taint
+ // below, I don't want there to be any problem with sharing
+ // locations of there are multiple calls to this routine
+ // within one tick.
+ int heightMapSize = heightMap.Length;
+ float[] localHeightMap = new float[heightMapSize];
+ for (int ii = 0; ii < heightMapSize; ii++)
+ {
+ float height = heightMap[ii];
+ if (height < minZ) minZ = height;
+ if (height > maxZ) maxZ = height;
+ localHeightMap[ii] = height;
+ }
+
+ Vector2 terrainRegionBase = new Vector2(tOffset.X, tOffset.Y);
+ BulletHeightMapInfo mapInfo;
+ if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo))
+ {
+ // If this is terrain we know about, it's easy to update
+ mapInfo.heightMap = localHeightMap;
+ m_physicsScene.TaintedObject("BSScene.SetTerrain:UpdateExisting", delegate()
+ {
+ DetailLog("{0},SetTerrain:UpdateExisting,baseX={1},baseY={2},minZ={3},maxZ={4}",
+ BSScene.DetailLogZero, tOffset.X, tOffset.Y, minZ, maxZ);
+ BulletSimAPI.UpdateHeightMap2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.heightMap);
+ });
+ }
+ else
+ {
+ // Our mega-prim child is giving us a new terrain to add to the phys world
+ uint newTerrainID = ++m_terrainCount;
+
+ Vector3 minCoords = tOffset;
+ minCoords.Z = minZ;
+ Vector3 maxCoords = new Vector3(tOffset.X + Constants.RegionSize,
+ tOffset.Y + Constants.RegionSize,
+ maxZ);
+ m_physicsScene.TaintedObject("BSScene.SetTerrain:NewTerrain", delegate()
+ {
+ DetailLog("{0},SetTerrain:NewTerrain,baseX={1},baseY={2}", BSScene.DetailLogZero, tOffset.X, tOffset.Y);
+ CreateNewTerrainSegment(newTerrainID, heightMap, minCoords, maxCoords);
+ });
+ }
+ }
+
+ // Someday we will have complex terrain with caves and tunnels
+ // For the moment, it's flat and convex
+ public float GetTerrainHeightAtXYZ(Vector3 loc)
+ {
+ return GetTerrainHeightAtXY(loc.X, loc.Y);
+ }
+
+ // Given an X and Y, find the height of the terrain.
+ // Since we could be handling multiple terrains for a mega-region,
+ // the base of the region is calcuated assuming all regions are
+ // the same size and that is the default.
+ // Once the heightMapInfo is found, we have all the information to
+ // compute the offset into the array.
+ public float GetTerrainHeightAtXY(float tX, float tY)
+ {
+ float ret = 30f;
+
+ int offsetX = ((int)(tX / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
+ int offsetY = ((int)(tY / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
+ Vector2 terrainBaseXY = new Vector2(offsetX, offsetY);
+
+ BulletHeightMapInfo mapInfo;
+ if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo))
+ {
+ float regionX = tX - offsetX;
+ float regionY = tY - offsetY;
+ regionX = regionX > mapInfo.sizeX ? 0 : regionX;
+ regionY = regionY > mapInfo.sizeY ? 0 : regionY;
+ ret = mapInfo.heightMap[(int)(regionX * mapInfo.sizeX + regionY)];
+ }
+ else
+ {
+ m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: x={1}, y={2}",
+ LogHeader, tX, tY);
+ }
+ return ret;
+ }
+
+ // Although no one seems to check this, I do support combining.
+ public bool SupportsCombining()
+ {
+ return true;
+ }
+ // This call says I am a child to region zero in a mega-region. 'pScene' is that
+ // of region zero, 'offset' is my offset from regions zero's origin, and
+ // 'extents' is the largest XY that is handled in my region.
+ public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
+ {
+ m_worldOffset = offset;
+ WorldExtents = new Vector2(extents.X, extents.Y);
+ m_parentScene = pScene;
+ }
+
+ // Unhook all the combining that I know about.
+ public void UnCombine(PhysicsScene pScene)
+ {
+ // Just like ODE, for the moment a NOP
+ }
+
+
+ private void DetailLog(string msg, params Object[] args)
+ {
+ m_physicsScene.PhysicsLogging.Write(msg, args);
+ }
+}
+}
View
61 OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -33,6 +33,9 @@
namespace OpenSim.Region.Physics.BulletSPlugin {
// Classes to allow some type checking for the API
+// These hold pointers to allocated objects in the unmanaged space.
+
+// The physics engine controller class created at initialization
public struct BulletSim
{
public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; }
@@ -42,6 +45,7 @@ public struct BulletSim
public IntPtr Ptr;
}
+// An allocated Bullet btRigidBody
public struct BulletBody
{
public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
@@ -49,12 +53,35 @@ public struct BulletBody
public uint ID;
}
+// An allocated Bullet btConstraint
public struct BulletConstraint
{
public BulletConstraint(IntPtr xx) { Ptr = xx; }
public IntPtr Ptr;
}
+// An allocated HeightMapThing which hold various heightmap info
+// Made a class rather than a struct so there would be only one
+// instance of this and C# will pass around pointers rather
+// than making copies.
+public class BulletHeightMapInfo
+{
+ public BulletHeightMapInfo(IntPtr xx, float[] hm) {
+ Ptr = xx;
+ heightMap = hm;
+ terrainRegionBase = new Vector2(0f, 0f);
+ maxRegionExtent = new Vector3(100f, 100f, 25f);
+ minZ = maxZ = 0f;
+ sizeX = sizeY = 256f;
+ }
+ public IntPtr Ptr;
+ public float[] heightMap;
+ public Vector2 terrainRegionBase;
+ public Vector3 maxRegionExtent;
+ public float sizeX, sizeY;
+ public float minZ, maxZ;
+}
+
// ===============================================================================
[StructLayout(LayoutKind.Sequential)]
public struct ConvexHull
@@ -231,6 +258,9 @@ static class BulletSimAPI {
int maxUpdates, IntPtr updateArray);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
+
+[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -414,12 +444,23 @@ static class BulletSimAPI {
// =====================================================================================
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
-public static extern IntPtr CreateGroundPlaneBody2(uint id, Vector3 center, float collisionMargin);
+public static extern IntPtr CreateGroundPlaneBody2(uint id, float height, float collisionMargin);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateTerrainBody2(uint id,
- Vector3 minCoords, Vector3 maxCoords, float collisionMargin,
- [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
+ IntPtr heightMapInfo,
+ float collisionMargin);
+
+[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+public static extern IntPtr CreateHeightmap2(Vector3 minCoords, Vector3 maxCoords,
+ [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
+
+[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+public static extern bool ReleaseHeightmapInfo2(IntPtr heightMapInfo);
+
+[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+public static extern void UpdateHeightMap2(IntPtr world, IntPtr heightMapInfo,
+ [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
// =====================================================================================
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -473,11 +514,16 @@ static class BulletSimAPI {
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
+// =====================================================================================
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
-public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj);
+public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
-public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
+public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
+
+// =====================================================================================
+[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+public static extern void Activate2(IntPtr obj, bool forceActivation);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 GetPosition2(IntPtr obj);
@@ -522,6 +568,9 @@ static class BulletSimAPI {
public static extern bool SetFriction2(IntPtr obj, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
+public static extern bool SetHitFraction2(IntPtr obj, float val);
+
+[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetRestitution2(IntPtr obj, float val);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -564,7 +613,7 @@ static class BulletSimAPI {
public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
-public static extern bool DestroyObject2(IntPtr world, uint id);
+public static extern bool DestroyObject2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void DumpPhysicsStatistics2(IntPtr sim);
Please sign in to comment.
Something went wrong with that request. Please try again.