GMax B3D Importer Source

Blitz3D Forums/Blitz3D Programming/GMax B3D Importer Source

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

long, long time ago i have started to program a simple *.b3d importer for GMax. Today i given up this shit...

I hate maxscript, yes I hate it.
see my lovely picture:





here the 1337 code for my begin of my importer:
---------------------------------------------------------------------------------------
struct b3dQuat_s
(
	w = 0 as float,
	x = 0 as float,
	y = 0 as float,
	z = 0 as float
)

struct b3dWeight_s
(
	nBoneID = 0 as integer,
	nVertex = 0 as integer,
	fWeight = 0 as float
)

struct b3dBB3D_s
(
	nVersion = 0 as integer
)

struct b3dTEXS_s
(
	sFilename = "" as string,
	nFlags    = 0 as integer,
	nBlend    = 0 as integer,
	fUOffset  = 0 as float,
	fVOffset  = 0 as float,
	fUScale   = 0 as float,
	fVScale   = 0 as float,
	fRotate   = 0 as float
)

struct b3dBRUS_s
(
	nTextureCount = 0 as integer,
	sName         = "" as string,
	fRed          = 0 as float,
	fGreen        = 0 as float,
	fBlue         = 0 as float,
	fAlpha        = 0 as float,
	fShininess    = 0 as float,
	nBlend        = 0 as integer,
	nFX           = 0 as integer,
	textureList   = #()
)

struct b3dVRTS_s
(
	nFlags           = 0 as integer,
	nTexCoordSet     = 0 as integer,
	nTexCoordSetSize = 0 as integer,
	fPosition        = [0, 0, 0],
	fNormal          = [0, 0, 0],
	fRed             = 0 as float,
	fGreen           = 0 as float,
	fBlue            = 0 as float,
	fAlpha           = 0 as float,
	fUVW0            = [0, 0, 0],
	fUVW1            = [0, 0, 0]
)

struct b3dTRIS_s
(
	nBrushID   = 0 as integer,
	vertexList = #()
)

struct b3dMESH_s
(
	nBrushID  = 0 as integer,
	sName     = "" as string,
	fPosition = [0, 0, 0],
	fScale    = [0, 0, 0],
	fRotate   = b3dQuat_s()
)
struct b3dBONE_s
(
	sName      = "" as string,
	nParentID  = 0 as integer,
	nChildID   = 0 as integer,
	fPosition  = [0, 0, 0],
	fScale     = [0, 0, 0],
	fRotate    = b3dQuat_s(),
	keyList    = #(),
	nStartPos  = 0 as integer,
	nEndPos    = 0 as integer
)

struct b3dKEYS_s
(
	nFlags    = 0 as integer,
	nFrame    = 0 as integer,
	fPosition = [0, 0, 0],
	fScale    = [0, 0, 0],
	fRotate   = b3dQuat_s()
)

struct b3dANIM_s
(
	nFlags  = 0 as integer,
	nFrames = 0 as integer,
	fFPS    = 0 as float
)

struct b3dNODE_s
(
	sName     = "" as string,
	fPosition = [0, 0, 0],
	fScale    = [0, 0, 0],
	fRotate   = b3dQuat_s(),
	nStartPos = 0 as integer,
	nEndPos   = 0 as integer
)


global b3dChunkID     = "" as string
global b3dChunkSize   = 0 as integer
global b3dChunkEndPos = 0 as integer

global b3dTEXSList   = #()
global b3dBRUSList   = #()
global b3dVRTSList   = #()
global b3dTRISList   = #()
global b3dBONEList   = #()
global b3dWeightList = #()

global b3dBB3D = b3dBB3D_s()
global b3dNODE = b3dNODE_s()
global b3dMESH = b3dMESH_s()
global b3dANIM = b3dANIM_s()

global b3dNodeStart = 0 as integer
global b3dNodeEnd   = 0 as integer

