Upload
lilka
View
37
Download
0
Embed Size (px)
DESCRIPTION
Fizikai szimul áció - járművek. Grafikus játékok fejlesztése Szécsi László Bendefy Zoltán 201 3 .05.07 . t14 a - pxvehicle. Járművek a PhysX-ben. PhysX ismétlés. A zsiráf betöltésekor egy doboz objektumot regisztrálunk a PhysX-ben. A PhysX ezen ütközést, gravitációt számol. - PowerPoint PPT Presentation
Citation preview
Fizikai szimuláció - járművek
Grafikus játékok fejlesztéseSzécsi László
Bendefy Zoltán2013.05.07. t14a-pxvehicle
Járművek a PhysX-ben
PhysX ismétlés
A zsiráf betöltésekor egy doboz objektumot regisztrálunk a PhysX-ben
Rendereléskor elkérjük a PhysX-től a doboz helyét, és irányát majd ezzel frissítjük a zsiráf modellt
A színtér animálásakor meg kell hívni a PhysX simulate(float dt) függvényét, ami szimulálja a fizikai világot (ütközést számol, gravitációt alkalmaz, stb.)
A PhysX ezen ütközést, gravitációt számol
PhysX ismétlés
PxActor
PxShape
PxScene
PxShape
*
*
1
1
PhysX ismétlés
• A fizikai actorokon erőt, impulzust is alkalmazhatunk (pl. a bowling golyón)
F
PhysX ismétlés
3D motor vs. Fizikai világ
Járművek a PhysX-ben
• Járművek létrehozása az eddig ismert eszközökkel (merevtestek, ízületek, erők) nehézkes (közelítések, pontatlanságok miatt).
Járművek a PhysX-ben
• Első közelítésben:– Legyen egy téglatestünk, tegyünk rá 4 db hengert
egy-egy forgó ízülettel.Hajtsuk meg a kerekeket forgatónyomatékkal!• És a rugózás?• És a fékek?• És a sebességváltó?• És a tankok?
• Használjuk inkább aPhysX Vehicle SDK-t!
Járművek felépítése - áttekintés
• Mit támogat a PhysX Vehicle SDK?– 4 kerekű járművek (ezzel foglalkozunk)– N kerekű járművek– N kerekű Lánctalpas járművek (tankok)
Járművek felépítése - áttekintés
• Mit támogat a PhysX Vehicle SDK?– Realisztikus járműszimuláció• Ackermann kormányzási geometria• Motor, fék, kézifék, sebességváltó, kuplung• Felfüggesztés (rugózás), differenciálmű, abroncstípusok
(téli gumi, stb.)• Mindezeket szabadon
paraméterezhetjük!
Járművek felépítése - áttekintés
• Járművek a VehicleSDK-ban:
Járművek felépítése - áttekintés
• A PxShape-ek tartalmazzák az egyes részek geometriáját: 4 kerék és egy karosszéria– A PxShape önmagában csak egy geometria, nem
egy fizikai szereplő
Járművek felépítése - áttekintés
Járművek felépítése - áttekintés
• PxRigidDynamic – Ez az Actor, aki az járművet mint fizikai objektumot reprezentálja a fizikai világban. A PhysX az Actorokra számol fizikai hatásokat, őket ütközteti.
• Az actor több PxShape-et tartalmazhat:
Járművek felépítése - áttekintés
• PxVehicleDrive4W – Adatstruktúra, ez tárolja a jármű paramétereit és a dinamikus tulajdonságait– Paraméterek: motor erőssége és fordulatszáma,
váltók száma, fékek ereje, stb.– Dinamikus tulajdonságok: aktuális sebesség,
aktuális súrlódás a kerekeken, motor sebessége, stb.
Járművek felépítése - áttekintés
• A motorban egy VehicleEntity osztályként fog megjelenni a jármű.
Járművek felépítése - áttekintés
• Az actor 5 PxShape alakzatához (4 kerék + karosszéria) tartozni fog egy-egy MultiMesh, ezek fognak megjelenni a képernyőn.
• A MultiMesheket, a fizikai actort, és a jármű Adatstruktúráját egy VehicleEntity nevű osztályban foglaljuk össze.
• VehicleEntity->render() ez ki fogja renderelni mind az 5 MultiMesh-t
• VehicleEntity->animate() ez fogja frissíteni a MultiMesh-ek pozícióját és irányát a PhysX oldalról kinyert adatokkal.
Járművek felépítése - áttekintés
Fizikai világ (PxShape) 3D-s motor (MultiMesh)
Pozíció, irány
Pozíció, irány
Járművek felépítése – lépések
1) Vehicle SDK, filter shader és Cooking inicializálása a PhysX inicializálása után:
Filter shader és Cooking lib később…
physics = PxCreatePhysics(…);(…)PxSceneDesc sceneDesc(physics->getTolerancesScale());(…)sceneDesc.filterShader = VehicleFilterShader; //gDefaultFilterShader;
scene = physics->createScene(sceneDesc);
cookinglib = PxCreateCooking(PX_PHYSICS_VERSION, *foundation, PxCookingParams());
PxInitVehicleSDK(*physics);
Járművek felépítése – lépések
2) Luából hívható C++ függvény, amely felépít egy járművet: spawnVehicle()A következő lépésekben (3.-8.) ennek a felépítő függvénynek a tartalmát nézzük végig!
3) A járműhoz tartozó MultiMesh-ek elkészítése (a 4 kerék + karosszéria)
Mesh::Multi::P echassis, ewheel;chassis = StaticPartEntity::create(echassis);wheel1 = StaticPartEntity::create(ewheel);(…)wheel4 = StaticPartEntity::create(ewheel);
Járművek felépítése – lépések
4) PxShape-k (azaz a fizikai alakzatok) elkészítése a 4 kerékhez, és a karosszériához.• Ennél a lépésnél szükség van a PhysX Cooking
Library-re.• Cooking Library: háromszögháló vagy konvex
burok alapú geometriát tud létrehozni.– A Cooking a PhysX számára hatékony formátumra
hozza a geometriát
Járművek felépítése – lépések
• Konvex burok:– Olyan háromszögháló, amely a legszűkebben
illeszkedik az eredeti háromszöghálóra úgy, hogy még konvex maradjon (csomagolófólia).
– Hatékony vele számolni, könnyen generálható
Járművek felépítése – lépések
• Esetünkben a 4 kerék és a karosszéria háromszöghálói konvexek, így nem fognak megváltozni a konvex burok képzés során.
Járművek felépítése – lépések
• Konvex burok készítés kódjaconst aiScene* assScene = importer.ReadFile( name, 0); //AssImppel betöltjük a modelltPxVec3* buffer; //vertexeket tartalmazó tömb, az Assimpból kinyert vertexekkel kell feltölteni(…)PxConvexMeshDesc convexDesc;convexDesc.points.count = assScene->mMeshes[0]->mNumVertices; //Vertexek számaconvexDesc.points.stride = sizeof(PxVec3); //Vertexek mérete (4*3=12 bájt)convexDesc.points.data = buffer; //Egy float tömb amely a vertexeket tartalmazzaconvexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
(…)MemoryOutputStream buf;if(cookinglib->cookConvexMesh(convexDesc, buf)){ MemoryInputDataCustom input(buf.getData(), buf.getSize()); convexMesh = scene->getPhysics().createConvexMesh(input);}
Járművek felépítése – lépések
• 5) Szimulációs adatok feltöltése egy descriptorba– Ebben a lépésben adjuk meg a jármű adatait.– Például a motor erősségének megadása:
PxVehicleDriveSimData4W& driveData(…)//Engine propertiesPxVehicleEngineData engine;engine.mPeakTorque = 700.0f; // Nm (Newton metre) default: 3000engine.mMaxOmega = 600.0f; //default: 600=approx 6000 rpmdriveData.setEngineData(engine);
//Brake max torquewheels[PxVehicleDrive4W::eFRONT_LEFT_WHEEL].mMaxBrakeTorque = 9000.0f;
//SuspensionPxVehicleSuspensionData susps[WHEEL_NUM];susps[0].mSpringStrength= 2200.0f;
Járművek felépítése – lépések
6) Actor beállítása– Ez reprezentálja az autót mint fizikai objektumot.– Létre kell hozni, és be kell kötni a PxShape
geometriákat (4 kerék + karosszéria)
7) Járművet leíró adatstruktúra elkészítése az (5.) pontban létrehozott descriptor alapján.
car = PxVehicleDrive4W::allocate(4);car->setup(&(scene->getPhysics()), actor, *wheelsSimData, driveSimData, 0);
Járművek felépítése – lépések
8) Vezethető felületek beállításaA meglévő fizikai anyagtulajdonságokhoz (PxMaterial) meg lehet adni egy súrlódási tényezőt.Pl.: aszfaltút: 0.95
jégmező: 0.3
Különböző gumitípusokat is definiálhatunk, egyedi súrlódás értékekkel.Pl.: téli gumi jobban tapad a jeges úton
for(int i = 0; i < materialCount; i++){ mSurfaceTirePairs->setTypePairFriction(i, 0, 0.3f); //jeges út beállítása}
Járművek felépítése – lépések
• 9) Filter shader beállítása– A járművet egy rugózás (suspension) tartja szintben– A PhysX minden frissítéskor egy Raycast-tal megnézi,
hogy milyen messze van a talaj az egyes kerekektől, és aszerint alkalmazza a rugóerőket.
– Valahogy meg kell tiltanunk, hogy a kerék ütközzön a talajjal, hogy ez működjön!
– Erre szolgál a Filter shader!– Lényegében egy C++ oldali függvény, amely lefut
minden ütközés előtt az ütköző objektumpárokra, és eldönti, hogy az ütközés érvényre jut-e. • Ehhez általunk beállított flageket használhat.
Járművek felépítése – lépések
Filter shaderben írhatunk egy saját függvényt, amely eldönti két objektumról (azok flagei alapján), hogy azok ütközhetnek-e.Először meg kell adni valami megkülönböztetést (flaget):
A COLLISION_FLAG_xxx egy típus azonosítóA COLLISION_FLAG_xxx_AGAINST adja meg, hogy az xxx típusú objektumok mivel ütközhetnekA filter shaderben ezen flagek alapján szűrjük ki az ütközéseket!
enum{COLLISION_FLAG_GROUND = 1 << 0, //a talajnál ezt tesszük a word0 nevű flagbeCOLLISION_FLAG_WHEEL = 1 << 1, //a kerekeknél ezt tesszük a word0 nevű flagbeCOLLISION_FLAG_CHASSIS = 1 << 2, //a karosszériánál ezt tesszük a word0 nevű flagbeCOLLISION_FLAG_OBSTACLE = 1 << 3, //egyéb objektumoknál ezt tesszük a word0 nevű flagbe
//A talajhoz ezt a flaget rendeljük a word1 nevű flagbe. //Jelentése: a talaj csak a karosszériával és egyéb objektumokkal ütközhet.COLLISION_FLAG_GROUND_AGAINST = COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE(…) };
Járművek felépítése – lépések
• Ezek után a Filter Shader kódja:
• Megyjegyzés:– filterData0 és filterData1 a két objektum amely épp
ütközik– Word0 és word1 az objektum két flagje (ld. Előző dia)
static PxFilterFlags VehicleFilterShader(…){ (…) if ((filterData0.word0 != 0 && filterData1.word0 != 0) && !(filterData0.word0 & filterData1.word1 || filterData1.word0 & filterData0.word1)) return PxFilterFlag::eSUPPRESS;
(…)}
9+1) A már meglévő fizikai objektumok beállítása (pl.: talaj)PxFilterData simFilterData;PxFilterData qryFilterData;
//Talaj esetén (lehet rajta vezetni, nem ütközik a kerékkel)simFilterData.word0= COLLISION_FLAG_GROUND;simFilterData.word1= COLLISION_FLAG_GROUND_AGAINST;qryFilterData.word3 = (PxU32)(SAMPLEVEHICLE_DRIVABLE_SURFACE);
//Dinamikus objektunok esetén (nem lehet rajta vezetni, ütközik a kerékkel)simFilterData.word0=COLLISION_FLAG_DRIVABLE_OBSTACLE;simFilterData.word1=COLLISION_FLAG_DRIVABLE_OBSTACLE_AGAINST;qryFilterData.word3 = (PxU32)(SAMPLEVEHICLE_UNDRIVABLE_SURFACE);
//A fizikai actor minden shape-jére:shapes[i]->setSimulationFilterData(simFilterData);shapes[i]->setQueryFilterData(qryFilterData);
Jármű kirajzolása és animálása
1) Kirajzolás:Egyszerűen kirajzoljuk az 5 MultiMesh-t
wheel1->render(renderParameters);wheel2->render(renderParameters);wheel3->render(renderParameters);wheel4->render(renderParameters);chassis->render(renderParameters);
Jármű kirajzolása és animálása
2) Animálás: input bekötése
Ezeket a változókat Lua-ból állítjuk be.Lua-ból a billentyűeseményekre beregisztáljuk a DriveVehicle() nevű C++ oldali függvényt, amely beállítja a fenti bool értékeket:
bool control_accel;bool control_brake;bool control_steerleft;bool control_steerright;
vehicleControlState = { script = function(entity, state) if keysPressed.VK_NUMPAD8 == true then O:driveVehicle(entity, { brake=0, accelerate = 1 } ) end end }
Jármű kirajzolása és animálása
Ezután, ha megvannak a vezérlő bool értékek:
A PxVehicleDrive…() függvény szűri, kisimítja a beadott értékeket, majd alkalmazza őket a járműre.
PxVehicleDrive4WRawInputData rawInputData;
rawInputData.setDigitalAccel(control_accel);rawInputData.setDigitalBrake(control_brake);rawInputData.setDigitalSteerLeft(control_steerleft);rawInputData.setDigitalSteerRight(control_steerright);
PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs(gKeySmoothingData,gSteerVsForwardSpeedTable,rawInputData,dt,*car);
Jármű kirajzolása és animálása
3) Raycastok számítása, jármű frissítéseif(NULL == mSqWheelRaycastBatchQuery){ mSqWheelRaycastBatchQuery= mSqData->setUpBatchedSceneQuery(actor->getScene());}PxVehicleSuspensionRaycasts(…);
PxVehicleUpdates(dt,actor->getScene()->getGravity(),*mSurfaceTirePairs,1,vehicles);
Jármű kirajzolása és animálása
4) MultiMesh-ek pozíciójának beállítása//Elkérjük az actortól mind az 5 Shape-tconst int numShapes=actor->getNbShapes();PxShape* carShapes[WHEEL_NUM + 1]; //4 wheels + chassisactor->getShapes(carShapes,numShapes);
wheel1->setPosition(~PxShapeExt::getGlobalPose(*carShapes[0]).p);wheel1->setRotation(~PxShapeExt::getGlobalPose(*carShapes[0]).q);
wheel2->setPosition(~PxShapeExt::getGlobalPose(*carShapes[1]).p);wheel2->setRotation(~PxShapeExt::getGlobalPose(*carShapes[1]).q);(…)
Végeredmény
Végeredmény