It is currently Fri Apr 28, 2017 8:43 pm

All times are UTC - 5 hours




 Page 1 of 1 [ 8 posts ] 
Author Message
 Post subject: Shader VMK 34 - Surface 3D
PostPosted: Sat Oct 12, 2013 12:19 pm 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
A new mko data structure is introduced in this VMK that allows you to define 3D surfaces. I implement the new Surface3d class and also make updates to the BaseMko, ShaderManager and Array2d classes to support this new renderable geometry.

The Surface3d class is constructed in a similar fashion to how the Flat Grid was made in the OpenGL Game Engine series, so if you are looking for more detailed explanations of the surface structure, have a look at the OpenGL Game Engine VMK17 Flat Grid class


Offline
 Profile  
 
 Post subject: Re: Shader VMK 34 - Surface 3D
PostPosted: Fri Apr 10, 2015 12:21 am 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
I added in the ability to set a flag in the Surface3d class along with the surface.bt mko template file.
After the vertex map file is read in, there is an unsigned short that follows. If this value is equal to 0 it will set our renderer to use unsigned shorts, if this value is anything else or greater then 0 it will set our renderer to use unsigned int. In our Surface3d class, I have a private bool member variable that is set to true or false respectively, also in this classes constructor, there is an extra default parameter added to the end after the id value. By default this is set to 0, however since this class is constructed through MkoFileReader::createMkoAsset() this unsigned short is read from the file and is automatically passed into the Surface3d constructor. The fact that this parameter is defaulted is of no consequence.

Here is what the new surface.bt file looks like:
//--------------------------------------
//--- 010 Editor v3.2.2 Binary Template
//
// File: MKO file format
// Author: Marek A. Krzeminski, MASc
// Revision: 1.0
// Purpose: describe the www.MarekKnows.com mko file format
//--------------------------------------

typedef struct {
    UCHAR_ARRAY rawVertexMap <fgcolor=cBlack, bgcolor=0x00ff00, comment="Path & Filename to mko type 1 file">;   
    unsigned short largeRenderFile <comment="A value of 0 = false : value > 0 = true">;
    unsigned int widthX <comment="Size must be larger than zero">;
    unsigned int lengthZ <comment="Size must be larger than zero">;
    unsigned int heightY <comment="Size must be larger than zero">;     
    RGBA_VALUE color <comment="Surface color",open=true>;   
} SURFACE_3D <read=readSurface3d,open=true>;

//--------------------------------------

string readSurface3d( SURFACE_3D& s3d ) {
    string s;
    SPrintf( s, "LargeRenderFile: %d, Surface W:%d L:%d H:%d, color R:%d G:%d B:%d A:%d", s3d.largeRenderFile, s3d.widthX, s3d.lengthZ, s3d.heightY, s3d.color.red, s3d.color.green, s3d.color.blue, s3d.color.alpha );
    return s;
}//readSurface3d


Make sure that in your surface.mko files that you added in this 2 bytes after the vertex map file data and just before the vertex and color data.

To read in the new Surface3d class with this added feature - here is the modified MkoFileReader::createMkoAsset<Surface3d> function:
// ----------------------------------------------------------------------------
// createMkoAsset()
template<>
Surface3d* MkoFileReader::createMkoAsset( const std::string& strId, unsigned uType ) {
   if ( uType != MKO_3D_SURFACE ) {
      throwError( __FUNCTION__ + std::string( " failed. File does not contain Surface3d data" ) );
   }

   // Get Vertex Map Filename
   std::string strVertexMapFilename( 128, 0 );
   if ( !getString( strVertexMapFilename, true ) ) {
      throwError( __FUNCTION__ + std::string( " invalid mko file, missing vertex map filename" ) ) ;
   }
   
   // Get Flag Value For Rendering Small or Large Data Sets
   unsigned short uLargeFile = 0;
   m_fileStream.read( reinterpret_cast<char*>( &uLargeFile ), sizeof( unsigned short ) );
   if ( m_fileStream.fail() ) {
      throwError( __FUNCTION__ + std::string( " invalid mko file, missing large file flag" ) );
   }

   struct SurfaceData {
      unsigned width;
      unsigned length;
      unsigned height;
      union {
         unsigned colorValue;
         struct ColorProperties {
            unsigned char red;
            unsigned char green;
            unsigned char blue;
            unsigned char alpha;
         } color;
      };
   } data;

   m_fileStream.read( reinterpret_cast<char*>( &data ), sizeof( SurfaceData ) );
   if ( m_fileStream.fail() ) {
      throwError( __FUNCTION__ + std::string( " invalid mko file, missing SurfaceData" ) );
   }
   
   Surface3d* pAsset = new Surface3d( data.width, data.length, data.height,
                              glm::vec4( data.color.red, data.color.green,
                                      data.color.blue, data.color.alpha ) / 255.0f,
                              strVertexMapFilename, strId, uLargeFile );

   return pAsset;

} // createMkoAsset<Surface3d>