global maxMesh
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
global sFileName   = "" as string
global sFilePath   = "" as string
global nFileLength = 0 as integer
global nFileStream = 0 as integer
global nFilePos    = 0 as integer
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadChunk nStream =
(
	local nI     = 0 as integer
	local sChunk = "" as string

	for nI = 1 to 4 do
	(
		sChunk += bit.intAsChar (readByte nStream #unsigned)
	)

	return sChunk
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadBB3D =
(
	b3dBB3D.nVersion = readLong nFileStream
	if b3dBB3D.nVersion != 1 then nFilePos = nFileLength
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadTEXS =
(
	if b3dChunkSize > 0 then
	(
		while nFilePos < b3dChunkEndPos do
		(
			local b3dTEXS = b3dTEXS_s()

			b3dTEXS.sFilename = readString nFileStream
			b3dTEXS.nFlags    = readLong nFileStream
			b3dTEXS.nBlend    = readLong nFileStream
			b3dTEXS.fUOffset  = readFloat nFileStream
			b3dTEXS.fVOffset  = readFloat nFileStream
			b3dTEXS.fUScale   = readFloat nFileStream
			b3dTEXS.fVScale   = readFloat nFileStream
			b3dTEXS.fRotate   = readFloat nFileStream

			append b3dTEXSList b3dTEXS
			nFilePos = ftell nFileStream
		)
	)
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadBRUS =
(
	local nI            = 0 as integer
	local nTextureCount = 0 as integer

	nTextureCount = readLong nFileStream

	if b3dChunkSize > 4 then
	(
		while nFilePos < b3dChunkEndPos do
		(
			local b3dBRUS = b3dBRUS_s()

			b3dBRUS.nTextureCount = nTextureCount
			b3dBRUS.sName         = readString nFileStream
			b3dBRUS.fRed          = readFloat nFileStream
			b3dBRUS.fGreen        = readFloat nFileStream
			b3dBRUS.fBlue         = readFloat nFileStream
			b3dBRUS.fAlpha        = readFloat nFileStream
			b3dBRUS.fShininess    = readFloat nFileStream
			b3dBRUS.nBlend        = readLong nFileStream
			b3dBRUS.nFX           = readLong nFileStream

			for nI = 1 to b3dBRUS.nTextureCount do
			(
				append b3dBRUS.textureList (readLong nFileStream)
			)

			append b3dBRUSList b3dBRUS
			nFilePos = ftell nFileStream
		)
	)
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadVRTS =
(
	local nFlags           = readLong nFileStream
	local nTexCoordSet     = readLong nFileStream
	local nTexCoordSetSize = readLong nFileStream

	if b3dChunkSize > 0 then
	(
		while nFilePos < b3dChunkEndPos do
		(
			local b3dVRTS = b3dVRTS_s()
		
			b3dVRTS.nFlags           = nFlags
			b3dVRTS.nTexCoordSet     = nTexCoordSet
			b3dVRTS.nTexCoordSetSize = nTexCoordSetSize

			b3dVRTS.fPosition.x = readFloat nFileStream
			b3dVRTS.fPosition.y = readFloat nFileStream
			b3dVRTS.fPosition.z = readFloat nFileStream

			if (bit.and b3dVRTS.nFlags 1 == 1) then
			(
				b3dVRTS.fNormal.x   = readFloat nFileStream
				b3dVRTS.fNormal.y   = readFloat nFileStream
				b3dVRTS.fNormal.z   = readFloat nFileStream
			)

			if (bit.and b3dVRTS.nFlags 2 == 2) then
			(
				b3dVRTS.fRed   = readFloat nFileStream
				b3dVRTS.fGreen = readFloat nFileStream
				b3dVRTS.fBlue  = readFloat nFileStream
				b3dVRTS.fAlpha = readFloat nFileStream
			)

			if b3dVRTS.nTexCoordSet > 0 then
			(
				if b3dVRTS.nTexCoordSetSize > 0 then b3dVRTS.fUVW0.x = readFloat nFileStream
				if b3dVRTS.nTexCoordSetSize > 1 then b3dVRTS.fUVW0.y = readFloat nFileStream
				if b3dVRTS.nTexCoordSetSize > 2 then b3dVRTS.fUVW0.z = readFloat nFileStream
			)

			if b3dVRTS.nTexCoordSet > 1 then
			(
				if b3dVRTS.nTexCoordSetSize > 0 then b3dVRTS.fUVW1.x = readFloat nFileStream
				if b3dVRTS.nTexCoordSetSize > 1 then b3dVRTS.fUVW1.y = readFloat nFileStream
				if b3dVRTS.nTexCoordSetSize > 2 then b3dVRTS.fUVW1.z = readFloat nFileStream
			)

			append b3dVRTSList b3dVRTS
			nFilePos = ftell nFileStream
		)
	)
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadTRIS =
(
	local b3dTRIS = b3dTRIS_s()
	local nI      = 0 as integer

	b3dTRIS.nBrushID = readLong nFileStream

	if b3dChunkSize > 0 then
	(
		while nFilePos < b3dChunkEndPos do
		(
			local nVertex = [0, 0, 0]

			nVertex.x = readLong nFileStream
			nVertex.y = readLong nFileStream
			nVertex.z = readLong nFileStream

			append b3dTRIS.vertexList nVertex
			nFilePos = ftell nFileStream
		)
		append b3dTRISList b3dTRIS
	)
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadMESH =
(
	b3dMESH.nBrushID  = readLong nFileStream
	b3dMESH.sName     = b3dNODE.sName
	b3dMESH.fPosition = b3dNODE.fPosition
	b3dMESH.fScale    = b3dNODE.fScale
	b3dMESH.fRotate   = b3dNODE.fRotate
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadBONE = 
(
	local b3dBONE = b3dBONE_s()
	local nI      = 0 as integer
	
	b3dBONE.sName     = b3dNODE.sName
	b3dBONE.fPosition = b3dNODE.fPosition
	b3dBONE.fScale    = b3dNODE.fScale
	b3dBONE.fRotate   = b3dNODE.fRotate

	
	for nI = 1 to (b3dChunkEndPos-nFilePos)/8-1 do
	(
		local b3dWeight = b3dWeight_s()
		
		b3dWeight.nBoneID = b3dBONEList.count
		b3dWeight.nVertex = readLong nFileStream
		b3dWeight.fWeight = readFloat nFileStream

		append b3dWeightList b3dWeight
	)

	b3dBONE.nStartPos = b3dNODE.nStartPos
	b3dBONE.nEndPos   = b3dNODE.nEndPos

	append b3dBONEList b3dBONE
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadKEYS = 
(
	local nFlags = 0 as integer

	nFlags = readLong nFileStream

	while nFilePos < b3dChunkEndPos do
	(
		local b3dKEYS = b3dKEYS_s()
		
		b3dKEYS.nFlags = nFlags
		b3dKEYS.nFrame = readLong nFileStream 

		if (bit.and b3dKEYS.nFlags 1 == 1) then
		(
			b3dKEYS.fPosition.x = readFloat nFileStream
			b3dKEYS.fPosition.y = readFloat nFileStream
			b3dKEYS.fPosition.z = readFloat nFileStream
		)

		if (bit.and b3dKEYS.nFlags 2 == 2) then
		(
			b3dKEYS.fScale.x = readFloat nFileStream
			b3dKEYS.fScale.y = readFloat nFileStream
			b3dKEYS.fScale.z = readFloat nFileStream
		)

		if (bit.and b3dKEYS.nFlags 4 == 4) then
		(
			b3dKEYS.fRotate.w = readFloat nFileStream
			b3dKEYS.fRotate.x = readFloat nFileStream
			b3dKEYS.fRotate.y = readFloat nFileStream
			b3dKEYS.fRotate.z = readFloat nFileStream
		)

		append b3dBONEList[b3dBONEList.count].keyList b3dKEYS
		nFilePos = ftell nFileStream
	)
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadANIM =
(
	b3dANIM.nFlags  = readLong nFileStream
	b3dANIM.nFrames = readLong nFileStream
	b3dANIM.fFPS    = readFloat nFileStream
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dReadNODE =
(
	b3dNODE.sName       = readString nFileStream
	b3dNODE.fPosition.x = readFloat nFileStream
	b3dNODE.fPosition.y = readFloat nFileStream
	b3dNODE.fPosition.z = readFloat nFileStream
	b3dNODE.fScale.x    = readFloat nFileStream
	b3dNODE.fScale.y    = readFloat nFileStream
	b3dNODE.fScale.z    = readFloat nFileStream
	b3dNODE.fRotate.w   = readFloat nFileStream
	b3dNODE.fRotate.x   = readFloat nFileStream
	b3dNODE.fRotate.y   = readFloat nFileStream
	b3dNODE.fRotate.z   = readFloat nFileStream

	b3dNODE.nStartPos = nFilePos
	b3dNODE.nEndPos   = b3dChunkEndPos
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function b3dOrderBones =
(
	local nCount  = 0 as integer
	local nIndexI = 0 as integer
	local nIndexJ = 0 as integer
	local nStart  = 0 as integer
	local nEnd    = 0 as integer

	nCount = b3dBONEList.count
	if nCount > 0 then
	(
		for nIndexI = 1 to nCount do
		(
			nStart = b3dBONEList[nIndexI].nStartPos
			nEnd   = b3dBONEList[nIndexI].nEndPos

			for nIndexJ = 1 to nCount do
			(
				if nStart < b3dBONEList[nIndexJ].nStartPos and \
				   nEnd > b3dBONEList[nIndexJ].nStartPos then
				(
					b3dBONEList[nIndexI].nChildID  = nIndexJ
					b3dBONEList[nIndexJ].nParentID = nIndexI
				)
			)
			print b3dBONEList[nIndexI]
		)
	)
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
function maxCreateMesh =
(
	local maxVertexList   = #()
	local maxTriangleList = #()
	local maxMaterialList = #()
	local nCount          = 0 as integer
	local nIndex          = 0 as integer

	-- its only a test to show why is maxscript fucking evil

	nCount = b3dVRTSList.count
	for nIndex = 1 to nCount do
	(
		local fPosition = [0, 0, 0]

		fPosition.x = b3dVRTSList[nIndex].fPosition.x*100.0
		fPosition.y = b3dVRTSList[nIndex].fPosition.z*100.0
		fPosition.z = b3dVRTSList[nIndex].fPosition.y*100.0

		append maxVertexList fPosition
	)

	nCount = b3dTRISList.count
	for nIndex = 1 to nCount do
	(
		local nVertex      = [0, 0, 0]
		local nVertexCount = 0 as integer
		local nVertexIndex = 0 as integer

		nVertexCount = b3dTRISList[nIndex].vertexList.count
		for nVertexIndex = 1 to nVertexCount do
		(
			nVertex = b3dTRISList[nIndex].vertexList[nVertexIndex]
			nVertex.x += 1 
			nVertex.y += 1 
			nVertex.z += 1 
			append maxVertexList nVertex
		)
	)

	print maxVertexList
	print maxTriangleList

	maxMesh = mesh vertices:maxVertexList faces:maxTriangleList

	update maxMesh TRUE
)
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
utility Blitz3DImporter "Blitz3D Importer" width:160 height:232
(
	bitmap imgLogo "Logo" pos:[8,8] width:144 height:32 fileName:"logo.bmp"
	groupBox grpImport " import " pos:[8,56] width:144 height:168
	button cmdOpen "open..." pos:[16,80] width:128 height:24 toolTip:"open a *.b3d file..."
	checkbox chkImportTetxures "import textures" pos:[16,120] width:128 height:16 checked:true
	checkbox chkImportAnimation "import animation" pos:[16,144] width:128 height:16 checked:true
	progressBar prgState "" pos:[16,200] width:128 height:16 color:(color 30 10 190)
	checkbox chkDebugreport "debugreport" pos:[16,168] width:120 height:16 checked:false
	

	on cmdOpen pressed do
	(
		prgState.value = 0
	
		sFileName = getOpenFileName caption:"load *.b3d file" \
		                            types:"Blitz3D(*.b3d)|*.b3d|All(*.*)|*.*"

		if doesFileExist sFileName then
		(
			sFilePath   = getFilenamePath sFileName
			nFileLength = getFileSize sFileName

			nFileStream = fopen sFileName "rb"

			while nFilePos < nFileLength do
			(
				nFilePos = ftell nFileStream

				b3dChunkID     = b3dReadChunk nFileStream
				b3dChunkSize   = readLong nFileStream
				b3dChunkEndPos = nFilePos + b3dChunkSize + 8

				print b3dChunkID

				case b3dChunkID of
				(
					"BB3D": b3dReadBB3D()
					"TEXS": b3dReadTEXS()
					"BRUS": b3dReadBRUS()
					"VRTS": b3dReadVRTS()
					"TRIS": b3dReadTRIS()
					"MESH": b3dReadMESH()
					"BONE": b3dReadBONE()
					"KEYS": b3dReadKEYS()
					"ANIM": b3dReadANIM()
					"NODE": b3dReadNODE()

					default: fseek nFileStream b3dChunkEndPos #seek_set
				)
				nFilePos = ftell nFileStream
				prgState.value = nFilePos as float / nFileLength as float * 100.0
		
			)

			fclose nFileStream
			b3dOrderBones()

			maxCreateMesh()
		)
		else
		(
			print "file does not exist"
		)
	)
)
---------------------------------------------------------------------------------------



or download it directly from http://vertex.art-fx.org/B3DImporter.zip

a simple code to create a mesh with texture an boneanimation is:
utility Test "Test"
(
	button cmdStart "start" pos:[23,16] width:109 height:28

	on cmdStart pressed do
	(
		-------------------------------------------------------------------------------------
		local texture
		local textureBMP
		local textureMap

		local vertexList     = #()
		local uvwList        = #()
		local faceList       = #()
		local materialIDList = #()

		local testMesh

		local faceIndex

		local testSkin
		local bone1
		local bone2
		-------------------------------------------------------------------------------------

		-------------------------------------------------------------------------------------
		textureBMP = OpenBitmap "C:\\Eigene Dateien\\gmax\\blub.bmp"

		textureMap = bitmapTexture bitmap:textureBMP name:"Texturemap1"

		texture                = standardMaterial Name:"Texture1"
		texture.shaderType     = 1 -- blinn
		texture.diffuseMap     = textureMap

		showTextureMap texture textureMap TRUE
		-------------------------------------------------------------------------------------

		-------------------------------------------------------------------------------------
		append vertexList [-50, 0,  50] -- left  | top
		append vertexList [ 50, 0,  50] -- right | top
		append vertexList [-50, 0, -50] -- left  | bottom
		append vertexList [ 50, 0, -50] -- right | bottom

		append uvwList [0, 1, 0]  -- left  | top
		append uvwList [1, 1, 0]  -- right | top
		append uvwList [0, 0, 0]  -- left  | bottom
		append uvwList [1, 0, 0]  -- right | bottom

		append faceList [4, 2, 1]
		append faceList [1, 3, 4]

		append materialIDList 1
		append materialIDList 1

		testMesh = mesh vertices:vertexList \
				tverts:uvwList \
                                faces:faceList \
		                materialIDs:materialIDList \
                                material:texture

		
		setNormal testMesh 1 [0, -1, 0] -- to front
		setNormal testMesh 2 [0, -1, 0] -- to front
		setNormal testMesh 3 [0, -1, 0] -- to front
		setNormal testMesh 4 [0, -1, 0] -- to front

		buildTVFaces testMesh
		for faceIndex = 1 to faceList.count do
		(
			setTVFace testMesh faceIndex faceList[faceIndex]
		)
		
		meshOps.setVertexColor testMesh 1 1 (Color 255 0 0) 
		meshOps.setVertexColor testMesh 2 1 (Color 255 255 0) 
		meshOps.setVertexColor testMesh 3 1 (Color 255 0 255) 
		meshOps.setVertexColor testMesh 4 1 (Color 0 255 0) 

		update testMesh TRUE
		-------------------------------------------------------------------------------------

		-------------------------------------------------------------------------------------
		bone1 = boneSys.createBone [0, 0, -50] [0, 0,  0] [0, 0, 0]
		bone2 = boneSys.createBone [0, 0,   0] [0, 0, 50] [0, 0, 0]
		bone2.parent = bone1
		
		max modify mode
		select testMesh
		testSkin = skin()
		addModifier testMesh testSkin

		skinOps.addBone testSkin bone1 1
		skinOps.addBone testSkin bone2 1
		
		skinOps.selectBone testSkin 1
		skinOps.setVertexWeights testSkin 1 2 1
		skinOps.setVertexWeights testSkin 2 2 1
		skinOps.setVertexWeights testSkin 3 1 1
		skinOps.setVertexWeights testSkin 4 1 1
		-------------------------------------------------------------------------------------

		-------------------------------------------------------------------------------------
		frameRate = 24
		animationRange = interval 0 99

		animate on
		(
			at time 0
			(
				rotate bone2 (eulerAngles 0 0 -75)
			)

			at time 99
			(
				rotate bone2 (eulerAngles 0 0 150)
			)
		)
		-------------------------------------------------------------------------------------
	)
)


cu olli