using bulletsharp physics engine project

andyhebear1

20-05-2013 02:19:20

where has project using bulletsharp physics engine ,andy body can help me? can give me url, i want use this physcis engine in my project

using System;
using System.Collections.Generic;
using System.Text;
using Mogre;
using BulletSharp;

public delegate void PhysicsWorldEvent(DiscreteDynamicsWorld world);
public delegate void PhysicsSimulateEvent(DiscreteDynamicsWorld world, float delateTime);

public class Bullet_PhysicsSystem : System.MarshalByRefObject, System.IDisposable {

#region event
/// <summary>
/// Is invoked right after the physics world is created.
/// </summary>
public event PhysicsWorldEvent PostCreateWorld;
/// <summary>
/// Is invoked right before the physics world is simulated.
/// </summary>
public event PhysicsSimulateEvent PreSimulate;
/// <summary>
/// Is invoked right after the physics world is simulated.
/// </summary>
public event PhysicsSimulateEvent PostSimulate;
/// <summary>
/// Is invoked just after PreSimulate but just before the physics world is simulated.
/// You should use this as a last "get everything ready" point before we simulate.
/// </summary>
public event PhysicsSimulateEvent FinaliseBeforeSimulation;

//public static event BulletSharp.ContactAdded ContactAdded;
#endregion

#region DebugDraw
/// <summary>
/// Should we draw debug lines or not?
/// </summary>
public bool UpdateDebugDraw = false;
//private bool _drawLines = false;
public bool SlowMo = false;
//DebugDrawModes _debugDrawMode;
public DebugDrawModes DebugDrawMode {
get { return this._debugDraw.DebugMode; }
set {
this._debugDraw.DebugMode = value;
}
}
public void SetDebugDrawVisible(bool visible) {
_debugDraw.SetVisible(visible);
}
void DoDebugDraw() {
if (UpdateDebugDraw) {
_debugDraw.BeginDraw();
_debugDraw.DrawWorld();
_debugDraw.EndDraw();
}
}
/// <summary>
/// 没加入到刚体管理器中的是绘制不了的
/// </summary>
/// <param name="pose"></param>
/// <param name="shape"></param>
/// <param name="color"></param>
public void DrawCollisionObject(Matrix4 pose, BulletSharp.CollisionShape shape,ColourValue color) {
if (UpdateDebugDraw) {
_debugDraw.BeginDraw();
_debugDraw.DrawShape(pose, shape, color);
_debugDraw.EndDraw();
}
}

#endregion

#region 属性
private BroadphaseInterface _broadphase;
//private SimpleBroadphase _broadphase;
//private DefaultCollisionConfiguration dcc;
private DefaultCollisionConfiguration _dcc;
private CollisionDispatcher _dispatcher;
//private Dispatcher dispatcher;
/// <summary>
/// 按次序约束驱动方案
/// </summary>
private SequentialImpulseConstraintSolver _solver;
//private ConstraintSolver solver;
private DiscreteDynamicsWorld _world;
private Mogre.SceneManager _sceneMgr;
private Bullet_DebugDrawer _debugDraw;
public string LevelName { get; private set; }
Bullet_FilterCallback _filterCallback;
Bullet_ContactResultCallback _contactCallback;
#endregion

public Bullet_PhysicsSystem(SceneManager sceneMgr) {
CreateWorld(Guid.NewGuid().ToString("N"));
//设置物理debug渲染
this._sceneMgr = sceneMgr;
this._debugDraw = new Bullet_DebugDrawer(sceneMgr, _world);
//this._world.DebugDrawer = this._debugDraw;
}

#region 创建与销毁
/// <summary>
/// Creates the world
/// </summary>
void CreateWorld(string levelName) {

DebugLog.Log("[PhysicsMain] Creating new world..." + levelName);
this.LevelName = levelName;
// have to make more of these every level because disposing the world apparently disposes of them too.
this._broadphase = new DbvtBroadphase();//new SimpleBroadphase(); //
//this._broadphase =new AxisSweep3_32Bit(new Vector3(-10000, -10000, -10000), new Vector3(10000, 10000, 10000), 1024);
//Vector3 worldMin = new Vector3(-10000, -10000, -10000);
//Vector3 worldMax = new Vector3(10000, 10000, 10000);
//this._broadphase = new AxisSweep3(worldMin, worldMax);
this._solver = new SequentialImpulseConstraintSolver();
this._dcc = new DefaultCollisionConfiguration();
this._dispatcher = new CollisionDispatcher(_dcc);
// set up this stuff... not quite sure what it's for, but you need it if you want the CCD to work for the karts
//this._dispatcher.RegisterCollisionCreateFunc(BroadphaseNativeType.ConvexHullShape, BroadphaseNativeType.ConvexHullShape,
// _dcc.GetCollisionAlgorithmCreateFunc(BroadphaseNativeType.TriangleMeshShape, BroadphaseNativeType.TriangleMeshShape));
//this._dispatcher.RegisterCollisionCreateFunc(BroadphaseNativeType.ConvexHullShape, BroadphaseNativeType.ConvexHullShape,
// _dcc.GetCollisionAlgorithmCreateFunc(BroadphaseNativeType.ConvexHullShape, BroadphaseNativeType.ConvexHullShape));

this._world = new DiscreteDynamicsWorld(_dispatcher, _broadphase, _solver, _dcc);
// and then turn on CCD
//this._world.DispatchInfo.UseContinuous = true;
this._world.Gravity = new Vector3(0f, -1f, 0f);
this._world.SolverInfo.SplitImpulse = 1;
//自定义碰撞过滤 下面3个方法不能初始化,应该是编译的原因
//this._filterCallback = new Bullet_FilterCallback();
//this._world.PairCache.SetOverlapFilterCallback(_filterCallback);
//this._dispatcher.NearCallback = MyNearCallback;
_contactCallback = new Bullet_ContactResultCallback(this);
//注册运算法则
GImpactCollisionAlgorithm.RegisterAlgorithm(this._dispatcher);

//
ManifoldPoint.ContactAdded += new ContactAddedEventHandler(ManifoldPoint_ContactAdded);
}

/// <summary>
/// 是否采用连续碰撞检测模式
/// </summary>
/// <param name="ccd"></param>
public void SetCCDCollisionMode(bool ccd) {
this._world.DispatchInfo.UseContinuous = ccd;//m_useContinuous
}
/// <summary>
/// 销毁
/// </summary>
private void Destroy() {
if (_world != null && !_world.IsDisposed) {
ManifoldPoint.ContactAdded -= new ContactAddedEventHandler(ManifoldPoint_ContactAdded);
Clear();
//
this._debugDraw.Dispose();
this._debugDraw = null;
this._sceneMgr = null;
//5
if (this._filterCallback != null) {
this._filterCallback.Dispose();
}
if (this._contactCallback != null) {
this._contactCallback.Dispose();
}
this._solver.Dispose();
this._dcc.Dispose();
this._dispatcher.Dispose();
this._world.Dispose();
this._broadphase.Dispose();
//5
this._filterCallback = null;
this._contactCallback = null;
this._broadphase = null;
this._solver = null;
this._dcc = null;
this._dispatcher = null;
this._world = null;
}
}

public void Clear() {
//remove/dispose constraints
int i;
for (i = _world.NumConstraints - 1; i >= 0; i--) {
TypedConstraint constraint = _world.GetConstraint(i);
_world.RemoveConstraint(constraint);
constraint.Dispose(); ;
}

//remove the rigidbodies from the dynamics world and delete them
for (i = _world.NumCollisionObjects - 1; i >= 0; i--) {
CollisionObject obj = _world.CollisionObjectArray[i];
RigidBody body = obj as RigidBody;
if (body != null && body.MotionState != null) {
body.MotionState.Dispose();
}
_world.RemoveCollisionObject(obj);
obj.Dispose();
}
// SGD :2013/6/13 10:55:29
// 说明:shape也要销毁
//delete collision shapes
foreach (CollisionShape shape in _collisionShapes) {
if (!shape.IsDisposed) {
shape.Dispose();
}
}
_collisionShapes.Clear();
// SGD :2013/6/14 14:26:57
// 说明:
foreach (CollisionObject cobj in _collisionObjs_NoInworld) {
if (!cobj.IsDisposed) {
cobj.Dispose();
}
}
_collisionObjs_NoInworld.Clear();
}
#endregion

#region 接触相关
void ManifoldPoint_ContactAdded(ManifoldPoint cp, CollisionObjectWrapper colObj0Wrap, int partId0, int index0, CollisionObjectWrapper colObj1Wrap, int partId1, int index1) {

//if ((colObj0Wrap.CollisionShape is GImpactMeshShape) && (colObj1Wrap.CollisionShape is GImpactMeshShape)) {
//Console.WriteLine("接触了[mesh]-mesh");
//}
float friction0 = colObj0Wrap.CollisionObject.Friction;
float friction1 = colObj1Wrap.CollisionObject.Friction;
float restitution0 = colObj0Wrap.CollisionObject.Restitution;
float restitution1 = colObj1Wrap.CollisionObject.Restitution;

if ((colObj0Wrap.CollisionObject.CollisionFlags & CollisionFlags.CustomMaterialCallback) == CollisionFlags.CustomMaterialCallback) {
friction0 = 1.0f;//partId0,index0
restitution0 = 0.0f;
}
if ((colObj1Wrap.CollisionObject.CollisionFlags & CollisionFlags.CustomMaterialCallback) == CollisionFlags.CustomMaterialCallback) {
if ((index1 & 1) == 1) {
friction1 = 1.0f;//partId1,index1
}
else {
friction1 = 0.0f;
}
restitution1 = 0.0f;
}

cp.CombinedFriction = calculateCombinedFriction(friction0, friction1);
cp.CombinedRestitution = calculateCombinedRestitution(restitution0, restitution1);

//this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction
//return true;
}
internal float calculateCombinedFriction(float friction0, float friction1) {
float friction = friction0 * friction1;

const float MAX_FRICTION = 10.0f;
if (friction < -MAX_FRICTION)
friction = -MAX_FRICTION;
if (friction > MAX_FRICTION)
friction = MAX_FRICTION;
return friction;

}
internal float calculateCombinedRestitution(float restitution0, float restitution1) {
return restitution0 * restitution1;
}
/// <summary>
/// 用细测阶段的NearCallBack 来过滤碰撞
/// </summary>
/// <param name="collisionPair"></param>
/// <param name="dispatcher"></param>
/// <param name="dispatchInfo"></param>
void MyNearCallback(BroadphasePair collisionPair, CollisionDispatcher dispatcher, DispatcherInfo dispatchInfo) {
// Do your collision logic here
// Only dispatch the Bullet collision information if you want the physics to continue
CollisionDispatcher.DefaultNearCallback(collisionPair, dispatcher, dispatchInfo);
}
#endregion

#region 管理器
AlignedCollisionShapeArray _collisionShapes = new AlignedCollisionShapeArray();
AlignedCollisionObjectArray _collisionObjs_NoInworld = new AlignedCollisionObjectArray();
/// <summary>
/// 碰撞shape在外面创建后需要加入到系统管理,防止内存溢出
/// </summary>
/// <param name="shape"></param>
public void AddCollisionShape(CollisionShape shape) {
_collisionShapes.Add(shape);
}
public void RemoveCollisonShape(CollisionShape shape) {
_collisionShapes.Remove(shape);
}
/// <summary>
/// 外面创建,但是不加入到物理系统中进行模拟的碰撞模块,方便统一释放
/// </summary>
/// <param name="cobj"></param>
public void AddCollisionObj_NoInWorld(CollisionObject cobj) {
_collisionObjs_NoInworld.Add(cobj);
}
public void RemoveCollisonObj_NoInWorld(CollisionObject cobj) {
_collisionObjs_NoInworld.Remove(cobj);
}
#endregion

#region 辅助静态方法
/// <summary>
/// Sets the orientation of this CollisionObject. This involves a bunch of matrix and quaternion stuff, so only use this if it's really necessary!
/// </summary>
/// <param name="newOrient"></param>
public static void SetOrientation(CollisionObject obj, Quaternion newOrient) {
Matrix4 mat = new Matrix4(newOrient);
// this avoids having to do GetTrans() and SetTrans(), which both do calculations that we don't want.
mat[0, 3] = obj.WorldTransform[0, 3];
mat[1, 3] = obj.WorldTransform[1, 3];
mat[2, 3] = obj.WorldTransform[2, 3];
mat[3, 3] = obj.WorldTransform[3, 3];
// update our body
obj.WorldTransform = mat;
}
public static void SetPosition(CollisionObject obj, Vector3 position) {
//Quaternion q = obj.WorldTransform.ExtractQuaternion();
// update our body
obj.WorldTransform.SetTrans(position);
}
public static void GetPoseMatrix4(Quaternion q, Vector3 position, out Matrix4 pose) {
pose = new Matrix4(q);
pose.SetTrans(position);
}
/// <summary>
///
/// </summary>
/// <param name="mesh">使用完外部自己销毁</param>
/// <returns></returns>
public static TriangleMesh Convert(OgreMeshData mesh) {

// get our two main objects
TriangleMesh BulletMesh = new TriangleMesh(true, false);

DebugLog.Log("[Loading] Converting " + mesh.meshName + " to a BulletSharp.TriangleMesh");

uint vertex_count = (uint)mesh.Vertices.Length; //default(uint);
Vector3[] vertices = mesh.Vertices; //default(Vector3[]);
uint index_count = (uint)mesh.Indices.Length; //default(uint);
uint[] indices = mesh.Indices; //default(uint[]);

//GetMeshInformation(mesh, ref vertex_count, ref vertices, ref index_count, ref indices, pos, orientation, scale);

BulletMesh.PreallocateIndexes((int)index_count);
BulletMesh.PreallocateVertices((int)vertex_count);
//BulletMesh.WeldingThreshold = 0.1f;

for (int a = 0; a < index_count; a += 3) {
BulletMesh.AddTriangle(vertices[indices[a]], vertices[indices[a + 1]], vertices[indices[a + 2]], true);
}

return BulletMesh;
}
/// <summary>
///
/// </summary>
/// <param name="mesh">使用完外部自己销毁</param>
/// <returns></returns>
public static ConvexHullShape ConvertToHull(OgreMeshData mesh) {

DebugLog.Log("[Loading] Converting " + mesh.meshName + " to a BulletSharp.ConvexHull");

uint vertex_count = (uint)mesh.Vertices.Length; //default(uint);
Vector3[] vertices = mesh.Vertices;//default(Vector3[]);
uint index_count = (uint)mesh.Indices.Length;//default(uint);
uint[] indices = mesh.Indices;//default(uint[]);

//GetMeshInformation(mesh, ref vertex_count, ref vertices, ref index_count, ref indices, pos, orientation, scale);

ConvexHullShape hull = new ConvexHullShape(mesh.Vertices);//vertices.Distinct().ToArray());

return hull;
}
#endregion

#region 更新
const int _maxSubsteps = 60; //45;
const float _fixedTimestep = 1f / 60f; //1f / 45f;
/// <summary>
/// Runs just before every frame. Simulates one frame of physics.
/// Physics simulation should be the only thing that's using FrameEnded!
/// </summary>
public void Update(float delateTime) {
if (_world.IsDisposed) return;
//delateTime = 0.02f;
// run the events that go just before we simulate
if (PreSimulate != null)
PreSimulate(_world, delateTime);
//
if (FinaliseBeforeSimulation != null)
FinaliseBeforeSimulation(_world, delateTime);
//
//clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation.
//_broadphase.OverlappingPairCache.CleanProxyFromPairs(staticBody.BroadphaseHandle, Dispatcher);

_world.StepSimulation(SlowMo ? delateTime / 10f : delateTime, _maxSubsteps, _fixedTimestep);

// run the events that go just after we simulate
if (PostSimulate != null)
PostSimulate(_world, delateTime);

this.DoDebugDraw();
}
#endregion

public bool ContactTest(CollisionObject obj1, CollisionObject obj2) {
bool hashit = false;
_contactCallback.ContactTestBegin();
_world.ContactPairTest(obj1, obj2, _contactCallback);//该方法不需要加入到world中
//
// _world.ContactTest(obj1, _contactCallback);//该方法需要加入到world中
if (_contactCallback.ContactCount > 0) {
hashit = true;
}
_contactCallback.ContactTestEnd();


return hashit;
}

/// <summary>
/// Create a static ground plane facing upwards.
/// 该方法已经执行world.addrigibody
/// </summary>
/// <param name="yposition">The Y position that the plane is located at.</param>
public RigidBody CreateGroundPlane(float yposition) {
// make an infinite plane so we don't fall forever. TODO: hook up an event so when we collide with this, we respawn back on the track
Matrix4 matrix = new Matrix4();
matrix.MakeTransform(new Vector3(0, yposition, 0), Vector3.UNIT_SCALE, new Quaternion(0, 0, 0, 1));

CollisionShape groundShape = new StaticPlaneShape(Vector3.NEGATIVE_UNIT_Y, 1);
RigidBodyConstructionInfo groundInfo = new RigidBodyConstructionInfo(0, new DefaultMotionState(matrix), groundShape, Vector3.ZERO);
RigidBody groundBody = new RigidBody(groundInfo);
//groundBody.UserObject = new CollisionObjectDataHolder(groundBody, PonykartCollisionGroups.Environment, "ground");
groundBody.CollisionFlags = groundBody.CollisionFlags | CollisionFlags.StaticObject | CollisionFlags.CustomMaterialCallback | CollisionFlags.DisableVisualizeObject;
//
groundInfo.Dispose();
this.AddCollisionShape(groundShape);
_world.AddRigidBody(groundBody);
//_world.AddRigidBody(groundBody, CollisionFilterGroups.StaticFilter, CollisionFilterGroups.DefaultFilter | CollisionFilterGroups.CharacterFilter);
return groundBody;
}
/// <summary>
/// 根据shape创建刚体 shape与RigidBody需要外面添加到管理器中
/// 该方法没有执行world.addrigibody
/// </summary>
/// <param name="mass"></param>
/// <param name="startTransform"></param>
/// <param name="shape"></param>
/// <returns></returns>
public RigidBody LocalCreateRigidBody(float mass, Matrix4 startTransform, CollisionShape shape) {
bool isDynamic = (mass != 0.0f);
Vector3 localInertia = Vector3.ZERO;
if (isDynamic) {
shape.CalculateLocalInertia(mass, out localInertia);
}
DefaultMotionState myMotionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, shape, localInertia);
RigidBody body = new RigidBody(rbInfo);
//运动临界值
body.ContactProcessingThreshold = 0.0f;
rbInfo.Dispose();
//_world.AddRigidBody(body);
return body;
}
public DiscreteDynamicsWorld World {
get { return _world; }
}
#if DEBUG
void test() {

}
#endif
#region IDisposable 成员
public bool IsDisposed { get { return disposedValue; } }
private bool disposedValue;
protected virtual void Dispose(bool disposing) {
if (!this.disposedValue) {
if (!disposing) {
Console.WriteLine("~Bullet_PhysicsSystem()");
}
// SGD :2013/6/13 9:41:09
// 说明:销毁物理
this.Destroy();
}
this.disposedValue = true;
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
~Bullet_PhysicsSystem() {
Dispose(false);
}
#endregion
}
// For more info:
// http://bulletphysics.org/mediawiki-1.5.8/index.php/MotionStates#Ogre3d
public class Bullet_MotionState : MotionState {
Entity entity;
SceneNode node;
public RigidBody Body { get; set; }

public Bullet_MotionState(Entity entity, SceneNode node, Matrix4 startTransform) {
this.entity = entity;
this.node = node;

node.Position = startTransform.GetTrans();
node.Orientation = startTransform.ExtractQuaternion();
}

public override Matrix4 WorldTransform {
get {
Matrix4 transform = new Matrix4(node.Orientation);
transform.SetTrans(node.Position);
return transform;
}
set {
node.Position = value.GetTrans();
node.Orientation = value.ExtractQuaternion();

if (Body.ActivationState == ActivationState.ActiveTag) {
entity.SetMaterialName("BoxMaterial/Active");
}
else {
entity.SetMaterialName("BoxMaterial/Passive");
}
}
}
}
/// <summary>
/// trigger
/// </summary>
internal class Bullet_ContactResultCallback : CollisionWorld.ContactResultCallback {

private Bullet_PhysicsSystem _Phyx;
private bool _OnTest = false;
public Bullet_ContactResultCallback(Bullet_PhysicsSystem world) {
this._Phyx = world;
}
public int ContactCount { get; private set; }
public List<Vector3> ContactPoints = new List<Vector3>();
public void ContactTestBegin() {
_OnTest = true;
ContactCount = 0;
ContactPoints.Clear();
}
public void ContactTestEnd() {
_OnTest = false;
}

public override float AddSingleResult(ManifoldPoint cp, CollisionObjectWrapper colObj0Wrap, int partId0, int index0, CollisionObjectWrapper colObj1Wrap, int partId1, int index1) {
if (_OnTest) {
Vector3 ptA = cp.PositionWorldOnA;
Vector3 ptB = cp.PositionWorldOnB;
//Vector3 min = new Vector3(-1, -1, -1);
//Vector3 max = new Vector3(1, 1, 1);
Vector3 center = (ptB + ptA) * 0.5f;
//world.DebugDrawer.DrawLine(ref ptA, ref ptB, System.Drawing.Color.Blue);
//Matrix t = Matrix.Translation(center);
//Matrix4 t = Matrix4.GetTrans(center);
//world.DebugDrawer.DrawBox(ref min, ref max, ref t, System.Drawing.Color.White);

ContactPoints.Add(center);
ContactCount++;
}
return 0f;
}
};
/// <summary>
/// custom collision filter用初测阶段的回调过滤器来过滤碰撞
/// 过滤碰撞的一个高效方法是注册一个初测阶段的回调过滤器。回调过滤器在碰撞管线的
///早期就被调用,同时预防碰撞对的产生。
/// </summary>
internal class Bullet_FilterCallback : OverlapFilterCallback {
Dictionary<int, KeyValuePair<int, int>> NoCollisionRigidBodys = new Dictionary<int, KeyValuePair<int, int>>();
/// <summary>
///
/// </summary>
/// <param name="proxy1_uid">proxy1_uid 不能超过16位</param>
/// <param name="proxy2_uid">proxy2_uid 不能超过16位</param>
public void RegistorNoCollisionRigidBodyPair(int proxy1_uid, int proxy2_uid) {
KeyValuePair<int, int> pair1 = new KeyValuePair<int, int>(proxy1_uid, proxy2_uid);
KeyValuePair<int, int> pair2 = new KeyValuePair<int, int>(proxy2_uid, proxy1_uid);
int key1 = (proxy1_uid << 16) + proxy2_uid;
int key2 = (proxy2_uid << 16) + proxy1_uid;
NoCollisionRigidBodys.Add(key1, pair1);
NoCollisionRigidBodys.Add(key2, pair2);
}

/// <summary>
///
/// </summary>
/// <param name="proxy1_uid">uid 不能超过16位</param>
/// <param name="proxy2_uid">uid 不能超过16位</param>
public void RemoveNoCollisionRigidBodyPair(int proxy1_uid, int proxy2_uid) {
int key1 = (proxy1_uid << 16) + proxy2_uid;
int key2 = (proxy2_uid << 16) + proxy1_uid;
if (NoCollisionRigidBodys.ContainsKey(key1)) {
NoCollisionRigidBodys.Remove(key1);
}
if (NoCollisionRigidBodys.ContainsKey(key2)) {
NoCollisionRigidBodys.Remove(key2);
}
}
public void ClearNoCollisionRigidBodyPairs() {
NoCollisionRigidBodys.Clear();
}
public override bool NeedBroadphaseCollision(BroadphaseProxy proxy0, BroadphaseProxy proxy1) {
if ((proxy0.CollisionFilterGroup & proxy1.CollisionFilterMask) == 0)
return false;
if ((proxy1.CollisionFilterGroup & proxy0.CollisionFilterMask) == 0)
return false;
int proxy1_uid = proxy0.Uid;
int proxy2_uid = proxy1.Uid;
int key1 = (proxy1_uid << 16) + proxy2_uid;
int key2 = (proxy2_uid << 16) + proxy1_uid;
KeyValuePair<int, int> pair;
bool nocollides = NoCollisionRigidBodys.TryGetValue(key1, out pair);
//add some additional logic here that modified 'collides'
if (nocollides) {
nocollides = (proxy2_uid == pair.Value);
}
return !nocollides;
}
};
//internal class Bullet_NearCollisionDispatcher : CollisionDispatcher {
//没必要实现 细测阶段的碰撞调度类,没提供该重写方法

//}