// And Here is the modified Surface3d class: For the Surface3d.h just add a private bool member variable to designate this change.
Here is the constructor:
// ----------------------------------------------------------------------------
// Surface3d()
// Creates A Rectangular 3D Surface Of The Size Specified And Stores It In
// A Vertex Array Object For Rendering. The Surface Verts Are Defined Like:
//
//     v0 --- v1 --- v2  ... vX
//    vX+1---vX+2---vX+3 ... vX+X
//     :      :      :        :
//     v  --- v  --- v   ... vX*Z
//
// The Number Of Vertices And Height Of Each Vertex (Y-Values) Are Defined
// By The Grayscale Image strVertexMapFilename
Surface3d::Surface3d( unsigned uWidth, unsigned uLength, unsigned uHeight, const glm::vec4& color, const std::string& strVertexMapFilename, const std::string& strId, unsigned short uiLargeRenderFile ) :
BaseMko( strId ),
m_vboPosition( 0 ),
m_vboIndices( 0 ),
m_vao( 0 ),
m_uNumIndices( 0 ) {
   MkoFileReader file( strVertexMapFilename );
   GrayArray2d* pVertexArray = file.getMko<GrayArray2d>();

   // After The Vertex Map File Is Valid, Set Our Flag For Large Render File
   if ( uiLargeRenderFile == 0 ) {
      m_isLargeRenderFile = false;
   } else {
      m_isLargeRenderFile = true;
   }

   unsigned uNumCoordX = pVertexArray->getWidth();
   unsigned uNumCoordZ = pVertexArray->getHeight(); // The height from Array2d represents the length in 3D space
   if ( uNumCoordX <= 1 || uNumCoordZ <= 1 ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << " Vertex Map Size (" << uNumCoordX << "," << uNumCoordZ << ") must be more then 1 row/column in size.";
      throw ExceptionHandler( strStream );
   }

   float fStepX  = uWidth  / static_cast<float>( uNumCoordX - 1 );
   float fStepZ  = uLength / static_cast<float>( uNumCoordZ - 1 );
   float fScaleY = uHeight / 255.0f;

   std::vector<float> vVertexPosition;
   if ( m_isLargeRenderFile ) {
      std::vector<unsigned> vIndices;
      
      for ( unsigned z = 0; z < uNumCoordZ; ++z ) {
         for ( unsigned x = 0; x < uNumCoordX; ++x ) {
            // Define Vertex Position (x,y,z)
            vVertexPosition.push_back( fStepX * x );
            vVertexPosition.push_back( fScaleY * (*pVertexArray)[x + uNumCoordX*z] );
            vVertexPosition.push_back( fStepZ * z );

            if ( x > 0 && z > 0 ) {
               // Define 2 Triangle Faces
               //  o--o
               //  | /|
               //  o/_x
               //
               vIndices.push_back( pVertexArray->getIndex( -1 + x, z     ) );
               vIndices.push_back( pVertexArray->getIndex(      x, z - 1 ) );
               vIndices.push_back( pVertexArray->getIndex( -1 + x, z - 1 ) );

               vIndices.push_back( pVertexArray->getIndex( -1 + x, z     ) );
               vIndices.push_back( pVertexArray->getIndex(      x, z     ) );
               vIndices.push_back( pVertexArray->getIndex(      x, z - 1 ) );
            }
         }
      }

      // Don't Need This Anymore
      delete pVertexArray;

      // Create Vertex Array Object
      glGenVertexArrays( 1, &m_vao );
      glBindVertexArray( m_vao ); // Start Array

      m_pShaderManager->setAttribute( A_COLOR, color );

      // Create Position Buffer And Store On Video Card
      glGenBuffers( 1, &m_vboPosition );
      glBindBuffer( GL_ARRAY_BUFFER, m_vboPosition );
      glBufferData( GL_ARRAY_BUFFER, vVertexPosition.size() * sizeof( vVertexPosition[0] ), &vVertexPosition[0], GL_STATIC_DRAW );
      m_pShaderManager->enableAttribute( A_POSITION );

      // Create Index Buffer
      glGenBuffers( 1, &m_vboIndices );
      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_vboIndices );
      glBufferData( GL_ELEMENT_ARRAY_BUFFER, vIndices.size() * sizeof( vIndices[0] ), &vIndices[0], GL_STATIC_DRAW );

      glBindVertexArray( 0 ); // Stop Array

      // Disable Attribute Pointers
      m_pShaderManager->disableAttribute( A_POSITION );

      // THIS MUST BE AFTER Vertex Array Buffer Is Unbound!
      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); // Stop Index Buffer
      glBindBuffer( GL_ARRAY_BUFFER, 0 ); // Stop Buffer

      // # Inidces = [2 * (# shares)] * 3 -> (# triangles) * 3
      m_uNumIndices = 2 * ( uNumCoordX - 1 ) * ( uNumCoordZ - 1 ) * 3;
      if ( m_uNumIndices > INVALID_UNSIGNED ) {
         std::ostringstream strStream;
         strStream << __FUNCTION__ << " m_uNumIndices{" <<  m_uNumIndices << "} exceeds capacity of unsigned.";
         throw ExceptionHandler( strStream );
      }

   } else {
      std::vector<unsigned short> vIndices; // Change This To std::vector<unsigned> If Rendering Huge Surfaces
      
      for ( unsigned z = 0; z < uNumCoordZ; ++z ) {
         for ( unsigned x = 0; x < uNumCoordX; ++x ) {
            // Define Vertex Position (x,y,z)
            vVertexPosition.push_back( fStepX * x );
            vVertexPosition.push_back( fScaleY * (*pVertexArray)[x + uNumCoordX*z] );
            vVertexPosition.push_back( fStepZ * z );

            if ( x > 0 && z > 0 ) {
               // Define 2 Triangle Faces
               //  o--o
               //  | /|
               //  o/_x
               //
               vIndices.push_back( pVertexArray->getIndex( -1 + x, z     ) );
               vIndices.push_back( pVertexArray->getIndex(      x, z - 1 ) );
               vIndices.push_back( pVertexArray->getIndex( -1 + x, z - 1 ) );

               vIndices.push_back( pVertexArray->getIndex( -1 + x, z     ) );
               vIndices.push_back( pVertexArray->getIndex(      x, z     ) );
               vIndices.push_back( pVertexArray->getIndex(      x, z - 1 ) );
            }
         }
      }

      // Don't Need This Anymore
      delete pVertexArray;

      // Create Vertex Array Object
      glGenVertexArrays( 1, &m_vao );
      glBindVertexArray( m_vao ); // Start Array

      m_pShaderManager->setAttribute( A_COLOR, color );

      // Create Position Buffer And Store On Video Card
      glGenBuffers( 1, &m_vboPosition );
      glBindBuffer( GL_ARRAY_BUFFER, m_vboPosition );
      glBufferData( GL_ARRAY_BUFFER, vVertexPosition.size() * sizeof( vVertexPosition[0] ), &vVertexPosition[0], GL_STATIC_DRAW );
      m_pShaderManager->enableAttribute( A_POSITION );

      // Create Index Buffer
      glGenBuffers( 1, &m_vboIndices );
      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_vboIndices );
      glBufferData( GL_ELEMENT_ARRAY_BUFFER, vIndices.size() * sizeof( vIndices[0] ), &vIndices[0], GL_STATIC_DRAW );

      glBindVertexArray( 0 ); // Stop Array

      // Disable Attribute Pointers
      m_pShaderManager->disableAttribute( A_POSITION );

      // THIS MUST BE AFTER Vertex Array Buffer Is Unbound!
      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); // Stop Index Buffer
      glBindBuffer( GL_ARRAY_BUFFER, 0 ); // Stop Buffer

      // # Inidces = [2 * (# shares)] * 3 -> (# triangles) * 3
      m_uNumIndices = 2 * ( uNumCoordX - 1 ) * ( uNumCoordZ - 1 ) * 3;
      if ( m_uNumIndices > INVALID_UNSIGNED_SHORT ) {
         std::ostringstream strStream;
         strStream << __FUNCTION__ << " m_uNumIndices{" <<  m_uNumIndices << "} exceeds capacity of unsigned short. Make sure the largeRenderFile flag in your mko file is not set to 0 if using large data sets." ;
         throw ExceptionHandler( strStream );
      }   
   }   

} // Surface3d


