2012-06-23 18 views
6

Mi sto un po 'confuso sul motivo per cui la mesh creata manualmente non viene visualizzata correttamente. Ho creato i vertici e i buffer degli indici e sembrano (anche se non sono sicuro al 100%) di contenere i valori corretti.Creazione di mesh manuale in Ogre3d?

In sostanza sto creando una griglia di mapSize * mapSize vetrices, ad un'altezza di 0, quindi creando i triangoli da essi.

void TerrainGeneration::createTerrainMesh() { 
    /// Create the mesh via the MeshManager 
     Ogre::MeshPtr msh = Ogre::MeshManager::getSingleton().createManual("TerrainTest", "General"); 
    Ogre::SubMesh* sub = msh->createSubMesh(); 

    const size_t nVertices = mapSize*mapSize; 
    const size_t vbufCount = 3*2*nVertices; 

    float vertices[vbufCount]; 

    size_t vBufCounter = 0; 
    for(int z = 0; z < mapSize; z++) { 
      for(int x = 0; x < mapSize; x++) { 
      //Position 
     vertices[vBufCounter] = x; 
     vertices[vBufCounter+1] = 0; 
     vertices[vBufCounter+2] = z; 
     //Normal 
     vertices[vBufCounter+3] = 0; 
     vertices[vBufCounter+4] = 1; 
     vertices[vBufCounter+5] = 0; 

     vBufCounter += 6; 
     } 
    } 

    Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem(); 
     Ogre::RGBA colours[nVertices]; 
     Ogre::RGBA *pColour = colours; 

    //Create triangles 
    const size_t ibufCount = 6*(mapSize - 1)*(mapSize - 1); 
    unsigned int faces[ibufCount]; 

    size_t iBufCounter = 0; 
    for(int x=0; x <= mapSize -2; x++) { 
    for(int y=0; y <= mapSize -2; y++) { 
     faces[iBufCounter] = vertices[(y*mapSize) + x]; 
     faces[iBufCounter+1] = vertices[((y+1)*mapSize) + x]; 
     faces[iBufCounter+2] = vertices[((y+1)*mapSize) + (x+1)]; 

     faces[iBufCounter+3] = vertices[(y*mapSize) + x]; 
     faces[iBufCounter+4] = vertices[((y+1)*mapSize) + (x+1)]; 
     faces[iBufCounter+5] = vertices[(y*mapSize) + (x+1)]; 

     iBufCounter += 6; 
    } 
} 









/// Create vertex data structure for n*n vertices shared between submeshes 
    msh->sharedVertexData = new Ogre::VertexData(); 
    msh->sharedVertexData->vertexCount = nVertices; 

/// Create declaration (memory format) of vertex data 
    Ogre::VertexDeclaration* decl = msh->sharedVertexData->vertexDeclaration; 
    size_t offset = 0; 
    // 1st buffer 
    decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); 
    offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); 
    decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); 
    offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); 
    /// Allocate vertex buffer of the requested number of vertices (vertexCount) 
    /// and bytes per vertex (offset) 
    Ogre::HardwareVertexBufferSharedPtr vbuf = 
    Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(
    offset, msh->sharedVertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); 
    /// Upload the vertex data to the card 
    vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); 

    /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer 
    Ogre::VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding; 
    bind->setBinding(0, vbuf); 

    /// Allocate index buffer of the requested number of vertices (ibufCount) 
    Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton(). 
    createIndexBuffer(
    Ogre::HardwareIndexBuffer::IT_16BIT, 
    ibufCount, 
    Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); 

    /// Upload the index data to the card 
    ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true); 

    /// Set parameters of the submesh 
    sub->useSharedVertices = true; 
    sub->indexData->indexBuffer = ibuf; 
    sub->indexData->indexCount = ibufCount; 
    sub->indexData->indexStart = 0; 

    /// Set bounding information (for culling) 
    msh->_setBounds(Ogre::AxisAlignedBox(-5000,-5000,-5000,5000,5000,5000)); 
    //msh->_setBoundingSphereRadius(Ogre::Math::Sqrt(3*100*100)); 

    /// Notify -Mesh object that it has been loaded 
    msh->load(); 

} 

I inizializzare la maglia e caricarlo come segue

Ogre::Entity* thisEntity = mSceneMgr->createEntity("cc", "TerrainTest", "General"); 
thisEntity->setMaterialName("Examples/Rockwall"); 
Ogre::SceneNode* thisSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); 
thisSceneNode->setPosition(0, 0, 0); 
thisSceneNode->attachObject(thisEntity); 

Qualsiasi visione sarebbe molto apprezzato.

+0

Non posso parlare direttamente alla tua domanda, ma ecco un pensiero: La vostra maglia ottenere tutto il triangolo orientamenti corretti? Inserisci il triangolo ABC in cui era necessario il triangolo BAC e puoi confondere molti motori mesh. – Managu

+0

Sì, credo che i miei triangoli siano corretti, Ogre richiede la selezione antioraria dei vertici per un viso. Ho provato anche in senso orario, solo incase. Il problema sembra essere che i vertici non sono distribuiti come mi aspetterei ma non sono davvero sicuro del perché. –

risposta

5

Ok, quindi ho ricevuto una risposta dai forum Ogre3d da una persona molto utile chiamata bstone.

Si scopre che durante la creazione del mio elenco di indici per creare le facce stavo erroneamente passando le coordinate dalla lista dei vertici piuttosto che gli indici dei vertici.

faces[iBufCounter] = vertices[(y*mapSize) + x]; 
faces[iBufCounter+1] = vertices[((y+1)*mapSize) + x]; 
faces[iBufCounter+2] = vertices[((y+1)*mapSize) + (x+1)]; 

faces[iBufCounter+3] = vertices[(y*mapSize) + x]; 
faces[iBufCounter+4] = vertices[((y+1)*mapSize) + (x+1)]; 
faces[iBufCounter+5] = vertices[(y*mapSize) + (x+1)]; 

Avrebbe dovuto essere

faces[iBufCounter] = (y*mapSize) + x; 
faces[iBufCounter+1] = ((y+1)*mapSize) + x; 
faces[iBufCounter+2] = ((y+1)*mapSize) + (x+1); 

faces[iBufCounter+3] = (y*mapSize) + x; 
faces[iBufCounter+4] = ((y+1)*mapSize) + (x+1); 
faces[iBufCounter+5] = (y*mapSize) + (x+1); 

Comunque ho ancora un problema nel mio codice da qualche parte, anche se da quello che altri hanno detto che probabilmente non è in questo codice che ho postato.

Un altro utente ha inoltre proposto che creo l'ina terreno modo molto più semplice e ha postato il seguente codice

int mapSize = 16; 
Ogre::ManualObject *man = m_sceneManager->createManualObject("TerrainTest"); 
man->begin("Examples/Rockwall",Ogre::RenderOperation::OT_TRIANGLE_LIST); 
for(int z = 0; z < mapSize; ++z) 
{ 
    for(int x = 0; x < mapSize; ++x) 
    { 
     man->position(x,0,z); 
     man->normal(0,1,0); 
     man->textureCoord(x,z); 
    } 
} 
for(int z = 0; z < mapSize-1; ++z) 
{ 
    for(int x = 0; x < mapSize-1; ++x) 
    { 
     man->quad((x) + (z) * mapSize, (x) + (z + 1) * mapSize, (x + 1) + (z + 1) * mapSize, (x + 1) + (z) * mapSize); 
    } 
} 
man->end(); 
m_sceneManager->getRootSceneNode()->attachObject(man);