problem loading 3ds models

Started by
1 comment, last by vbuser1338 18 years, 8 months ago
I am trying to load a 3ds model that I export from Wings3d but I read the Main Chunk right and then it goes all wrong. I am basing it on the tutorial at http://www.spacesimulator.net/tut4_3dsloader.html. I just want to load the vertex data and the texture coords but I can't get it to work. I read in the first chunk which ends up to be '4d4d' but then the next chunk to read I expect to be the Editor Chunk but i get 200. I have no clue why I am getting this weird number. Here is my source if anyone sees anything wrong with the code. And I have tried different models made in different programs just to check if wings exported it wrong or something but I get the same thing.

#include <iostream>
#include <fstream>	// File I/O
#include <cstdlib>	// exit
#include <string>	// strings

class Vertex {
	float x,y,z;
	float u,v;
};

class Model {
	private:
	
	public:
		Model();
		~Model();
		Vertex* vertex;
		std::string name;	// The name of the model
};

Model::Model() {
	vertex = NULL;	// Set it to null
}

Model::~Model() {
	delete [] vertex;	// Free the vertices
}

int main (int argc, char * const argv[]) {
	Model cube;							// The model to load
	
	std::ifstream model("axe.3ds",std::ios::in);	// The file to load
	if(!model.is_open()) {
		std::cerr << "Invalid model name";
		exit(1);
	}
	
	unsigned short chunkID;		// The ID of the chunk ( hexidecimal ) - 2 bytes
	unsigned long chunkLength;	// The length of the chunk	- 4 bytes
	unsigned char name[20];		// Name of the model
	
	while(model.peek()) {
		if(model.eof()) {
			std::cerr << "Reading past end of file";
			exit(1);
		}
		
		// Read in data about the chunk
		model.read((char*)&chunkID,2);		// Read the 2 bytes for the chunk
		int pos = model.tellg();
		std::cout << "pos " << pos << std::endl;
		model.read((char*)&chunkLength,4);	// Read the 4 bytes for the length
		pos = model.tellg();
		std::cout << "pos " << pos << std::endl;
		
		std::cout << std::hex << chunkID << std::endl;
		std::cout << std::dec << "Chunk Length:" << chunkLength << std::endl;
		
		// Which chunk are we on
		switch (chunkID) {
			// Main chunck nothing to do but don't skip	
			case 0x4d4d:
				std::cout << "Main chunk\n";
			break;
			
			// 3d Editor Chunk don't need
			case 0x3d3d:
				std::cout << "Editor chunk\n";
			break;
				
			// The Object block contains the name
			case 0x4000:
				model.read((char*)&name,20);	// Read in max of 20 bytes
				cube.name = (char*)name;		// Record the name
				std::cout << "Name of model is " << cube.name << std::endl;
			break;
				
			// The defaul case
			default:
				std::cout << "Default case\n";
				model.seekg(chunkLength - 6,std::ios::cur);	// Go to next chunk ( account for 6 bytes read )
		}				
	}
	model.close();	// Close the file
	
    return 0;
}

and this is the output I get pos 2 pos 6 4d4d Chunk Length:3216573440 Main chunk pos 8 pos 12 200 Chunk Length:167772160 Default case pos -1 pos -1 200 Chunk Length:167772160 Default case Reading past end of file Executable “3ds Loader” has exited with status 1. As you can see it reads the first chunk right but not the second. Can anyone help me figure out why this is happening. Thanks for any help, vbuser
Advertisement
Here's a dump of the chunks from their sample program:
ChunkID: 0x4d4dChunkLength: 21824ChunkID: 0x2ChunkLength: 10ChunkID: 0x3d3dChunkLength: 21808ChunkID: 0x3d3eChunkLength: 10ChunkID: 0xafffChunkLength: 192ChunkID: 0xafffChunkLength: 166ChunkID: 0x100ChunkLength: 10ChunkID: 0x4000ChunkLength: 21424ChunkID: 0x4100ChunkLength: 21407ChunkID: 0x4110ChunkLength: 7796ChunkID: 0x4140ChunkLength: 5200ChunkID: 0x4111ChunkLength: 1306ChunkID: 0x4160ChunkLength: 54ChunkID: 0x4165ChunkLength: 7ChunkID: 0x4120ChunkLength: 7038ChunkID: 0x4130ChunkLength: 1024ChunkID: 0x4150ChunkLength: 2006


I don't know if this helps, but you can see the next chunk in their sample file is not the editor chunk. Also, your chunk lengths seem too large... I am too tired to look too deep into it, but maybe this will give you a start.
I just downloaded the source and it has a funtion to convert chars to different data types because thats how it reads it in. The code it uses is
 float ConvertEndianf(float infloat) {	union floatunion { unsigned char part[4]; float float_value; } Converter;	char swap_char;		Converter.float_value = infloat;	swap_char = Converter.part[0]; Converter.part[0] = Converter.part[3]; Converter.part[3] = swap_char;	swap_char = Converter.part[1]; Converter.part[1] = Converter.part[2]; Converter.part[2] = swap_char;		return Converter.float_value; }  unsigned long ConvertEndianul(unsigned long inlong) { 	union longunion { unsigned char part[4]; unsigned long long_value; } Converter;	char swap_char;		Converter.long_value = inlong;	swap_char = Converter.part[0]; Converter.part[0] = Converter.part[3]; Converter.part[3] = swap_char;	swap_char = Converter.part[1]; Converter.part[1] = Converter.part[2]; Converter.part[2] = swap_char;		return Converter.long_value; }  unsigned short ConvertEndianus(unsigned short inshort) {	union shortunion { unsigned char part[2]; unsigned short short_value; } Converter;	char swap_char;		Converter.short_value = inshort;	swap_char = Converter.part[0]; Converter.part[0] = Converter.part[1]; Converter.part[1] = swap_char;		return Converter.short_value; }

I don't know exactly why they have to flip it from right to left but it seems to work so it doesn't bother me. They don't seem to include everything you need to load the model.
Thanks for the help.
vbuser

This topic is closed to new replies.

Advertisement