Physx/PhysxWorld.cs

1293 lines
53 KiB
C#
Raw Permalink Normal View History

2023-07-31 13:55:44 +08:00
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using MagicPhysX; // for enable Extension Methods.
using MagicPhysX.Toolkit;
using Physx;
using static System.Formats.Asn1.AsnWriter;
using static System.Runtime.InteropServices.JavaScript.JSType;
using static MagicPhysX.NativeMethods; // recommend to use C API.
using static PhysX.PhysxWorldRaycastResultCb_1;
//测试bug问题总结 使用注意点 C Api(踩坑血泪史)
/*
1 physx_create_foundation api api调用访问非法内存
2 api 访
3 PxGemometry PxBoxGeometry_new
4 PxShapeFlag.SimulationShape PxShapeFlag.TriggerShape true
true时 false( )
5 addforce actor已经加入scence了
6 onTriger回调方法时候shap PxShapeFlag.TriggerShape属性的时候是无法触发的
7 gemomry参数时候shap shap
8 shap添加进刚体release方法 physx内部内存管理机制 shap是引用计数的
relase方法
9 PxShapeFlag.SimulationShape filetershader filterback (filterback func ,)
10 raycast (使,)
*/
namespace PhysX
{
//先使用原来的命名方法 后续改为微软命名风格
public enum PhysxShapeType
{
PX_BOX = 1,
PX_SPHERE = 2,
PX_CAPSULE = 3
};
public enum PhysxObjectType
{
PX_INVALIDE,
PX_STATICOBJECT,
PX_AIRSHIP,
PX_SPELL,
PX_SPELLTARGETSTATOCOBJECT,
PX_MONSTERGROUP,
PX_TRIGGER,
PX_MONSTER
};
public enum PhysxCollisionTypes
{
PX_COL_NOTHING = 0, //<Collide with nothing
PX_COL_AIR_SHIP = 1 << 1, //<Collide with ships
PX_COL_STATIC_OBJ = 1 << 2, //<Collide with static_obj
PX_COL_SPELL_OBJ = 1 << 3, //<Collide with spell data
PX_COL_SPELL_TARGET_STATIC_OBJ = 1 << 4, // Collide with spell target obj
PX_COL_MONSTER_GROUP_OBJ = 1 << 5, // Collide with monster target obj
PX_COL_TRIGGER_OBJ = 1 << 6,
PX_COL_MONSTER = 1 << 7 // Collide with skill obj
};
public enum PhysxTestTypes
{
PX_CCD = 1 << 29, // CCD type
};
//碰撞结果 放在common中更合适
public unsafe struct PhysxCollisionHitResult
{
public PhysxCollisionHitResult()
{
hit_type = PhysxObjectType.PX_INVALIDE;
pos.x = 0.0f;
pos.y = 0.0f;
pos.z = 0.0f;
user_ptr = null;
shape_ptr = null;
actor_ptr = null;
}
public bool HasResult() { return hit_type != PhysxObjectType.PX_INVALIDE; }
public PhysxObjectType hit_type;
public PxVec3 pos;
public void* user_ptr;
public PxShape* shape_ptr;
public PxRigidActor* actor_ptr;
};
//struct ClassType
//等效于 Unsafe.AsRef<PxRigidStatic>(handler);故不实现
public unsafe static class PxConstValue
{
public const int MaskAirShipCollidesWith = (int)(PhysxCollisionTypes.PX_COL_STATIC_OBJ | PhysxCollisionTypes.PX_COL_SPELL_OBJ | PhysxCollisionTypes.PX_COL_TRIGGER_OBJ);
public const int MaskStaticCollidesWith = (int)(PhysxCollisionTypes.PX_COL_SPELL_OBJ | PhysxCollisionTypes.PX_COL_AIR_SHIP | PhysxCollisionTypes.PX_COL_MONSTER_GROUP_OBJ);
public const int MaskSpellCollidesWith = (int)(PhysxCollisionTypes.PX_COL_STATIC_OBJ | PhysxCollisionTypes.PX_COL_AIR_SHIP | PhysxCollisionTypes.PX_COL_SPELL_TARGET_STATIC_OBJ | PhysxCollisionTypes.PX_COL_MONSTER);
public const int MaskSpellTargetCollidesWith = (int)PhysxCollisionTypes.PX_COL_SPELL_OBJ;
public const int MaskAirShipNoColldierWith = (int)PhysxCollisionTypes.PX_COL_NOTHING;
public const int MaskMonsterGroupColldierWith = (int)PhysxCollisionTypes.PX_COL_STATIC_OBJ;
public const int MaskTriggerColldierWith = (int)(PhysxCollisionTypes.PX_COL_AIR_SHIP | PhysxCollisionTypes.PX_COL_MONSTER);
public const int MaskMonsterColldersWith = (int)(PhysxCollisionTypes.PX_COL_SPELL_OBJ | PhysxCollisionTypes.PX_COL_TRIGGER_OBJ);
public static PhysxObjectType PhysxGetUserType(PxRigidActor* actor)
{
if (actor->userData == null)
{
return PhysxObjectType.PX_STATICOBJECT;
}
else
{
//TODO 需要补充业务代码
//return actor0->getPhysxType();
}
return PhysxObjectType.PX_INVALIDE;
}
//public delegate* unmanaged[Cdecl]<UInt32, PxFilterData, UInt32, PxFilterData, PxPairFlags*, void*, UInt32, PxFilterFlags> tmp;
public static PxFilterFlags PhysxWorldFilterShader(
UInt32 attributes0,
PxFilterData filterData0,
UInt32 attributes1,
PxFilterData filterData1, PxPairFlags* pairFlags,
void* constantBlock, UInt32 constantBlockSize)
{
// let triggers through
if (phys_PxFilterObjectIsTrigger(attributes0) ||
phys_PxFilterObjectIsTrigger(attributes1))
{
*pairFlags = PxPairFlags.ContactDefault;
if (((filterData0.word0 & filterData1.word1) != 0) &&
((filterData1.word0 & filterData0.word1) != 0))
{
*pairFlags = PxPairFlags.SolveContact |
PxPairFlags.DetectDiscreteContact |
PxPairFlags.NotifyTouchFound |
PxPairFlags.NotifyTouchLost |
PxPairFlags.NotifyContactPoints;
}
return 0 | PxFilterFlags.Callback;
}
return PxFilterFlags.Callback;
}
}
//create_raycast_filter_callback_func
public unsafe struct MyOwnerFilterCallbackPhysx //: public physx::PxSimulationFilterCallback
{
public static PxFilterFlags pairFound(
UInt32 pairID, UInt32 attributes0,
PxFilterData filterData0, PxActor* a0,
PxShape* s0, UInt32 attributes1,
PxFilterData filterData1, PxActor* a1,
PxShape* s1, PxPairFlags* pairFlags)
{
*pairFlags = PxPairFlags.ContactDefault;
PxRigidActor* first = (PxRigidActor*)a0;
PxRigidActor* second = (PxRigidActor*)a1;
if (first == null || second == null)
{
PhysxObjectType type0 = PxConstValue.PhysxGetUserType(first);
PhysxObjectType type1 = PxConstValue.PhysxGetUserType(second);
if ((type0 == PhysxObjectType.PX_SPELL) && (type1 == PhysxObjectType.PX_AIRSHIP || type1 == PhysxObjectType.PX_MONSTER))
{
return PxFilterFlags.Kill;
}
}
return PxFilterFlags.Kill;
}
public static void pairLost(UInt32 pairID,
UInt32 attributes0,
PxFilterData filterData0,
UInt32 attributes1,
PxFilterData filterData1, bool objectRemoved)
{
}
public static bool statusChange(UInt32* pairID, PxPairFlags* pairFlags,
PxFilterFlags* filterFlags)
{
return false;
}
}
/////////////////////////////////////////////////////////////////////////
// PhysxWorldRaycastResultCb
/////////////////////////////////////////////////////////////////////////
public unsafe struct PhysxWorldRaycastResultCb_1
{
//userdata部分
public struct RaycastUserData
{
public PxVec3 m_rayFromWorld; // used to calculate hitPointWorld from hitFraction
public PxVec3 m_rayToWorld;
public PxVec3 m_hitNormalWorld;
public PxVec3 m_hitPointWorld;
public PxRigidActor* actor_;
}
public RaycastUserData userData;
public PhysxWorldRaycastResultCb_1(PxVec3* rayFromWorld, PxVec3* rayToWorld)
{
userData.m_rayFromWorld = *rayFromWorld;
userData.m_rayToWorld = *rayToWorld;
}
//uint flag
public delegate*<PxRigidActor*, PxFilterData*, PxShape*, uint, void*, PxQueryHitType> callback;
public static PxQueryHitType preFilter(PxRigidActor* actor, PxFilterData* filterData, PxShape* shape,
uint flags, void* userData)
{
////filterData need adjust
//子弹屏蔽
if ((RaycastUserData*)userData != null)
{
PxRigidActor* obj0 = actor;
//TODO 根据自己理解暂时修改 userData 为PhysxWorldRaycastResultCb 中的自定义数据
PxRigidActor* obj1 = ((RaycastUserData*)userData)->actor_;
if (obj0 != null && obj1 != null)
{
int type0 = (int)PxConstValue.PhysxGetUserType(obj0);
int type1 = (int)PxConstValue.PhysxGetUserType(obj1);
if ((type0 == (int)PhysxObjectType.PX_SPELL) && (type1 == (int)PhysxObjectType.PX_AIRSHIP))
{
//业务代码先屏蔽
}
else if ((type0 == (int)PhysxObjectType.PX_AIRSHIP) && (type1 == (int)PhysxObjectType.PX_SPELL))
{
//业务代码先屏蔽
}
else if ((type0 == (int)PhysxObjectType.PX_SPELLTARGETSTATOCOBJECT) && (type1 == (int)PhysxObjectType.PX_SPELL))
{
//业务代码先屏蔽
}
else if ((type1 == (int)PhysxObjectType.PX_SPELLTARGETSTATOCOBJECT) && (type0 == (int)PhysxObjectType.PX_SPELL))
{
//业务代码先屏蔽
}
}
}
return PxQueryHitType.Block;
}
}
//此接口废弃 此接口使用的继承方式 c#中无法使用c++风格的api 只能数据和方法分离 不就是传说中的Ecs么
//public static extern PxQueryFilterCallback* create_raycast_filter_callback_func
//public unsafe struct PhysxWorldRaycastResultCb /* :PxQueryFilterCallback */
//{
//};
//释放内存逻辑暂不实现 需要根据业务详细考虑
public unsafe struct WorldUserData : IDisposable
{
public WorldUserData()
{
px_scene_ = null;
stamp_ = 0;
_physxBase = new PhysxBase();
// trigger_mgr_ = null;
}
public void Dispose()
{
}
public string PVD_HOST = "127.0.0.1";
public float DEFAULT_DENSITY = 10.0f;
public PhysxBase _physxBase;
public UInt64 test_sync_time_;
public bool is_init_world_;
public PxScene* px_scene_;
public UInt64 stamp_;
public TriggerManager trigger_mgr_;
//是否是这样弄?
public PxTriggerPair pairs;
public UInt32 count = 128;
public int userid;
}
//public static extern PxFilterFlags PxSimulationFilterCallback_pairFound_mut
//先使用原来的风格 后续改为微软命名风格
//主要继承PxSimulationEventCallback 然后触发PxSimulationEventCallback中回调函数
public unsafe struct PhysxWorld : IDisposable // : public PhysxBase, public physx::PxSimulationEventCallback {
{
//继承而来
//PhysxBase _physxBase;
SimulationEventCallbackInfo* _event_call_back;
PxSimulationFilterCallback* filter_callback_;
WorldUserData _worldUserData;
//Interlocked.Add;
//原子操作
static UInt64 atomic_next_id_;
//UInt64 test_sync_time_;
public PhysxWorld() { }
//~PhysxWorld();
public void Dispose()
{
//destroy_simulation_event_callbacks(_event_call_back);
if (_worldUserData.px_scene_ != null)
{
//TODO 构造px_scene_ 使用的 scentdesc 是否需要释放?
_worldUserData.px_scene_->ReleaseMut();
}
}
public void SetPvdHost(string host)
{
_worldUserData.PVD_HOST = host;
}
//长方体
public PxBoxGeometry* CreateBoxGeo(float lon, float wide, float height)
{
PxBoxGeometry temp = PxBoxGeometry_new(lon, wide, height);
return &temp;
}
//球体
public PxSphereGeometry* CreateSphereGeo(float radius)
{
PxSphereGeometry temp = PxSphereGeometry_new(radius);
return &temp;
}
//胶囊体
public PxCapsuleGeometry* CreateCapsuleGeo(float radius, float height, int capsuleAxis)
{
PxCapsuleGeometry temp = PxCapsuleGeometry_new(radius, height * 0.5f);
return &temp;
}
//创建几何体
public PxGeometry* CreateGeometry(int shape_type, PxVec3* min_position, PxVec3* max_position)
{
PxGeometry* geometry = null;
PxVec3 size;
size.x = (MathF.Abs(max_position->x - min_position->x));
size.y = (MathF.Abs(max_position->y - min_position->y));
size.z = (MathF.Abs(max_position->z - min_position->z));
switch (shape_type)
{
case (int)PhysxShapeType.PX_SPHERE:
{
float max_r = MathF.Max(size.x, size.y);
max_r = MathF.Max(max_r, size.z);
geometry = (PxGeometry*)CreateSphereGeo(max_r * 0.5f);
break;
}
case (int)PhysxShapeType.PX_BOX:
{
geometry = (PxGeometry*)CreateBoxGeo(size.x * 0.5f, size.y * 0.5f, size.z * 0.5f);
break;
}
case (int)PhysxShapeType.PX_CAPSULE:
{
float len = MathF.Max(size.x, size.y);
len = MathF.Max(len, size.z);
int direction = 0;
float radius = 0.0f;
float height = len;
if (len == size.x)
{
direction = 0;
radius = MathF.Max(size.y, size.z) * 0.5f;
}
else if (len == size.y)
{
direction = 1;
radius = MathF.Max(size.x, size.z) * 0.5f;
}
else if (len == size.z)
{
direction = 2;
radius = MathF.Max(size.x, size.y) * 0.5f;
}
if (MathF.Abs(radius) < 0.000001) return geometry;
if (MathF.Abs(height) < 0.000001) return geometry;
geometry = (PxGeometry*)CreateCapsuleGeo(radius, height - 2 * radius, direction);
break;
}
}
return geometry;
}
//创建一个形状
PxShape* CreateShap(PxGeometry* geometry, bool isExclusive = false,
PxShapeFlags shapeFlags = PxShapeFlags.Visualization |
PxShapeFlags.SceneQueryShape |
PxShapeFlags.SimulationShape)
{
return PxPhysics_createShape_mut(PhysxCommon.Instance.GetPhysics(),
geometry, PhysxCommon.Instance.GetDefaultMaterial(), isExclusive, shapeFlags);
}
/////////////////////////////////////////////////////////////////////////
// implement add Trigger shape
/////////////////////////////////////////////////////////////////////////
bool AddBoxTrigger(PxRigidDynamic* actor, float lon,
float wide, float height,
UInt32 effectType, UInt32 effectValue,
TriggerCallBack.TRIGGER_FUNC enter, TriggerCallBack.TRIGGER_FUNC leave)
{
PxBoxGeometry* box = CreateBoxGeo(lon, wide, height);
PxShape* shap = CreateShap((PxGeometry*)box, true); //! must be exclusive
if (shap == null)
{
return false;
}
return AddTriggerFromShape(actor, shap, effectType, effectValue, enter, leave);
}
bool AddSphereTrigger(PxRigidDynamic* actor, float radius,
UInt32 effectType, UInt64 effectValue,
TriggerCallBack.TRIGGER_FUNC enter, TriggerCallBack.TRIGGER_FUNC leave)
{
if (radius < 0.001f)
{
return false;
}
PxSphereGeometry* sphere = CreateSphereGeo(radius);
PxShape* shap = CreateShap((PxGeometry*)sphere, true);
if (shap == null)
{
return false;
}
return AddTriggerFromShape(actor, shap, effectType, effectValue, enter, leave);
}
bool AddSphereTrigger(void* userPointer, PxVec3 startPosition,
PxQuat startOrientation,
UInt32 filterGroup, UInt32 filterMask,
float radius, UInt32 effectType,
UInt64 effectValue, TriggerCallBack.TRIGGER_FUNC enter,
TriggerCallBack.TRIGGER_FUNC leave)
{
if (radius < 0.001f) return false;
PxSphereGeometry* sphere = CreateSphereGeo(radius);
PxShape* shap = CreateShap((PxGeometry*)sphere, true);
if (shap == null) return false;
PxFilterData filterData;
filterData.word0 = filterGroup; // word0 = own ID
filterData.word1 = filterMask; // word1 = ID mask to filter pairs that
// trigger a contact callback;
shap->SetSimulationFilterDataMut(&filterData);
shap->SetFlagMut(PxShapeFlag.SimulationShape, false);
shap->SetFlagMut(PxShapeFlag.TriggerShape, true);
PxTransform tf = new PxTransform();
tf.p = startPosition;
tf.q = startOrientation;
PxRigidDynamic* actor = shap != null ?
//PxCreateDynamic( physx_common::GetInst()->GetPhysics(), PxTransform(startPosition, startOrientation), *shap, 10.0f): null;
phys_PxCreateDynamic_1(PhysxCommon.Instance.GetPhysics(), &tf, shap, 10.0f) : null;
if (actor == null)
{
shap->ReleaseMut();
return false;
}
return true;
}
bool AddCapsuleTrigger(PxRigidDynamic* actor, float radius,
float height, UInt32 effectType,
UInt64 effectValue, TriggerCallBack.TRIGGER_FUNC enter,
TriggerCallBack.TRIGGER_FUNC leave)
{
PxCapsuleGeometry* capsule = CreateCapsuleGeo(radius, height, 0);
PxShape* shap = (PxShape*)CreateShap((PxGeometry*)capsule, true);
if (shap == null) return false;
return AddTriggerFromShape(actor, shap, effectType, effectValue, enter, leave);
}
bool AddTriggerFromShape(PxRigidDynamic* actor, PxShape* shape,
UInt32 effectType, UInt64 effectValue,
TriggerCallBack.TRIGGER_FUNC enter, TriggerCallBack.TRIGGER_FUNC leave)
{
if (shape == null) return false;
PxFilterData filterData;
filterData.word0 = (uint)PhysxCollisionTypes.PX_COL_TRIGGER_OBJ; // word0 = own ID
filterData.word1 = (uint)PxConstValue.MaskTriggerColldierWith; // word1 = ID mask to filter pairs that // trigger a contact callback;
shape->SetSimulationFilterDataMut(&filterData);
((PxRigidActor*)actor)->AttachShapeMut(shape);
shape->SetFlagMut(PxShapeFlag.SimulationShape, false);
shape->SetFlagMut(PxShapeFlag.TriggerShape, true);
//trigger_mgr_.Push(std::make_shared<TriggerCallBack>( shape, effectType, effectValue, std::forward<TRIGGER_FUNC>(enter), std::forward<TRIGGER_FUNC>(leave)));
//需要注意 TriggerCallBack * 的释放 智能指针
TriggerCallBack tmp = new TriggerCallBack(shape, effectType, effectValue, enter, leave);
_worldUserData.trigger_mgr_.Push(&tmp);
2023-07-31 14:10:52 +08:00
//这一步是减少引用次数 和用户数据无关 防止内存泄露
2023-07-31 13:55:44 +08:00
//shape->ReleaseMut();
return true;
}
void DeleteTriggerCallBack(PxRigidActor* actor)
{
if (actor != null)
{
_worldUserData.trigger_mgr_.OnReleaseActor(actor);
}
}
void ResetTrigger(PxRigidActor* actor)
{
if (actor != null)
{
_worldUserData.trigger_mgr_.ResetTriggersInActor(actor);
}
}
/////////////////////////////////////////////////////////////////////////
PxRigidActor* AddCollisionToDynamicsWord(
int mass, void* userPointer, int userIndex, int userIndex2,
int shape_type, PxVec3* min_position, PxVec3* max_position,
PxVec3 startPosition, PxQuat startOrientation,
PxVec3* hero_position = null)
{
2023-07-31 14:10:52 +08:00
//这一部是错误的 api 有bug 不可以返回指针类型 必须在当前栈对象创建PxGemometry
2023-07-31 13:55:44 +08:00
PxGeometry* geometry = CreateGeometry(shape_type, min_position, max_position);
if (geometry == null)
{
return null;
}
PxVec3 center;
center.x = ((max_position->x + min_position->x) * 0.5f);
center.y = ((max_position->y + min_position->y) * 0.5f);
center.z = ((max_position->z + min_position->z) * 0.5f);
float fmax = float.MaxValue;
if (mass <= 0)
{
startPosition = center;
}
//PxSceneWriteLock scopedLock(*px_scene_);
_worldUserData.px_scene_->LockWriteMut(null, 0);
PxRigidActor* rigActor = null;
if (userIndex == (int)PhysxObjectType.PX_STATICOBJECT)
{
//TODO
//需要确认 继承关系 才可以类型强转
var identity = PxTransform_new_2(PxIDENTITY.PxIdentity);
var pxTran = new PxTransform { p = startPosition, q = startOrientation };
rigActor = (PxRigidActor*)phys_PxCreateStatic(
PhysxCommon.Instance.GetPhysics(), &pxTran, geometry,
PhysxCommon.Instance.GetDefaultMaterial(), &identity);
}
else
{
var identity = PxTransform_new_2(PxIDENTITY.PxIdentity);
var pxTran = new PxTransform { p = startPosition, q = startOrientation };
rigActor = (PxRigidActor*)phys_PxCreateDynamic(
PhysxCommon.Instance.GetPhysics(), &pxTran, geometry,
PhysxCommon.Instance.GetDefaultMaterial(), 10.0f, &identity);
if (rigActor == null)
{
//TODO 销毁api
//delete geometry;
return null;
}
//rigActor->SetActorFlag(PxActorFlag.DisableGravity, true);
PxActor_setActorFlag_mut((PxActor*)rigActor, PxActorFlag.DisableGravity, true);
//rigActor setAngularDamping(0);
PxRigidBody_setAngularDamping_mut((PxRigidBody*)rigActor, 0);
PxRigidBody_setLinearDamping_mut((PxRigidBody*)rigActor, 0);
PxRigidBody_setLinearDamping_mut((PxRigidBody*)rigActor, 0);
PxVec3 tmp = new Vector3(0, 0, 0);
((PxRigidDynamic*)rigActor)->SetLinearVelocityMut(&tmp, false);
PxShape* treasureShape = null;
rigActor->GetShapes(&treasureShape, 1, 0);
treasureShape->SetContactOffsetMut(0.2f);
treasureShape->SetRestOffsetMut(0.01f);
if (shape_type == (int)PhysxShapeType.PX_CAPSULE)
{
//胶囊调整为沿z轴线缩放
//PxTransform relativePose( PxQuat(PxHalfPi, PxVec3(0, 1, 0)));
var quat = new PxQuat { w = PhysxCommon.PxHalfPi, x = 0, y = 1, z = 0 };
var relativePose = new PxTransform { p = startPosition, q = startOrientation };
treasureShape->SetLocalPoseMut(&relativePose);
}
}
if (rigActor == null)
{
//TODO
//delete geometry;
return null;
}
2023-07-31 14:10:52 +08:00
//可以简化逻辑 调用新的api 直接设置密度和质量
2023-07-31 13:55:44 +08:00
// add collision mask
if (mass > 0)
{
if (userIndex == (int)PhysxObjectType.PX_MONSTERGROUP)
{
SetupFiltering(rigActor, (int)PhysxCollisionTypes.PX_COL_MONSTER_GROUP_OBJ, PxConstValue.MaskMonsterGroupColldierWith);
}
else if (userIndex == (int)PhysxObjectType.PX_TRIGGER)
{
SetupFiltering(rigActor, (int)PhysxCollisionTypes.PX_COL_TRIGGER_OBJ, PxConstValue.MaskTriggerColldierWith);
}
else if (userIndex == (int)PhysxObjectType.PX_MONSTER)
{
SetupFiltering(rigActor, (int)PhysxCollisionTypes.PX_COL_MONSTER, PxConstValue.MaskMonsterColldersWith);
}
else
{
SetupFiltering(rigActor, (int)PhysxCollisionTypes.PX_COL_AIR_SHIP, PxConstValue.MaskAirShipCollidesWith);
}
}
else
SetupFiltering(rigActor, (int)PhysxCollisionTypes.PX_COL_STATIC_OBJ, PxConstValue.MaskStaticCollidesWith);
_worldUserData._physxBase.AddPhysicsActors(rigActor);
if (mass > 0)
{
if ((PxRigidDynamic*)rigActor != null)
{
((PxRigidBody*)rigActor)->SetMassMut(fmax);
((PxRigidBody*)rigActor)->SetRigidBodyFlagMut(PxRigidBodyFlag.EnableCcd, true);
}
}
else
{
// rigActor->is<physx::PxRigidDynamic*>()->setMass(mass);
}
//rigActor->userData = ClassType::CreateClassType(userPointer, (PhysxObjectType)userIndex);
_worldUserData.px_scene_->AddActorMut((PxActor*)rigActor, null);
_worldUserData.px_scene_->UnlockWriteMut();
return rigActor;
}
PxRigidActor* AddSpellCollison(
int mass, void* userPointer, int userIndex, int shape_type, int range,
PxVec3 startPosition, PxQuat startOrientation,
PxVec3* spell_position = null)
{
return default(PxRigidActor*);
}
PxRigidActor* AddFlyerCollison(
int mass, void* userPointer, int userIndex,
//Eternity::FlatBuffer::FlyerColliderData* collider_data,
void* collider_data, //用户数据
PxVec3 startPosition, PxQuat startOrientation)
{
//return default(PxRigidActor*);
return null;
}
public bool AddActorToDaynamicWorld(PxRigidActor* actor)
{
_worldUserData.px_scene_->AddActorMut((PxActor*)actor, null);
return true;
}
public void PickUpActor(PxRigidActor* actor)
{
_worldUserData.px_scene_->RemoveActorMut((PxActor*)actor, true);
}
int StepSimulation(/*KScene* secene,*/ UInt64 delta_time = 0)
{
//update 时间更新代码
UInt32 error = 0;
_worldUserData.px_scene_->SimulateMut(delta_time * 0.001f, null, null, 0, controlSimulation: true);
_worldUserData.px_scene_->FetchResultsMut(true, &error);
_worldUserData.trigger_mgr_.Update();
SyncUser();
return 1;
}
// world 类自身方法 start
public void OnInit()
{
if (filter_callback_ != null)
{
//delete filter_callback_;
//filter_callback_->dispose();
filter_callback_ = null;
}
MyOwnerFilterCallbackPhysx tmp = new MyOwnerFilterCallbackPhysx();
filter_callback_ = (PxSimulationFilterCallback*)&tmp;
_worldUserData.trigger_mgr_.Clear();
if (!PhysxCommon.Instance.InitPhyxsSDK())
{
//LogMgr::GetInstance()->Error(
// "[PhysxWorld]InitPhyxsSDK() cannot init physxSDK!!!!");
return;
}
_worldUserData = new WorldUserData();
CreatePxScene();
_worldUserData.is_init_world_ = true;
}
void CreatePxScene()
{
if (_worldUserData.px_scene_ != null)
{
_worldUserData.px_scene_->ReleaseMut();
_worldUserData.px_scene_ = null;
}
PxSceneDesc sceneDesc = PxSceneDesc_new(PxPhysics_getTolerancesScale(PhysxCommon.Instance.GetPhysics()));
sceneDesc.gravity = new Vector3(0.0f, 0.0f, 0.0f);
sceneDesc.cpuDispatcher = (PxCpuDispatcher*)PhysxCommon.Instance.GetCpuDispatcher();
delegate*<UInt32, PxFilterData, UInt32, PxFilterData, PxPairFlags*, void*, UInt32, PxFilterFlags> callback;
callback = &(PxConstValue.PhysxWorldFilterShader);
sceneDesc.filterShader = (void*)(delegate* unmanaged[Cdecl]<UInt32, PxFilterData, UInt32, PxFilterData, PxPairFlags*, void*, UInt32, PxFilterFlags>)callback;
//sceneDesc.simulationEventCallback = this;
delegate*<void*, PxContactPairHeader*, PxContactPair*, uint, void> tmpContact = &onContact;
_event_call_back->collision_callback = (delegate* unmanaged[Cdecl]<void*, PxContactPairHeader*, PxContactPair*, uint, void>)tmpContact;
2023-07-31 14:10:52 +08:00
//根据需要填写用户数据
_event_call_back->collision_user_data = null;
2023-07-31 13:55:44 +08:00
delegate*<void*, PxTriggerPair*, uint, void> tmpTrigger = &onTrigger;
_event_call_back->trigger_callback = (delegate* unmanaged[Cdecl]<void*, PxTriggerPair*, uint, void>)tmpTrigger;
2023-07-31 14:10:52 +08:00
_event_call_back->trigger_user_data = null;
2023-07-31 13:55:44 +08:00
//其余方法没有重载 不需要设置回调函数
sceneDesc.simulationEventCallback = create_simulation_event_callbacks(_event_call_back);
//TODO: 这个需要关注下
//sceneDesc.simulationEventCallback->OnContactMut();
//TODO count该如何传参数
fixed (PxTriggerPair* ptr = &_worldUserData.pairs)
{
sceneDesc.simulationEventCallback->OnTriggerMut(ptr, _worldUserData.count);
}
_worldUserData.px_scene_ = PxPhysics_createScene_mut(PhysxCommon.Instance.GetPhysics(), &sceneDesc);
if (_worldUserData.px_scene_ == null)
{
//LogMgr::GetInstance()->Error(
// "PhysxWorld::CreatePxScene() error:px_scene_ is null");
return;
}
}
void ChangePVDStatus(bool flag = false)
{
if (_worldUserData.px_scene_ == null) return;
PxPvdSceneClient* pvdClient = _worldUserData.px_scene_->GetScenePvdClientMut();
if (pvdClient != null)
{
pvdClient->SetScenePvdFlagMut(PxPvdSceneFlag.TransmitConstraints, flag);
pvdClient->SetScenePvdFlagMut(PxPvdSceneFlag.TransmitContacts, flag);
pvdClient->SetScenePvdFlagMut(PxPvdSceneFlag.TransmitScenequeries, flag);
}
}
PxScene* GetActiveScene() { return _worldUserData.px_scene_; }
bool IsInitWorld() { return _worldUserData.is_init_world_; }
void SyncUser()
{
UInt32 nbDynamics = _worldUserData.px_scene_->GetNbActors(PxActorTypeFlags.RigidDynamic);
if (nbDynamics < 1) { return; }
//std::vector<PxRigidActor*> actors(nbDynamics);
PxRigidActor*[] actors = new PxRigidActor*[nbDynamics];
fixed (PxRigidActor** actorPtr = actors)
{
_worldUserData.px_scene_->GetActors(PxActorTypeFlags.RigidDynamic, (PxActor**)actorPtr, nbDynamics, 0);
}
//PxSceneWriteLock scopedLock(*px_scene_);
//PxSceneWriteLock* sceneLock = PxSceneWriteLock_new_alloc(px_scene_, null, 0);
_worldUserData.px_scene_->LockWriteMut(null, 0);
for (UInt32 a = 0; a < nbDynamics; ++a)
{
//PxRigidActor* actor = actors[a]->is < PxRigidActor > ();
PxRigidActor* actor = actors[a];
if (actor == null)
{
continue;
}
// PxRigidDynamic* dynamic = static_cast<PxRigidDynamic*>(actor);
PxRigidDynamic* dynamic = (PxRigidDynamic*)(actor);
PxShape* shape;
actor->GetShapes(&shape, 1, 0);
PhysxObjectType type0 = PxConstValue.PhysxGetUserType(actor);
if (type0 == PhysxObjectType.PX_AIRSHIP ||
type0 == PhysxObjectType.PX_MONSTER ||
type0 == PhysxObjectType.PX_MONSTERGROUP ||
type0 == PhysxObjectType.PX_TRIGGER)
{
//业务代码
}
else if (type0 == PhysxObjectType.PX_SPELL)
{
//业务代码
}
}
_worldUserData.px_scene_->UnlockWriteMut();
//PxSceneWriteLock_delete(sceneLock);
}
void DeleteCollisionWorld()
{
if (!_worldUserData.is_init_world_ || _worldUserData.px_scene_ == null) return;
UInt32 error;
//px_scene_->simulate(STEP_SECOND);
//px_scene_->SimulateMut(10);
//px_scene_->fetchResults(true, &error);
//TODO 10 是为了语法不报错 需要填写实际业务代码实际STEP_SECOND
_worldUserData.px_scene_->SimulateMut(10, null, null, 0, controlSimulation: true);
_worldUserData.px_scene_->FetchResultsMut(true, &error);
//PxScene_fetchResults_mut(px_scene_, true, &error);
_worldUserData.trigger_mgr_.Clear();
foreach (PxRigidActor* it in _worldUserData._physxBase._physicsActors)
{
if ((it != null) && (it->userData != null))
{
//TODO
//释放用户数据
it->userData = null;
}
}
_worldUserData._physxBase.RemoveAllActor();
if (filter_callback_ != null)
{
//TODO:
//delete filter_callback_;
filter_callback_ = null;
}
//px_scene_->release();
_worldUserData.px_scene_->ReleaseMut();
_worldUserData.px_scene_ = null;
_worldUserData.is_init_world_ = false;
}
void RemoveAirShipOrSpell(PxRigidActor* obj)
{
if (obj != null)
{
DeleteTriggerCallBack(obj);
UInt32 error;
_worldUserData.px_scene_->SimulateMut(10, null, null, 0, controlSimulation: true);
_worldUserData.px_scene_->FetchResultsMut(true, &error);
//PxSceneWriteLock scopedLock(*px_scene_);
PxSceneWriteLock* sceneLock = PxSceneWriteLock_new_alloc(_worldUserData.px_scene_, null, 0);
if (obj->userData != null)
{
//delete obj->userData;
//TODO 释放用户数据
obj->userData = null;
}
_worldUserData._physxBase.RemoveActor(obj);
PxSceneWriteLock_delete(sceneLock);
}
}
void SetupFiltering(PxRigidActor* actor, UInt32 filterGroup,
UInt32 filterMask)
{
_worldUserData.px_scene_->LockWriteMut(null, 0);
PxFilterData filterData = default;
filterData.word0 = filterGroup; // word0 = own ID
filterData.word1 = filterMask; // word1 = ID mask to filter pairs that
filterData.word3 |= (1 << 29); // trigger a contact callback;
UInt32 numShapes = actor->GetNbShapes();
PxShape*[] shapes = new PxShape*[numShapes];
fixed (PxShape** p = shapes)
{
actor->GetShapes(p, numShapes, 0);
for (UInt32 i = 0; i < numShapes; i++)
{
PxShape* shape = shapes[i];
//shape->setSimulationFilterData(filterData);
shape->SetSimulationFilterDataMut(&filterData);
}
}
_worldUserData.px_scene_->UnlockWriteMut();
}
// world 类自身方法 end
bool RayTest(
PxRigidActor* actor, PxVec3 start_position,
PxVec3 normalizedDir, int mask, int group,
PhysxCollisionHitResult* hit_result,
float distance = float.MaxValue)
{
if (actor == null) return false;
PxRaycastHit* rayHit= stackalloc PxRaycastHit[1];
PxQueryFilterData filterData;
filterData.flags = (PxQueryFlags)mask;
PhysxWorldRaycastResultCb_1 CB = new PhysxWorldRaycastResultCb_1(&start_position, &normalizedDir);
CB.callback = &(PhysxWorldRaycastResultCb_1.preFilter);
PxQueryFilterCallback* fliterCallBack = create_raycast_filter_callback_func(
(delegate* unmanaged[Cdecl]<PxRigidActor*, PxFilterData*, PxShape*, uint, void*, PxQueryHitType>)(CB.callback), (void*)&CB.userData);
bool hasBlock = PxSceneQueryExt_raycastSingle(_worldUserData.px_scene_, &start_position, &normalizedDir, distance, PxHitFlags.Default,rayHit, &filterData, fliterCallBack, null);
PxQueryFilterCallback_delete(fliterCallBack);
if (hasBlock)
{
hit_result->hit_type = PxConstValue.PhysxGetUserType(rayHit->actor);
hit_result->pos = rayHit->position;
PxVec3 disPos = start_position.Multiply(&hit_result->pos);
float length = disPos.Magnitude();
//TODO:
//hit_result->user_ptr = rayHit.block.actor->userData;
hit_result->shape_ptr = rayHit->shape;
hit_result->actor_ptr = rayHit->actor;
return true;
}
return false;
}
bool SweepCheck(PxGeometry* geometry,
PxTransform* shapePose,
PxVec3* unitDir,
PhysxCollisionHitResult* hit_result)
{
if (_worldUserData.px_scene_ == null) return false;
//PxSweepBuffer sweepHit =default;
PxSweepHit sweepHit = default(PxSweepHit);
PxQueryFilterData filterData = default;
filterData.flags = PxQueryFlags.Static;
float distance = 0.1f;
bool hasHit = PxSceneQueryExt_sweepSingle(_worldUserData.px_scene_, geometry, shapePose, unitDir, distance, PxHitFlags.Default, &sweepHit, &filterData, null, null, 0.0f);
if (hasHit = true)
{
//hit_result->hit_type = PxConstValue.PhysxGetUserType(sweepHit.actor);
//// hit_result.pos = sweepHit.block.position;
//hit_result->user_ptr = sweepHit.actor->userData;
//hit_result->shape_ptr = sweepHit.shape;
//hit_result->actor_ptr = sweepHit.actor;
return true;
}
return false;
}
bool OverlapCheck(PxGeometry* geometry,
PxTransform* shapePose,
List<IntPtr> hero_list)
{
if (_worldUserData.px_scene_ == null) return false;
PxOverlapHit* hitBuffer = stackalloc PxOverlapHit[128];
PxQueryFilterData filterData;
filterData.flags = PxQueryFlags.Dynamic;
bool hasOverLap = PxSceneQueryExt_overlapAny(_worldUserData.px_scene_, geometry, shapePose, hitBuffer, null,null);
if (hasOverLap )
{
return true;
}
return false;
}
bool RayCastStatic(
PxVec3 start_pos, PxVec3 normalized_dir,
float distance = float.MaxValue)
{
//PxRaycastBuffer rayHits = default;
PxRaycastHit rayHit = default;
PxQueryFilterData filterData;
filterData.flags = PxQueryFlags.Static;
//注意normalized_dir 需要经过 标准向量化
bool hasblock = PxSceneQueryExt_raycastSingle(_worldUserData.px_scene_, &start_pos, &normalized_dir, distance, PxHitFlags.Default, &rayHit, &filterData, null, null);
if (hasblock == true)
{
return true;
}
return false;
}
void RayCastDynamic(PxVec3 start_pos, PxVec3 normalized_dir,
float distance, List<IntPtr>* hero_list)
{
PxRaycastHit* rayHit = stackalloc PxRaycastHit[128];
PxQueryFilterData filterData = default;
filterData.flags = PxQueryFlags.Dynamic;
//如果查询数据超过128 最多返回128 经测试不会崩溃
int buffSize = PxSceneQueryExt_raycastMultiple(_worldUserData.px_scene_ , & start_pos, &normalized_dir, distance, PxHitFlags.Default, rayHit, 128 , null, &filterData, null ,null);
for (int i = 0; i < buffSize; i++)
{
PxRigidActor* tmp = rayHit[i].actor;
PhysxObjectType type = PxConstValue.PhysxGetUserType(tmp);
if (type == PhysxObjectType.PX_AIRSHIP ||
type == PhysxObjectType.PX_MONSTER)
{
}
}
}
//工具方法 end
// 静态回调方法
public static void onTrigger(void* userData, PxTriggerPair* pairs, UInt32 count)
{
if (userData == null) { return; }
WorldUserData* _worldUserData = (WorldUserData*)userData;
for (UInt32 i = 0; i < count; i++)
{
PxTriggerPair* tp = &pairs[i];
// ignore pairs when shapes have been deleted
if ((tp->flags & (PxTriggerPairFlags.RemovedShapeTrigger |
PxTriggerPairFlags.RemovedShapeOther)) != 0)
{
continue;
}
if (tp->otherActor == null || tp->triggerActor == null)
{
continue;
}
//TriggerCallBackPtr cb_ptr = trigger_mgr_.FindTrigger(tp->triggerShape);
//记得释放指针 TriggerCallBackPtr是智能指针定义
TriggerCallBack* cb_ptr = _worldUserData->trigger_mgr_.FindTrigger(tp->triggerShape);
if (cb_ptr == null)
{
continue;
}
if ((tp->status & PxPairFlag.NotifyTouchFound) != 0)
{
cb_ptr->OnEnter((PxRigidActor*)tp->triggerActor, (PxRigidActor*)tp->otherActor, cb_ptr->effectType_);
}
else if ((tp->status & PxPairFlag.NotifyTouchLost) != 0)
{
cb_ptr->OnLeave((PxRigidActor*)tp->triggerActor, (PxRigidActor*)tp->otherActor, cb_ptr->effectType_);
}
}
}
public static void onContact(void* userData, PxContactPairHeader* pairHeader, PxContactPair* pairs, UInt32 nbPairs)
{
if (userData == null) { return; }
WorldUserData* _worldUserData = (WorldUserData*)userData;
//List<PxContactPairPoint> contactPoints;
IntPtr[] contactPoints = new IntPtr[128];
for (UInt32 i = 0; i < nbPairs; i++)
{
PxContactPair* cp = &pairs[i];
PhysxObjectType type0 = PxConstValue.PhysxGetUserType((PxRigidActor*)pairHeader->actors[0]);
PhysxObjectType type1 = PxConstValue.PhysxGetUserType((PxRigidActor*)pairHeader->actors[1]);
if (((int)cp->events & (int)(PxPairFlag.NotifyTouchFound |
PxPairFlag.NotifyTouchCcd)) != 0)
{
UInt32 contactCount = cp->contactCount;
if (contactCount < 1) continue;
Array.Resize<IntPtr>(ref contactPoints, (int)contactCount);
//structgen_pad0 函数地址
fixed (IntPtr* contactPointsPtr = contactPoints)
{
PxContactPairPoint* conPtr0 = (PxContactPairPoint*)contactPointsPtr->ToPointer();
cp->ExtractContacts(conPtr0, contactCount);
}
for (UInt32 j = 0; j < contactCount; j++)
{
if ((type0 == PhysxObjectType.PX_AIRSHIP &&
type1 == PhysxObjectType.PX_STATICOBJECT) ||
(type1 == PhysxObjectType.PX_AIRSHIP &&
type0 == PhysxObjectType.PX_STATICOBJECT))
{
PxRigidDynamic* dynamic = null;
//KHero* hero = null;
void* hero = null; // 用户数据
if (type0 == PhysxObjectType.PX_AIRSHIP)
{
//dynamic = Unsafe.AsRef<PxRigidDynamic>(ptr);
dynamic = (PxRigidDynamic*)(pairHeader->actors[0]);
}
else
{
//dynamic = Unsafe.AsRef<PxRigidDynamic>(ptr);
dynamic = (PxRigidDynamic*)(pairHeader->actors[0]);
}
if (dynamic != null)
{
//hero = static_cast<ClassType*>(dynamic->userData)->is < KHero *> ();
//if (!hero || hero->hit_wall_) continue;
//UInt64 now = KG_GetTickCount();
//TODO:需要根据实际业务完善
UInt64 now = 100;
if (now - _worldUserData->test_sync_time_ <= 1000) continue;
if (type1 != PhysxObjectType.PX_STATICOBJECT) continue;
//auto player = hero->GetOwnerPlayer();
//if (!player) continue;
//PxRigidStatic* static_actor = static_cast<PxRigidStatic*>(pairHeader.actors[1]);
PxRigidStatic* static_actor = (PxRigidStatic*)(pairHeader->actors[1]);
UInt32 num = ((PxRigidActor*)(static_actor))->GetNbShapes();
PxShape*[] shapes = new PxShape*[num];
fixed (PxShape** p = shapes)
{
UInt32 nbShapes = ((PxRigidActor*)(static_actor))->GetShapes(p, num, 0);
if (num != nbShapes) continue;
}
//将碰撞盒子发给客户端显示
//List<GeometryInfo> geometry_list;
for (UInt32 k = 0; k < num; k++)
{
//if (shapes[k]->GetGeometryType() != PxGeometryType.Box)
// continue;
//必须这么写 和system GetType重名了 总是会调用System GetType
var geoType = NativeMethodsGroupingExtensions.GetType(ref *shapes[k]->GetGeometry());
if (geoType != PxGeometryType.Box)
continue;
PxVec3 st_pos = ((PxRigidActor*)(static_actor))->GetGlobalPose().p;
PxQuat st_quat = ((PxRigidActor*)(static_actor))->GetGlobalPose().q;
//GeometryInfo info;
if (shapes[k]->GetGeometry() != null)
{
PxBoxGeometry* box_geometry = (PxBoxGeometry*)(shapes[k]->GetGeometry());
//业务代码
}
}
_worldUserData->test_sync_time_ = now;
}
continue;
}
else if ((type0 == PhysxObjectType.PX_AIRSHIP ||
type0 == PhysxObjectType.PX_MONSTER) &&
type1 == PhysxObjectType.PX_SPELL)
{
//业务代码
}
else if (type0 == PhysxObjectType.PX_SPELL &&
(type1 == PhysxObjectType.PX_AIRSHIP ||
type1 == PhysxObjectType.PX_MONSTER))
{
//业务代码
}
else if (type0 == PhysxObjectType.PX_SPELL &&
type1 == PhysxObjectType.PX_STATICOBJECT)
{
//业务代码
}
else if (type0 == PhysxObjectType.PX_STATICOBJECT &&
type1 == PhysxObjectType.PX_SPELL)
{
//业务代码
}
}
}
else if (((int)cp->events & (int)PxPairFlag.NotifyTouchLost) != 0)
{
if ((type0 == PhysxObjectType.PX_AIRSHIP &&
type1 == PhysxObjectType.PX_STATICOBJECT) ||
(type1 == PhysxObjectType.PX_AIRSHIP &&
type0 == PhysxObjectType.PX_STATICOBJECT))
{
PxRigidDynamic* dynamic = null;
//KHero* hero = null;
void* hero = null; //业务代码
if (type0 == PhysxObjectType.PX_AIRSHIP)
{
dynamic = (PxRigidDynamic*)(pairHeader->actors[0]);
}
else
{
dynamic = (PxRigidDynamic*)(pairHeader->actors[1]);
}
if (dynamic != null)
{
if (dynamic->userData != null)
{
// hero = static_cast<ClassType*>(dynamic->userData)->is < KHero *> ();
}
if (hero == null)
{
// hero->hit_wall_ = false;
}
}
}
}
}
}
public static void onConstraintBreak(void* userData, PxConstraintInfo* info, UInt32 flag) { }
public static void onWake(void* userData, PxActor** actors, UInt32 count) { }
public static void onSleep(void* userData, PxActor** actors, UInt32 count) { }
public static void onAdvance(void* userData, PxRigidBody** ppRigid, PxTransform* pTrans, UInt32 nb) { }
}
}