🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

MS3d file format

Started by
2 comments, last by prince_of_persia 16 years, 10 months ago
this is for reading some data in a txt file : inline int ReadObject(char *st, glObject *o){ FILE *file; unsigned int i; file = fopen(st, "r"); if (!file) return FALSE; //points fscanf(file, "%d", &(o->nPoints)); for (i=1;i<=o->nPoints;i++){ fscanf(file, "%f", &(o->points.x)); fscanf(file, "%f", &(o->points.y)); fscanf(file, "%f", &(o->points.z)); } //planes fscanf(file, "%d", &(o->nPlanes)); for (i=0;i<o->nPlanes;i++){ fscanf(file, "%d", &(o->planes.p[0])); fscanf(file, "%d", &(o->planes.p[1])); fscanf(file, "%d", &(o->planes.p[2])); fscanf(file, "%f", &(o->planes.normals[0].x)); fscanf(file, "%f", &(o->planes.normals[0].y)); fscanf(file, "%f", &(o->planes.normals[0].z)); fscanf(file, "%f", &(o->planes.normals[1].x)); fscanf(file, "%f", &(o->planes.normals[1].y)); fscanf(file, "%f", &(o->planes.normals[1].z)); fscanf(file, "%f", &(o->planes.normals[2].x)); fscanf(file, "%f", &(o->planes.normals[2].y)); fscanf(file, "%f", &(o->planes.normals[2].z)); } return TRUE; } and next this pointer send to another functions for rendering the stencil shadow . now i want read this data from MS3D file format and send new pointer to that functions render shadows. now only i want read upper data from a MS3d file only.
Advertisement
Hi,

Firstly, I'm not sure what it is exactly you are asking, do you want to know about the format of MS3D or are you looking for someone to give you code to load it? If it is the former I can help you, if not then I doubt anyone is going to write the code for you.

There is a description of the MS3D file format here

Now as you said you only wanted to read the upper data from the MS3D file I'm guessing you mean everything besides the animation specific stuff (bones etc.) in the lower half of the file. In which case this can be done quite easily. First you will need the structures to store the data, you will also need to typedef byte and word, because despite what your girlfriend tells you, size matters:

#ifndef bytetypedef unsigned char byte;#endif // byte#ifndef wordtypedef unsigned short word;#endif // wordstruct {    char    id[10];                                     // always "MS3D000000"    int     version;                                    // 3} ms3d_header_t;struct {    byte    flags;                                      // SELECTED | SELECTED2 | HIDDEN    float   vertex[3];                                  //    char    boneId;                                     // -1 = no bone    byte    referenceCount;} ms3d_vertex_t;struct {    word    flags;                                      // SELECTED | SELECTED2 | HIDDEN    word    vertexIndices[3];                           //    float   vertexNormals[3][3];                        //    float   s[3];                                       //    float   t[3];                                       //    byte    smoothingGroup;                             // 1 - 32    byte    groupIndex;                                 //} ms3d_triangle_t;struct {    byte            flags;                              // SELECTED | HIDDEN    char            name[32];                           //    word            numtriangles;                       //    word            triangleIndices[numtriangles];      // the groups group the triangles    char            materialIndex;                      // -1 = no material} ms3d_group_t;


Now reading the ms3d file is a piece of cake. In C++ you would do something like this:

#include <fstream>using std::ifstream;bool ReadMS3D(const string& filename) {   ifstream fileIn(filename.c_str(), std::ios::binary);   if (!fileIn.is_open()) {       return false; //The file didnt exist or something   }   ms3d_header_t header;   vector<ms3d_vertex_t> vertices;   vector<ms3d_triangle_t> triangles;   vector<ms3d_group_t> groups;   word numVertices, numTriangles, numGroups;//read the header    fileIn.read(reinterpret_cast<char*>(&header), sizeof(ms3d_header_t));     //Check the header is valid here   //now read in the number of vertices   fileIn.read(reinterpret_cast<char*>(&numVertices), sizeof(word));   //resize the vector to store the vertices you are about to read   vertices.resize(numVertices);   //Read the data into the array   fileIn.read(reinterpret_cast<char*>(&vertices[0]), sizeof(ms3d_vertex_t) * numVertices);   //now read in the number of triangles   fileIn.read(reinterpret_cast<char*>(&numTriangles), sizeof(word));   //resize the vector to store the triangles you are about to read   triangles.resize(numTriangles);   //Read the data into the array   fileIn.read(reinterpret_cast<char*>(&triangles[0]), sizeof(ms3d_triangle_t) * numTriangles);/*    Then do the same with the groups, and materials if you want them. Please note though, the group structure contains another array, this will probably mean you will need to read the groups on an attribute-by-attribute basis rather than the whole set of structures at once like above.*/}


If it helps I have an UNFINISHED MS3D loader here:
ms3d.cpp
ms3d.h

Please bare in mind that is not complete code so it wont just compile but it will give you an idea on how to do it. Also, the structures will need to be packed take a look at the ms3d.h file to find out how.

If you have any more questions just ask, good luck!
Member of the NeHe team.
******************************************************************************
this is model class :
******************************************************************************


class Model{	public:		double m_totalFrames,m_FPS; 		//	Mesh		struct Mesh		{			int m_materialIndex;			int m_numTriangles;			int *m_pTriangleIndices;		};		//	Material properties		struct Material		{			float m_ambient[4], m_diffuse[4], m_specular[4], m_emissive[4];			float m_shininess;			GLuint m_texture;			char *m_pTextureFilename;		};		//	Triangle structure		struct Triangle		{			float m_vertexNormals[3][3];			float m_s[3], m_t[3];			int m_vertexIndices[3];		};		//	Vertex structure		struct Vertex		{			char m_boneID;	// for skeletal animation			float m_location[3];		};		// { NEW }		//	Animation keyframe information		struct Keyframe		{			int m_jointIndex;			float m_time;	// in milliseconds			float m_parameter[3];		};		//	Skeleton bone joint		struct Joint		{			float m_localRotation[3];			float m_localTranslation[3];			Matrix m_absolute, m_relative;			int m_numRotationKeyframes, m_numTranslationKeyframes;			Keyframe *m_pTranslationKeyframes;			Keyframe *m_pRotationKeyframes;			int m_currentTranslationKeyframe, m_currentRotationKeyframe;			Matrix m_final;			int m_parent;		};		// { end NEW }	public:									/*	Constructor. */		Model();		/*	Destructor. */		virtual ~Model();		/*				Load the model data into the private variables. 				filename			Model filename		*/		virtual bool loadModelData( const char *filename ) = 0;		/*			Draw the model.		*/		void draw(int start_f,int end_f,bool looping);		/*			Called if OpenGL context was lost and we need to reload textures, display lists, etc.		*/		void reloadTextures();	protected:// { NEW }		/*				Set the values of a particular keyframe for a particular joint.				jointIndex		The joint to setup the keyframe for				keyframeIndex	The maximum number of keyframes				time			The time in milliseconds of the keyframe				parameter		The rotation/translation values for the keyframe				isRotation		Whether it is a rotation or a translation keyframe		*/		void setJointKeyframe( int jointIndex, int keyframeIndex, float time, float *parameter, bool isRotation );		/*	Setup joint matrices. */		void setupJoints();				/*	Set looping factor for animation. *///--<i changed it move from protukted to pablic(by sadegh)		void setLooping( bool looping ) { m_looping = looping; }		/*	Advance animation by a frame. */		void advanceAnimation(int start_f ,int end_f,bool looping);		/*	Restart animation. */		void restart();// { end NEW }	protected:		//	Meshes used		int m_numMeshes;		Mesh *m_pMeshes;		//	Materials used		int m_numMaterials;		Material *m_pMaterials;		//	Triangles used		int m_numTriangles;		Triangle *m_pTriangles;		//	Vertices Used		int m_numVertices;		Vertex *m_pVertices;// { NEW }		//	Joint information		int m_numJoints;		Joint *m_pJoints;		//	Timer variable		Timer *m_pTimer;		//	Total animation time		double m_totalTime;		//	Is the animation looping?		bool m_looping;// { end NEW }};



& this is loader


bool MilkshapeModel::loadModelData( const char *filename ){	ifstream inputFile( filename, ios::in | ios::binary | ios::nocreate );	if ( inputFile.fail())		return false;	// "Couldn't open the model file."	char pathTemp[PATH_MAX+1];	int pathLength;	for ( pathLength = strlen( filename ); pathLength--; ) {		if ( filename[pathLength] == '/' || filename[pathLength] == '\\' ) {			break;		}	}	strncpy( pathTemp, filename, pathLength );	inputFile.seekg( 0, ios::end );	long fileSize = inputFile.tellg();	inputFile.seekg( 0, ios::beg );	byte *pBuffer = new byte[fileSize];	inputFile.read( pBuffer, fileSize );	inputFile.close();	const byte *pPtr = pBuffer;	MS3DHeader *pHeader = ( MS3DHeader* )pPtr;	pPtr += sizeof( MS3DHeader );	if ( strncmp( pHeader->m_ID, "MS3D000000", 10 ) != 0 )		return false; // "Not a valid Milkshape3D model file."	if ( pHeader->m_version < 3 || pHeader->m_version > 4 )		return false; // "Unhandled file version. Only Milkshape3D Version 1.3 and 1.4 is supported." );	int nVertices = *( word* )pPtr; 	m_numVertices = nVertices;	m_pVertices = new Vertex[nVertices];	pPtr += sizeof( word );	int i;	for ( i = 0; i < nVertices; i++ )	{		MS3DVertex *pVertex = ( MS3DVertex* )pPtr;		m_pVertices.m_boneID = pVertex->m_boneID;		memcpy( m_pVertices.m_location, pVertex->m_vertex, sizeof( float )*3 );		pPtr += sizeof( MS3DVertex );	}	int nTriangles = *( word* )pPtr;	m_numTriangles = nTriangles;	m_pTriangles = new Triangle[nTriangles];	pPtr += sizeof( word );	for ( i = 0; i < nTriangles; i++ )	{		MS3DTriangle *pTriangle = ( MS3DTriangle* )pPtr;		int vertexIndices[3] = { pTriangle->m_vertexIndices[0], pTriangle->m_vertexIndices[1], pTriangle->m_vertexIndices[2] };		float t[3] = { 1.0f-pTriangle->m_t[0], 1.0f-pTriangle->m_t[1], 1.0f-pTriangle->m_t[2] };		memcpy( m_pTriangles.m_vertexNormals, pTriangle->m_vertexNormals, sizeof( float )*3*3 );		memcpy( m_pTriangles.m_s, pTriangle->m_s, sizeof( float )*3 );		memcpy( m_pTriangles.m_t, t, sizeof( float )*3 );		memcpy( m_pTriangles.m_vertexIndices, vertexIndices, sizeof( int )*3 );		pPtr += sizeof( MS3DTriangle );	}	int nGroups = *( word* )pPtr;	m_numMeshes = nGroups;	m_pMeshes = new Mesh[nGroups];	pPtr += sizeof( word );	for ( i = 0; i < nGroups; i++ )	{		pPtr += sizeof( byte );	// flags		pPtr += 32;				// name		word nTriangles = *( word* )pPtr;		pPtr += sizeof( word );		int *pTriangleIndices = new int[nTriangles];		for ( int j = 0; j < nTriangles; j++ )		{			pTriangleIndices[j] = *( word* )pPtr;			pPtr += sizeof( word );		}		char materialIndex = *( char* )pPtr;		pPtr += sizeof( char );			m_pMeshes.m_materialIndex = materialIndex;		m_pMeshes.m_numTriangles = nTriangles;		m_pMeshes.m_pTriangleIndices = pTriangleIndices;	}	int nMaterials = *( word* )pPtr;	m_numMaterials = nMaterials;	m_pMaterials = new Material[nMaterials];	pPtr += sizeof( word );	for ( i = 0; i < nMaterials; i++ )	{		MS3DMaterial *pMaterial = ( MS3DMaterial* )pPtr;		memcpy( m_pMaterials.m_ambient, pMaterial->m_ambient, sizeof( float )*4 );		memcpy( m_pMaterials.m_diffuse, pMaterial->m_diffuse, sizeof( float )*4 );		memcpy( m_pMaterials.m_specular, pMaterial->m_specular, sizeof( float )*4 );		memcpy( m_pMaterials.m_emissive, pMaterial->m_emissive, sizeof( float )*4 );		m_pMaterials.m_shininess = pMaterial->m_shininess;		if ( strncmp( pMaterial->m_texture, ".\\", 2 ) == 0 ) {			// MS3D 1.5.x relative path			strcpy( pathTemp + pathLength, pMaterial->m_texture + 1 );			m_pMaterials.m_pTextureFilename = new char[strlen( pathTemp )+1];			strcpy( m_pMaterials.m_pTextureFilename, pathTemp );		}		else {			// MS3D 1.4.x or earlier - absolute path			m_pMaterials.m_pTextureFilename = new char[strlen( pMaterial->m_texture )+1];			strcpy( m_pMaterials.m_pTextureFilename, pMaterial->m_texture );		}		pPtr += sizeof( MS3DMaterial );	}	reloadTextures();// { NEW }	// Load Skeletal Animation Stuff	float animFPS = *( float* )pPtr;	pPtr += sizeof( float );	// skip currentTime	pPtr += sizeof( float );			int totalFrames = *( int* )pPtr;	pPtr += sizeof( int );	m_totalFrames = totalFrames;// <-- add this.. 	m_FPS = animFPS; // <-- add this..					m_totalTime = totalFrames*1000.0/animFPS;	m_numJoints = *( word* )pPtr;	pPtr += sizeof( word );	m_pJoints = new Joint[m_numJoints];	struct JointNameListRec	{		int m_jointIndex;		const char *m_pName;	};	const byte *pTempPtr = pPtr;	JointNameListRec *pNameList = new JointNameListRec[m_numJoints];	for ( i = 0; i < m_numJoints; i++ )	{		MS3DJoint *pJoint = ( MS3DJoint* )pTempPtr;		pTempPtr += sizeof( MS3DJoint );		pTempPtr += sizeof( MS3DKeyframe )*( pJoint->m_numRotationKeyframes+pJoint->m_numTranslationKeyframes );		pNameList.m_jointIndex = i;		pNameList.m_pName = pJoint->m_name;	}	for ( i = 0; i < m_numJoints; i++ )	{		MS3DJoint *pJoint = ( MS3DJoint* )pPtr;		pPtr += sizeof( MS3DJoint );		int j, parentIndex = -1;		if ( strlen( pJoint->m_parentName ) > 0 )		{			for ( j = 0; j < m_numJoints; j++ )			{				if ( stricmp( pNameList[j].m_pName, pJoint->m_parentName ) == 0 )				{					parentIndex = pNameList[j].m_jointIndex;					break;				}			}			if ( parentIndex == -1 ) // Unable to find parent bone in MS3D file				return false;		}		memcpy( m_pJoints.m_localRotation, pJoint->m_rotation, sizeof( float )*3 );		memcpy( m_pJoints.m_localTranslation, pJoint->m_translation, sizeof( float )*3 );		m_pJoints.m_parent = parentIndex;		m_pJoints.m_numRotationKeyframes = pJoint->m_numRotationKeyframes;		m_pJoints.m_pRotationKeyframes = new Keyframe[pJoint->m_numRotationKeyframes];		m_pJoints.m_numTranslationKeyframes = pJoint->m_numTranslationKeyframes;		m_pJoints.m_pTranslationKeyframes = new Keyframe[pJoint->m_numTranslationKeyframes];		for ( j = 0; j < pJoint->m_numRotationKeyframes; j++ )		{			MS3DKeyframe *pKeyframe = ( MS3DKeyframe* )pPtr;			pPtr += sizeof( MS3DKeyframe );			setJointKeyframe( i, j, pKeyframe->m_time*1000.0f, pKeyframe->m_parameter, true );		}		for ( j = 0; j < pJoint->m_numTranslationKeyframes; j++ )		{			MS3DKeyframe *pKeyframe = ( MS3DKeyframe* )pPtr;			pPtr += sizeof( MS3DKeyframe );			setJointKeyframe( i, j, pKeyframe->m_time*1000.0f, pKeyframe->m_parameter, false );		}	}	delete[] pNameList;	setupJoints();// { end NEW }	delete[] pBuffer;	return true;}


now i must add this data to the class and add reading code to loader:

GLuint nPlanes, nPoints;
sPoint points[100];
sPoint planes[200];



defination of sPoint , sPoint is :
// vertex in 3d-coordinate systemstruct sPoint{	float x, y, z;};// plane equationstruct sPlaneEq{	float a, b, c, d;};// structure describing an object's facestruct sPlane{	unsigned int p[3];	sPoint normals[3];	unsigned int neigh[3];	sPlaneEq PlaneEq;	bool visible;};



thanx


this is link of it :

http://rapidshare.com/files/48277718/SHEED_ENGINE_0.zip.html

this program render shadow for TXT file ,now i want render shadow for a MS3D file .
in this toturial model structure have upper data (that say before) but my MS3D class has not that , i must add to that and send pointer to CAST SHADOW and other function.

can u or frinds complit this ?

is best of the best if upload your new project for other to see and download it.

i most say it is based on NEHE .

thanx

This topic is closed to new replies.

Advertisement