Here is the render function:
// ----------------------------------------------------------------------------
// render()
void Surface3d::render() {
   if ( m_isLargeRenderFile ) {
      glBindVertexArray( m_vao );
      glDrawElements( GL_TRIANGLES, m_uNumIndices, GL_UNSIGNED_INT, nullptr );
      glBindVertexArray( 0 );
   } else{
      glBindVertexArray( m_vao );
      glDrawElements( GL_TRIANGLES, m_uNumIndices, GL_UNSIGNED_SHORT, nullptr );
      glBindVertexArray( 0 );
   }
} // render


Once you get this to work properly; if you open your surface.mko file in a hex editor and set this unsigned short to 0, it will go through the logic flow to set the properties for OpenGL to render with unsigned shorts. If it is anything other than 0 it will set your OpenGL to render with unsigned int. This is a nice addition to have so each of your surface.mko files can be individually marked for rendering small surfaces such as a table top, vehicle etc. or for large files like terrain.


Offline
 Profile  
 
 Post subject: Re: Shader VMK 34 - Surface 3D
PostPosted: Fri Apr 10, 2015 7:52 am 
Site Admin

Joined: Sun Feb 11, 2007 8:59 am
Posts: 1094
Location: Ontario Canada
Here are a few suggestions to improve your code:

1. Inside MkoFileReader::createMkoAsset put your new unsigned short uLargeFile variable inside the SurfaceData struct so that you don't have to read it in separately, you can just use the existing m_fileStream.read call to do it for you.

2. Change the Surface3d constructor signature so that it accepts a bool isLargeRenderFile as the last parameter rather than unsigned short uiLargeRenderFile.

3. Inside the Surface3d constructor you now have a whole bunch of duplicate code because of the if branch for m_isLargeRenderFile. I'd put most of the code inside a templated function that returns uNumIndices and takes in a std::vector<T>& and what ever other variables you need to do all the work to generate the buffers. The only difference between the 2 branches is how you define the std::vector for the vIndices, and the check at the end on whether to throw an exception or not. All the remaining code can go into the template function.

4. I'd also simplify the render function to look like this instead:

glBindVertexArray( m_vao );
glDrawElements( GL_TRIANGLES, m_uNumIndices, m_isLargeRenderFile  ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, nullptr );
glBindVertexArray( 0 );


Offline
 Profile  
 
 Post subject: Re: Shader VMK 34 - Surface 3D
PostPosted: Fri Apr 10, 2015 12:40 pm 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
Thank you for the advice, I'll have to work on it. This was just to get it up and running making sure the *.bt and *.mko files were working properly. Now that I have that up and running I can now use a template as you suggested.


Offline
 Profile  
 
 Post subject: Re: Shader VMK 34 - Surface 3D
PostPosted: Fri Apr 10, 2015 2:34 pm 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
I made modifications to the code, and this is what I have come up with so far.

