{"id":1682,"date":"2015-03-21T20:11:39","date_gmt":"2015-03-21T20:11:39","guid":{"rendered":"http:\/\/anthroponaute.fr\/blog-informatique\/?p=1682"},"modified":"2015-11-13T19:56:36","modified_gmt":"2015-11-13T19:56:36","slug":"integration-de-newton-dynamics-dans-irrlicht","status":"publish","type":"post","link":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/?p=1682","title":{"rendered":"Int\u00e9gration de Newton Dynamics dans Irrlicht 3D"},"content":{"rendered":"<p><a href=\"https:\/\/anthropoya.cluster014.ovh.net\/blog-informatique\/wp-content\/uploads\/2015\/03\/physics.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone  wp-image-1685\" src=\"https:\/\/anthropoya.cluster014.ovh.net\/blog-informatique\/wp-content\/uploads\/2015\/03\/physics.jpg\" alt=\"physics\" width=\"541\" height=\"301\" srcset=\"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/03\/physics.jpg 1224w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/03\/physics-300x167.jpg 300w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/03\/physics-1024x571.jpg 1024w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/03\/physics-624x348.jpg 624w\" sizes=\"(max-width: 541px) 100vw, 541px\" \/><\/a><\/p>\n<p><strong>Intro :<\/strong><\/p>\n<p>Un moteur physique dans un jeu vid\u00e9o permet de simuler les ph\u00e9nom\u00e8nes physiques du monde r\u00e9\u00e9l. Il fait bouger les objets dans le jeu par des mouvements r\u00e9alistes.<\/p>\n<p>Ici nous allons utiliser le moteur physique <strong>Newton Dynamics<\/strong> pour l&rsquo;int\u00e9grer dans le moteur 3D <strong>Irrlicht<\/strong>.<\/p>\n<p>Site web de Newton Dynamics : <a href=\"http:\/\/www.newtondynamics.com\">www.newtondynamics.com<\/a><\/p>\n<p><strong>Pr\u00e9requis :<\/strong><\/p>\n<p>Savoir lire un peu du C++.<\/p>\n<p><strong>Explications :<br \/>\n<\/strong><\/p>\n<p>Mettez dans un fichier PhysicsManager.h le code suivant :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\r\n#ifndef PHYSICS_MANAGER_H\r\n#define PHYSICS_MANAGER_H\r\n\r\n#include &lt;irrlicht.h&gt;\r\n#include &lt;Newton.h&gt;\r\n\r\n#include &lt;string&gt;\r\n#include &lt;iostream&gt;\r\n#include &lt;fstream&gt;\r\n\r\n#define GAME_CUBE_MASS 15.0f\r\n\r\nusing namespace irr;\r\n\r\nclass PhysicsManager\r\n{\r\npublic:\r\n\u00a0\u00a0\u00a0 PhysicsManager();\r\n\u00a0\u00a0\u00a0 virtual ~PhysicsManager();\r\n\r\n\u00a0\u00a0\u00a0 \/\/ Lance un cube depuis la position de la cam\u00e9ra\r\n\u00a0\u00a0\u00a0 void LaunchCube(scene::ISceneNode* pCubeSceneNode, const core::vector3df&amp; direction);\r\n\r\n\u00a0\u00a0\u00a0 \/\/ Analyse un mesh et construit un objet de collision Newton correspondant\r\n\u00a0\u00a0\u00a0 NewtonCollision* CreateCollisionFromMesh(scene::IMesh* pIrrlichtMesh, const core::vector3df&amp; v3Scale);\r\n\r\n\u00a0\u00a0\u00a0 \/\/ Cr\u00e9\u00e9 un objet de collision Newton d'une forme englobante et correspondante avec la forme complexe du mesh pass\u00e9\r\n\u00a0\u00a0\u00a0 \/\/ en param\u00e8tre\r\n\u00a0\u00a0\u00a0 NewtonCollision* CreateCollisionConvexHullFromMesh(scene::IMesh* pIrrlichtMesh);\r\n\r\n\u00a0\u00a0\u00a0 \/\/ Pr\u00e9pare un objet Newton Body pour la gestion physique\r\n\u00a0\u00a0\u00a0 void InitializeRigidBody(const scene::ISceneNode* pSceneNode, NewtonBody* pBody);\r\n\r\n\u00a0\u00a0\u00a0 \/\/ Retourne vrai si le fichier cache de collision Newton existe\r\n\u00a0\u00a0\u00a0 bool PhysicsManager::CollisionCacheFileExist(const std::string&amp; sCacheFileName);\r\n\r\n\u00a0\u00a0\u00a0 \/* Callbacks *\/\r\n\u00a0\u00a0\u00a0 static void SetTransform(const NewtonBody* pBody, const float* matrix, int threadIndex);\r\n\u00a0\u00a0\u00a0 static void ApplyGravity(const NewtonBody* pBody, float timestep, int threadIndex);\r\n\r\n\u00a0\u00a0\u00a0 \/\/ Rafraichit le moteur physique Newton\r\n\u00a0\u00a0\u00a0 void Update(float fValue);\r\n\r\n\u00a0\u00a0\u00a0 \/\/ Ajoute un objet \u00e0 traiter au moteur 3D\r\n\u00a0\u00a0\u00a0 void CreateDynamicBody(scene::IMeshSceneNode* pMeshNode, float fMass,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 bool bUseCache, const std::string&amp; sCacheName);\r\n\r\n\u00a0\u00a0\u00a0 static void SerializeCollision(void* serializeHandle, const void* buffer, int size);\r\n\u00a0\u00a0\u00a0 static void DeSerializeCollision(void* serializeHandle, void* buffer, int size);\r\n\r\nprivate:\r\n\u00a0\u00a0\u00a0 \/\/ L'objet principale de la librairie Newton\r\n\u00a0\u00a0\u00a0 NewtonWorld* m_pNewtonWorld;\r\n};\r\n\r\n#endif\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Mettez dans un fichier PhysicsManager.cpp le code suivant :<\/p>\n<p>Cette fonction s&rsquo;occupe de lancer un cube dans la direction sp\u00e9cifi\u00e9e.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid PhysicsManager::LaunchCube(scene::ISceneNode* pCubeSceneNode, const core::vector3df&amp; direction)\r\n{\r\n\u00a0\u00a0\u00a0 NewtonCollision* pNewtonCollisionBox = nullptr; \u00a0\r\n\u00a0\u00a0\u00a0 NewtonBody* pBody = nullptr;\r\n\r\n\u00a0\u00a0\u00a0 \/\/ Calcule la taille englobante de la scene node\r\n\u00a0\u00a0\u00a0 core::vector3df size(pCubeSceneNode-&gt;getBoundingBox().MaxEdge - pCubeSceneNode-&gt;getBoundingBox().MinEdge);\r\n\r\n\u00a0\u00a0\u00a0 \/\/ En effet un objet NewtonCollision doit \u00eatre agrandi ou r\u00e9duit par rapport \u00e0 la v\u00e9ritable \u00e9chelle de la SceneNode\r\n\u00a0\u00a0\u00a0 pNewtonCollisionBox = NewtonCreateBox(m_pNewtonWorld, size.X, size.Y, size.Z, 0, 0);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 \/\/ Cr\u00e9\u00e9 l'objet NewtonBody\r\n\u00a0\u00a0\u00a0 const float* matrix = core::IdentityMatrix.pointer();\r\n\u00a0\u00a0\u00a0 pBody = NewtonCreateDynamicBody(m_pNewtonWorld, pNewtonCollisionBox, matrix);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 \/\/ On d\u00e9truit l'objet collision dont on n'a plus besoin\r\n\u00a0\u00a0\u00a0 NewtonDestroyCollision(pNewtonCollisionBox);\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 \/\/ On lui envoit les transformations de la sc\u00e8ne node (position, rotation).\r\n\u00a0\u00a0\u00a0 NewtonBodySetMatrix(pBody, pCubeSceneNode-&gt;getRelativeTransformation().pointer());\r\n\r\n\u00a0\u00a0\u00a0 \/\/ On envoit un pointeur de la sc\u00e8ne node pour pouvoir le r\u00e9cup\u00e9rer plus tard.\r\n\u00a0\u00a0\u00a0 NewtonBodySetUserData(pBody, pCubeSceneNode);\r\n\r\n\u00a0\u00a0\u00a0 \/\/ Pr\u00e9pare l'objet pour le traitement physique 3D\r\n\u00a0\u00a0\u00a0 InitializeRigidBody(pCubeSceneNode, pBody);\r\n\r\n\u00a0\u00a0\u00a0 float directionArray[3];\r\n\r\n\u00a0\u00a0\u00a0 directionArray[0] = direction.X;\r\n\u00a0\u00a0\u00a0 directionArray[1] = direction.Y;\r\n\u00a0\u00a0\u00a0 directionArray[2] = direction.Z;\r\n\r\n\u00a0\u00a0\u00a0 \/\/ On lui impulse un mouvement dans la direction directionArray\r\n\u00a0\u00a0\u00a0 NewtonBodySetVelocity(pBody, directionArray);\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>La fonction suivante s&rsquo;occupe de cr\u00e9er un objet Newton Body compl\u00e8tement statique et muni d&rsquo;une collision solide.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nNewtonCollision* PhysicsManager::CreateCollisionFromMesh(scene::IMesh* pIrrlichtMesh, const core::vector3df&amp; v3Scale)\r\n{\r\n\u00a0\u00a0\u00a0 \/\/ On pr\u00e9pare un certain type d'objet de collision\r\n\u00a0\u00a0\u00a0 NewtonCollision* pNewtonCollision = NewtonCreateTreeCollision(m_pNewtonWorld, 0);\r\n\r\n\u00a0\u00a0\u00a0 NewtonTreeCollisionBeginBuild(pNewtonCollision);\r\n\r\n\u00a0\u00a0\u00a0 scene::IMeshBuffer* pMeshBuffer = nullptr;\r\n\u00a0\u00a0\u00a0 int index1, index2, index3;\r\n\r\n\u00a0\u00a0\u00a0 \/** Faire attention au format des vertex !! **\/\r\n\u00a0\u00a0\u00a0 \/** Si vous utilisez une autre d\u00e9claration de vertex, changez la ici ! **\/\r\n\u00a0\u00a0\u00a0 const video::S3DVertex2TCoords* pVertices = nullptr;\r\n\u00a0\u00a0\u00a0 const u16* pIndices = nullptr;\r\n\u00a0\u00a0\u00a0 float floatArray[9] = {0};\r\n\r\n\u00a0\u00a0\u00a0 for (unsigned int iMeshBufferNumber = 0; iMeshBufferNumber &lt; pIrrlichtMesh-&gt;getMeshBufferCount() ; ++iMeshBufferNumber)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pMeshBuffer = pIrrlichtMesh-&gt;getMeshBuffer(iMeshBufferNumber);\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pIndices = pMeshBuffer-&gt;getIndices();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pVertices = (video::S3DVertex2TCoords*) pMeshBuffer-&gt;getVertices();\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for (unsigned int j = 0; j &lt; pMeshBuffer-&gt;getIndexCount(); j += 3)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 index1 = pIndices[j + 0];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 index2 = pIndices[j + 1];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 index3 = pIndices[j + 2];\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 floatArray[0] = pVertices[index1].Pos.X * v3Scale.X;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 floatArray[1] = pVertices[index1].Pos.Y * v3Scale.Y;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 floatArray[2] = pVertices[index1].Pos.Z * v3Scale.Z;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 floatArray[3] = pVertices[index2].Pos.X * v3Scale.X;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 floatArray[4] = pVertices[index2].Pos.Y * v3Scale.Y;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 floatArray[5] = pVertices[index2].Pos.Z * v3Scale.Z;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 floatArray[6] = pVertices[index3].Pos.X * v3Scale.X;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 floatArray[7] = pVertices[index3].Pos.Y * v3Scale.Y;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 floatArray[8] = pVertices[index3].Pos.Z * v3Scale.Z;\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NewtonTreeCollisionAddFace(pNewtonCollision, 3, floatArray, sizeof(float)*3, 0);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 \/\/ Finalise la contrustion de l'objet collision\r\n\u00a0\u00a0\u00a0 NewtonTreeCollisionEndBuild(pNewtonCollision, 1);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 return pNewtonCollision;\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>La fonction suivante cr\u00e9\u00e9e un objet collision englobant la forme du mesh pass\u00e9 en param\u00e8tre.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/ Cr\u00e9\u00e9e un objet collision avec la forme englobante d'un mesh\r\nNewtonCollision* PhysicsManager::CreateCollisionConvexHullFromMesh(scene::IMesh* pIrrlichtMesh)\r\n{\r\n\u00a0\u00a0\u00a0 unsigned int iMeshBufferNumber = 0;\r\n\u00a0\u00a0\u00a0 scene::IMeshBuffer* pMeshBuffer = nullptr;\r\n\u00a0\u00a0\u00a0 float* afVertices = nullptr;\r\n\r\n\u00a0\u00a0\u00a0 unsigned int iTotalVertices = 0;\r\n\r\n\u00a0\u00a0\u00a0 for (iMeshBufferNumber = 0; iMeshBufferNumber &lt; pIrrlichtMesh-&gt;getMeshBufferCount() ; ++iMeshBufferNumber)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 iTotalVertices += pIrrlichtMesh-&gt;getMeshBuffer(iMeshBufferNumber)-&gt;getVertexCount();\r\n\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0 afVertices = new float[iTotalVertices * 3];\r\n\u00a0\u00a0\u00a0 u32 iTmpCounter = 0;\r\n\r\n\u00a0\u00a0\u00a0 for (iMeshBufferNumber = 0 ; iMeshBufferNumber &lt; pIrrlichtMesh-&gt;getMeshBufferCount() ; ++iMeshBufferNumber)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pMeshBuffer = pIrrlichtMesh-&gt;getMeshBuffer(iMeshBufferNumber);\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 video::S3DVertex2TCoords* S3vertices = (video::S3DVertex2TCoords*)pMeshBuffer-&gt;getVertices();\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for(unsigned int i = 0; i &lt; pMeshBuffer-&gt;getVertexCount(); ++i)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 afVertices[iTmpCounter++] = S3vertices[i].Pos.X;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 afVertices[iTmpCounter++] = S3vertices[i].Pos.Y;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 afVertices[iTmpCounter++] = S3vertices[i].Pos.Z;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0 NewtonCollision* pNewtonCollision = NewtonCreateConvexHull(m_pNewtonWorld, iTotalVertices, afVertices,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sizeof(float)*3, 0.1f, 0, nullptr);\r\n\r\n\u00a0\u00a0\u00a0 delete [] afVertices;\r\n\r\n\u00a0\u00a0\u00a0 return pNewtonCollision;\r\n} \r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Les fonctions suivantes sont des callbacks (c&rsquo;est-\u00e0-dire des fonctions appel\u00e9es de mani\u00e8re<br \/>\ninterne \u00e0 Newton Dynamics).<br \/>\nLa premi\u00e8re sert \u00e0 Irrlicht, elle permet de\u00a0 savoir comment doivent \u00eatre mis en mouvement les SceneNode enregistr\u00e9es.<br \/>\nLa deuxi\u00e8me indique \u00e0 Newton comment doivent \u00eatre configur\u00e9 la pesanteur.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid PhysicsManager::SetTransform(const NewtonBody* const pBody, const float* matrix, int threadIndex)\r\n{\r\n\u00a0\u00a0\u00a0 scene::ISceneNode* pSceneNode = (scene::ISceneNode*) NewtonBodyGetUserData(pBody);\r\n\r\n\u00a0\u00a0\u00a0 if (pSceneNode)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 core::matrix4 transform;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 transform.setM(matrix);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pSceneNode-&gt;setPosition(transform.getTranslation());\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pSceneNode-&gt;setRotation(transform.getRotationDegrees());\r\n\u00a0\u00a0\u00a0 }\u00a0\u00a0 \u00a0\r\n}\r\n\r\nvoid PhysicsManager::ApplyGravity(const NewtonBody* pBody, float timestep, int threadIndex)\r\n{\r\n\u00a0\u00a0 \/* Cette fonction est une fonction Callback. Elle sera appel\u00e9e \u00e0 chaque fois\r\n\u00a0\u00a0 qu'une modification aura lieu sur le corps. *\/\r\n\r\n\u00a0\u00a0 \/\/ On r\u00e9cup\u00e8re en premier lieu la masse ainsi que l'inertie\r\n\u00a0\u00a0 float masse; \/\/ Contiendra la masse de l'objet pris en param\u00e8tre par la fonction\r\n\u00a0\u00a0 float inertieX, inertieY, inertieZ; \/\/ Contiendra l'inertie du corps\r\n\u00a0\u00a0 float force[3]; \/\/ Sp\u00e9cifiera la force appliqu\u00e9e sur le corps\r\n\r\n\u00a0\u00a0 NewtonBodyGetMassMatrix(pBody, &amp;masse, &amp;inertieX, &amp;inertieY, &amp;inertieZ);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 force[0] = 0.0f; \/\/ X\r\n\u00a0\u00a0 force[1] = -masse * 9.81f; \/\/\/ timestep; \/\/ 9.81 est l'attraction gravitationnelle de la Terre (Y)\r\n\u00a0\u00a0 force[2] = 0.0f; \/\/ Z\r\n\r\n\u00a0\u00a0 NewtonBodyAddForce(pBody, force); \/\/ On ajoute la force au corps\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Cette fonction ajoute une MeshSceneNode au traitement de Newton Dynamics.<br \/>\nElle fait appel \u00e0 CreateCollisionFromMesh(&#8230;) pour cr\u00e9er l&rsquo;objet de collision.<br \/>\nElle s&rsquo;occupe aussi de sauvegarder dans un fichier .cache les donn\u00e9es de collisions. Cela permettra d&rsquo;acc\u00e9l\u00e9rer le calcul et le traitement de la structure de collision du Mesh si un fichier .cache \u00e0 \u00e9t\u00e9 trouv\u00e9.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid PhysicsManager::CreateDynamicBody(scene::IMeshSceneNode* pMeshNode, float fMass,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 bool bUseCache, const std::string&amp; sCacheName)\r\n{\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 std::string sCacheFileName = &quot;&quot;;\r\n\u00a0\u00a0\u00a0 NewtonCollision* pNewtonCollision = nullptr;\r\n\u00a0\u00a0\u00a0 FILE* pCacheFile = nullptr;\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 if (sCacheName == &quot;&quot;)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sCacheFileName = pMeshNode-&gt;getName(); \/\/ On utilise le nom de la scene node pour nommer le fichier cache\r\n\r\n\u00a0\u00a0\u00a0 if (sCacheName != &quot;&quot;)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sCacheFileName = sCacheName; \/\/ On utilise un cache sp\u00e9cifique\r\n\r\n\u00a0\u00a0\u00a0 if (!sCacheFileName.empty())\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sCacheFileName += &quot;.cache&quot;;\r\n\r\n\u00a0\u00a0\u00a0 \/\/ On utilise le cache si le fichier existe d\u00e9j\u00e0\r\n\u00a0\u00a0\u00a0 if (bUseCache &amp;&amp; CollisionCacheFileExist(sCacheFileName))\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pCacheFile = fopen(sCacheFileName.c_str(), &quot;rb&quot;);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ On cr\u00e9\u00e9r un objet collision directement depuis un cache pr\u00e9c\u00e9demment cr\u00e9\u00e9\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pNewtonCollision = NewtonCreateCollisionFromSerialization(m_pNewtonWorld, DeSerializeCollision, pCacheFile);\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 else\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ On cr\u00e9\u00e9r un objet collision directement depuis le ou les meshbuffers de la SceneNode\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pNewtonCollision = CreateCollisionFromMesh(pMeshNode-&gt;getMesh(), pMeshNode-&gt;getScale());\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ On cr\u00e9\u00e9 le cache\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if(!sCacheFileName.empty()) \/\/ ... si le fichier n'existe pas d\u00e9j\u00e0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pCacheFile = fopen(sCacheFileName.c_str(), &quot;wb&quot;);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ On s\u00e9rialize l'objet NewtonCollision vers un fichier\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 NewtonCollisionSerialize(m_pNewtonWorld, pNewtonCollision, SerializeCollision, pCacheFile);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 if (pCacheFile)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 fclose(pCacheFile);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pCacheFile = nullptr;\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0 \/\/ On met la bonne \u00e9chelle\r\n\u00a0\u00a0\u00a0 NewtonCollisionSetScale(pNewtonCollision, pMeshNode-&gt;getScale().X, pMeshNode-&gt;getScale().Y, pMeshNode-&gt;getScale().Z);\r\n\r\n\u00a0\u00a0\u00a0 const float* matrix = core::IdentityMatrix.pointer();\r\n\u00a0\u00a0\u00a0 NewtonBody* pBody = NewtonCreateDynamicBody(m_pNewtonWorld, pNewtonCollision, matrix);\r\n\r\n\u00a0\u00a0\u00a0 NewtonDestroyCollision(pNewtonCollision);\u00a0\u00a0 \u00a0\r\n\r\n\u00a0\u00a0\u00a0 \/\/ On remet la matrice des correctes transformations\r\n\u00a0\u00a0\u00a0 core::matrix4 transformation;\r\n\u00a0\u00a0\u00a0 transformation.setTranslation(pMeshNode-&gt;getPosition());\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 transformation.setScale(pMeshNode-&gt;getScale()); \r\n\r\n\u00a0\u00a0\u00a0 NewtonBodySetMatrix(pBody, transformation.pointer());\r\n\r\n\u00a0\u00a0\u00a0 \/\/ On envoit un pointeur de la sc\u00e8ne node pour pouvoir le r\u00e9cup\u00e9rer plus tard.\r\n\u00a0\u00a0\u00a0 NewtonBodySetUserData(pBody, pMeshNode);\r\n\u00a0\u00a0\u00a0 \/\/ On lui envoit les transformations de la sc\u00e8ne node (position, rotation).\r\n\u00a0\u00a0\u00a0 NewtonBodySetMatrix(pBody, pMeshNode-&gt;getRelativeTransformation().pointer());\r\n\r\n\u00a0\u00a0\u00a0 InitializeRigidBody(pMeshNode, pBody);\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Ces fonctions suivantes indiquent \u00e0 Newton Dynamics comment charger ou sauvegarder<br \/>\nun fichier de collision .cache.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid PhysicsManager::SerializeCollision(void* serializeHandle, const void* buffer, int size)\r\n{\r\n\u00a0\u00a0\u00a0 fwrite(buffer, size, 1, (FILE*)serializeHandle);\r\n}\r\n\r\nvoid PhysicsManager::DeSerializeCollision(void* serializeHandle, void* buffer, int size)\r\n{\r\n\u00a0\u00a0\u00a0 fread(buffer, size, 1, (FILE*)serializeHandle);\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Voici les autres fonctions du fichier PhysicsManager.cpp :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nPhysicsManager::PhysicsManager()\r\n{\r\n\u00a0\u00a0\u00a0 m_pNewtonWorld = NewtonCreate();\r\n\r\n\u00a0\u00a0\u00a0 NewtonSetSolverModel(m_pNewtonWorld, 1);\r\n}\r\n\r\nPhysicsManager::~PhysicsManager()\r\n{\r\n\u00a0\u00a0\u00a0 NewtonDestroyAllBodies(m_pNewtonWorld);\r\n\u00a0\u00a0\u00a0 NewtonDestroy(m_pNewtonWorld);\r\n}\r\n\r\nvoid PhysicsManager::Update(float fValue)\r\n{\r\n\u00a0\u00a0\u00a0 \/\/ Rafraichit le moteur Newton\r\n\u00a0\u00a0\u00a0 NewtonUpdate(m_pNewtonWorld, fValue);\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Pour utiliser Newton dans Irrlicht, nous proposons le programme suivant :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &lt;Irrlicht.h&gt;\r\n#include &lt;Newton.h&gt;\r\n\r\n#include &lt;Windows.h&gt;\r\n#include &lt;iostream&gt;\r\n\r\n#include &quot;PhysicsManager.h&quot;\r\n\r\nusing namespace irr;\r\nusing namespace core;\r\nusing namespace scene;\r\n\r\n\/* Il faut int\u00e9grer la librairie d'Irrlicht dans les propri\u00e9t\u00e9 du projet *\/\r\n#pragma comment(lib, &quot;Irrlicht.lib&quot;)\r\n\r\n\/* J'ai aussi joint dans l'archive .zip plusieurs fichier .lib et .dll\u00a0 de la libraire de Newton *\/\r\n#pragma comment(lib, &quot;newton_d.lib&quot;)\r\n\r\nPhysicsManager *m_pPhysicsManager = nullptr;\r\nICameraSceneNode* cam = nullptr;\r\nISceneManager* smgr = nullptr;\r\nvideo::IVideoDriver* driver = nullptr;\r\n\r\nclass MyEventReceiver : public IEventReceiver\r\n{\r\npublic:\r\n\u00a0\u00a0 \u00a0virtual bool OnEvent(const SEvent&amp; event)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/** Launch cube **\/\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (event.KeyInput.Key == KEY_SPACE)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0IMeshSceneNode* node = smgr-&gt;addCubeSceneNode(24, nullptr, -1, cam-&gt;getAbsolutePosition());\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0core::vector3df vect = cam-&gt;getTarget() - cam-&gt;getAbsolutePosition();\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0node-&gt;setMaterialTexture(0, driver-&gt;getTexture(&quot;box.jpg&quot;));\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0node-&gt;setMaterialFlag(video::EMF_LIGHTING, false);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0m_pPhysicsManager-&gt;LaunchCube(node, vect);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return false;\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0MyEventReceiver()\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0}\r\n\r\nprivate:\r\n};\r\n\r\nint main()\r\n{\r\n\u00a0\u00a0 \u00a0m_pPhysicsManager = new PhysicsManager();\r\n\u00a0\u00a0 \u00a0MyEventReceiver receiver;\r\n\r\n\u00a0\u00a0 \u00a0IrrlichtDevice *device =\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0createDevice(video::EDT_OPENGL, dimension2d&lt;u32&gt;(1280, 1024), 16,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0false, false, false, &amp;receiver);\r\n\u00a0\r\n\u00a0\u00a0 \u00a0if (!device)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return 1;\r\n\u00a0\r\n\u00a0\u00a0 \u00a0device-&gt;setWindowCaption(L&quot;Impl\u00e9mentation Newton Dynamics&quot;);\r\n\u00a0\r\n\u00a0\u00a0 \u00a0driver = device-&gt;getVideoDriver();\r\n\u00a0\u00a0 \u00a0smgr = device-&gt;getSceneManager();\r\n\u00a0\u00a0 \u00a0gui::IGUIEnvironment* guienv = device-&gt;getGUIEnvironment();\r\n\u00a0\r\n\u00a0\u00a0 \u00a0device-&gt;getFileSystem()-&gt;addZipFileArchive(&quot;map-20kdm2.pk3&quot;);\r\n\u00a0\u00a0 \u00a0scene::IAnimatedMesh* mesh = smgr-&gt;getMesh(&quot;20kdm2.bsp&quot;);\r\n\u00a0\u00a0 \u00a0IMeshSceneNode* node = 0;\r\n\r\n\u00a0\u00a0 \u00a0if (mesh)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0node = smgr-&gt;addOctreeSceneNode(mesh-&gt;getMesh(0), 0, -1, 1024);\r\n\r\n\u00a0\u00a0 \u00a0node-&gt;setPosition(core::vector3df(-1300,-144,-1249));\r\n\r\n\u00a0\u00a0\u00a0 \u00a0cam = smgr-&gt;addCameraSceneNodeFPS();\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\/\/ On cr\u00e9\u00e9 l'objet collision du niveau Quake3 pour Newton Dynamics\r\n\u00a0\u00a0 \u00a0m_pPhysicsManager-&gt;CreateDynamicBody(node, 10.0f, true, &quot;Collision&quot;);\r\n\r\n\u00a0\u00a0 \u00a0device-&gt;getCursorControl()-&gt;setVisible(false);\r\n\r\n\u00a0\u00a0 \u00a0while(device-&gt;run())\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0driver-&gt;beginScene(true, true, video::SColor(255,100,101,140));\r\n\u00a0\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0smgr-&gt;drawAll();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0guienv-&gt;drawAll();\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0m_pPhysicsManager-&gt;Update(1\/120.0f);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0driver-&gt;endScene();\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\r\n\u00a0\u00a0 \u00a0device-&gt;drop();\r\n\r\n\u00a0\u00a0 \u00a0delete m_pPhysicsManager;\r\n\u00a0\r\n\u00a0\u00a0 \u00a0return 0;\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>R\u00e9sum\u00e9 :<\/strong><\/p>\n<p>Nous avons int\u00e9grer le moteur physique Newton Dynamics dans le moteur 3D Irrlicht.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Intro : Un moteur physique dans un jeu vid\u00e9o permet de simuler les ph\u00e9nom\u00e8nes physiques du monde r\u00e9\u00e9l. Il fait bouger les objets dans le jeu par des mouvements r\u00e9alistes. Ici nous allons utiliser le moteur physique Newton Dynamics pour l&rsquo;int\u00e9grer dans le moteur 3D Irrlicht. Site web de Newton Dynamics : www.newtondynamics.com Pr\u00e9requis : [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11],"tags":[],"_links":{"self":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/1682"}],"collection":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1682"}],"version-history":[{"count":58,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/1682\/revisions"}],"predecessor-version":[{"id":3469,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/1682\/revisions\/3469"}],"wp:attachment":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1682"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1682"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1682"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}