Jump to content
  • Advertisement
Sign in to follow this  
SL33pY_Kr3W

MS3DModel Loader ( fstream problem)

This topic is 4404 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I'm having some trouble using the read() function of the ifstream class in my milkshape 3d model loader. It takes an array of chars as its first argument, but I need it to accept an array of bytes. I initially tried to type cast a byte pointer to a char pointer, and the file reads, but it fails when I check the ms3d header. I explain the situation, step by step, in the /* comments */ as a guide.
/* This is main.cpp.  I use this to test my loader*/
#include"WEModel.h"

int main()
{
    //test the loading of a milkshape 3d model
    WEModel superMoo;
    int error;
    
    //load
    /*This is where I test the function in question.  This code returns the error number: 2 */
    error = superMoo.WELoadMS3DModel( "moo.ms3d" );
    
    /*I check the error and find that the ms3d header did not pass my test*/
    if( error )
    {
        switch( error )
        {
                case 1:
                     printf( "can't open" );
                     break;
                case 2:
                     printf( "wrong header" );
                     break;
                case 3:
                     printf( "wrong version" );
                default:break;
        }
    }
    
    /*This is where it gets weird.  The program pauses and I will read the error message in the console.  I then hit a key and expect the program to end.  Instead, it crashes*/
    system("pause");
        
    return 0;
}




/* By the way: the milkshape 3d file specification defines byte as...*/
typedef unsigned char byte;
 
 
//the function in question
int WEModel::WELoadMS3DModel( char* fileName )
{
    //vars 
    int begin;
    int size;
    int vertexNum;
    int triangleNum;
    int meshNum;
    int materialNum;
    
    byte* pModel; /* This is where the file will be read to*/
    byte* pPlace;/* This is what I use to increment through the file.  No problems here*/
    std::ifstream file;
    
    //open the file
    file.open( fileName, std::ios::binary );
    
    //has the file been opened?  /* This test passes */
    if( file.fail() )
      return 1;
    
    //determine the size of the file;
    file.seekg( 0, std::ios::beg );
    begin = file.tellg();
    file.seekg( 0, std::ios::end );
    size = file.tellg();
    size -= begin;
    file.seekg( 0, std::ios::beg );
    
    //load the file
    /* PROBLEM AREA: pModel is a pointer to a byte.  When I type cast it to a (char*) the file is read BUT it fails the first test below.*/
    pModel = new byte[size];
    file.read( pModel, size );/* the culprit*/
    file.close();
    pPlace = pModel;
    
    //check the header
    ms3d_header_t* pHeader = (ms3d_header_t*) pPlace;
    
    //MS3D000000
    /* PROBLEM AREA: always fails the first test.  I think it has to do with the type cast to (char*)*/
    if( strcmp( pHeader->id, "MS3D000000" ) != 0 )
    {
        if( pModel )
          delete[] pModel;
        
        return 2;
    }
    
    if( pHeader->version < 3 || pHeader->version > 4)
    {
        if( pModel )
          delete[] pModel;
          
        return 3;
    }
    
 
    /*ANY CODE AFTER THIS POINT COMPILES FINE, BUT IT HAS NEVER BEEN TESTED.  I've included it to show what my function hopes to accomplish, but it has no importance to my question as of yet.*/
 

    //increment
    pPlace = pPlace + sizeof( ms3d_header_t );
    
    //vertices
    vertexNum = (int)*pPlace;
    
    pPlace = pPlace + sizeof( word );
    ms3d_vertex_t* pVertex = (ms3d_vertex_t*)pPlace;
    m_vertices = new WEVertex[vertexNum];
    
    //load up the vertices and increment
    for( int i = 0; i < vertexNum; i++ )
    {
      m_vertices.m_pos.m_X = pVertex->vertex[0];
      m_vertices.m_pos.m_Y = pVertex->vertex[1];
      m_vertices.m_pos.m_Z = pVertex->vertex[2];
      
      pVertex = (ms3d_vertex_t*)( pPlace + sizeof( ms3d_vertex_t ) );
    }
    //number of triangles
    pPlace = (byte*)pVertex;
    triangleNum = (int)*pPlace;
    m_polygons = new WEPolygon[triangleNum];
    
    //increment
    pPlace = pPlace + sizeof( word );
    
    ms3d_triangle_t* pTriangle = ( ms3d_triangle_t*)pPlace;
    
    //load and increment triangles
    for( int i = 0; i < triangleNum; i++ )
    {
         //load vertex indices
         m_polygons.m_vertexIndices[0] = (int)pTriangle->vertexIndices[0];
         m_polygons.m_vertexIndices[1] = (int)pTriangle->vertexIndices[1];
         m_polygons.m_vertexIndices[2] = (int)pTriangle->vertexIndices[2];
         
         //load vertex normals
         for( int j = 0; j < 3; j++ )
         {
              m_polygons.m_vertexNormals[j].m_X = (double)pTriangle->vertexNormals[j][0];
              m_polygons.m_vertexNormals[j].m_Y = (double)pTriangle->vertexNormals[j][1];
              m_polygons.m_vertexNormals[j].m_Z = (double)pTriangle->vertexNormals[j][2];
         }
         
         //increment the triangle
         pTriangle = (ms3d_triangle_t*)(pPlace + sizeof(ms3d_triangle_t));
    }
    
    //get ready for meshes
    pPlace = (byte*)pTriangle;
    meshNum = *((int*)pPlace);
    m_meshNum = meshNum;
    m_meshes = new WEMesh[meshNum];
    pPlace = pPlace + sizeof(word);
    ms3d_group_t* pMesh = (ms3d_group_t*)pPlace;
    
    //increment and load meshes (groups)
    for( int i = 0; i < meshNum; i++ )
    {
         m_meshes.m_triangleNum = (int)pMesh->numtriangles;
         
         m_meshes.m_triangleIndices = new int[m_meshes.m_triangleNum];
         
         //match up indices
         for( int j = 0; j < m_meshes.m_triangleNum; j++ )
         {
              m_meshes.m_triangleIndices[j] = (int)pMesh->triangleIndices[j];
         }
         
         //material index
         m_meshes.m_materialIndex = (int)pMesh->materialIndex;
         
         //increment
         pMesh = (ms3d_group_t*)(pPlace + sizeof( *pMesh ));
    }
    
    //material
    pPlace = (byte*)pMesh;
    materialNum = *((int*)pPlace);
    m_materialNum = materialNum;
    m_materials = new WEMaterial[materialNum];
    pPlace = pPlace + sizeof(word);
    ms3d_material_t* pMaterial = (ms3d_material_t*)pPlace;
    
    //load and increment materials
    for( int i = 0; i < materialNum; i++ )
    {
         for( int j = 0; j < 4; j++ )
         {
              m_materials.m_ambient[j] = (double)pMaterial->ambient[j];
              m_materials.m_diffuse[j] = (double)pMaterial->diffuse[j];
              m_materials.m_specular[j] = (double)pMaterial->specular[j];
              m_materials.m_emissive[j] = (double)pMaterial->emissive[j];
         }
         
         m_materials.m_shininess = (double)pMaterial->shininess;
         
         pMaterial = (ms3d_material_t*)( pPlace + sizeof(ms3d_material_t));
    }
    
    //more to come
    pPlace = (byte*)pMaterial;
    
    //free up used memory
    delete[] pModel;
    
    return 0;
}