MkoFileReader::createMkoAsset
// ----------------------------------------------------------------------------
// createMkoAsset()
template<>
Surface3d* MkoFileReader::createMkoAsset( const std::string& strId, unsigned uType ) {
   if ( uType != MKO_3D_SURFACE ) {
      throwError( __FUNCTION__ + std::string( " failed. File does not contain Surface3d data" ) );
   }

   // Get Vertex Map Filename
   std::string strVertexMapFilename( 128, 0 );
   if ( !getString( strVertexMapFilename, true ) ) {
      throwError( __FUNCTION__ + std::string( " invalid mko file, missing vertex map filename" ) ) ;
   }
   
   struct SurfaceData {
      unsigned short uLargeFile;
      unsigned width;
      unsigned length;
      unsigned height;
      union {
         unsigned colorValue;
         struct ColorProperties {
            unsigned char red;
            unsigned char green;
            unsigned char blue;
            unsigned char alpha;
         } color;
      };
   } data;

   m_fileStream.read( reinterpret_cast<char*>( &data ), sizeof( SurfaceData ) );
   if ( m_fileStream.fail() ) {
      throwError( __FUNCTION__ + std::string( " invalid mko file, missing SurfaceData" ) );
   }
   
   Surface3d* pAsset = new Surface3d( data.width, data.length, data.height,
                              glm::vec4( data.color.red, data.color.green,
                                      data.color.blue, data.color.alpha ) / 255.0f,
                              strVertexMapFilename, strId, data.uLargeFile );

   return pAsset;

} // createMkoAsset<Surface3d>


Here is the function template signature
template<typename T>
void generateBuffers( unsigned uWidth, unsigned uLength, unsigned uHeight, const glm::vec4& color, const std::string& strVertexMapFilename, std::vector<T>& vIndices );


I changed signature for Surface3d constructor to accept a bool instead of unsigned short.
Here is the new constructor:
// ----------------------------------------------------------------------------
// Surface3d()
// Creates A Rectangular 3D Surface Of The Size Specified And Stores It In
// A Vertex Array Object For Rendering. The Surface Verts Are Defined Like:
//
//     v0 --- v1 --- v2  ... vX
//    vX+1---vX+2---vX+3 ... vX+X
//     :      :      :        :
//     v  --- v  --- v   ... vX*Z
//
// The Number Of Vertices And Height Of Each Vertex (Y-Values) Are Defined
// By The Grayscale Image strVertexMapFilename
Surface3d::Surface3d( unsigned uWidth, unsigned uLength, unsigned uHeight, const glm::vec4& color, const std::string& strVertexMapFilename, const std::string& strId, bool isLargeRenderFile ) :
BaseMko( strId ),
m_vboPosition( 0 ),
m_vboIndices( 0 ),
m_vao( 0 ),
m_uNumIndices( 0 ),
m_isLargeRenderFile( isLargeRenderFile ) {      
   
   if ( isLargeRenderFile ) {
      std::vector<unsigned int> vIndices;
      generateBuffers( uWidth, uLength, uHeight, color, strVertexMapFilename, vIndices );

      if ( m_uNumIndices > INVALID_UNSIGNED ) {
         std::ostringstream strStream;
         strStream << __FUNCTION__ << " m_uNumIndices{" <<  m_uNumIndices << "} exceeds capacity of unsigned.";
         throw ExceptionHandler( strStream );
      }

   } else {
      std::vector<unsigned short> vIndices;
      generateBuffers(  uWidth, uLength, uHeight, color, strVertexMapFilename, vIndices );

      if ( m_uNumIndices > INVALID_UNSIGNED_SHORT ) {
         std::ostringstream strStream;
         strStream << __FUNCTION__ << " m_uNumIndices{" <<  m_uNumIndices << "} exceeds capacity of unsigned short. Make sure the largeRenderFile flag in your mko file is not set to 0 if using a large render file." ;
         throw ExceptionHandler( strStream );
      }   
   }

} // Surface3d


