It is currently Sat Aug 22, 2020 4:15 am


All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: How to covert volume data into OGRE mesh and texture it?
PostPosted: Tue Mar 01, 2011 9:46 am 

Joined: Fri Sep 10, 2010 5:38 am
Posts: 30
How to covert volume data into OGRE mesh and texture it? the simpleExample only do it in OpenGL and without texture it. I simply losted it. Can anyone provide links or tutorials toward it to solve my problem? Thank you 1000 times.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: How to covert volume data into OGRE mesh and texture it?
PostPosted: Tue Mar 01, 2011 1:08 pm 

Joined: Tue Feb 22, 2011 10:21 pm
Posts: 12
It isn't a tutorial, but you can have a look at this topic : viewtopic.php?f=2&t=77
It helped me a lot.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: How to covert volume data into OGRE mesh and texture it?
PostPosted: Tue Mar 01, 2011 1:10 pm 

Joined: Sun Jan 23, 2011 6:06 am
Posts: 92
Here is some test code I used when I started learning PolyVox. Sorry it is a bit messy:

Code:
#include "windows.h"

#include <iostream>
#include <sstream>
#include <vector>

// ogre test application. based on old ogre testapplication or whatever it was called
#include "mainOgreApplication.h"

// Polyvox includes
#include <Volume.h>
#include <MaterialDensityPair.h>
#include <SurfaceMesh.h>
#include <CubicSurfaceExtractor.h>
#include <MeshDecimator.h>


typedef PolyVox::MaterialDensityPair<uint8_t, 7, 1> PolyVoxVoxel;                  // 1 bit for density SOLID / NONSOLID only. Use 7 bits for material to allow 128 material types. Really only useful for cubic extraction i guess...
typedef PolyVox::Volume<PolyVoxVoxel> PolyVoxVolume;                           // typedef for volume based on 71 pair type
typedef PolyVox::SurfaceMesh<PolyVox::PositionMaterial> PolyVoxMesh;               // polyvox mesh without normals
typedef PolyVox::CubicSurfaceExtractor<PolyVoxVoxel> PolyVoxCubicSurfaceExtractor;      // cubic surface extractor without normals for 71 pair type
typedef PolyVox::MeshDecimator<PolyVox::PositionMaterial> PolyVoxMeshDecimator;         // decimator for 71 pair type

// just some defines for changing demo behaviour
#define VOLUME_SIZE 64   // volume size in voxels
#define SPHERE_SIZE 40   // size of the sphere to cut out of the corner
const bool RENDER_DECIMATED_MESH = false;

class TestApplication : public OgreApplication
{
public:
   TestApplication(void):mPolyVoxVolume(0), mLastTime(0), mManualObjectNode(0) {;}

