Thread: Error when loading 3ds file

  1. #1
    Registered User
    Join Date
    Jan 2006
    Location
    Sweden
    Posts
    92

    Error when loading 3ds file

    Hi, I've written a 3Ds file loader for my OpenGL program. It is very simple and only includes the model.

    This is one of my first C++ programs and I know this is quite advanced but I found a nice tutorial and decided to let go of Flash and learn C++ along with OpenGL.

    Anyway, this is the loader code:
    (Code in TDs.h)
    Code:
    #ifndef _3DS_H
    #define _3DS_H
    
    #include "main.h"
    #include <vector>
    
    #define CHUNK_MAIN 0x4D4D
    #define CHUNK_3D_EDITOR 0x3D3D
    #define CHUNK_BLOCK 0x4000
    #define CHUNK_TRIANGULAR 0x4100
    #define CHUNK_VERTICES 0x4110
    #define CHUNK_FACES 0x4120
    #define CHUNK_MAPPING 0x4140
    
    using namespace std;
    
    struct vector3{
           vector3(){}
           float x;
           float y;
           float z;
           vector3(float newX, float newY, float newZ){
                        x=newX;
                        y=newY;
                        z=newZ;
                         }
    };
    
    struct tFace
    {
           int vertexIndex[3];
           int coordIndex[3];
    };
    
    struct tDobj
    {
           int numOfVerts;
           int numOfFaces;
           char name;
           vector3 *pVerts;
           tFace *pFaces;   
    };
    struct tDmodel
    {
           int numOfObjects;
           vector<tDobj> pObject;
    };
            
    struct tChunk
    {
           unsigned short int id;
           unsigned int length;
           unsigned int bytesRead;
    };
    class TdsLoader
    {
          public:
                 TdsLoader();
                 bool TdsLoader::load3Ds(char* filename, tDmodel* pModel);
          private:
                 void TdsLoader::readToNextChunk(tDmodel* pModel, tChunk* mainChunk);
                 void TdsLoader::readVertices(tDobj* pObject, tChunk* mainChunk);
                 void TdsLoader::readChunk(tChunk* chunk);
                 void TdsLoader::readObjectChunk(tDobj* pObject, tChunk* mainChunk);
                 void TdsLoader::readVertexIndicies(tDobj* pObject, tChunk* mainChunk);
                 tChunk* mainChunk;
                 tChunk* brChunk;
                 FILE* file;
                  
    };
    #endif
    (Code in TDs.cpp)

    Code:
    #include "main.h"
    #include "TDs.h"
    #include <stdio.h>
    #include <vector>
    
    TdsLoader::TdsLoader() {}
    
    bool TdsLoader::load3Ds (char *filename, tDmodel* pModel)
    {
           tChunk* mainChunk;
           tChunk* brChunk;
           file = NULL;
           
           MessageBox(NULL, "Opening File...", "Information", MB_OK);
           if (!filename)
           {  
              return false;
              }
           file = fopen(filename, "rb");
           if (!file)
           {
                     MessageBox(NULL, "Unable to open file", "Error", 0);
                     return false;
           }
          readToNextChunk(pModel, mainChunk);
    }
           
    void TdsLoader::readToNextChunk(tDmodel *pModel, tChunk *mainChunk)
    {        
           int i=0;
           int* buffer;
           tDobj newObject = {0};
           MessageBox(NULL, "Reading Chunk", "Information", MB_OK);
           readChunk(mainChunk);
           MessageBox(NULL, "Checking chunk...", "Information", MB_OK);  
           switch (mainChunk->id)
           {
                  case CHUNK_MAIN:
                       MessageBox(NULL, "Main chunk found", "Information", MB_OK);
                       readToNextChunk(pModel, mainChunk);
                       break;
                       
                  case CHUNK_BLOCK:
                       MessageBox(NULL, "Block chunk found", "Information", MB_OK);
                       pModel->numOfObjects++;
                       pModel->pObject.push_back(newObject);
                       char temp_name;                   
                       do
                       {
                       fread(&temp_name, 1, 1, file);
                       pModel->pObject[pModel->numOfObjects-1].name += temp_name;
                       i++;
                       }
                       while (&temp_name != "\0" && i<20);
                       readObjectChunk(&pModel->pObject[pModel->numOfObjects-1], mainChunk);
                       break;
                       
                  default:
                       MessageBox(NULL, "Default chunk found", "Information", MB_OK);
                       mainChunk->bytesRead += fread(buffer, 1, mainChunk->length - mainChunk->bytesRead, file);
                       readToNextChunk(pModel, mainChunk);
                       break;
                  
           }
    }            
    
    void TdsLoader::readChunk(tChunk* chunk)
    {
       MessageBox(NULL, "Checking id", "Information", MB_OK);
       chunk->bytesRead = fread(&chunk->id, 1, 2, file);
        MessageBox(NULL, "Checking length", "Information", MB_OK);
       chunk->bytesRead += fread(&chunk->length, 1, 4, file);
    }                 
                       
    void TdsLoader::readObjectChunk(tDobj* pObject, tChunk* mainChunk)
    {
         brChunk = new tChunk;
         brChunk->length = mainChunk->length;
         readChunk(brChunk);
         while (mainChunk->bytesRead < mainChunk->length)
         {
               switch (brChunk->id)
               {
                      case CHUNK_TRIANGULAR:
                           readObjectChunk(pObject, brChunk);
                           break;
                      case CHUNK_VERTICES:
                           readVertices(pObject, brChunk);
                           break;
                      case CHUNK_FACES:
                           readVertexIndicies(pObject, brChunk);
                           break;
                      default:
                           brChunk->bytesRead += fread(NULL, brChunk->length - brChunk->bytesRead, 1, file);
                           break;
               }
         mainChunk->bytesRead += brChunk->bytesRead;
         }
         
    }                                    
    void TdsLoader::readVertices(tDobj* pObject, tChunk* mainChunk)
    {
        
         brChunk->bytesRead += fread(&(pObject->numOfVerts), sizeof(unsigned short), 1, file);
         
         pObject->pVerts = new vector3[pObject->numOfVerts];
         
         mainChunk->bytesRead += fread(pObject->pVerts, 1, mainChunk->length - mainChunk->bytesRead, file);
         
    }
    void TdsLoader::readVertexIndicies(tDobj* pObject, tChunk* mainChunk)
    {
         unsigned short index=0;
         mainChunk->bytesRead += fread(&(pObject->numOfFaces), 1, 2, file);
         pObject->pFaces = new tFace [pObject->numOfFaces];
         for (int i=0; i < pObject->numOfFaces; i++)
         {
             for (int j=0; j < 4; j++)
             {
                 mainChunk->bytesRead += fread(&index, 1, sizeof(index), file);
             if (j>3)
             {
                pObject->pFaces[i].vertexIndex[j] = index;
                }
             }
         }
    }
    And finally the code to initialize this in main.cpp:

    Code:
    tDmodel theModel;
       
        TdsLoader modelLoader;
       
        if (!modelLoader.load3Ds("modell.3DS", &theModel))
        {
           MessageBox(NULL, "Unable to load model", "ERROR", MB_OK);
           }
    This program compiles nicely (after some hours of struggeling ) but when I run it and it reaches the TdsLoader::readChunk function Visual C++ sends me this message:

    "Unhandled exception at 0x00422012 in GLengine.exe: 0xC0000005: Access violation writing location 0xcccccccc.

    And when I compiled it in Dev-Cpp it just crashed at that point. From the debugging information I've noticed that the file pointer is "BadPntr" or something similar in the Visual Studio "Whatch" window.

    Anyone knows what might cause this? Help is really appreciated.

    Thanks - The Wazaa

  2. #2
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    try an open GL forum,

    http://nehe.gamedev.net/

    it's an open gl site

  3. #3
    Registered User
    Join Date
    Jan 2006
    Location
    Sweden
    Posts
    92
    Well, are you sure that the problen is caused by OpenGL? I'm not, the loader might be for an OpenGL model, but that code is pure C++, of what I know at least.
    I'll try there if noone here knows it though ^^

  4. #4
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    bool TdsLoader::load3Ds (char *filename, tDmodel* pModel)
    {
           tChunk* mainChunk;
           tChunk* brChunk;
           file = NULL;
           
           MessageBox(NULL, "Opening File...", "Information", MB_OK);
           if (!filename)
           {  
              return false;
              }
           file = fopen(filename, "rb");
           if (!file)
           {
                     MessageBox(NULL, "Unable to open file", "Error", 0);
                     return false;
           }
          readToNextChunk(pModel, mainChunk);
    }
           
    void TdsLoader::readToNextChunk(tDmodel *pModel, tChunk *mainChunk)
    {        
           int i=0;
           int* buffer;
           tDobj newObject = {0};
           MessageBox(NULL, "Reading Chunk", "Information", MB_OK);
           readChunk(mainChunk);
           MessageBox(NULL, "Checking chunk...", "Information", MB_OK);  
           switch (mainChunk->id)
           {
                  case CHUNK_MAIN:
                       MessageBox(NULL, "Main chunk found", "Information", MB_OK);
                       readToNextChunk(pModel, mainChunk);
                       break;
                       
                  case CHUNK_BLOCK:
                       MessageBox(NULL, "Block chunk found", "Information", MB_OK);
                       pModel->numOfObjects++;
                       pModel->pObject.push_back(newObject);
                       char temp_name;                   
                       do
                       {
                       fread(&temp_name, 1, 1, file);
                       pModel->pObject[pModel->numOfObjects-1].name += temp_name;
                       i++;
                       }
                       while (&temp_name != "\0" && i<20);
                       readObjectChunk(&pModel->pObject[pModel->numOfObjects-1], mainChunk);
                       break;
                       
                  default:
                       MessageBox(NULL, "Default chunk found", "Information", MB_OK);
                       mainChunk->bytesRead += fread(buffer, 1, mainChunk->length - mainChunk->bytesRead, file);
                       readToNextChunk(pModel, mainChunk);
                       break;
                  
           }
    }            
    
    void TdsLoader::readChunk(tChunk* chunk)
    {
       MessageBox(NULL, "Checking id", "Information", MB_OK);
       chunk->bytesRead = fread(&chunk->id, 1, 2, file);
        MessageBox(NULL, "Checking length", "Information", MB_OK);
       chunk->bytesRead += fread(&chunk->length, 1, 4, file);
    }
    Well, your memory management needs work. You call load3Ds from main; load3Ds declares an uninitialized tChunk pointer called mainChunk. This uninitialized pointer then gets passed into the readToNextChunk function which passes it again to the readChunk function. Within the readChunk function you are reading into this uninitialized pointer with those two fread calls. Somethings not right there! Only your readObjectChunk and readVertexIndicies and readVertex functions do any dynamic memory allocation. You are also not cleaning up your memory which you should be doing in the objects destructor.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  5. #5
    Registered User
    Join Date
    Jan 2006
    Location
    Sweden
    Posts
    92
    Ah, thanks a lot I thought that the pointers might need something to point to but didn't consider it for so long ^^ Now it points to a real chunk.

    About that memory cleaning so do I assume that I do it with memset() and delete, what is the difference between delete and memset by the way? I guess I have to add that when this works (There is now a destructor which uses both delete and memset, like this: )

    Code:
    TdsLoader::~TdsLoader() 
    {
    	memset(&realChunk, 0, sizeof(tChunk));
    	delete &realChunk;
    	delete mainChunk;
    	delete brChunk;
    	delete file;
    }

    There's a new problem now though:
    When I read in the default chunk I read to a buffer (int buffer[50000] = {0}; ) which I declares on the same place as the last buffer. I get this error:

    Unhandled exception at 0x0042a295 in GLengine.exe: 0xC00000FD: Stack overflow.

    Is it like I think that it loads too much into the buffer in one time? If I make the buffer bigger I get overflow once I declares it :-/ Anyone knows how to fix that ?

  6. #6
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597
    you're allocating 200k BYTES in each call to readToNextChunk. this is a recursive function, so you allocate 200k, call readToNextChunk, allocate another 200k, call readToNextChunk, allocate another 200k, call readToNextChunk, allocate another 200k, call readToNextChunk, allocate another 200k, and so on....

    can you see how you'd run out of stack space?
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  7. #7
    Registered User Jaqui's Avatar
    Join Date
    Feb 2005
    Posts
    416
    when allocating the memory, plan for large mesh to be read in.
    it's far better to correctly allocate more than required and free it cleanly afterwards than to run short. I have seen .3ds mesh objects in excess of 3 mb.
    [ though the 79 mb .obj mesh file is definately larger ]


    The best idea would be to see how much space the file is using on the drive, and allocate exactly that amount before even opening the file and reading it in.
    Quote Originally Posted by Jeff Henager
    If the average user can put a CD in and boot the system and follow the prompts, he can install and use Linux. If he can't do that simple task, he doesn't need to be around technology.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 03:44 PM
  2. C++ std routines
    By siavoshkc in forum C++ Programming
    Replies: 33
    Last Post: 07-28-2006, 12:13 AM
  3. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  4. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  5. archive format
    By Nor in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 08-05-2003, 07:01 PM