Skip to main content
GameDev.net gamedev.net
🔒 Locked

Milkshape Texture Problem

Started by JCK Apr 5, 2005 at 8:35 PM 12 replies 4.6k views
Original Post
JCK
JCK
Hello again everyone. I am having problems texturing in my program. I am using Brett Porter's code from NeHe, and it is outdated (uses Milkshape 1.3&1.4). Brett Porter's site is supposed to have the updated code but for some reason it is down. I was hoping someone could shed some light as to why the texture mapping problem occurs and how to fix it. I am also using SDL along with OGL and was wondering if there is a way to store the textures on an SDL Surface then change them to OGL textures. The current bitmap loading code is done with a GLaux function (that I want to stay away from), is there a way to get around that? I really want to keep my code pure SDL/OGL. Thanks ^_^
JCK
JCK
The textures somehow aren't applied to the mesh and it ends up being rendered white.

If you look at the NeHe source from Brett Porter's Milkshape tutorial (lesson 31 I believe), and try to load models that were made using milkshape 1.5+, you will also see what I am refering to.

In his own tutorials he even says that he corrected the problems and released the new source; however, the site seems to not be updated and the link for his source is broken.

Quote:
From Brett Porter @ http://rsn.gamedev.net/tutorials/ms3danim.asp
Fixed texture loading: Milkshape 1.5.x introduced relative paths - these work now.


I was just wondering if anyone knows exactly how to solve this problem since his source is unavailable.

Any hint as to what is needed is greatly appreciated.
Kalidor
Kalidor
Quote:
Original post by JCK
...
Quote:
From Brett Porter @ http://rsn.gamedev.net/tutorials/ms3danim.asp
Fixed texture loading: Milkshape 1.5.x introduced relative paths - these work now.

...
Any hint as to what is needed is greatly appreciated.


From that quote it sounds like in versions <1.5 all textures in the file were pointed to by their full path (ie: "C:\dir1\dir2\textures\texture1.tga") but now they are relative to where the model is saved (ie: "..\textures\texture1.tga" if it was saved in some other directory inside dir2 in the previous example), or maybe relative to Milkshape's base directory. You'll have to find some specifications for >1.5 format versions to find exactly what it's relative to and then take that into account in your code.
JCK
JCK
Quote:
Original post by Kalidor
...
From that quote it sounds like in versions <1.5 all textures in the file were pointed to by their full path (ie: "C:\dir1\dir2\textures\texture1.tga") but now they are relative to where the model is saved.


You know, I didn't even think that he meant relative path names in reference to directories. I thought it had something to do with the way Milkshape textured the meshes.

Thanks Kalidor, I'm going to take a look at that right now and see if that is the problem.
JCK
JCK
Ok, if the relative path names are the problem, then I'm not sure if I'm seeing it at all in the code. Here is the code specific to the textures:

From Model.cpp
void Model::draw() {	GLboolean texEnabled = glIsEnabled( GL_TEXTURE_2D );	// Draw by group	for ( int i = 0; i < m_numMeshes; i++ )	{		int materialIndex = m_pMeshes.m_materialIndex;		if ( materialIndex >= 0 )		{			glMaterialfv( GL_FRONT, GL_AMBIENT, m_pMaterials[materialIndex].m_ambient );			glMaterialfv( GL_FRONT, GL_DIFFUSE, m_pMaterials[materialIndex].m_diffuse );			glMaterialfv( GL_FRONT, GL_SPECULAR, m_pMaterials[materialIndex].m_specular );			glMaterialfv( GL_FRONT, GL_EMISSION, m_pMaterials[materialIndex].m_emissive );			glMaterialf( GL_FRONT, GL_SHININESS, m_pMaterials[materialIndex].m_shininess );			if ( m_pMaterials[materialIndex].m_texture > 0 )			{				glBindTexture( GL_TEXTURE_2D, m_pMaterials[materialIndex].m_texture );				glEnable( GL_TEXTURE_2D );			}			else				glDisable( GL_TEXTURE_2D );		}		else		{			// Material properties?			glDisable( GL_TEXTURE_2D );		}		glBegin( GL_TRIANGLES );		{			for ( int j = 0; j < m_pMeshes.m_numTriangles; j++ )			{				int triangleIndex = m_pMeshes.m_pTriangleIndices[j];				const Triangle* pTri = &m_pTriangles[triangleIndex];				for ( int k = 0; k < 3; k++ )				{					int index = pTri->m_vertexIndices[k];					glNormal3fv( pTri->m_vertexNormals[k] );					glTexCoord2f( pTri->m_s[k], pTri->m_t[k] );					glVertex3fv( m_pVertices[index].m_location );				}			}		}		glEnd();	}	if ( texEnabled )		glEnable( GL_TEXTURE_2D );	else		glDisable( GL_TEXTURE_2D );}void Model::reloadTextures(){	for ( int i = 0; i < m_numMaterials; i++ )		if ( strlen( m_pMaterials.m_pTextureFilename ) > 0 )			m_pMaterials.m_texture = LoadGLTexture( m_pMaterials.m_pTextureFilename );		else			m_pMaterials.m_texture = 0;}


From MilkshapeModel.cpp
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."	inputFile.seekg( 0, ios::end );	long fileSize = inputFile.tellg();	inputFile.seekg( 0, ios::beg );	byte *pBuffer = new byte[fileSize];	inputFile.read( (char *)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;		m_pMaterials.m_pTextureFilename = new char[strlen( pMaterial->m_texture )+1];		strcpy( m_pMaterials.m_pTextureFilename, pMaterial->m_texture );		pPtr += sizeof( MS3DMaterial );	}	reloadTextures();	delete[] pBuffer;	return true;}


From main.cpp
AUX_RGBImageRec *LoadBMP(const char *Filename)						// Loads A Bitmap Image{	FILE *File=NULL;												// File Handle	if (!Filename)													// Make Sure A Filename Was Given	{		return NULL;												// If Not Return NULL	}	File=fopen(Filename,"r");										// Check To See If The File Exists	if (File)														// Does The File Exist?	{		fclose(File);												// Close The Handle		return auxDIBImageLoad(Filename);							// Load The Bitmap And Return A Pointer	}	return NULL;													// If Load Failed Return NULL}GLuint LoadGLTexture( const char *filename )						// Load Bitmaps And Convert To Textures{	AUX_RGBImageRec *pImage;										// Create Storage Space For The Texture	GLuint texture = 0;												// Texture ID	pImage = LoadBMP( filename );									// Loads The Bitmap Specified By filename	// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit	if ( pImage != NULL && pImage->data != NULL )					// If Texture Image Exists	{		glGenTextures(1, &texture);									// Create The Texture		// Typical Texture Generation Using Data From The Bitmap		glBindTexture(GL_TEXTURE_2D, texture);		glTexImage2D(GL_TEXTURE_2D, 0, 3, pImage->sizeX, pImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, pImage->data);		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);		free(pImage->data);											// Free The Texture Image Memory		free(pImage);												// Free The Image Structure	}	return texture;													// Return The Status}
mrbastard
mrbastard
If it is a problem with the path, then I can see why it would cause the problem: reloadTextures doesn't check if the texture load worked, so even if it couldn't find the file it will try to draw the texture anyway. So if the textures weren't found the texture handles would all be 0, hence the whiteness. (read reloadTextures.... not that you posted it ;¬) )

Something that won't be immediately helpful, but maybe in future: ms3d <1.5 had 2 textures per material, one for colour, the other an alpha mask. Recent versions ignore the second texture and just have the first as RGBA (so no mask needed).
[size="1"]
levjs
levjs
No, what it is is the position of the .ms3d file relative to the texture files. It has nothing to do with the code. For example, if you put the ms3d file on the desktop origananly, and the textures are in your project folder, then when you move the ms3d file to put it in your project folder, the milkshape file will look for the pictures in the place relative to the old position, except, they won't be there, because the relative position will have changed. Does this make sence. I had the same problem before i figured it out. If you want i can send you a project with the ms3d file loaded in with textures for an example. I will need an email adress though. Tell me if what i said helps you or if you don't understand it.
Levi
mrbastard
mrbastard
My point was that the reason it isn't obvious is that the code doesn't react if the textures weren't found.
[size="1"]
JCK
JCK
Quote:
Original post by levjs
No, what it is is the position of the .ms3d file relative to the texture files. It has nothing to do with the code. For example, if you put the ms3d file on the desktop origananly, and the textures are in your project folder, then when you move the ms3d file to put it in your project folder, the milkshape file will look for the pictures in the place relative to the old position, except, they won't be there, because the relative position will have changed. Does this make sence. I had the same problem before i figured it out. If you want i can send you a project with the ms3d file loaded in with textures for an example. I will need an email adress though. Tell me if what i said helps you or if you don't understand it.
Levi


I would love source, thanks: DirtyInvincible@gmail.com

I'm still quite unclear about how that is the problem. Technically, if the .ms3d file points to a specific location then bases the location of the textures relative to that position, then they aren't relative at all. They are still absolute, because the point of reference is defined as an absolute location. If they were truely relative, this wouldn't cause an issue. During my debugging, I checked to see if the pathnames were ok, and they were. Not only were they ok, but they were also relative to the .ms3d file. Which is why this is bugging me. Everyone is saying it is a problem with pathnames, but it doesn't seem at all like the problem.

The current code reads the file name correctly, it finds the file correctly, it even reads in some information, which I assumed was the texture. I just don't see why it isn't applying the texture to the mesh, or what it had to do with pathnames.
levjs
levjs
I will send you a project with a ms3d file loaded in. If you export a ms3d file with textures into a Milkshape 3D ASCII, at the bottom of the txt file that results, you will see the textures. Here is an example.
Do you see how the path is just \Data\.bmp not a full pathname. This is because the ms3d file is in a folder and the textures it are loading are in a folder within the folder called Data. So if you moved the ms3d file to the desktop, then the textures would no longer be able to be called because the Data folder needs to stay in the same position relative to the ms3d file. Do you understand? I will send you the project with the ms3d file sometime today.
Levi
Materials: 6
"Wood"
0.200000 0.200000 0.200000 1.000000
0.800000 0.800000 0.800000 1.000000
0.000000 0.000000 0.000000 1.000000
0.000000 0.000000 0.000000 1.000000
0.000000
1.000000
".\Data\wood.bmp"
""
"Slate"
0.200000 0.200000 0.200000 1.000000
0.800000 0.800000 0.800000 1.000000
0.000000 0.000000 0.000000 1.000000
0.000000 0.000000 0.000000 1.000000
0.000000
1.000000
".\Data\slate.bmp"
""
"Door"
0.200000 0.200000 0.200000 1.000000
0.800000 0.800000 0.800000 1.000000
0.000000 0.000000 0.000000 1.000000
0.000000 0.000000 0.000000 1.000000
0.000000
1.000000
".\Data\door.bmp"
""
levjs
levjs
Also are you putting the Model->reloadTextures(); line in the initGL function. Replacing Model with whatever your pointer for your model is in your program. Without this line it will not load the textures.
Levi
JCK
JCK
Quote:
Original post by levjs
Also are you putting the Model->reloadTextures(); line in the initGL function. Replacing Model with whatever your pointer for your model is in your program. Without this line it will not load the textures.
Levi


OMG, Levi, you are my hero. That was the problem. I was reloading the textures before my window initialization. No wonder why they didn't load. >_<

Thanks for the help!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.