Here is my function template:
// ----------------------------------------------------------------------------
// generateBuffers()
template<typename T>
void Surface3d::generateBuffers(  unsigned uWidth, unsigned uLength, unsigned uHeight, const glm::vec4& color, const std::string& strVertexMapFilename, std::vector<T>& vIndices ) {
   MkoFileReader file( strVertexMapFilename );
   GrayArray2d* pVertexArray = file.getMko<GrayArray2d>();


   unsigned uNumCoordX = pVertexArray->getWidth();
   unsigned uNumCoordZ = pVertexArray->getHeight(); // The height from Array2d represents the length in 3D space
   if ( uNumCoordX <= 1 || uNumCoordZ <= 1 ) {
      std::ostringstream strStream;
      strStream << __FUNCTION__ << " Vertex Map Size (" << uNumCoordX << "," << uNumCoordZ << ") must be more then 1 row/column in size.";
      throw ExceptionHandler( strStream );
   }

   float fStepX  = uWidth  / static_cast<float>( uNumCoordX - 1 );
   float fStepZ  = uLength / static_cast<float>( uNumCoordZ - 1 );
   float fScaleY = uHeight / 255.0f;

   std::vector<float> vVertexPosition;
   
   for ( unsigned z = 0; z < uNumCoordZ; ++z ) {
      for ( unsigned x = 0; x < uNumCoordX; ++x ) {
         // Define Vertex Position (x,y,z)
         vVertexPosition.push_back( fStepX * x );
         vVertexPosition.push_back( fScaleY * (*pVertexArray)[x + uNumCoordX*z] );
         vVertexPosition.push_back( fStepZ * z );

         if ( x > 0 && z > 0 ) {
            // Define 2 Triangle Faces
            //  o--o
            //  | /|
            //  o/_x
            //
            vIndices.push_back( pVertexArray->getIndex( -1 + x, z     ) );
            vIndices.push_back( pVertexArray->getIndex(      x, z - 1 ) );
            vIndices.push_back( pVertexArray->getIndex( -1 + x, z - 1 ) );

            vIndices.push_back( pVertexArray->getIndex( -1 + x, z     ) );
            vIndices.push_back( pVertexArray->getIndex(      x, z     ) );
            vIndices.push_back( pVertexArray->getIndex(      x, z - 1 ) );
         }
      }
   }

   // Don't Need This Anymore
   m_pAssetStorage->release( pVertexArray->getId() );

   // Create Vertex Array Object
   glGenVertexArrays( 1, &m_vao );
   glBindVertexArray( m_vao ); // Start Array

   m_pShaderManager->setAttribute( A_COLOR, color );

   // Create Position Buffer And Store On Video Card
   glGenBuffers( 1, &m_vboPosition );
   glBindBuffer( GL_ARRAY_BUFFER, m_vboPosition );
   glBufferData( GL_ARRAY_BUFFER, vVertexPosition.size() * sizeof( vVertexPosition[0] ), &vVertexPosition[0], GL_STATIC_DRAW );
   m_pShaderManager->enableAttribute( A_POSITION );

   // Create Index Buffer
   glGenBuffers( 1, &m_vboIndices );
   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_vboIndices );
   glBufferData( GL_ELEMENT_ARRAY_BUFFER, vIndices.size() * sizeof( vIndices[0] ), &vIndices[0], GL_STATIC_DRAW );

   glBindVertexArray( 0 ); // Stop Array

   // Disable Attribute Pointers
   m_pShaderManager->disableAttribute( A_POSITION );

   // THIS MUST BE AFTER Vertex Array Buffer Is Unbound!
   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); // Stop Index Buffer
   glBindBuffer( GL_ARRAY_BUFFER, 0 ); // Stop Buffer

   // # Inidces = [2 * (# shares)] * 3 -> (# triangles) * 3
   m_uNumIndices = 2 * ( uNumCoordX - 1 ) * ( uNumCoordZ - 1 ) * 3;

} // generateBuffers()


I made the changes to the render function to your suggestion in the comments.

Everything compiles, builds and runs without error. When the Surface3d constructor leaves scope and returns back into the createMkoAsset() where it returns pAsset all the data is there. When the code comes back into the Surface3d class for the render call, all data is there and present, however nothing is being rendered to the screen. I am not sure why.


Offline
 Profile  
 
 Post subject: Re: Shader VMK 34 - Surface 3D
PostPosted: Fri Apr 10, 2015 3:52 pm 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
I don't know why it is doing this, but the problem was not in the Surface3d class.

