Pages: 1
Bonjour,
J'ai récemment rencontré ce problème. Quand j'ajoute ma heightmap, le relief part vers le haut et les faces de collision sont en dessous. Pas très clair alors voici une image :
Je n'ai pas trouvé comment inversé , voici mon code :
/// Ajout du terrain à la scene. ITexture *texture=driver->getTexture("media/terrain.png"); ITerrainSceneNode *terrain=smgr->addTerrainSceneNode(texture->getName(), 0 , -1, vector3df(0.0f, 0.0f, 0.0f), vector3df(0.0f, 0.0f, 0.0f), vector3df(1.0f, 1.0f, 1.0f)); terrain->setMaterialFlag(EMF_LIGHTING, false); terrain->setMaterialTexture(0, driver->getTexture("media/terrain.png")); terrain->setPosition(vector3df(0.0f, 0.0f, 0.0f)); terrain->setScale(vector3df(4.0f, 1.0f, 4.0f)); /// btHeightfieldTerrainShape. vector3df scale=terrain->getScale(); aabbox3d<f32> box=terrain->getBoundingBox(); const vector3df size=box.getExtent()/scale; f32 minHeight=((ITerrainSceneNode*)terrain)->getHeight(0, 0); f32 maxHeight=minHeight; int arraySize=texture->getSize().Height; ///f32 heightData[512*arraySize]; f32 heightData[512*arraySize]; const f32 stepWidthX=size.X/arraySize; const f32 stepWidthZ=size.Z/arraySize; u32 runVal=0; vector3df minEdge=box.MinEdge/scale; vector3df maxEdge=box.MaxEdge/scale; //Récupération du min et du max de la hauteur du terrain for(f32 z=minEdge.Z; z<maxEdge.Z; z+=stepWidthZ) { for(f32 x=minEdge.X; x<maxEdge.X; x+=stepWidthX) { const f32 curVal=((ITerrainSceneNode*)terrain)->getHeight(x, z); heightData[runVal++]=curVal; if(curVal>maxHeight){maxHeight=curVal;} if(curVal<minHeight){minHeight=curVal;} } } f32 *heightDataPtr=heightData; // Collision Objects. btCollisionShape *groundShape=new btHeightfieldTerrainShape(arraySize, arraySize, heightDataPtr, 1.f, minHeight, maxHeight, 1, PHY_FLOAT, false); //btCollisionShape * groundShape = new btHeightfieldTerrainShape(512, 512, heightDataPtr, 1.f, minHeight, maxHeight, 1, PHY_FLOAT, true); groundShape->setLocalScaling(btVector3(4.0f, 1.0f, 4.0f)); //btCollisionShape *sphereShape= new btSphereShape(10); // Ground Motion State. btTransform transform; transform.setIdentity(); transform.setOrigin(btVector3(0.0f, 0.0f, 0.0f)); btDefaultMotionState *groundMotionState=new btDefaultMotionState(transform); // Ground Rigid Body. btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0, groundMotionState, groundShape, btVector3(0, 0, 0)); btRigidBody *groundRigidBody=new btRigidBody(groundRigidBodyCI); groundRigidBody->setUserPointer((void *)terrain); // Adding ground rigid body to the world. World->addRigidBody(groundRigidBody);
Si vous avez une idée ... Merci pour vos réponses.
Hors ligne
uhm je suppose que tu passe souvent a travert ?
le dernier parametre de btHeightfieldTerrainShape est normalement utiliser pour ça il me semble(bool flipQuadEdges)
setUseDiamondSubdivision permet également d'interragir avec la direction des faces
perso je n'est pas de soucis, si ça ne résoue pas ton probleme il y a moyen de le contourné avec un custom material
Hors ligne
oui je passe à travers, et si je fais une rotation de 180 degrès du terrain je ne passe plus à travers mais les forcément les normales ne correspondent plas à la map. Après je peut faire ma heightmap en inversée aussi mais çà me paraît hyper tordu comme idée lol.
Tas solution est la bonne, je viens de vérifier sur le net et je ne suis pas le seul dans ce cas, les normales sont inversées. J'ai trouvé un code qui devrait aussi jouer le même rôle que le tien mais je n'ai pas envie de copier/coller car de toutes façon je ne sais pas comment l'utiliser. Voici le code :
static bool myCustomMaterialCombinerCallback( btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1 ) { // one-sided triangles if (colObj1Wrap->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE) { auto triShape = static_cast<const btTriangleShape*>( colObj1Wrap->getCollisionShape() ); const btVector3* v = triShape->m_vertices1; btVector3 faceNormalLs = btCross(v[1] - v[0], v[2] - v[0]); faceNormalLs.normalize(); btVector3 faceNormalWs = colObj1Wrap->getWorldTransform().getBasis() * faceNormalLs; float nDotF = btDot( faceNormalWs, cp.m_normalWorldOnB ); if ( nDotF <= 0.0f ) { // flip the contact normal to be aligned with the face normal cp.m_normalWorldOnB += -2.0f * nDotF * faceNormalWs; } } //this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction return false; } void BulletPhysics::init() { // somewhere in your init code you need to setup the callback gContactAddedCallback = myCustomMaterialCombinerCallback; }
Et le poste concerné :
http://bulletphysics.org/Bullet/phpBB3/ … p?t=10224/
çà me géne de te demander çà, car tu ma déja bien aidé jusqu'ici, mais où je dois modifier mon code pour fliper les normal ?
Hors ligne
mon code n'était autre que le code de bullet pour te montré comment interagissais le paramètre flipNormal du constructeur aussi que
setUseDiamondSubdivision de btHeightfieldTerrainShape
commence par tester ces deux paramètre peut-être ?
pour les matériaux personnaliser, a vrai dire je n'est jamais regarder ^^", d’après l'exemple MultiMaterialDemo de bullet
extern ContactAddedCallback gContactAddedCallback;
donc tu doit pouvoir effectivement l'utilise tel qu’elle ... et ne pas oublier
terrain->setCollisionFlags(terrain->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
réponse rapide j'ai du travaille
Hors ligne
Pages: 1