   virtual ~TestApplication()
   {
      delete mPolyVoxCubicSurfaceExtractor;

      delete mPolyVoxDecimatedMeshMaterial1;
      delete mPolyVoxDecimatedMeshMaterial2;
      delete mPolyVoxDecimatedMeshMaterial3;
      delete mPolyVoxDecimatedMeshMaterial4;

      delete mPolyVoxMeshMaterialALL;
      //delete mPolyVoxMeshMaterial1;      // cant delete these due to use of shared_ptr. will be deallocated automatically by the auto pointer.
      //delete mPolyVoxMeshMaterial2;
      //delete mPolyVoxMeshMaterial3;
      //delete mPolyVoxMeshMaterial4;

      delete mPolyVoxVolume;
   }

protected:
   virtual void createScene()
   {
      mSceneMgr->setAmbientLight(Ogre::ColourValue::White);   // set full light for testing

      // polyvox testscene

      Ogre::LogManager::getSingleton().logMessage("");   // create an empty space at the start of log
      logTime("createScene START: ");

      // allocate data first
      mPolyVoxVolume = new PolyVoxVolume(VOLUME_SIZE, VOLUME_SIZE, VOLUME_SIZE);   // create cubic volume with default block size 32

      mPolyVoxMeshMaterialALL = new PolyVoxMesh();         // regular mesh
      mPolyVoxMeshMaterial1 = new PolyVoxMesh();            // regular mesh
      mPolyVoxMeshMaterial2 = new PolyVoxMesh();            // regular mesh
      mPolyVoxMeshMaterial3 = new PolyVoxMesh();            // regular mesh
      mPolyVoxMeshMaterial4 = new PolyVoxMesh();            // regular mesh

      mPolyVoxDecimatedMeshMaterial1 = new PolyVoxMesh();      // decimated mesh
      mPolyVoxDecimatedMeshMaterial2 = new PolyVoxMesh();      // decimated mesh
      mPolyVoxDecimatedMeshMaterial3 = new PolyVoxMesh();      // decimated mesh
      mPolyVoxDecimatedMeshMaterial4 = new PolyVoxMesh();      // decimated mesh

      // only need single extractor since will extract single mesh first
      mPolyVoxCubicSurfaceExtractor = new PolyVoxCubicSurfaceExtractor(mPolyVoxVolume, mPolyVoxVolume->getEnclosingRegion(), mPolyVoxMeshMaterialALL);   // just enclose entire volume with single region

      logTime("createScene volume data created : ");

      // completely fill volume with data. have to skip border to prevent decimation issues.
      for(uint16_t px = 0 ; px < mPolyVoxVolume->getWidth() ; px++)
      {
         uint8_t materialNumber = 4 * px / VOLUME_SIZE;   // 4 materials spread evenly across x axis

         for(uint16_t py = 0 ; py < mPolyVoxVolume->getHeight() ; py++)
         {
            for(uint16_t pz = 0 ; pz < mPolyVoxVolume->getDepth() ; pz++)
            {
               // add a sphere cut into the corner. position is 0, VOLUME_SIZE, 0

               uint16_t distX = px;
               uint16_t distY = VOLUME_SIZE - py;
               uint16_t distZ = pz;
               double distance = sqrt( (double)(distX*distX + distY*distY + distZ*distZ) );   // double conversion necessary for compile without error

               if(distance < SPHERE_SIZE)
                  mPolyVoxVolume->setVoxelAt(px, py, pz, PolyVoxVoxel(materialNumber, 0));   // set voxel data in volume. set to non solid if inside sphere radius.
               else
                  mPolyVoxVolume->setVoxelAt(px, py, pz, PolyVoxVoxel(materialNumber, 1));   // set voxel data in volume. set to solid if outside sphere radius.
            }
         }
      }

      logTime("createScene volume data filled : ");

      // extract cubic surface
      mPolyVoxCubicSurfaceExtractor->execute();   // execute to grab single mesh first

      logTime("createScene surface extraction executed : ");


      // before decimating, need to split into submeshes

      // material 0
      std::set<uint8_t> setMaterial1;
      setMaterial1.insert(0);

      polyvox_shared_ptr<PolyVoxMesh> meshPointerMaterial1 = mPolyVoxMeshMaterialALL->extractSubset(setMaterial1);   // test: use actual pointer to test return
      mPolyVoxMeshMaterial1 = meshPointerMaterial1.get();

      // material 1
      std::set<uint8_t> setMaterial2;
      setMaterial2.insert(1);

      polyvox_shared_ptr<PolyVoxMesh> meshPointerMaterial2 = mPolyVoxMeshMaterialALL->extractSubset(setMaterial2);
      mPolyVoxMeshMaterial2 = meshPointerMaterial2.get();

      // material 2
      std::set<uint8_t> setMaterial3;
      setMaterial3.insert(2);

      polyvox_shared_ptr<PolyVoxMesh> meshPointerMaterial3 = mPolyVoxMeshMaterialALL->extractSubset(setMaterial3);
      mPolyVoxMeshMaterial3 = meshPointerMaterial3.get();

      // material 3
      std::set<uint8_t> setMaterial4;
      setMaterial4.insert(3);

      polyvox_shared_ptr<PolyVoxMesh> meshPointerMaterial4 = mPolyVoxMeshMaterialALL->extractSubset(setMaterial4);
      mPolyVoxMeshMaterial4 = meshPointerMaterial4.get();


      // decimated each mesh separately

      if(RENDER_DECIMATED_MESH == true)
      {
         // unlike PolyVoxCubicSurfaceExtractor which can be created in advance, mesh decimator will fail with access violation if allocated in advance. must allocate AFTER mesh extraction. kind of annoying...

         // prepare mesh decimators
         PolyVoxMeshDecimator decimator1(mPolyVoxMeshMaterial1, mPolyVoxDecimatedMeshMaterial1);   
         decimator1.execute();

         PolyVoxMeshDecimator decimator2(mPolyVoxMeshMaterial2, mPolyVoxDecimatedMeshMaterial2);
         decimator2.execute();

         PolyVoxMeshDecimator decimator3(mPolyVoxMeshMaterial3, mPolyVoxDecimatedMeshMaterial3);
         decimator3.execute();

         PolyVoxMeshDecimator decimator4(mPolyVoxMeshMaterial4, mPolyVoxDecimatedMeshMaterial4);
         decimator4.execute();

         logTime("createScene mesh decimated : ");

         // convert the meshes to ogre

         mOgreManualObjectMaterial1 = convertPolyVoxMesh(mPolyVoxDecimatedMeshMaterial1, "WireframeNoLightWhite");      
         mOgreManualObjectMaterial2 = convertPolyVoxMesh(mPolyVoxDecimatedMeshMaterial2, "WireframeNoLightRed");      
         mOgreManualObjectMaterial3 = convertPolyVoxMesh(mPolyVoxDecimatedMeshMaterial3, "WireframeNoLightGreen");      
         mOgreManualObjectMaterial4 = convertPolyVoxMesh(mPolyVoxDecimatedMeshMaterial4, "WireframeNoLightBlue");      
      }
      else
      {
         mOgreManualObjectMaterial1 = convertPolyVoxMesh(mPolyVoxMeshMaterial1, "WireframeNoLightWhite");            
         mOgreManualObjectMaterial2 = convertPolyVoxMesh(mPolyVoxMeshMaterial2, "WireframeNoLightRed");            
         mOgreManualObjectMaterial3 = convertPolyVoxMesh(mPolyVoxMeshMaterial3, "WireframeNoLightGreen");            
         mOgreManualObjectMaterial4 = convertPolyVoxMesh(mPolyVoxMeshMaterial4, "WireframeNoLightBlue");            
      }

      logTime("createScene convert mesh to manualObject : ");

      mManualObjectNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("manualObjectSceneNode", Ogre::Vector3(0.0f, 0.0f, 0.0f));

      mManualObjectNode->setScale(0.1f, 0.1f, 0.1f);
      mManualObjectNode->setVisible(true);

      if(mOgreManualObjectMaterial1) mManualObjectNode->attachObject(mOgreManualObjectMaterial1);
      if(mOgreManualObjectMaterial2) mManualObjectNode->attachObject(mOgreManualObjectMaterial2);
      if(mOgreManualObjectMaterial3) mManualObjectNode->attachObject(mOgreManualObjectMaterial3);
      if(mOgreManualObjectMaterial4) mManualObjectNode->attachObject(mOgreManualObjectMaterial4);

      // adjust camera
      mCameraSceneNode->setPosition(Ogre::Vector3(-5, 11, -4));   
      mCameraSceneNode->lookAt(Ogre::Vector3(0, 6, 0), Ogre::Node::TransformSpace::TS_WORLD);   

   }

