#0 

09-05-2015 02:31:49

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

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 :

http://img11.hostingpics.net/thumbs/mini_772819prob.jpg

Je n'ai pas trouvé comment inversé , voici mon code :

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


#1 

09-05-2015 19:28:21

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 897
Site web

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

Code c++ :



            if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
            {
        //first triangle
        getVertex(x,j,vertices[0]);
        getVertex(x+1,j,vertices[1]);
        getVertex(x+1,j+1,vertices[2]);
        callback->processTriangle(vertices,x,j);
        //second triangle
        getVertex(x,j,vertices[0]);
        getVertex(x+1,j+1,vertices[1]);
        getVertex(x,j+1,vertices[2]);
        callback->processTriangle(vertices,x,j);               
            } else
            {
        //first triangle
        getVertex(x,j,vertices[0]);
        getVertex(x,j+1,vertices[1]);
        getVertex(x+1,j,vertices[2]);
        callback->processTriangle(vertices,x,j);
        //second triangle
        getVertex(x+1,j,vertices[0]);
        getVertex(x,j+1,vertices[1]);
        getVertex(x+1,j+1,vertices[2]);
        callback->processTriangle(vertices,x,j);
            }



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 wink

Hors ligne


#2 

09-05-2015 23:40:43

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

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 :

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


#3 

10-05-2015 12:24:46

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 897
Site web

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 wink

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 smile

Hors ligne


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
Analysé par
872 membres
1421 sujets
11099 messages
Dernier membre inscrit: Glider
3 invités en ligne
Aucun membre connecté
RSS Feed