milkshape models...

BlitzMax Forums/BlitzMax OpenGL Programming/milkshape models...

Hey all,
I would like to load 3d models into my program and Nehe's
Milkshape model loader seems to be a good start. Problem
is, the loader says it only supports milkshape file versions 1.3 and 1.4.
The current Milkshape version is 1.7. Where can I find an old build?

Or better yet, are there any newer ways to load 3d models?
What are you guys currently using?

heres some code I hacked out of a nehe demo (had to do a bit of fixing, because of the way max has changed over time)

'********
' taken from nehe 31 tutorial
' debugged!

' Mesh
Type Mesh
	Field m_materialIndex:Int
	Field m_numTriangles:Int
	Field m_pTriangleIndices:Int[]
End Type
' Material properties
Type Material
	Field m_ambient:Float[4], m_diffuse:Float[4], m_specular:Float[4], m_emissive:Float[4]
	Field m_shininess:Float
	Field m_texture:Int
	Field m_pTextureFilename:String
End Type
' Triangle structure
Type Triangle
	Field m_vertexNormals:Float[3,3]
	Field m_s:Float[3], m_t:Float[3]
	Field m_vertexIndices:Int[3]
End Type
' Vertex structure
Type Vertex
	Field m_boneID:Byte		' For skeletal animation
	Field m_location:Float[3]
End Type
' *********************************************************************************************
' Model class   extend for other model types
' *********************************************************************************************
Type Model Abstract
	' Meshes used
	Field m_numMeshes:Int
	Field m_pMeshes:Mesh[]
	' Materials used
	Field m_numMaterials:Int
	Field m_pMaterials:Material[]
	' Triangles used
	Field m_numTriangles:Int
	Field m_pTriangles:Triangle[]
	' Vertices Used
	Field m_numVertices:Int
	Field m_pVertices:Vertex[]

	Method draw() 
		Local texEnabled:Byte=glIsEnabled(GL_TEXTURE_2D)
		' Draw by group
		Local i:Int
		For i=0 Until m_numMeshes
			Local materialIndex:Int=m_pMeshes[i].m_materialIndex
			If materialIndex >= 0 Then
				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 Then
					glBindTexture(GL_TEXTURE_2D, m_pMaterials[materialIndex].m_texture )
					glEnable(GL_TEXTURE_2D )
				Else
					glDisable(GL_TEXTURE_2D)
				EndIf
			Else
				' Material properties?
				glDisable(GL_TEXTURE_2D)
			EndIf
			glBegin(GL_TRIANGLES)
				For Local j:Int=0 Until m_pMeshes[i].m_numTriangles
					Local triangleIndex:Int = m_pMeshes[i].m_pTriangleIndices[j]
					For Local k:Int=0 Until 3
						Local index:Int = m_pTriangles[triangleIndex].m_vertexIndices[k]
						glNormal3fv(Varptr m_pTriangles[triangleIndex].m_vertexNormals[k,0])
						glTexCoord2f(m_pTriangles[triangleIndex].m_s[k], m_pTriangles[triangleIndex].m_t[k])
						glVertex3fv(Varptr m_pVertices[index].m_location[0])
					Next
				Next
			glEnd()
		Next
		If texEnabled Then
			glEnable(GL_TEXTURE_2D)
		Else
			glDisable(GL_TEXTURE_2D)
		EndIf
	End Method

	Method reloadTextures()
'		Print m_numMaterials
		For Local i:Int=0 Until m_numMaterials
			If m_pMaterials[i].m_pTextureFilename.length > 0 Then
'				m_pMaterials[i].m_texture = LoadGLTexture(m_pMaterials[i].m_pTextureFilename)
				m_pMaterials[i].m_texture =GLTexFromPixmap(LoadPixmap(m_pMaterials[i].m_pTextureFilename),True)
			Else
				m_pMaterials[i].m_texture = 0
			EndIf
		Next
	End Method
	
End Type

	' Size of MS3D structure
	Global S_MS3DHeader:Int=14, S_MS3DVertex:Int=15, S_MS3DTriangle:Int=70
	Global S_MS3DMaterial:Int=361, S_MS3DJoint:Int=93, S_MS3DKeyframe:Int=16

