1293 lines
53 KiB
C#
1293 lines
53 KiB
C#
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);
|
||
|
||
//这一步是减少引用次数 和用户数据无关 防止内存泄露
|
||
//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)
|
||
{
|
||
|
||
//这一部是错误的 api 有bug 不可以返回指针类型 必须在当前栈对象创建PxGemometry !!
|
||
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;
|
||
}
|
||
|
||
|
||
//可以简化逻辑 调用新的api 直接设置密度和质量
|
||
// 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;
|
||
//根据需要填写用户数据
|
||
_event_call_back->collision_user_data = null;
|
||
|
||
delegate*<void*, PxTriggerPair*, uint, void> tmpTrigger = &onTrigger;
|
||
_event_call_back->trigger_callback = (delegate* unmanaged[Cdecl]<void*, PxTriggerPair*, uint, void>)tmpTrigger;
|
||
_event_call_back->trigger_user_data = null;
|
||
|
||
//其余方法没有重载 不需要设置回调函数
|
||
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) { }
|
||
|
||
}
|
||
}
|