Voila, vu que je ne peut pas utiliser d'animation pour mes objets destructibles, j'ai commencé à apprendre comment utiliser Newton. J'utilise donc Newton 2.35 et Irrlicht 1.8 et j'ai passé la matinée à faire tourner Newton avec Irrlicht. J'ai obtenu un cube qui tombe sur un autre cube, ce dernier étant le sol.
C'est un début, maintenant, il me faudrait pouvoir faire la collision avec des trimeshs et là, c'est le drame! La documentation est presque inexistante.
Par contre, j'ai vu ça http://newtondynamics.com/wiki/index.ph … llFromMesh mais pour créer un NewtonMesh, aucune idée!
Enfin, pour mon problème, j'ai l'impression que je devrais utiliser les joints.
Je pense qu'on peut accrocher des meshs entre eux et briser les joints avec une certaines force exercé sur ces derniers.
J'ai vu cette vidéo : http://www.youtube.com/watch?v=T5xr1PdnDM4
Pour résumer :
1 / Comment fait-on pour créer un NewtonBody à partir d'un mesh d'Irrlicht?
2 / Comment se servir des joints? Parce que je pourrais tester comme dans la vidéo avec des cubes.
Edit : J'ai peut-être quelques pistes, les objets composés :
1 / http://newtondynamics.com/wiki/index.ph … dCollision
2 / Dans Newton.h : typedef int (*NewtonCollisionCompoundBreakableCallback) (NewtonMesh* const mesh, void* const userData, dFloat* const planeMatrixOut);
NEWTON_API NewtonCollision* NewtonCreateCompoundBreakable (const NewtonWorld* const newtonWorld, int meshCount,
const NewtonMesh** const solids, const int* const shapeIDArray,
const dFloat* const densities, const int* const internalFaceMaterial,
int shapeID, int debriID, dFloat debriSeparationGap);
et d'autres fonction qui vont avec mais pas de doc dessus certainement une fonctionnalité récemment ajouté.
3 / dgCollisionCompoundBreakable.h
Dernière modification par johnplayer (11-06-2012 22:06:07)
Hors ligne
Salut,
même si je n'ai pas trop de temps à moi cette semaine, je vais essayer de te fournir un petit truc qui t e permettra d'avancer et d'y voir j'espère plus clair.
C'est le code complet de N3xtD, le moteur basé sur Irrlicht et qui était destiné aux langages Basics.
voici le lien: http://www.packupload.com/ED0IS96KRQM
Pour le coté physique, tu as pour les bases tout ce qu'il te faut (c'est le fichiers préfixé n3xtd_Phys...). Dans le répertore 'source' en particulier, regardes les fichiers n3xtd_PhysRigidBody.cpp et
n3xtd_PhysBodyUtils.cpp tu y trouvera toutes les fonction de créations des shapes (y compris les mesh shape concave et convex).
Je sais que balancer du code comme cela, surtout que c'est brute de fonderie, c'est pas forcement rendre service.
Mais ceci dit, en rentrant un peu dedans, tu devrais y trouver tout ce qu'il te faut, y compris aussi quelques bricoles pas forcement lié uniquement à la physique.
Les fonctions sont simples et intuitive, c'était pour du Basic, donc pas trop dur à appréhender.
Si tu bloque sur certaines fonctions, n'hésites pas, j'ai dans un coin de ma petit mémoire une grande partie du code encore, et je devrait arriver à expliquer mes approche sans trop de problème.
bon code et j'espère que cela t'aideras
Hors ligne
Salut, je ne sais pas si ça peut t'aider, moi j'utilise le code suivant dans VEM pour utiliser Newton et Irrlicht, ça fonctionne très bien. Regarde les paramètres des fonctions, c'est assez clair.
La méthode de Newton ne créé pas de forme concave, seulement convexe, il faut donc associer plusieurs formes convexes pour obtenir une concave, je fais ce traitement également et c'est plutôt cool.
NewtonCollision* GrNewton::createCollisionFromMesh(NewtonWorld *nWorld, irr::scene::IMesh* irr_mesh, float tolerance, float scaleX, float scaleY, float scaleZ, int shapeID, const float* offsetMatrix) { int nMeshBuffer = 0; //Mesh Buffer count irr::scene::IMeshBuffer *mesh_buffer = 0; float *vertices; //Array to store vertices irr::u32 nVertices = 0; //Get number of vertices for( nMeshBuffer=0 ; nMeshBuffer < irr_mesh->getMeshBufferCount() ; nMeshBuffer++ ) { nVertices += irr_mesh->getMeshBuffer(nMeshBuffer)->getVertexCount(); } //create buffer for vertices vertices = new float[nVertices * 3]; irr::u32 tmpCounter = 0; //Get (irr_)mesh buffers and copy face vertices for( nMeshBuffer=0 ; nMeshBuffer < irr_mesh->getMeshBufferCount() ; nMeshBuffer++ ) { mesh_buffer = irr_mesh->getMeshBuffer(nMeshBuffer); //Get pointer to vertices and indices irr::video::S3DVertex *S3vertices = (irr::video::S3DVertex*)mesh_buffer->getVertices(); //copy vertices from mesh to buffer for(int i=0; i<mesh_buffer->getVertexCount(); i++) { vertices[tmpCounter++] = S3vertices[i].Pos.X * scaleX / GrConstants::IRR_SCALE; vertices[tmpCounter++] = S3vertices[i].Pos.Y * scaleZ / GrConstants::IRR_SCALE; vertices[tmpCounter++] = S3vertices[i].Pos.Z * scaleY / GrConstants::IRR_SCALE; } } //Create Newton collision object NewtonCollision *collision_obj = NewtonCreateConvexHull(nWorld,nVertices,vertices,sizeof(float)*3,tolerance,shapeID,offsetMatrix); //delete vertices delete [] vertices; return collision_obj; } NewtonCollision* GrNewton::createTreeCollisionFromMesh(NewtonWorld* nWorld, irr::scene::IMesh* irr_mesh, float scaleX, float scaleY, float scaleZ) { //Create new (tree optimized) collision mesh NewtonCollision* collision_obj = NewtonCreateTreeCollision(nWorld,0); //Begin collision mesh construction NewtonTreeCollisionBeginBuild(collision_obj); int nMeshBuffer = 0; //Mesh Buffer count int v_index[3] = {0,0,0}; //vertex indices irr::scene::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 irr::video::S3DVertex *vertices = (irr::video::S3DVertex*)mesh_buffer->getVertices(); irr::u16 *indices = mesh_buffer->getIndices(); //Fill collision mesh for(int 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 * scaleX / GrConstants::IRR_SCALE; array[1] = vertices[ v_index[0] ].Pos.Y * scaleZ / GrConstants::IRR_SCALE; array[2] = vertices[ v_index[0] ].Pos.Z * scaleY / GrConstants::IRR_SCALE; // 2nd position vertex array[3] = vertices[ v_index[1] ].Pos.X * scaleX / GrConstants::IRR_SCALE; array[4] = vertices[ v_index[1] ].Pos.Y * scaleZ / GrConstants::IRR_SCALE; array[5] = vertices[ v_index[1] ].Pos.Z * scaleY / GrConstants::IRR_SCALE; // 3rd position vertex array[6] = vertices[ v_index[2] ].Pos.X * scaleX / GrConstants::IRR_SCALE; array[7] = vertices[ v_index[2] ].Pos.Y * scaleZ / GrConstants::IRR_SCALE; array[8] = vertices[ v_index[2] ].Pos.Z * scaleY / GrConstants::IRR_SCALE; //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; }
Hors ligne
Merci pour les réponse. Alors, Tmyke merci pour les sources.
En fait, entre temps j'ai commencé ça mais ça me déforme les meshs mais sinon tant que c'est un cube ou un cube avec un chanfrein ça marche nickel. J'ai dû faire une erreur mais je ne vois pas.
NewtonCollision* CreateNewtonConvexHull(const NewtonWorld* const World, IMesh *IrrMesh, float tolerance=0.002f) { /// Variables int count = 0; array<dFloat> vertexCloud; int strideInBytes = sizeof(float)*3; int shapeID = -1; dFloat *offsetMatrix = NULL; /// pour chaque meshbuffer for(u32 a=0; a < IrrMesh->getMeshBufferCount(); ++a) { /// récupère le buffer IMeshBuffer *buffer = IrrMesh->getMeshBuffer(a); /// récpère le nombre de vertices et d'indices int nb_vertices = buffer->getVertexCount(); int nb_indices = buffer->getIndexCount(); /// récupère le tableau de vertices et d'indices du buffer array<S3DVertex> tmp; tmp.set_pointer( (S3DVertex*)buffer->getVertices(), nb_vertices ); array<u16> tmp2; tmp2.set_pointer( buffer->getIndices(), nb_indices ); /// création de la liste de vertices for(int a=0; a < nb_indices; ++a) { /// on converti le vertex Irrlicht en vertex Newton avec le scale vertexCloud.push_back( tmp[tmp2[a]].Pos.X * IRR_TO_NEWTON ); vertexCloud.push_back( tmp[tmp2[a]].Pos.Y * IRR_TO_NEWTON ); vertexCloud.push_back( tmp[tmp2[a]].Pos.Z * IRR_TO_NEWTON ); /// on met à jour le nombres de vertices ++count; } } /// création du NewtonMesh NewtonCollision *maNewtonCollision = NewtonCreateConvexHull(World, count, vertexCloud.pointer(),strideInBytes, tolerance, shapeID, offsetMatrix); /// on retourne le mesh return maNewtonCollision; }
Par contre Gehogor, il y a un truc qui me chiffonne. Moi, la liste de vertices je la créé en prenant les indices et rajoutant un vertex pour chaque indice. Mais toi, tu lui envoie juste la liste de vertex. Comment Newton fait pour trouver les triangles?
Hors ligne
En effet, je lui envoie juste la liste mais une liste ordonnée, il doit sons doute recréer son maillage sachant que se sont des trios de donnée et en plus il connait la taille d'un des composants grâce à "sizeof(float)*3".
Sache aussi que je n'ai pas observé de bug de maillage, j'ai testé pas mal de formes différentes comme des barrières, des carcasses de robot, des tables, des personnages... et le comportement physique était au rendez-vous.
Hors ligne
J'ai essayé ta fonction "NewtonCollision* GrNewton::createTreeCollisionFromMesh(...)" mais ça n'a strictement aucun effet chez moi. Il renvoie une NewtonCollision valide mais le mesh reste à la position où je le place avec Irrlicht. Je juste remanié le code pour qu'il coïncide avec mes variables.
Voilà le code remanié
#define GRAVITY -9.8f #define NEWTON_TO_IRR 32.0f #define IRR_TO_NEWTON (1.0f/NEWTON_TO_IRR) 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; }
Dans mon main, j'ai :
//NC_NodeCaisse001 = NewtonCreateBox(World, size.X, size.Y, size.Z, -1, NULL); //NC_NodeCaisse001 = CreateNewtonConvexHull(World, Caisse001); NC_NodeCaisse001 = createTreeCollisionFromMesh(World, Caisse001); if(NC_NodeCaisse001){ ...
Si j'utilise une des 2 premières fonctions en commentaire je n'ai pas de problème. Bref, je ne comprends pas ce qu'il se passe.
Edit : La fonction "createTreeCollisionFromMesh" marche avec un plan mais pas avec un cube chanfreiné.
Edit 2 : Enfait, il y a les collisions mais pas de physique. Il n'est pas soumis à la gravité, pourtant j'ai un body valide.
Dernière modification par johnplayer (14-06-2012 16:09:39)
Hors ligne
Attention, je crois que tu n'a pas encore totalement appréhendé le mécanisme de Newton (commun à la plupart des Moteur Physique).
Quand tu créé un NewtonCollision*, en fait ce n'est pas vraiment lié à la physique dynamique, en fait à ce moment là tu ne fait que créer un shape au sein de Newton .
Si tu veux l'employer au sein d'une simulation dynamique, il faut une seconde étape qui est celle qui consiste à créer un body. Celui-ci aura comme info une forme géométrique
(donc dans ce cas le shape définit et taggué par la pointeur NewtonCollision), une masse voir aussi par exemple une position initiale.
Tu passes alors par la fonction NewtonCreateBody, qui prend comme paramètre le world Newton initialisé, ta géométrie (un pointeur donc NewtonCollision), ainsi
qu'une attitude dans l'environement (une matrice).
Ton body est alors définis et sera pris en compte dans la simulation.
Hors ligne
Ouaip tout à fait mon très cher Tmyke, et ensuite il faut ré-implémenter des méthodes callback de Newton pour que les body, qui doivent être lié à des NewtonCollision, puissent subir les effets de la physique.
La méthode ci-dessous est appelée par Newton, la position récupérée te permettra de mettre à jour la position de tes 3D:
void GrNewton::SetMeshTransformMesh(const NewtonBody* body,const float* matrix,int threadIndex) { // body Le pointeur du body pour connaitre l'objet qui doit être déplacé. // matrix La nouvelle position calculée pour l=ce même body. }
Et Enfin la méthode suivante est applée par Newton avant le process de calcul, on y créé des forces et couples qui agiront sur un body:
void GrNewton::ApplyForceAndTorqueEvent(const NewtonBody* body,dFloat timestep,int threadIndex) { float mass,Ixx,Iyy,Izz,force[3],torque[3]; NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz); force[0] = 0.0f; force[2] = 0.0f; force[1] = GrConstants::GRAVITY * mass; torque[0] = 0.0f; torque[2] = 0.0f; torque[1] = 0.0f; NewtonBodyAddForce(body, force); NewtonBodyAddTorque(body, torque); }
Les z et y sont inversés tout comme Irrlicht pour les mêmes raisons historiques des premiers jeux vidéo 2D plan XY.
Dernière modification par Gehogor (14-06-2012 19:25:12)
Hors ligne
Je sais, c'est juste que je n'ai pas mis tout le code mais quand je créé un newtoncollision avec le NewtonTreeCollision que ça ne marche plus. Tiens je passe le code de création de l'objet avec son insertion dans Newton :
IMesh *Caisse001 = smgr->getMesh("../MEDIAS/caisse/morceau_principal.3ds"); ImeshSceneNode *NodeCaisse001 = smgr->addMeshSceneNode(Caisse001); if( NodeCaisse001 ) { NodeCaisse001->setMaterialFlag(EMF_LIGHTING, false); NodeCaisse001->setMaterialTexture(0, driver->getTexture("../MEDIAS/stones.jpg")); NodeCaisse001->setPosition( vector3df(0,0,0) ); /// ajout de la physique à NodeCaisse001 NewtonCollision* NC_NodeCaisse001 = NULL; NewtonBody* NB_NodeCaisse001 = NULL; /// récupère la taille de la boundingbox du node pour la creation d'une collision de type "BOX" vector3df size = NodeCaisse001->getBoundingBox().getExtent() * IRR_TO_NEWTON; #ifdef _DEBUG printf("NodeCaisse001 - size Newton : X=%f; Y=%f; Z=%f;\n", size.X, size.Y, size.Z); #endif /// créé la collision //------------------------------------- METHODE 1 : OK ------------------------------------// //NC_NodeCaisse001 = NewtonCreateBox(World, size.X, size.Y, size.Z, -1, NULL); //------------------------------------- METHODE 2 : OK tant que le mesh est convexe ------------------------------------// NC_NodeCaisse001 = CreateNewtonConvexHull(World, Caisse001); //------------------------------------- METHODE 3 : collision OK mais le body ne joue plus son rôle, pas de gravité, le mesh reste là où je l'ai mis avec Irrlicht ------------------------------------// //NC_NodeCaisse001 = createTreeCollisionFromMesh(World, Caisse001); if(NC_NodeCaisse001) { #ifdef _DEBUG printf("Newton Collision - NodeCaisse001 : OK\n"); #endif /// transforme la matrice du node pour NEWTON matrix4 matrix = NodeCaisse001->getRelativeTransformation(); vector3df origin = NodeCaisse001->getRelativeTransformation().getTranslation() * IRR_TO_NEWTON; matrix.setTranslation(origin); /// créé le corps pour l'application d'effets sur le node irrlicht NB_NodeCaisse001 = NewtonCreateBody(World, NC_NodeCaisse001, matrix.pointer()); if(NB_NodeCaisse001) { #ifdef _DEBUG printf("Newton Body - NodeCaisse001 : OK\n"); #endif /// NewtonReleaseCollision(World, NC_NodeCaisse001); /// NewtonBodySetUserData(NB_NodeCaisse001, NodeCaisse001); /// NewtonBodySetTransformCallback(NB_NodeCaisse001, PhysicsSetTransform); NewtonBodySetForceAndTorqueCallback(NB_NodeCaisse001, PhysicsApplyForceAndTorque); /// définit la masse et l'inertie de l'objet NewtonBodySetMassMatrix (NB_NodeCaisse001, 100.0f, 0.0f, 0.0f, 0.0f); } #ifdef _DEBUG else printf("Newton Body - NodeCaisse001 : PROBLEME\n"); #endif } #ifdef _DEBUG else printf("Newton Collision - NodeCaisse001 : PROBLEME\n"); #endif #ifdef _DEBUG printf("NodeCaisse001 : OK\n"); } else { printf("NodeCaisse001 : PROBLEME\n"); #endif }
En fait, si j'utilise les 2 premières méthodes ça marche, mes objets tombent se heurtent, c'est joli. Mais avec l'arbre de collision, l'objet qui l'utilise se fait heurter par les autres donc il y a collision, mais lui ne bouge pas alors que la création du body reste la même. Au final, je ne change que la création de ma collision.
Hors ligne
Ok, ok, j'avoue j'ai regardé de plus près mon code et j'ai remarqué que je n’utilisais pas "createTreeCollisionFromMesh". Mais pourquoi ??
J'ai repris la doc de Newton sur la méthode "NewtonCreateTreeCollision" et j'ai lu une remarque intéressante:
http://newtondynamics.com/wiki/index.ph … eCollision
Je ne suis pas un fou en anglais mais j'ai l'impression qu'il est indiqué que lorsqu'on attache une treeCollision à un body, l'effet de la massa s'annule automatiquement, le dit corps devient statique, peut être comme un terrain.
Qu'en penses-tu ? Comme ça fait longtemps que je n'avais pas repris cette partie de code, j'avais sans doute eu la même conclusion. Ca explique sans doute ton bug qui n'en ai peut être pas un, juste le comportement normal......
Dernière modification par Gehogor (15-06-2012 00:01:09)
Hors ligne
Exact, la masse n'est pas pris en compte. Mais je vais utiliser "NewtonCreateTreeCollision" pour mon terrain et mes objets statiques. Dans un sens, c'est normal car il doit être utilisé pour les meshs non fermés comme un plan par exemple. Et puis ce serait sacrément complexe à gérer comme collision^^. Pour ce qui est des "CollisionCompoundBreakable", je vais peut-être pouvoir m'en passer. En fait, je ferai exploser mes caisses grâce à une animation skelettale puis, à la fin de l'animation, je supprimerai le node. Comme ça je supprimerai des polygones pour en remettre d'autres, c'est-à-dire ce que libère la caisse (munitions ou autres).
J'aurai certainement d'autres questions plus tard mais il faut d'abord que je fasse une camera à la troisième personne et un terrain de test (pente graduelle, escalier...).
Hors ligne
Options | Liens officiels | Caractéristiques | Statistiques | Communauté |
---|---|---|---|---|
Corrections |
|
xhtml 1.0 css 2.1 Propulsé par FluxBB Traduit par FluxBB.fr |
882 membres 1429 sujets 11119 messages |
Dernier membre inscrit: LiseBuisson96 95 invités en ligne Aucun membre connecté RSS Feed |