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 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 ::it erator 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 ::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 ::it erator 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
XML <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"/>
XML
Kerék rugózása suspensionOffsetDirection contactPoint toContact along across eredeti pozíció
Kerék rugózása suspensionOffsetDirection contactPoint r across új pozíció pullBack
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) < ) 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
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"/>
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 motors; std::vector 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 ::iterator i = motors.begin(); while(i != motors.end()){ delete *i; i++; } std::vector ::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 ::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 ::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); }
XML
XML
PhysicsEntity void control(const ControlContext& context);
PhysicsEntity.cpp void PhysicsEntity::control( const ControlContext& context){ std::vector :: iterator wii = wheels.begin(); while(wii != wheels.end()){ (*wii)->control(context); wii++; }
Steer in render D3DXMATRIX modelMatrix, rollMatrix, steerMatrix; D3DXMatrixRotationX(&rollMatrix, rollAngle); pose.getColumnMajor44((NxF32*)&modelMatrix); D3DXMatrixRotationY(&steerMatrix, shape->getSteerAngle()); D3DXMatrixMultiply(&modelMatrix, &steerMatrix, &modelMatrix); D3DXMatrixMultiply(&modelMatrix, &rollMatrix, &modelMatrix);