Bonjour à tous,
comme le titre vous l'explique, j'essaye de créer une gravité avec Newton et le moteur Irrlicht. J'ai créer, grâce au tutos que j'ai pu trouver sur internet, un code qui est censé modélisé un cube et le soumettre a la gravité. Mais mon code ne fonctionne pas, il m'affiche un cube mais il est immobile. Voici mon code :
main.hpp :
#ifndef MAIN_HPP
#define MAIN_HPP
#include <irr/Irrlicht.h>
#include <iostream>
#include "newton.h"
void drawScene();
void force(NewtonBody *body);
void initScene();
#endif
main.cpp :
#include "main.hpp"
static NewtonWorld* world;
static NewtonBody* body;
irr::IrrlichtDevice *device = 0;
irr::video::IVideoDriver *driver = 0;
irr::scene::ISceneManager *sceneManager = 0;
irr::scene::ISceneNode *cubeNode = 0;
irr::scene::ISceneNode *cam = 0;
unsigned int lasttick;
void initScene()
{
device = irr::createDevice(irr::video::EDT_OPENGL, irr::core::dimension2d<irr::u32>(640,480), false);
driver = device->getVideoDriver();
sceneManager = device->getSceneManager();
sceneManager->addSkyBoxSceneNode(driver->getTexture("data/irrlicht2_up.bmp"),driver->getTexture("data/irrlicht2_dn.bmp"),driver->getTexture("data/irrlicht2_rt.bmp"),driver->getTexture("data/irrlicht2_lf.bmp"),driver->getTexture("data/irrlicht2_ft.bmp"),driver->getTexture("data/irrlicht2_bk.bmp"));
world = NewtonCreate (NULL, NULL);
irr::scene::IMesh* cubeMesh = sceneManager->getMesh("data/smallcube.3ds");
cubeNode = sceneManager->addMeshSceneNode(cubeMesh);
cubeNode->setMaterialTexture(0, driver->getTexture("data/crate.jpg"));
cubeNode->setMaterialFlag(irr::video::EMF_LIGHTING, false);
NewtonCollision *collision;
collision = NewtonCreateBox(world, 0, 0, 0, NULL);
body = NewtonCreateBody (world, collision);
NewtonReleaseCollision (world, collision);
NewtonBodySetUserData(body, cubeNode);
float masse = 100.0;
NewtonBodySetMassMatrix(body, masse, 1.0f, 1.0f, 1.0f);
irr::core::matrix4 mat;
mat.setTranslation(irr::core::vector3df(0.0,0.0,0.0));
NewtonBodySetMatrix(body, mat.pointer());
irr::scene::ICameraSceneNode* cam = sceneManager->addCameraSceneNode();
cam->setPosition(irr::core::vector3df(200,100,0));
cam->setTarget(irr::core::vector3df(0,0,0));
irr::core::vector3df inertie;
irr::core::vector3df taille = irr::core::vector3df(10,10,10);
inertie.X = (masse/12)*(pow(taille.Y,2)+pow(taille.Z,2));
inertie.Y = (masse/12)*(pow(taille.X,2)+pow(taille.Z,2));
inertie.Z = (masse/12)*(pow(taille.X,2)+pow(taille.Y,2));
NewtonBodySetMassMatrix (body, masse, inertie.X, inertie.Y, inertie.Z);
force(body);
}
void force(NewtonBody *body){
float masse;
irr::core::vector3df inertie;
float force[3];
NewtonBodyGetMassMatrix (body, &masse, &inertie.X, &inertie.Y, &inertie.Z);
force[0] = 0.0f;
force[1] = -9.81 * masse;
force[2] = 0.0f;
NewtonBodyAddForce(body, force);
}
void drawScene(){
if (device->getTimer()->getTime() > lasttick + 10)
{
lasttick = device->getTimer()->getTime();
NewtonUpdate(world, 0.01f);
}
irr::core::matrix4 mat;
NewtonBodyGetMatrix(body, mat.pointer());
cubeNode->setPosition(mat.getTranslation());
cubeNode->setRotation(mat.getRotationDegrees());
}
int main()
{
initScene();
while(device->run())
{
drawScene();
driver->beginScene(true, true, irr::video::SColor(255,255,255,255));
sceneManager->drawAll();
driver->endScene();
}
NewtonDestroy(world);
device->drop();
return 0;
}
Mais je ne comprend pas où plante le code. Pourriez vous m'aider ?
Merci d'avance.
Hors ligne
Salut Kaze,
Sur quelle version de newton tu bosses ?
Je pourrais regarder ça dans la soirée si personne t'a débloqué avant.
A plus tard donc
Hors ligne
Il me semble que c'est la version 2.3 mais je n'en suis vraiment pas sur. Et merci pour ton aide.
Dernière modification par Kaze (10-08-2012 19:13:25)
Hors ligne
Salut Kaze, alors j'ai vu deux trois tucs:
Déjà, pour ton code:
NewtonBodySetUserData(body, cubeNode);
Écris plutôt:
NewtonBodySetUserData(body,reinterpret_cast<void*>(cubeNode));
De cette manière, tu dis au compilo comment le pointeur de ton cubeNode doit être.
De plus, lorsque Newton désire changer la position du cube, il appelle le pointeur d'une méthode que tu peux capter, c'est la méthode:
void GrNewton::SetMeshTransformMesh(const NewtonBody* body,const float* matrix,int threadIndex) { // On retransforme le pointeur dans la bonne forme. ISceneNode*cubeNode = reinterpret_cast<ISceneNode*>(NewtonBodyGetUserData(body)); if(cubeNode == 0) return; // Conversion et création de la bonne matrice, ... cubeNode->setPosition(mat.getTranslation()); cubeNode->setRotation(mat.getRotationDegrees()); }
Cette méthode se configure comme ça dans l'initialisation de ton code:
...ton code NewtonBodySetUserData(body, cubeNode); // Association d'une "Callback" (ici:SetMeshTransformMesh) à l'objet Newton, // elle sera appellée lorsque l'objet bougera selon le moteur Newton (il y a bcp d'exemple là dessus). NewtonBodySetTransformCallback(body,SetMeshTransformMesh);
Il est donc inutile d'écrire le code suivant dans la méthode "drawScene()":
NewtonBodyGetMatrix(body, mat.pointer());
Voilà, j'espère qu'il n'y avait que ça, désolé de ne pas être plus précis, ma fille pleure, il faut que j'y aille !
Dernière modification par Gehogor (11-08-2012 09:10:16)
Hors ligne
Hello, merci Gehogor .Petit contre temps hier soir j'ai pas pût regarder mais si tu l'as aidé c'est cool ! amusez vous bien.
Je retourne dans mon code moi
Hors ligne
Waouh !!! Moi qui ne comprend rien à Newton je suis un peu perdu. J'ai compris la première modification (même si je n'ai pas compris à quoi servait cette fonction) mais pour la seconde ... j'ai laché. Faut dire que même les tutos que j'ai pu trouvé ne m'ont pas été d'une grande aide.
Est-ce qu'il serait possible d'être plus précis ? Ou si vous avez un code qui me permette de mieux comprendre Newton (même s'il ne fait pas ce que je veux) ? Ce serait génial. Sinon merci de vous pencher sur mon problème.
Hors ligne
Dans ta boucle de rendu tu dois faire un NewtonUpdate(...). Regarde dans la doc pour le paramètrage.
Je te passe un bout de code pour un framerate libre (pas de vsync):
void Systeme::rendu() { /// variables pour le chronomètrage de l'execution des frames mTimeElapsed = 0; u32 startTime = 0; /// variable pour le rafraichissement de la physique u32 lastTime = 0; /// entrée dans la boucle while(mDevice->run()) { /// on enregistre le temps de départ de la frame startTime = mDevice->getTimer()->getTime(); /// update la physique if( startTime > (lastTime + TIME_STEP_MS) ) { NewtonUpdate(mWorld, TIME_STEP_S ); lastTime = startTime; } /// commence l'update de l'écran mDriver->beginScene(true, true, mBackgroundColor); /// dessine la scène mSmgr->drawAll(); /// fin de l'update de l'écran mDriver->endScene(); /// on calcule et enregistre le temps d'éxécution de la frame mTimeElapsed = mDevice->getTimer()->getTime() - startTime; #ifdef _DEBUG stringw str = L"My Game ["; str += mDriver->getName();str += "] "; str += "Temps de frame: "; str += mTimeElapsed; str += " ms"; mDevice->setWindowCaption(str.c_str()); #endif } }
Dernière modification par johnplayer (11-08-2012 16:35:18)
Hors ligne
Je n'ai pas compris. Ma fonction drawScene() utilise NewtonUpdate. Je ne vois pas ce que ton code change vu que lorsque j'integre ton code, mon cube est toujours immobile.
Hors ligne
En effet Johnplayer, j'ai failli lui faire la même remarque mais en fait il appelle correctement la méthode "NewtonUpadte()" qui se cache discrètement dans la méthode "drawScene()".
Un callback est un processus qui appelle une méthode via son pointeur. C'est très pratique, lorsque Newton fait ses calculs et qu'il veut donner ses résultats, à savoir, les nouvelles positions, forces, couples, vitesses et accélération d'un corps, il est possible de les récupérer via ses méthodes callback. Les plus importantes sont:
// Association d'une "Callback" (ici:SetMeshTransformMesh) à l'objet Newton, // elle sera appellée lorsque l'objet bougera selon le moteur Newton (il y a bcp d'exemple là dessus). NewtonBodySetTransformCallback(newBody,SetMeshTransformMesh); // Association d'une "Callback" (ici:ApplyForceAndTorqueEvent) à l'objet Newton, // elle sera appellée lorsque l'objet devra subir une force (il y a bcp d'exemple là dessus). NewtonBodySetForceAndTorqueCallback(newBody,ApplyForceAndTorqueEvent);
"ApplyForceAndTorqueEvent" est la méthode qui permet d'indiquer à Newton quels forces et couples on désire appliquer à nos corps, la plupart du temps, c'est la gravité. Elle est donc appelée avant le processus de calcul de Newton.
Ensuite, "SetMeshTransformMesh" est la méthode qui permet de récupérer le pointeur du corps qui vient de bouger après le calcul de Newton.
Lorsque tu appelles les méthodes "NewtonBodySetTransformCallback" et "NewtonBodySetForceAndTorqueCallback", tu indiques en fait à Newton quelles méthodes il doit appeler pour faire ses calculs.
Je pense qu'il faut que tu jettes un oeil encore plus attentif sur les docs et exemples, ce serait un très bon investissement pour ton avenir d'utilisateur de puissantes lib...
Courage.
Hors ligne
En effet, j'ai pas été très attentif. Regarde aussi la taille de ton cube et celle du body. Il y a un rapport de 32 entre l'échelle d'irrlicht et celle de newton.
Hors ligne
Merci Gehogor, je vais essayer de voir ces differentes fonctions et je reviendrai si j'ai d'autres problèmes.
Dernière modification par Kaze (11-08-2012 19:56:51)
Hors ligne
Juste comme ça johnplayer, pourquoi y a t-il un rapport 32 entre Irrlicht et Newton ?
De mon coté j'ai en effet une échelle de 39.370078... ce qui est en faite 100/2.54, car 2.54 cm représente 1 inch. Cette échelle est dû à mes fichiers 3ds qui avaient été mal converti, raisons historiques... J'avais constaté ça avec mon module de mesure de distance.
Mais cette échelle s'annule entre Irrlicht et Newton, autrement dit, j'ai un rapport 1 entre les deux.
-> Donc je n'ai pas de rapport de 32.
Je n'ai jamais constaté de bug de rendu, peux-tu m'expliquer d'où vient ton 32 ?
Je pourrai peut-être améliorer des choses de mon coté.
Dernière modification par Gehogor (11-08-2012 22:00:06)
Hors ligne
Par exemple, pour avoir une collision correcte avec un cube:
// rapport d'échelle
#define NEWTON_TO_IRR 32.0f
#define IRR_TO_NEWTON (1.0f/NEWTON_TO_IRR)
/// cube irrlicht
ISceneNode *Node001 = smgr->addCubeSceneNode(200);
/// récupère la taille de la boundingbox du node pour la creation d'une collision de type "BOX"
vector3df size = Node001->getBoundingBox().getExtent() * IRR_TO_NEWTON; // ADAPTATION DE L'ECHELLE AVEC UN COEF
/// créé le cube qui servira pour le calcul de collision
NewtonCollision* NC_Node001 = NewtonCreateBox(World, size.X, size.Y, size.Z, -1, NULL);
En appliquant le coef les collisions sont bonnes. J'utilise ce coef aussi pour les mesh importés.
NewtonCollision* createTreeCollisionFromMesh(NewtonWorld* nWorld, IMesh* irr_mesh) { //Create new (tree optimized) collision mesh NewtonCollision* collision_obj = NewtonCreateTreeCollision(nWorld,0); //Begin collision mesh construction NewtonTreeCollisionBeginBuild(collision_obj); u32 nMeshBuffer = 0; //Mesh Buffer count u16 v_index[3] = {0,0,0}; //vertex indices IMeshBuffer *mesh_buffer = 0; float array[9]; //Array to store 3 vertices //Get (irr_)mesh buffers and copy face by face to collision mesh for( nMeshBuffer=0 ; nMeshBuffer < irr_mesh->getMeshBufferCount() ; nMeshBuffer++ ) { mesh_buffer = irr_mesh->getMeshBuffer(nMeshBuffer); //Get pointer to vertices and indices S3DVertex *vertices = (S3DVertex*)mesh_buffer->getVertices(); u16 *indices = mesh_buffer->getIndices(); //Fill collision mesh for(u32 i=0; i<mesh_buffer->getIndexCount(); i+=3) { v_index[0] = indices[ i ]; v_index[1] = indices[i+1]; v_index[2] = indices[i+2]; // 1st position vertex array[0] = vertices[ v_index[0] ].Pos.X * IRR_TO_NEWTON; array[1] = vertices[ v_index[0] ].Pos.Y * IRR_TO_NEWTON; array[2] = vertices[ v_index[0] ].Pos.Z * IRR_TO_NEWTON; // 2nd position vertex array[3] = vertices[ v_index[1] ].Pos.X * IRR_TO_NEWTON; array[4] = vertices[ v_index[1] ].Pos.Y * IRR_TO_NEWTON; array[5] = vertices[ v_index[1] ].Pos.Z * IRR_TO_NEWTON; // 3rd position vertex array[6] = vertices[ v_index[2] ].Pos.X * IRR_TO_NEWTON; array[7] = vertices[ v_index[2] ].Pos.Y * IRR_TO_NEWTON; array[8] = vertices[ v_index[2] ].Pos.Z * IRR_TO_NEWTON; //Add new face to collision mesh NewtonTreeCollisionAddFace( collision_obj, //collision mesh to add face to 3, //number of vertices in array (float*)array, //pointer to vertex array 3*sizeof(float),//size of each vertex 1); //ID of the face } } //End collision contruction , set 1 as 2dn param for optimization NewtonTreeCollisionEndBuild(collision_obj,0); return collision_obj; }
J'ai testé newton 2.35 avec irrlicht 1.8 et ça marche nickel avec ces coefs. Si je ne les appliquent pas les meshs se traversent. Et puisque les coefs résolvent le problème pour les meshs régénérés directement avec Irrlicht (addCubeSceneNode, addSphereSceneNode...), j'en ai déduit que c'est un problème d'échelle entre irrlicht et newton.
Hors ligne
Après avoir lu de nouveau les docs, je peux vous assurer ... n'avoir rien compris à cette idée de callback. Je ne comprend pas à quoi elle sert, où il faut placer cette méthode, et surtout ce qui la compose : "ApplyForceAndTorqueEvent".
Pourtant, dans mon code, je donne au cube un corps que Newton peux utiliser, ensuite je lui applique une force. Je ne vois pas quel est le but de cette méthode. Il faut l'appeler à chaque fois que l'objet se déplace, mais je ne comprend pas ce qu'elle fait de plus que "NewtonBodyAddForce(body, force); " Serait il possible que vous m'expliquiez au moins ce qu'est " ApplyForceAndTorqueEvent " ?
En fait j'ai créer, à partir d'un code trouver sur internet, les deux callbacks :
<code>
void SetMeshTransformEvent(NewtonBody* body, float* matrix)
{
// Copie de la matrice
matrix4 mat;
memcpy(mat.pointer(), matrix, sizeof(float)*16);
// Retreive the user data attached to the newton body
ISceneNode *tmp = (ISceneNode *)NewtonBodyGetUserData(body);
if (tmp)
{
tmp->setPosition(mat.getTranslation());
tmp->setRotation(mat.getRotationDegrees());
}
}
void ApplyForceAndTorqueEvent(NewtonBody* body)
{
float masse;
float inertieX;
float inertieY;
float inertieZ;
float force[3];
float torque[3];
NewtonBodyGetMassMatrix (body, &masse, &inertieX, &inertieY, &inertieZ);
force[0] = 0.0f;
force[1] = -6.81 * masse;
force[2] = 0.0f;
torque[0] = 0.0f;
torque[1] = 0.0f;
torque[2] = 0.0f;
NewtonBodyAddForce(body, force);
NewtonBodyAddTorque(body, torque);
}
</code>
Et je les appelles avec :
<code>
NewtonBodySetTransformCallback(body, SetMeshTransformEvent);
NewtonBodySetForceAndTorqueCallback(body, ApplyForceAndTorqueEvent);
</code>
Mais je ne vois pas où est transmis la matrice nécessaire à la méthode SetMeshTransformEvent. S'il est question de la matrice de body, je pourrais la récupérer avec un NewtonBodyGetMatrix ?
Merci d'avance.
Dernière modification par Kaze (12-08-2012 00:58:07)
Hors ligne
Ok, j'applique l'échelle de la même manière. Mais je ne comprends toujours pas pourquoi tu utilises "32". Es-tu sûr que, lorsque un cube est en collision avec un autre, il n'y a aucune pénétration, en regardant bien de près ? Comment as-tu déterminé 32 ?
Sur l'image suivante, je fais un essai de collision avec un cube générer par irrlicht:
Le coefficient 32 n'est pas suffisant, je suis obligé de prendre 39.37, mais ça c'est normal, c'est l'échelle globale de mon appli.
J'ai également fait un essai avec aucune échelle, tout est à 1.0. Et là, ça fonctionne sans problème.
Sans doute que quelque chose m'échappe dans ce code, il est temps que je me couche. C'est bizarre quand même...
Désolé d'insister, mais c'est comme ça qu'on fait les choses bien et qu'on évite des soucis futurs.
Dernière modification par Gehogor (12-08-2012 00:54:37)
Hors ligne
Comme je l'ai dit dans mon précédant message, j'ai récupérer les callbacks d'un autre programme pour essayer. Voici mon nouveau code :
main.hpp :
main.cpp :
Mais mon cube reste encore et toujours immobile, et je n'ai pas bien compris le fonctionnement de ces callbacks (même si ça va mieux qu'avant).
Hors ligne
Ça me semble mieux, par contre:
D'un coté tu mets à jour en position ton node dans "SetMeshTransformEvent" et de l'autre tu ré-écrases cette même position dans la méthode "drawScene()" avec une matrice identité, soit pas de translation, pas de rotation, ...
Il faut donc enlever la partie dans "drawScene()" qui ne sert à rien à part de dire à ton node: "Non, tu ne bougeras pas !".
Hors ligne
Tiens voila un main complet qui fonction avec newton 2.35 et irrlicht 1.8 :
Note : Dans le callback applyforceandtorque seul la force est appliquée donc petite modifs à faire.
Note 2 : si tu ne vois pas le cube tombé et qu'il est déjà posé sur l'autre cube, augmente la position Y de cube002.
/// IRRLICHT #include "irrlicht.h" using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; /// NEWTON #include "newton.h" #include "dMatrix.h" /// Constantes #define GRAVITY -9.8f #define NEWTON_TO_IRR 32.0f #define IRR_TO_NEWTON (1.0f/NEWTON_TO_IRR) void PhysicsApplyForceAndTorque (const NewtonBody* body, float, int) { dFloat Ixx; dFloat Iyy; dFloat Izz; dFloat mass; NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz); dVector force (0.0f, mass * GRAVITY, 0.0f); NewtonBodySetForce (body, &force.m_x); } // set the transformation of a rigid body //You have to do this so that the Newton body and irrLicht scene node are in sync, //and you actually see the changes created by the physics simulation void PhysicsSetTransform (const NewtonBody* body, const dFloat* matrix, int) { scene::ISceneNode* primitive; // get the graphic object form the rigid body //Newton can store a pointer to the scene node in the body object. primitive = (scene::ISceneNode*) NewtonBodyGetUserData (body); // set the transformation matrix for this rigid body dMatrix& mat = *((dMatrix*)matrix); //Create a matrix to store the irrLicht transformation that will correspond //to the Newton transformation matrix4 irrMatrix; //There's no easy way to get the information from one to the other, so a memory copy is required. //The matrix is a 4x4 float memcpy (irrMatrix.pointer(), &mat, 16*sizeof(float)); //In order to get the transform right, you have to apply the translation and the rotation //from the Newton body to the irrLicht scene node. vector3df position (irrMatrix.getTranslation()); position *= NEWTON_TO_IRR; vector3df rotation; NewtonGetEulerAngle(irrMatrix.pointer(), &rotation.X); rotation = rotation * RADTODEG; primitive->setPosition (position); primitive->setRotation(rotation); } /// classe pour la gestion des événements class MyEventReceiver : public IEventReceiver { public: MyEventReceiver(IrrlichtDevice*dev) { device = dev; } IrrlichtDevice* device; virtual bool OnEvent(const SEvent& event) { if (event.EventType == EET_KEY_INPUT_EVENT) { if(event.KeyInput.PressedDown) { switch(event.KeyInput.Key) { case KEY_ESCAPE: device->closeDevice(); // QUITTE L'APPLICATION return true; default: break; } } } /// aucun événement n'a été traité return false; } }; int main(int argc, char** argv) { /// Initialisation de NEWTON static NewtonWorld* World = NewtonCreate(); NewtonSetPlatformArchitecture(World, 0); float minSize[3] = {-5000.0f, -5000.0f, -5000.0f}; float maxSize[3] = {5000.0f, 5000.0f, 5000.0f}; NewtonSetWorldSize(World, &minSize[0], &maxSize[0]); NewtonSetSolverModel(World, 1); NewtonSetFrictionModel(World, 1); /// materiau par défaut NewtonMaterialSetDefaultFriction( World, 0, 0, 0.5f, 0.5f); NewtonMaterialSetDefaultElasticity( World, 0, 0, 0.0f); NewtonMaterialSetDefaultSoftness( World, 0, 0, 1.0f); //NewtonMaterialSetDefaultCollidable( World, 0, 2, 1); // autorise les collisions entre le groupID 2 et 3, le 1 veut dire true /// Intitialisation d'IRRLICHT IrrlichtDevice *device = createDevice(EDT_OPENGL, dimension2du(1280, 720), 32, false, false, false, 0); device->setWindowCaption(L"Irrlicht Engine Essais"); /// Créé et applique le gestionnaire d'événements MyEventReceiver receiver(device); device->setEventReceiver(&receiver); /// Créé les environnements IVideoDriver* driver = device->getVideoDriver(); ISceneManager* smgr = device->getSceneManager(); IGUIEnvironment* guienv = device->getGUIEnvironment(); IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices(); /// Créé la camera ICameraSceneNode *NodeCamera = smgr->addCameraSceneNodeFPS(); NodeCamera->setFarValue(1000000.0f); //NodeCamera->setPosition(vector3df(-2300,20,2300)); //NodeCamera->setTarget( vector3df(0,0,0) ); device->getCursorControl()->setVisible(false); /// Créations /// CUBE symbolisant le sol ISceneNode *Node001 = smgr->addCubeSceneNode(500); if( Node001 ) { Node001->setMaterialFlag(EMF_LIGHTING, false); Node001->setMaterialTexture(0, driver->getTexture("../MEDIAS/water.jpg")); Node001->setPosition( vector3df(0,-500,0) ); /// ajout de la physique à Node002 NewtonCollision* NC_Node001 = NULL; NewtonBody* NB_Node001 = NULL; /// récupère la taille de la boundingbox du node pour la creation d'une collision de type "BOX" vector3df size = Node001->getBoundingBox().getExtent() * IRR_TO_NEWTON; #ifdef _DEBUG printf("Node001 - size Newton : X=%f; Y=%f; Z=%f;\n", size.X, size.Y, size.Z); #endif /// créé le cube qui servira pour le calcul de collision NC_Node001 = NewtonCreateBox(World, size.X, size.Y, size.Z, -1, NULL); if(NC_Node001) { #ifdef _DEBUG printf("Newton Collision - Node001 : OK\n"); #endif /// transforme la matrice du node pour NEWTON matrix4 matrix = Node001->getRelativeTransformation(); vector3df origin = Node001->getRelativeTransformation().getTranslation() * IRR_TO_NEWTON; matrix.setTranslation(origin); /// créé le corps pour l'application d'effets sur le node irrlicht NB_Node001 = NewtonCreateBody(World, NC_Node001, matrix.pointer()); if(NB_Node001) { #ifdef _DEBUG printf("Newton Body - Node001 : OK\n"); #endif /// NewtonReleaseCollision(World, NC_Node001); /// NewtonBodySetUserData(NB_Node001, Node001); /// NewtonBodySetTransformCallback(NB_Node001, PhysicsSetTransform); NewtonBodySetForceAndTorqueCallback(NB_Node001, PhysicsApplyForceAndTorque); /// définit la masse et l'inertie de l'objet NewtonBodySetMassMatrix (NB_Node001, 0.0f, 0.0f, 0.0f, 0.0f); } #ifdef _DEBUG else printf("Newton Body - Node001 : PROBLEME\n"); #endif } #ifdef _DEBUG else printf("Newton Collision - Node001 : PROBLEME\n"); #endif #ifdef _DEBUG printf("Node001 : OK\n"); } else { printf("Node001 : PROBLEME\n"); #endif } /// CUBE tombant sur le sol ISceneNode *Node002 = smgr->addCubeSceneNode(20); if( Node002 ) { Node002->setMaterialFlag(EMF_LIGHTING, false); Node002->setMaterialTexture(0, driver->getTexture("../MEDIAS/water.jpg")); Node002->setPosition( vector3df(0,1000,0) ); /// ajout de la physique à Node002 NewtonCollision* NC_Node002 = NULL; NewtonBody* NB_Node002 = NULL; /// récupère la taille de la boundingbox du node pour la creation d'une collision de type "BOX" vector3df size = Node002->getBoundingBox().getExtent() * IRR_TO_NEWTON; #ifdef _DEBUG printf("Node002 - size Newton : X=%f; Y=%f; Z=%f;\n", size.X, size.Y, size.Z); #endif /// créé le cube qui servira pour le calcul de collision NC_Node002 = NewtonCreateBox(World, size.X, size.Y, size.Z, -1, NULL); if(NC_Node002) { #ifdef _DEBUG printf("Newton Collision - Node002 : OK\n"); #endif /// transforme la matrice du node pour NEWTON matrix4 matrix = Node002->getRelativeTransformation(); vector3df origin = Node002->getRelativeTransformation().getTranslation() * IRR_TO_NEWTON; matrix.setTranslation(origin); /// créé le corps pour l'application d'effets sur le node irrlicht NB_Node002 = NewtonCreateBody(World, NC_Node002, matrix.pointer()); if(NB_Node002) { #ifdef _DEBUG printf("Newton Body - Node002 : OK\n"); #endif /// NewtonReleaseCollision(World, NC_Node002); /// NewtonBodySetUserData(NB_Node002, Node002); /// NewtonBodySetTransformCallback(NB_Node002, PhysicsSetTransform); NewtonBodySetForceAndTorqueCallback(NB_Node002, PhysicsApplyForceAndTorque); /// définit la masse et l'inertie de l'objet NewtonBodySetMassMatrix (NB_Node002, 1.0f, 0.0f, 0.0f, 0.0f); } #ifdef _DEBUG else printf("Newton Body - Node002 : PROBLEME\n"); #endif } #ifdef _DEBUG else printf("Newton Collision - Node002 : PROBLEME\n"); #endif #ifdef _DEBUG printf("Node002 : OK\n"); } else { printf("Node002 : PROBLEME\n"); #endif } /// Boucle de rendu int lastFPS = -1; u32 lastTime = 0; f32 timestepS = 0.017f; u32 timestepMS = timestepS * 500; #ifdef _DEBUG printf("On entre dans la boucle de rendu.\n"); #endif while(device->run()) { /// update la physique u32 courantTime = device->getTimer()->getTime(); if( courantTime > (lastTime + timestepMS) ) { NewtonUpdate(World, timestepS ); lastTime = courantTime; } /// dessine la frame driver->beginScene(true, true, SColor(0,200,200,200)); smgr->drawAll(); guienv->drawAll(); driver->endScene(); /// affiche le nombre de fps dans la barre de titre int fps_int = driver->getFPS(); if (lastFPS != fps_int) { stringw str = L"Irrlicht Engine Essais ["; str += driver->getName(); str += "] FPS:"; str += fps_int; str += " | Triangles :"; str += driver->getPrimitiveCountDrawn(); device->setWindowCaption(str.c_str()); lastFPS = fps_int; } } /// libération de Newton NewtonDestroyAllBodies(World); NewtonDestroy (World); /// libération d'Irrlicht device->drop(); /// sortie du programme return 0; }
Hors ligne
Merci à vous deux, je vais essayer de corriger mon code et j'étudierai celui qu'à envoyé Johnplayer. Je reviendrai peut-être si j'ai de nouveau problèmes.
J'ai supprimé la partie de ma méthode drawScene et ... ça marche impec !!!!
Encore merci.
Dernière modification par Kaze (12-08-2012 18:26:49)
Hors ligne
J'ai un autre petit problème qui doit être tout bête. J'avais en fait installé la version 1.53 de newton et tout fonctionne. J'ai voulu installer la version 2.35 pour tester le code de johnplayer mais le compilo me dit qu'à travers dMatrix.h, le fichier dVector.h est introuvable alors qu'il se trouve dans le même dossier :
/Dev-Cpp/include/newt/dMath/dMatrix.h D:\Projet\\Irrlicht\tuto\18-eighteenth- Physique 3\test collision\C dVector.h: No such file or directory.
J'ai bien tout linké comme il faut et mis les bons .dll mais je ne comprend pas pourquoi il ne trouve pas le fichier. En plus dans mon dossier test collision, je n'ai rien qui a pour nom "C" ?
Pourriez vous m'aider de nouveau ?
Hors ligne
Si tu as C::B, dans les options de projets>>Sherach directory>>Compiler, tu dois mettre un path du genre "Newton 2.35\packages" et "Newton 2.35\packages\dMath". dVector.h se trouve dans dMath je crois.
Hors ligne
OK. J'en profite pour poser une autre chose : J'ai un peu modifié mon code pour avoir trois cubes, un avec une masse nulle, un avec une masse = 100.0 et un autre avec une masse = 200.0. Comme on peux si attendre, le cube à masse nul reste immobile, pourtant les deux autres cubes tombent à la même vitesse alors que j'ai paramétrer la gravité pour qu'elle dépende du poids. Je vous donne donc mon code :
main.hpp
main.cpp
Je ne comprend pas pourquoi ça ne fonctionne pas. Pourriez vous m'aider pendant que je cherche de mon coté.
Dernière modification par Kaze (13-08-2012 01:15:12)
Hors ligne
Très cher Kaze, cette constatation fait partie des lois physiques que notre monde subi, en effet, la chute d'un corps ou plutôt son accélération de chute ne dépend pas de la masse mais que de l'accélération de pesanteur (enfin, à preuve du contraire, on ne sait jamais on pourrait faire de nouvelles découvertes).
Une plume chutera aussi vite qu'une voiture dans le vide, en respectant le fait qu'il n'y ait aucun frottement (l'air par exemple).
Hors ligne
Je suis au courant mais pourtant, lorsque l'on crée un monde on lui applique un certain coefficient de friction qui est égal à 0.9 par défaut. Donc on crée un monde où il y a des frottements et par définition, les objets devraient tomber à deux vitesses différentes. C'est pour ça que je ne comprend pas.
Hors ligne
Dans la fonction"ApplyForceAndTorqueEvent"
remplace : NewtonBodyAddForce(body, force); NewtonBodyAddTorque(body, torque); par : NewtonBodySetForce(body, force); NewtonBodySetTorque(body, torque);
Parce que c'est vrai que 2 objets de masses différentes soumis à la même force de gravité tombe à la même vitesse. Mais là, en occurrence, les objets ont une gravité différente puisque dans "ApplyForceAndTorqueEvent", il multiplie la gravité par la masse. Par contre, le fait que tu ajoutes la force peut poser problème. Donc un "set" au lieu de "add" résoudrai peut-être le problème...
Hors ligne