' *********************************************************************************************
' Model MilkshapeModel
' *********************************************************************************************
Type MilkshapeModel Extends Model

	Field  vert:tbank,ind:tbank
	Method loadModelData:Int(filename:String)
		Local In:tstream=OpenFile(filename)
		If Not In Then Return False
		Local File_Size:Int=FileSize(filename)
		Local i:Int, j:Int
		' Read headerfile
		Local ID:String=ReadString(In,10)
		' Is valid Milkshape3D model file
		If ID <> "MS3D000000" Then DebugStop'Return False
		Local Version:Int=Readint(In)
		' Is valid version (Version 1.3 and 1.4 is supported)
		If Version < 3 Or Version > 4 Then DebugStop'Return False
		' Read vertice info
		m_numVertices=ReadShort(In)													' Vertices count (stored)
		m_pVertices=m_pVertices[..m_numVertices]										' Resize vertice array
		vert=CreateBank(m_numVertices*16+16)
		For i=0 Until m_numVertices
			m_pVertices[i]=New VERTEX
			ReadByte(In)																' Read m_flags (discarded)
			m_pVertices[i].m_location[0]=ReadFloat(In)									' Read X coordinate (stored)
			m_pVertices[i].m_location[1]=ReadFloat(In)									' Read Y coordinate (stored)
			m_pVertices[i].m_location[2]=ReadFloat(In)									' Read Z coordinate (stored)
			PokeFloat vert,i*16,m_pVertices[i].m_location[0]	
			PokeFloat vert,(i*16)+4,m_pVertices[i].m_location[1]		
			PokeFloat vert,(i*16)+8,m_pVertices[i].m_location[2]		
			m_pVertices[i].m_boneID=ReadByte(In)										' Read Bone ID (stored)
			ReadByte(In)																' Read Ref count (discarded)
		Next
		' Read triangle info
		m_numTriangles=ReadShort(In)													' Triangle count
		m_pTriangles=m_pTriangles[..m_numTriangles]		' Resize triangle array
		ind=CreateBank(m_numTriangles*12+12)
		For i=0 Until m_numTriangles
			m_pTriangles[i]=New Triangle
			ReadShort(In)																' Read m_flags (discarded)
			m_pTriangles[i].m_vertexIndices[0]=ReadShort(In)								' Read vertex indice 1 (stored)
			m_pTriangles[i].m_vertexIndices[1]=ReadShort(In)								' Read vertex indice 2 (stored)
			m_pTriangles[i].m_vertexIndices[2]=ReadShort(In)								' Read vertex indice 3 (stored)
			PokeInt ind,i*12,Int m_pTriangles[i].m_vertexIndices[0]		
			PokeInt ind,(i*12)+4,Int m_pTriangles[i].m_vertexIndices[1]		
			PokeInt ind,(i*12)+8,Int m_pTriangles[i].m_vertexIndices[2]		
			m_pTriangles[i].m_vertexNormals[0,0]=ReadFloat(In)							' Read vertex 1 normal X (stored)
			m_pTriangles[i].m_vertexNormals[0,1]=ReadFloat(In)							' Read vertex 1 normal Y (stored)
			m_pTriangles[i].m_vertexNormals[0,2]=ReadFloat(In)							' Read vertex 1 normal Z (stored)
			m_pTriangles[i].m_vertexNormals[1,0]=ReadFloat(In)							' Read vertex 2 normal X (stored)
			m_pTriangles[i].m_vertexNormals[1,1]=ReadFloat(In)							' Read vertex 2 normal Y (stored)
			m_pTriangles[i].m_vertexNormals[1,2]=ReadFloat(In)							' Read vertex 2 normal Z (stored)			
			m_pTriangles[i].m_vertexNormals[2,0]=ReadFloat(In)							' Read vertex 3 normal X (stored)
			m_pTriangles[i].m_vertexNormals[2,1]=ReadFloat(In)							' Read vertex 3 normal Y (stored)
			m_pTriangles[i].m_vertexNormals[2,2]=ReadFloat(In)							' Read vertex 3 normal Z (stored)
			m_pTriangles[i].m_s[0]=ReadFloat(In)
			m_pTriangles[i].m_s[1]=ReadFloat(In)
			m_pTriangles[i].m_s[2]=ReadFloat(In)
			m_pTriangles[i].m_t[0]=ReadFloat(In)
			m_pTriangles[i].m_t[1]=ReadFloat(In)
			m_pTriangles[i].m_t[2]=ReadFloat(In)
			ReadByte(In)																' Read smooth group (discarded)
			ReadByte(In)																' Read group index (discarded)
		Next
		' Read mesh info
		m_numMeshes=ReadShort(In)	
														' Mesh count
		m_pMeshes=m_pMeshes[..m_numMeshes]												' Resize mesh array
		For i=0 Until m_numMeshes
			m_pMeshes[i]=New Mesh
			ReadByte(In)																' Read m_flags (discarded)
			ReadString(In,32)															' Read m_name (discarded)
			Local nTriangles:Int=ReadShort(In)													' Read triangle count
			m_pMeshes[i].m_pTriangleIndices=m_pMeshes[i].m_pTriangleIndices[..nTriangles]	' Resize array
			For j=0 Until nTriangles
				m_pMeshes[i].m_pTriangleIndices[j]=ReadShort(In)							' Read triangle index (stored)
			Next
			m_pMeshes[i].m_materialIndex = ReadByte(In)									' Read material index
			m_pMeshes[i].m_numTriangles = nTriangles
		Next

		' Read material info
		m_numMaterials=ReadShort(In)
		m_pMaterials=m_pMaterials[..m_numMaterials]
		For i=0 Until m_numMaterials
			m_pMaterials[i]=New Material
			ReadString(In,32)															' Read material name (discarded)
			m_pMaterials[i].m_ambient[0]=ReadFloat(In)									' Read ambient material (stored)
			m_pMaterials[i].m_ambient[1]=ReadFloat(In)									' Read ambient material (stored)
			m_pMaterials[i].m_ambient[2]=ReadFloat(In)									' Read ambient material (stored)
			m_pMaterials[i].m_ambient[3]=ReadFloat(In)									' Read ambient material (stored)
			m_pMaterials[i].m_diffuse[0]=ReadFloat(In)									' Read diffuse material (stored)
			m_pMaterials[i].m_diffuse[1]=ReadFloat(In)									' Read diffuse material (stored)
			m_pMaterials[i].m_diffuse[2]=ReadFloat(In)									' Read diffuse material (stored)
			m_pMaterials[i].m_diffuse[3]=ReadFloat(In)									' Read diffuse material (stored)			
			m_pMaterials[i].m_specular[0]=ReadFloat(In)									' Read specular material (stored)
			m_pMaterials[i].m_specular[1]=ReadFloat(In)									' Read specular material (stored)
			m_pMaterials[i].m_specular[2]=ReadFloat(In)									' Read specular material (stored)
			m_pMaterials[i].m_specular[3]=ReadFloat(In)									' Read specular material (stored)
			m_pMaterials[i].m_emissive[0]=ReadFloat(In)									' Read emissive material (stored)
			m_pMaterials[i].m_emissive[1]=ReadFloat(In)									' Read emissive material (stored)
			m_pMaterials[i].m_emissive[2]=ReadFloat(In)									' Read emissive material (stored)
			m_pMaterials[i].m_emissive[3]=ReadFloat(In)									' Read emissive material (stored)
			m_pMaterials[i].m_shininess=ReadFloat(In)									' Read shininess material (stored)
			ReadFloat(In)																' Read transparency (discarded)
			ReadByte(In)																' Read mode (discarded)
			m_pMaterials[i].m_pTextureFilename=ReadString(In,128)							' Read texture filename (stored)
			Local s:String
			For Local x:Int=1 To 128
				If Asc(Mid(m_pMaterials[i].m_pTextureFilename,x,1))=0 Then 
					Exit
				Else
					s=s+Mid(m_pMaterials[i].m_pTextureFilename,x,1)
				EndIf
			Next
			m_pMaterials[i].m_pTextureFilename=s
			ReadString(In,128)														' Read alphamap (discarded)
		Next

		CloseStream(In)		
		Return True
	End Method
End Type

use like this

meshmodel=New MilkShapeModel
meshmodel.loadmodeldata("amodel.ms3d")
meshmodel.reloadtextures()


You should have the textures in the same (Current) directory as the milkshape model, I've loaded created from scratch models with v1.7.6 of milkshape

Hehe. Yeah, I ended up doing exactly that, myself. Here I thought I was special.