   void logTime(Ogre::String message)
   {
      // log time in milliseconds to ogre log. just used for testing how long each stage takes in milliseconds
      unsigned int ogreTime = mRoot->getTimer()->getMilliseconds();
      unsigned int time = ogreTime - mLastTime;   // time since last log. want to measure each step individually.
      mLastTime = ogreTime;
      std::stringstream sstream;
      sstream << time;
      Ogre::String logMessage = message;
      logMessage += sstream.str();
      logMessage += "\n";
      Ogre::LogManager::getSingleton().logMessage(logMessage);
   }


   // convert polyvox mesh to ogre mesh
   Ogre::ManualObject* convertPolyVoxMesh(PolyVoxMesh* mesh, Ogre::String materialName)
   {
      Ogre::ManualObject* ogreManualObject = NULL;

      if(mesh && mesh->getNoOfVertices() > 0 && mesh->getNoOfIndices() > 0)   // make sure mesh is allocated and valid first
      {
         const vector<uint32_t>& indexVector = mesh->getIndices();                     // get a vector of all indices
         const std::vector<PolyVox::PositionMaterial>& vertexVector = mesh->getVertices();   // get a vector of all vertices

         ogreManualObject = mSceneMgr->createManualObject();   // create manual object

         numOgreIndices = mesh->getNoOfIndices();
         numOgreVertices = mesh->getNoOfVertices();

         ogreManualObject->estimateIndexCount(numOgreIndices);   // set index/vertex counts before starting to speed up allocations
         ogreManualObject->estimateVertexCount(numOgreVertices);

         ogreManualObject->begin(materialName, Ogre::RenderOperation::OT_TRIANGLE_LIST);   // start adding triangles

         PolyVox::Vector3DFloat positionTempVar;

         // iterate through vertices
         for(int v = 0 ; v < numOgreVertices ; v++)
         {
            positionTempVar = vertexVector[v].getPosition();   // get position vector from vertex list

            ogreManualObject->position((Ogre::Real)(positionTempVar.getX()), (Ogre::Real)(positionTempVar.getY()), (Ogre::Real)(positionTempVar.getZ()));   // add a new vertex to ogre manualobject
         }

         // iterate through indices
         for(int i = 0 ; i < numOgreIndices ; i++)
         {
            ogreManualObject->index((Ogre::uint32)(indexVector[i]));   // set indices in same order as polyvox mesh (if using DirectX render system, may differ for OpenGL)
         }

         ogreManualObject->end();   // stop adding triangles
      }

      return ogreManualObject;
   }


   
private:

   PolyVoxVolume* mPolyVoxVolume;                           // single volume encompassing all volumetric data

   PolyVoxMesh* mPolyVoxMeshMaterialALL;                     // single material extracted before extracting per-material submeshes

   PolyVoxMesh* mPolyVoxMeshMaterial1;                        // polyvox mesh used for extraction
   PolyVoxMesh* mPolyVoxMeshMaterial2;                        
   PolyVoxMesh* mPolyVoxMeshMaterial3;                        
   PolyVoxMesh* mPolyVoxMeshMaterial4;                        

   PolyVoxMesh* mPolyVoxDecimatedMeshMaterial1;               // decimated mesh
   PolyVoxMesh* mPolyVoxDecimatedMeshMaterial2;               
   PolyVoxMesh* mPolyVoxDecimatedMeshMaterial3;                        
   PolyVoxMesh* mPolyVoxDecimatedMeshMaterial4;                     

   PolyVoxCubicSurfaceExtractor* mPolyVoxCubicSurfaceExtractor;   // cubic surface extractor (without normals)

   Ogre::ManualObject* mOgreManualObjectMaterial1;               // ogre manual object for drawing a single mesh
   Ogre::ManualObject* mOgreManualObjectMaterial2;                  
   Ogre::ManualObject* mOgreManualObjectMaterial3;                  
   Ogre::ManualObject* mOgreManualObjectMaterial4;                  

   Ogre::SceneNode* mManualObjectNode;                        // ogre scene node to attach manual object

   uint32_t numOgreIndices;                              // for recording and reporting # of ogre indices/vertices
   uint32_t numOgreVertices;

   unsigned int mLastTime;   

};



Obviously this is only as a demo case and would need to be written totally differently for practical use.

Also, the extractSubset() function is no longer a member of PolyVox::SurfaceMesh, this code was written for the 13/01/2011 PolyVox version. There is another way to handle materials, see addSurfacePatchRenderable and related functions in Thermite (start with ThermiteGameLogic.h)

Because this is cubic extraction without normals, you will need to generate normals yourself or change to a different extraction method. Also, PolyVox does not generate texture coordinates, you will need to do this in your vertex or pixel shaders too.

I can't really be bothered posting the OgreApplication class, it is based on the standard Ogre demo classes from before the new demo framework was created, I am sure you can extract what you need from the code above.

I hope this helps. Maybe someone can post a better example...


Top
Offline Profile  
Reply with quote  
 Post subject: Re: How to covert volume data into OGRE mesh and texture it?
PostPosted: Tue Mar 01, 2011 8:20 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
For converting the extracted SurfaceMesh into a form Ogre can render, your best option is probably the ManualObject class. I'm actually working directly with hardware buffers myself but the ManualObject provides an easier interface.

As for texturing, PolyVox does not provide anything (not even texture coordinates). Most people are using techniques like triplanar texturing but you are not required to. I've also experimented with projecting a cube map around the mesh and also with procedural textures. It really depends what you are trying to achive.

As for lighting, the SurfaceExtractor and CubicSurfaceExtractorWithNormals both provide normals but the CubicSurfaceExtractor does not. In the case of the latter you can generate normals in the pixel shader.


Top
Offline Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Theme created StylerBB.net