| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- #include "PhysCharacter.h"
- #include "PhysicsScene.h"
- class UserControllerHitReport : public NxUserControllerHitReport
- {
- public:
- virtual NxControllerAction onShapeHit(const NxControllerShapeHit& hit)
- {
-
- //return NX_ACTION_NONE;
- if(hit.shape)
- {
- NxActor& actor = hit.shape->getActor();
- if(actor.isDynamic())
- {
- NxCollisionGroup group = hit.shape->getGroup();
- if(group == phys_ragdoll)
- {
- if(hit.dir.y < -0.8f)
- {
- NxVec3 vec = hit.dir*Clampf(hit.length, -0.01f, 0.01f);
- vec.x = 0.0f;
- vec.z = 0.0f;
- //actor.addForceAtLocalPos(vec, NxVec3(0,0,0), NX_IMPULSE);
- //actor.addForceAtLocalPos(vec, NxVec3(0,0,0), NX_FORCE);
- }
- }
- NxActor* ControllerActor = hit.controller->getActor();
- PhysCharacter* pChar = (PhysCharacter*)ControllerActor->userData;
- bool bKinematic = actor.readBodyFlag(NX_BF_KINEMATIC);
- if(group != phys_ragdoll && pChar->isApplyForce && !bKinematic)
- {
- NxVec3 vec = hit.dir* pChar->force;
- vec.y = 0.0f;
- NxActor& actor = hit.shape->getActor();
- actor.addForceAtLocalPos(vec, NxVec3(0,0,0), NX_FORCE );
- }
- }
- }
- return NX_ACTION_NONE;
- };
- virtual NxControllerAction onControllerHit(const NxControllersHit& hit)
- {
- // NxVec3 p = hit.controller->getPosition();
- // NxVec3 e = hit.other->getPosition();
- return NX_ACTION_NONE;
- };
- static UserControllerHitReport report;
- };
- UserControllerHitReport UserControllerHitReport::report;
- PhysCharacter::PhysCharacter(const char * filename, long fileline, float r, float h, IPhysicsScene * _scene) :
- IPhysCharacter(_scene)
- {
- SetFileLine(filename, fileline);
- controller = null;
- desc.radius = r;
- desc.height = 1.0f;
- //#ifndef _XBOX
- // //desc.stepOffset = 0.015f;
- // //desc.skinWidth = 0.01f;
- // desc.stepOffset = 0.1f;
- // desc.skinWidth = 0.05f;
- //#else
- desc.stepOffset = 0.23f;
- desc.skinWidth = 0.1f;
- //#endif
- desc.upDirection = NX_Y;
- static float slopeLimit = cosf(NxMath::degToRad(65.0f));
- desc.slopeLimit = slopeLimit;
- desc.userData = this;
- desc.position = NxExtendedVec3(0.0f, 0.0f, 0.0f);
- desc.callback = &UserControllerHitReport::report;
- isApplyForce = false;
- force = 0.0f;
- move_collisionflags = 0;
- SetHeight(h);
- Activate(true);
- sceneChangedIndex = 0xFFFFFFFF;
- }
- PhysCharacter::~PhysCharacter()
- {
- if(controller)
- {
- ((PhysicsScene *)scene)->CtrManager().releaseController(*controller);
- controller = null;
- }
- }
- //Установить радиус персонажу
- void PhysCharacter::SetRadius(float v)
- {
- desc.radius = v;
- if(controller)
- {
- controller->setRadius(v);
- }
- }
- //Получить радиус персонажа
- float PhysCharacter::GetRadius()
- {
- return desc.radius;
- }
- //Установить высоту персонажу
- void PhysCharacter::SetHeight(float v)
- {
- float r = GetRadius();
- v -= r*2.0f;
- if(v < 0.0001f) v = 0.0001f;
- desc.height = v;
- if(controller)
- {
- controller->setHeight(v);
- }
- }
- //Получить высоту персонажа
- float PhysCharacter::GetHeight()
- {
- return desc.height + desc.radius*2.0f;
- }
- //Установить позицию
- void PhysCharacter::SetPosition(const Vector & pos)
- {
- desc.position = Nxe(pos);
- desc.position.y += desc.skinWidth * 1.1f;
- if(controller)
- {
- controller->setPosition(desc.position);
- }
- }
- //Получить позицию
- Vector PhysCharacter::GetPosition()
- {
- if(controller)
- {
- desc.position = controller->getFilteredPosition();
- desc.position.y -= desc.skinWidth;
- }
- return Nxe(desc.position);
- }
- //Передвинуть персонажа
- dword PhysCharacter::Move(const Vector & move, dword collisionGroups)
- {
- if(!controller) return 0;
- NxU32 flags;
- NxVec3 m = Nx(move);
- if(fabs(m.y) < 1e-35f)
- {
- if(m.y <= 0.0f)
- {
- m.y = -1e-20f;
- }else{
- m.y = 1e-20f;
- }
- }
- dword newSceneChangedIndex = scene->GetSceneChangedIndex();
- if (newSceneChangedIndex != sceneChangedIndex)
- {
- sceneChangedIndex = newSceneChangedIndex;
- controller->reportSceneChanged();
- }
- controller->move(m, collisionGroups, 0.001f, flags, 1.0f);
- move_collisionflags = flags;
- /*IPhysicsScene::RaycastResult detail;
- IPhysBase* ragdoll = scene->Raycast(GetPosition(),GetPosition()+Vector(0,-desc.height-0.2f,0),phys_mask(phys_ragdoll),&detail);
- if (ragdoll)
- {
- Vector velocity = move;
- velocity *= 60.0f * 10.0f * 0.4f;
- velocity.y = 5.0f;
- //VANO изменил, тут баг, может быть IPhysMesh*, IPhysPlane* и так далее
- //((IPhysRagdoll*)ragdoll)->ApplyForce(velocity);
- if (ragdoll->UserNumber() == 666)
- {
- //((IPhysRagdoll*)ragdoll)->ApplyForce(velocity);
- }
- }*/
- return (dword)flags;
- }
- //Активировать/деактивировать персонажа
- void PhysCharacter::Activate(bool isActive)
- {
- if(isActive)
- {
- if (!controller)
- {
- controller = (NxCapsuleController *)((PhysicsScene *)scene)->CtrManager().createController(&((PhysicsScene *)scene)->Scene(), desc);
- NxActor * controllerActor = controller->getActor();
- // VANO:: TEMP CHANGE {
- if (controllerActor)
- {
- // VANO:: TEMP CHANGE }
- controllerActor->userData = this;
- controllerActor->setGroup((NxActorGroup)phys_player);
- NxU32 count = controllerActor->getNbShapes();
- NxShape * const * shapes = controllerActor->getShapes();
- for(NxU32 i = 0; i < count; i++)
- {
- shapes[i]->setGroup((NxCollisionGroup)phys_playerctrl);
- }
- //desc.position.y += desc.skinWidth;
- controller->setPosition(desc.position);
- // коллизим контроллеры строго по маске
- controller->setInteraction(NXIF_INTERACTION_USE_FILTER);
- // VANO:: TEMP CHANGE {
- }
- else
- {
- ((PhysicsScene *)scene)->CtrManager().releaseController(*controller);
- controller = null;
- }
- // VANO:: TEMP CHANGE }
- }
- }
- else
- {
- if(controller)
- {
- ((PhysicsScene *)scene)->CtrManager().releaseController(*controller);
- controller = null;
- }
- }
- }
- //Если не 0.0f, то на все объекты при столкновении будет приложена сила v
- void PhysCharacter::ApplyForceToObjects(float v)
- {
- force = v;
- isApplyForce = (fabs(force) > 1e-30f);
- }
- //Возвращает коллижн флаги с последнего выполненого Move
- dword PhysCharacter::GetMoveCollisionFlags()
- {
- return dword(move_collisionflags);
- }
|