When I added the unsigned short into the structure, it was not reading the data in correctly from the file.
// ----------------------------------------------------------------------------
// createMkoAsset()
template<>
Surface3d* MkoFileReader::createMkoAsset( const std::string& strId, unsigned uType ) {
   if ( uType != MKO_3D_SURFACE ) {
      throwError( __FUNCTION__ + std::string( " failed. File does not contain Surface3d data" ) );
   }

   // Get Vertex Map Filename
   std::string strVertexMapFilename( 128, 0 );
   if ( !getString( strVertexMapFilename, true ) ) {
      throwError( __FUNCTION__ + std::string( " invalid mko file, missing vertex map filename" ) ) ;
   }   
   struct SurfaceData {
      unsigned short  uLargeFile;
      unsigned width;
      unsigned length;
      unsigned height;
      union {
         unsigned colorValue;
         struct ColorProperties {
            unsigned char red;
            unsigned char green;
            unsigned char blue;
            unsigned char alpha;
         } color;
      };
   } data;

   m_fileStream.read( reinterpret_cast<char*>( &data ), sizeof( SurfaceData ) );
   if ( m_fileStream.fail() ) {
      throwError( __FUNCTION__ + std::string( " invalid mko file, missing SurfaceData" ) );
   }
   
   Surface3d* pAsset = new Surface3d( data.width, data.length, data.height,
                              glm::vec4( data.color.red, data.color.green,
                                      data.color.blue, data.color.alpha ) / 255.0f,
                              strVertexMapFilename, strId, data.uLargeFile );

   return pAsset;

} // createMkoAsset<Surface3d>


This above was not reading in the data from surface1.mko and was giving me wrong data for the width, length, height and color values, but the string and the uLarge file were correct.

When I changed this function back to how I originally had it, where I was reading from the file for 2 bytes, then read in the structure it is now working correctly. Not sure why it is behaving like this.


Offline
 Profile  
 
 Post subject: Re: Shader VMK 34 - Surface 3D
PostPosted: Fri Apr 10, 2015 8:06 pm 

Joined: Sat Aug 16, 2008 7:58 am
Posts: 447
I found out what was going on here in the createMkoAsset() function. When I moved the unsigned short into the data structure as the first parameter it was giving me the wrong values even though the SurfaceData struct in the function matched they data types and order within the file. I added the variable for uLargeFile back into the SurfaceData struct within createMkoAsset but I changed it from an unsigned short to an unsigned int. It took me a while to figure it out, but this goes back to my early days of learning to program when I was first introduced to c / c++ and that happens to be how the data is aligned within structures. Instead of adding a second unsigned short arbitrary meaningless variable to keep the packing of word size alignment correct, I chose the simpler option of just setting this to an unsigned int. Everything works as expected.

The Surface3d class is the same as I had mentioned above, but here is the new createMko() function:
// ----------------------------------------------------------------------------
// createMkoAsset()
template<>
Surface3d* MkoFileReader::createMkoAsset( const std::string& strId, unsigned uType ) {
   if ( uType != MKO_3D_SURFACE ) {
      throwError( __FUNCTION__ + std::string( " failed. File does not contain Surface3d data" ) );
   }

   // Get Vertex Map Filename
   std::string strVertexMapFilename( 128, 0 );
   if ( !getString( strVertexMapFilename, true ) ) {
      throwError( __FUNCTION__ + std::string( " invalid mko file, missing vertex map filename" ) ) ;
   }
   
   struct SurfaceData {
      unsigned int uLargeFile;
      unsigned width;
      unsigned length;
      unsigned height;
      union {
         unsigned colorValue;
         struct ColorProperties {
            unsigned char red;
            unsigned char green;
            unsigned char blue;
            unsigned char alpha;
         } color;
      };
   } data;

   m_fileStream.read( reinterpret_cast<char*>( &data ), sizeof( SurfaceData ) );
   if ( m_fileStream.fail() ) {
      throwError( __FUNCTION__ + std::string( " invalid mko file, missing SurfaceData" ) );
   }
   
   Surface3d* pAsset = new Surface3d( data.width, data.length, data.height,
                              glm::vec4( data.color.red, data.color.green,
                                      data.color.blue, data.color.alpha ) / 255.0f,
                              strVertexMapFilename, strId, (data.uLargeFile  > 0 ?  true : false ) );

   return pAsset;

} // createMkoAsset<Surface3d>


Also I added in the ternary operator switch into the constructor's last parameter so I wouldn't get the warning message of converting from an unsigned int to bool performance warning.


Offline
 Profile  
 
 Post subject: Re: Shader VMK 34 - Surface 3D
PostPosted: Sat Oct 24, 2015 11:09 pm 

Joined: Wed Sep 30, 2015 3:10 am
Posts: 7
The fact that this parameter is defaulted is of no consequence.
casino


Offline
 Profile  
 
Display posts from previous:  Sort by  
 Page 1 of 1 [ 8 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 1 guest


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

Jump to:  

cron