Share this post


Link to post
Share on other sites
Advertisement
Have you tryed to change the check like this
if( strcmp( (char*)pHeader->id, "MS3D000000" ) != 0 )

I assume this problem could be in strcmp (I assume that pHeader->id has the null-terminator)?

Share this post


Link to post
Share on other sites
If the program crashes when it ends, there's a 99.99% chance that it's because of something you're doing wrong in the WEModel's destructor. Check to make sure you're not deleting something twice.

Share this post


Link to post
Share on other sites
@ nsto: Thanks. I was deleting hanging pointers, but it works great now.

@Paulius: I tried what you said, but it did nothing. On a whim, I decided to just comment out the tests, and run the function. The program locked up numerous times, and I just kept on localizing, and commenting out problem code until it ran without a hitch. I'm really starting to think that the Milkshape 3D model specification that I'm using is out of date, and that the tests were doing their job.

New Question: Will the "MilkShape 3D 1.4.0 File Format Specification" work for Milkshape 3D ver 1.7.9? ( I think I can hazzard a guess: no )

In that case, would anyone know where I can find an up to date file format specification?

Share this post


Link to post
Share on other sites
here

Your problem is almost certainly where you check the version of ms3d that created the file: you're returning if it's not 1.3 or 1.4...

if( pHeader->version < 3 || pHeader->version > 4)
{
if( pModel )
delete[] pModel;

return 3;
}


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!