550 likes | 721 Views
PhysX aut ó. Sz écsi László. Let öltés. di ák: bagira .iit.bme.hu /~szecsi/GraphGame / l12-car. ppt modell: bagira .iit.bme.hu /~szecsi/GraphGame / pickup.zip. Új class: PhysicsEntityWheel. class ShadedMesh; class RenderContext; class PhysicsEntityWheel { ShadedMesh* shadedMesh;
E N D
PhysX autó Szécsi László
Letöltés • diák: • bagira.iit.bme.hu/~szecsi/GraphGame • /l12-car.ppt • modell: • bagira.iit.bme.hu/~szecsi/GraphGame • /pickup.zip
Új class: PhysicsEntityWheel • class ShadedMesh; • class RenderContext; • class PhysicsEntityWheel{ • ShadedMesh* shadedMesh; • NxWheelShape* shape; • double rollAngle; • public: • PhysicsEntityWheel(ShadedMesh* shadedMesh); • void render(const RenderContext& context); • void animate(double dt); • void setShape(NxWheelShape* shape); • };
PhysicsEntityWheel.cpp • #include "ShadedMesh.h" • #include "RenderContext.h" • #include "Camera.h" • PhysicsEntityWheel:: • PhysicsEntityWheel( • ShadedMesh* shadedMesh){ • this->shadedMesh = shadedMesh; • rollAngle = 0.0; • }
PhysicsEntityWheel.cpp • void PhysicsEntityWheel::animate(double dt) • { • rollAngle += dt * shape->getAxleSpeed(); • } • void PhysicsEntityWheel::setShape( • NxWheelShape* shape) • { • this->shape = shape; • }
PhysicsEntityWheel.cpp • void PhysicsEntityWheel::render(const RenderContext& context){ • D3DXMATRIX modelMatrix, rollMatrix; • D3DXMatrixRotationX(&rollMatrix, rollAngle); • NxMat34 pose = shape->getGlobalPose(); • pose.getColumnMajor44((NxF32*)&modelMatrix); • D3DXMatrixMultiply(&modelMatrix, • &rollMatrix, &modelMatrix); • D3DXMATRIX modelMatrixInverse; • D3DXMatrixInverse(&modelMatrixInverse, NULL, &modelMatrix); • context.effect->SetMatrix("modelMatrix", &modelMatrix); • context.effect->SetMatrix("modelMatrixInverse", &modelMatrixInverse); • D3DXMATRIX modelViewProjMatrix = modelMatrix * context.camera->getViewMatrix() * • context.camera->getProjMatrix(); • context.effect->SetMatrix("modelViewProjMatrix", &modelViewProjMatrix); • D3DXMATRIX modelViewMatrix = modelMatrix * context.camera->getViewMatrix(); • context.effect->SetMatrix("modelViewMatrix", &modelViewMatrix); • shadedMesh->render(context); • }
PhysicsEntity osztályba • class PhysicsEntityWheel; • //… • std::vector<PhysicsEntityWheel*> wheels; • public: • void animate(double dt); • void addWheel( • PhysicsEntityWheel* wheel); • void finishWheels();
PhysicsEntity.cpp • #include "PhysicsEntityWheel.h"
PhysicsEntity.cpp • void PhysicsEntity::render(const RenderContext& context){ • // … • shadedMesh->render(context); • std::vector<PhysicsEntityWheel*>::iterator wii = wheels.begin(); • while(wii != wheels.end()) { • (*wii)->render(context); • wii++; • } • }
PhysicsEntity.cpp • void PhysicsEntity::addWheel( • PhysicsEntityWheel* wheel) • { • wheels.push_back(wheel); • }
PhysicsEntity.cpp • void PhysicsEntity::finishWheels() { • NxShape*const* nxShapes = nxActor->getShapes(); • unsigned int nNxShapes = nxActor->getNbShapes(); • std::vector<PhysicsEntityWheel*>::iterator wii = wheels.begin(); • unsigned int iNxShapes=0; • while(wii != wheels.end() && iNxShapes < nNxShapes) { • if(nxShapes[iNxShapes]->getType() == NX_SHAPE_WHEEL){ • (*wii)->setShape((NxWheelShape*)nxShapes[iNxShapes]); • wii++; • } • iNxShapes++; • } • }
PhysicsEntity.cpp • void PhysicsEntity::animate(double dt) • { • std::vector<PhysicsEntityWheel*>::iterator wii = wheels.begin(); • while(wii != wheels.end()) • { • (*wii)->animate(dt); • wii++; • } • }
EntityCore • void loadNxWheelShapes(XMLNode& physicsModelNode, PhysicsModel* physicsModel); • void loadPhysicsEntityWheels(XMLNode& physicsEntityNode, PhysicsEntity* physicsEntity);
EngineCore.cpp • #include "PhysicsEntityWheel.h"
EnginePhysics::loadPhysicsModels • loadNxSphereShapes(physicsModelNode, physicsModel); • loadNxWheelShapes(physicsModelNode, physicsModel); • physicsModelDirectory • [physicsModelName] = physicsModel;
EngineCore.cpp • void EngineCore::loadNxWheelShapes(XMLNode& physicsModelNode, PhysicsModel* physicsModel){ • int iShape = 0; • XMLNode shapeNode; • while( !(shapeNode = physicsModelNode.getChildNode(L"NxWheelShape", iShape)).isEmpty() ) { • NxWheelShapeDesc* nxWheelShapeDesc = new NxWheelShapeDesc(); • loadShapeDesc(shapeNode, nxWheelShapeDesc, D3DXVECTOR3(0, 0, 1)); • nxWheelShapeDesc->radius = shapeNode.readDouble(L"radius", 0.5); • nxWheelShapeDesc->suspensionTravel = shapeNode.readDouble(L"suspension", 0.2); • nxWheelShapeDesc->suspension.spring = shapeNode.readDouble(L"springRestitution",7000.0); • nxWheelShapeDesc->suspension.damper = shapeNode.readDouble(L"springDamping", 800); • nxWheelShapeDesc->suspension.targetValue = shapeNode.readDouble(L"springBias", 0.0); • nxWheelShapeDesc->inverseWheelMass = shapeNode.readDouble(L"inverseMass", 0.1); • const wchar_t* physicsMaterialName = shapeNode|L"material"; • PhysicsMaterialDirectory::iterator iPhysicsMaterial = • physicsMaterialDirectory.find(physicsMaterialName); • if(iPhysicsMaterial != physicsMaterialDirectory.end()) • nxWheelShapeDesc->materialIndex = iPhysicsMaterial->second->getMaterialIndex(); • physicsModel->addShape(nxWheelShapeDesc); • iShape++; • } • }
EnginePhysics::loadPhysicsEntities • PhysicsEntity* physicsEntity = new PhysicsEntity(iShadedMesh->second, iPhysicsModel->second, nxScene, position); • loadPhysicsEntityWheels( • physicsEntityNode, physicsEntity); • group->add(physicsEntity);
EngineCore.cpp • void EngineCore::loadPhysicsEntityWheels(XMLNode& physicsEntityNode, PhysicsEntity* physicsEntity){ • int iWheel = 0; • XMLNode wheelNode; • while( !(wheelNode = physicsEntityNode.getChildNode(L"Wheel", iWheel)).isEmpty() ) • { • const wchar_t* shadedMeshName = wheelNode|L"shadedMesh"; • ShadedMeshDirectory::iterator iShadedMesh = shadedMeshDirectory.find(shadedMeshName); • if(iShadedMesh != shadedMeshDirectory.end()) • { • PhysicsEntityWheel* wheel = new PhysicsEntityWheel(iShadedMesh->second); • physicsEntity->addWheel(wheel); • } • iWheel++; • } • physicsEntity->finishWheels(); • }
XML • <Mesh name="wheel" xFileName="media\\wheel.x" />
XML • <PhysicsModel name="pickup"> • <NxBoxShape position.y="9" dimension.x="16.5" dimension.y="3" dimension.z="6.7" /> • <NxBoxShape position.y="14" dimension.x="4" dimension.y="2" dimension.z="6.2" /> • <NxWheelShape material="wheel" position.x="-10" position.y="4" position.z="-7" axis.x="1" approximation="10" radius="4.0" width="2" suspension="0.2" springRestitution="7000" springDamping="800" springBias="0" • maxBrakeForce="1" frictionToFront="0.1" frictionToSide="0.99"/> • <NxWheelShape material="wheel" position.x="-10" position.y="4" position.z="7" axis.x="-1" approximation="10" radius="4.0" width="2" suspension="0.2" springRestitution="7000" springDamping="800" springBias="0" • maxBrakeForce="1" frictionToFront="0.1" frictionToSide="0.99"/> • <NxWheelShape material="wheel" position.x="12" position.y="4" position.z="-7" axis.x="1" approximation="10" radius="4.0" width="2" suspension="0.2" springRestitution="7000" springDamping="800" springBias="0" • maxBrakeForce="1" frictionToFront="0.1" frictionToSide="0.99"/> • <NxWheelShape material="wheel" position.x="12" position.y="4" position.z="7" axis.x="-1" approximation="10" radius="4.0" width="2" suspension="0.2" springRestitution="7000" springDamping="800" springBias="0" • maxBrakeForce="1" frictionToFront="0.1" frictionToSide="0.99"/> • </PhysicsModel>
XML • <PhysicsEntity name="pickup" shadedMesh="pickup" physicsModel="pickup" position.y="30" > • <Wheel shadedMesh="wheel" /> • <Wheel shadedMesh="wheel" /> • <Wheel shadedMesh="wheel" /> • <Wheel shadedMesh="wheel" /> • </PhysicsEntity> • <PhysicsEntity name="nmi" shadedMesh="pickup" physicsModel="pickup" position.x="6" position.y="50" position.z="6" > • <Wheel shadedMesh="wheel" /> • <Wheel shadedMesh="wheel" /> • <Wheel shadedMesh="wheel" /> • <Wheel shadedMesh="wheel" /> • </PhysicsEntity>
Kerék rugózása eredeti pozíció suspensionOffsetDirection along toContact across contactPoint
Kerék rugózása új pozíció suspensionOffsetDirection pullBack r across contactPoint
Kereket a rugózott pozícióba rajzolni • void PhysicsEntityWheel::render(const RenderContext& context){ • NxMat34 pose = shape->getGlobalPose(); • NxWheelContactData wcd;// hozzáérünk-e? • NxShape* contactShape = shape->getContact(wcd); • // merre mozoghat a kerék • NxVec3 suspensionOffsetDirection; • pose.M.getColumn(1, suspensionOffsetDirection); • suspensionOffsetDirection = • -suspensionOffsetDirection; • // folyt.
Elmozdítás az érintkezéshez • if (contactShape && wcd.contactForce > -1000){ • NxVec3 toContact = wcd.contactPoint - pose.t; • double alongLength = • suspensionOffsetDirection.dot(toContact); • NxVec3 across = toContact - alongLength * • suspensionOffsetDirection; • double r = shape->getRadius(); • double pullBack = sqrt(r*r - across.dot(across)); • pose.t += (alongLength - pullBack) * • suspensionOffsetDirection; • }else{ • pose.t += shape->getSuspensionTravel() * • suspensionOffsetDirection; • }
Felborulás ellen • tegyük lejjebb a súlypontot • nehéz fémlap alulra, többi doboz legyen könnyű • sűrűség betölése a shape-ekbe
void EngineCore::loadShapeDesc(XMLNode& shapeNode, NxShapeDesc* shapeDesc, D3DXVECTOR3 originalAxis) { • shapeDesc->localPose.t = shapeNode.readNxVec3(L"position"); • D3DXVECTOR3 axis = shapeNode.readVector(L"axis"); • if( D3DXVec3Length(&axis) < 0.001 ) • axis = originalAxis; • D3DXVECTOR3 turnAxis; • D3DXVec3Cross(&turnAxis, &axis, &originalAxis); • D3DXVec3Normalize(&axis, &axis); • D3DXMATRIX turnMatrix; • D3DXMatrixRotationAxis(&turnMatrix, &turnAxis, • acos(D3DXVec3Dot(&axis, &originalAxis))); • shapeDesc->localPose.M.setColumnMajorStride4((NxF32*)&turnMatrix); • shapeDesc->density = • shapeNode.readDouble(L"density"); • }
XML - finomhangolás • <PhysicsModel name="pickup"> • <NxBoxShape density="0.1" position.y="9" dimension.x="16.5" dimension.y="3" dimension.z="6.7" /> • <NxBoxShape density="0.1" position.y="14" dimension.x="4" dimension.y="2" dimension.z="6.2" /> • <NxBoxShape density="300" position.y="2.2" dimension.x="4" dimension.y="0.1" dimension.z="6" />
XML Folyt. • <NxWheelShape material="wheel" • position.x="-10" position.y="6" position.z="-7" axis.x="1" approximation="10" radius="4.0" width="2" suspension="2" springRestitution="7000" springDamping="800" springBias="0" maxBrakeForce="1" frictionToFront="0.1" frictionToSide="0.6"/> • <NxWheelShape material="wheel" position.x="-10" position.y="6" position.z="7" axis.x="-1" approximation="10" radius="4.0" width="2" suspension="2" springRestitution="7000" springDamping="800" springBias="0" • maxBrakeForce="1" frictionToFront="0.1" frictionToSide="0.6"/> • <NxWheelShape material="wheel" position.x="12" position.y="6" position.z="-7" axis.x="1" approximation="10" radius="4.0" width="2" suspension="2" springRestitution="7000" springDamping="800" springBias="0" • maxBrakeForce="1" frictionToFront="0.1" frictionToSide="0.6"/> • <NxWheelShape material="wheel" position.x="12" position.y="6" position.z="7" axis.x="-1" approximation="10" radius="4.0" width="2" suspension="2" springRestitution="7000" springDamping="800" springBias="0" • maxBrakeForce="1" frictionToFront="0.1" frictionToSide="0.6"/> • </PhysicsModel>
Csináljunk vezérlést • Wheel-be vezérlő-referencia • WheelController vezérlő • (RigidBodyControl mintájára)
PhysicsEntityWheel • friend class WheelController; • WheelController* controller; • double torque; • double steerAngle; • public: • void control(const ControlContext& context); • void setController(WheelController* controller);
PhysicsEntityWheel.cpp • PhysicsEntityWheel:: • PhysicsEntityWheel(ShadedMesh* shadedMesh){ • this->shadedMesh = shadedMesh; • rollAngle = 0.0; • torque = 0.0; • steerAngle = 0.0; • controller = NULL; • }
PhysicsEntityWheel.cpp • void PhysicsEntityWheel::animate( • double dt) • { • rollAngle += dt * • shape->getAxleSpeed(); • shape->setMotorTorque(torque); • shape->setSteerAngle(steerAngle); • }
PhysicsEntityWheel.cpp • #include "WheelController.h" • void PhysicsEntityWheel::control( • const ControlContext& context){ • torque = 0.0; • steerAngle = 0.0; • if(controller) • controller->apply(this, context); • } • void PhysicsEntityWheel::setController( • WheelController* controller){ • this->controller = controller; • }
új class: WheelController • class Motor; • class Steer; • class PhysicsEntityWheel; • class ControlContext; • class WheelController{ • std::vector<Motor*> motors; • std::vector<Steer*> steers; • public: • WheelController(void); • ~WheelController(void); • void addMotor(Motor* motor); • void addSteer(Steer* steer); • void apply(PhysicsEntityWheel* wheel, const ControlContext& context); • };
WheelController.cpp • #include "DXUT.h" • #include "WheelController.h" • #include "PhysicsEntityWheel.h" • #include "Motor.h" • #include "Steer.h" • #include "ControlStatus.h" • #include "ControlContext.h" • WheelController::WheelController( • void){}
WheelController.cpp • WheelController::~WheelController(void){ • std::vector<Motor*>::iterator i = motors.begin(); • while(i != motors.end()){ • delete *i; • i++; • } • std::vector<Steer*>::iterator si = steers.begin(); • while(si != steers.end()){ • delete *si; • si++; • } • }
WheelController.cpp • void WheelController::addMotor( • Motor* motor){ • motors.push_back(motor); • } • void WheelController::addSteer( • Steer* steer){ • steers.push_back(steer); • }
WheelController.cpp • void WheelController::apply( • PhysicsEntityWheel* wheel, const ControlContext& context){ • std::vector<Motor*>::iterator i = motors.begin(); • while(i != motors.end()){ • Motor* motor = *i; • if(context.controlStatus.keyPressed[motor->key]) • { • wheel->torque += motor->torque.x; • } • i++; • } • std::vector<Steer*>::iterator si = steers.begin(); • while(si != steers.end()){ • Steer* steer= *si; • if(context.controlStatus.keyPressed[steer->key]) • wheel->steerAngle = steer->turn.x; • si++; • } • }
Steer (motor már van) • class Steer{ • friend class WheelController; • unsigned int key; • D3DXVECTOR3 turn; • public: • Steer(unsigned int key, • const D3DXVECTOR3& turn); • };
Steer.cpp • #include "DXUT.h" • #include "Steer.h" • Steer::Steer(unsigned int key, const D3DXVECTOR3& turn) • { • this->key = key; • this->turn = turn; • }
a régi Motor jó, de: • class Motor • { • friend class MotorControl; • friend class WheelController;
EngineCore • WheelControllerDirectory wheelControllerDirectory; • void loadWheelControllers(XMLNode& xMainNode); • void loadWheelMotors(XMLNode& controllerNode, WheelController* controller); • void loadWheelSteers(XMLNode& controllerNode, WheelController* controller);
EngineCore.cpp • #include "WheelController.h" • #include "Steer.h"
EngineCore.cpp • void EngineCore::loadLevel(){ • loadWheelControllers(propsNode); • loadGroup(…
EngineCore::releaseManagedResources • { • WheelControllerDirectory::iterator i = • wheelControllerDirectory.begin(); • while(i != • wheelControllerDirectory.end()){ • delete i->second; • i++; • } • }
EngineCore.cpp • void EngineCore::loadWheelControllers(XMLNode& xMainNode){ • int iWheelController = 0; • XMLNode wheelControllerNode; • while( !(wheelControllerNode = xMainNode.getChildNode(L"WheelController", • iWheelController)).isEmpty() ){ • const wchar_t* name = wheelControllerNode|L"name"; • if(name){ • WheelController* wheelController = • new WheelController(); • wheelControllerDirectory[name] = wheelController; • loadWheelMotors(wheelControllerNode, wheelController); • loadWheelSteers(wheelControllerNode, wheelController); • } • iWheelController++; • } • }
EngineCore.cpp • void EngineCore::loadWheelMotors( • XMLNode& controllerNode, WheelController* controller){ • int iMotor = 0;XMLNode motorNode; • while( !(motorNode = controllerNode.getChildNode(L“Motor", • iMotor)).isEmpty() ){ • NxVec3 force = motorNode.readNxVec3(L"force"); • NxVec3 torque = motorNode.readNxVec3(L"torque"); • unsigned int keyCode = mtorNode.readLong(L"key"); • const wchar_t* codeTypeString = motorNode|L"codeType"; • if(codeTypeString • && wcscmp(codeTypeString, L"numpad") == 0) • keyCode += VK_NUMPAD0; • motorController->addMotor( • new Motor(keyCode, force, torque)); • iMotor++; • } • }
EngineCore.cpp • void EngineCore::loadWheelSteers( • XMLNode& controllerNode, WheelController* controller){ • int iSteer = 0;XMLNode steerNode; • while( !(steerNode = controllerNode.getChildNode(L"Steer", • iSteer)).isEmpty() ){ • D3DXVECTOR3 turn = steerNode.readVector(L"turn"); • unsigned int keyCode = steerNode.readLong(L"key"); • const wchar_t* codeTypeString = steerNode|L"codeType"; • if(codeTypeString • && wcscmp(codeTypeString, L"numpad") == 0) • keyCode += VK_NUMPAD0; • controller->addSteer(new Steer(keyCode, turn)); • iSteer++; • } • }
EngineCore::loadPhysicsEntityWheels • physicsEntity->addWheel(wheel); • const wchar_t* controllerName = wheelNode|L"controller"; • if(controllerName){ • WheelControllerDirectory::iterator • iWheelController = • wheelControllerDirectory.find( • controllerName); • if(iWheelController != • wheelControllerDirectory.end()) • wheel->setController( • iWheelController->second); • }