Code archives/3D Graphics - Mesh/Static Direct X, hierarchical mesh

This code has been declared by its author to be Public Domain code.

Download source code

Static Direct X, hierarchical mesh by D4NM4N2007
Here is my version of the static X exporter (built around shamblers from the code arcs) with some heavy modifications.
Works with DX viewer/ fussy progs when using the NAN patch.
This version should organise the texture indexes for multiple children meshes.

Update: Truncate added for smaller files

Update: Code added to remove 'NaN's and replace to '0.0' -(thanks for the info b32!)

Please improve on it further and let me know what i was doing right/wrong.

This should work wthout additonal stuff, if not let me know

-----------------------------------------------------
----------------NOTE!!!------------------------------
Messagebox is not needed, all you need is the output from it if it is a question, or just replace with a debuglog if simply a message.
In the case of trunc= set trunc=1 if you want the file truncated and NANs removed (reccomended) or 0 if you want it human readable for debugging.

----------------------------------------------------------

----------------------------------------------------------
Global XE_XF,XE_MAXtextures

Type XE_texdata
	Field idx,h,fn$
End Type
Function writemesh(mesh,e_filename$)
        ;Change to 0 for human readable but (((bigger))) output
        trunc=1

	;reset texture list
	XE_MAXtextures=0
	For td.xe_texdata =Each XE_texdata:Delete td:Next
	
	;open output file
	filenameout$=e_filename$
	XE_XF=WriteFile (filenameout$);
	
	;File version 
	WriteLine XE_XF,"xof 0302txt 0064"
	WriteLine XE_XF,""
	;Header 
	WriteLine XE_XF,"Header {"
	WriteLine XE_XF,"1;"
	WriteLine XE_XF,"0;"
	WriteLine XE_XF,"1;"
	WriteLine XE_XF,"}"
	WriteLine XE_XF,""
	
	WriteLine XE_XF,"//Exported By D-Mapper Registered to "+regname$

	;Write all materials in meshes

	XE_MAXtextures=0

	RecursiveAddMaterial(mesh,forcematerial$,e_directory)
	WriteLine XE_XF," //Truncatemarker" ; textures cannot be truncated for giles

	;Start of frame root
	WriteLine XE_XF,"Frame root {"
	WriteLine XE_XF,"   FrameTransformMatrix {"
	WriteLine XE_XF,"      1.000000,0.000000,0.000000,0.000000,"
	WriteLine XE_XF,"      0.000000,1.000000,0.000000,0.000000,"
	WriteLine XE_XF,"      0.000000,0.000000,1.000000,0.000000,"
	WriteLine XE_XF,"      0.000000,0.000000,0.000000,1.000000;;"
	WriteLine XE_XF,"   }"

	;chiname$=EntityName(mesh)
	RecursiveAddMesh(mesh)

	WriteLine XE_XF,"} //End of root"
	CloseFile XE_XF

	If trunc
		Rfile=ReadFile(filenameout$)
		Wfile=WriteFile(filenameout$+"temp.x")
		If rfile<>0 And wfile<>0
			headerwrite=1
			While Not Eof(rfile)
				lines=lines+1
				If headerwrite
					l$=ReadLine(rfile)
					WriteLine(wfile,l$)
					If Instr(l$,"//Exported By") headerwrite=0
				Else
					l$=ReadLine(rfile)
					If Instr (l$,"//") Then l$=usv(ReadLine(rfile),1,"//")
					l$=Trim(l$)
					WriteLine wfile,l$
					;dat$=dat$+l$
					;If MilliSecs()>gtime+1000 gtime=MilliSecs():messagebox(-1,0,300,"Truncating ","Collapsing whitespace, end Of Line characters and ","comments, Please Wait..","","Line "+lines+" "+ l$)

				EndIf
			Wend
			CloseFile rfile
			CloseFile wfile
		Else
			
			messagebox(0,0,300,"Error","Cannot create/read required file!",rfile,wfile)
		EndIf	
       EndIf
       ;CopyFile filenameout$+"temp",filenameout$

       ;anti NAN patch for X exporter
       fileR=openfile (filenameout)
       fileW=openfile (tempfilename)
       if fileR while not eof(fileR)
           l$=readline(fileR)             
           l$=replace (l$,"NaN","0.0")
           writeline(fileW,l$)
      wend
      closefile fileR
      closefile fileW
      copyfile fileW,fileR
      deletefile fileW

	
End Function


Function RecursiveAddMaterial(h,forcematerial$,e_directory$="")
DebugLog CountChildren(h)

	If EntityClass$(h)="Mesh"
		;get neccacaries
		For surfc=1 To CountSurfaces(h)
			surf=GetSurface(h,surfc)
			brush=GetSurfaceBrush(surf)
			tex=GetBrushTexture (brush)
			
			;get rid of tex path & copy textures
			If forcematerial$="" Then
				from$=TextureName(tex)
				XE_XFilen$=strip_path(from)
				CopyFile from,e_directory+XE_XFilen$
				DebugLog "Copying tex to "+e_directory+XE_XFilen$
			Else
				XE_XFilen$=strip_path(forcematerial$)
			EndIf 
	
			;mark possible 'new' texture index
			Tindex=XE_MAXtextures
	
			;see id texture is alreadt in database, if so make tindex match the existing one
			For txs.XE_texdata = Each XE_texdata
				If txs\fn=XE_XFilen$ Then noadd=1:Tindex=txs\idx
			Next
	
			;Save texture data in index with surface handle for an index key
			txs.XE_texdata = New XE_texdata
			txs\h = surf
			txs\idx = Tindex
			txs\fn = XE_XFilen$
			
			;only add texture if a new one is present
			If Not noadd
				WriteLine XE_XF,"Material dx_brush"+Str(Tindex)+" {"
				WriteLine XE_XF,"   1.000000;1.000000;1.000000;1.000000;;"
				WriteLine XE_XF,"   0.000000;"
				WriteLine XE_XF,"   1.000000;1.000000;1.000000;;"
				WriteLine XE_XF,"   0.000000;0.000000;0.000000;;"
				WriteLine XE_XF,"   TextureFilename {"
				WriteLine XE_XF,"      "+Chr(34)+XE_XFilen$+Chr(34)+";"
				WriteLine XE_XF,"   }"
				WriteLine XE_XF,"}"
				XE_MAXtextures=XE_MAXtextures+1
			EndIf 
	
			;do the cleaning
			FreeTexture Tex
			FreeBrush brush
		Next 
	EndIf 

	For cc =CountChildren(h) To 1 Step -1
		chi=GetChild (h,cc)
		RecursiveAddMaterial(chi,forcematerial$)
	Next 

End Function

Function GetStringofMatElement$(mesh,x,y)
	me$=GetMatElement(mesh,x,y)
	dp$=usv(me$,2,".")
	final$=me$
	If Len(dp$)=0
		final$=me$+"000000"
	ElseIf Len(dp$)=1
		final$=me$+"00000"
	ElseIf Len(dp$)=2
		final$=me$+"0000"
	ElseIf Len(dp$)=3
		final$=me$+"000"
	ElseIf Len(dp$)=4
		final$=me$+"00"
	ElseIf Len(dp$)=5
		final$=me$+"0"
	EndIf
	DebugLog "Matrix="+me$+" ("+dp$+") "+final$
	Return final$
End Function

Global recuse_depth
Function RecursiveAddMesh(h,basescaleX#=1,basescaleY#=1,basescaleZ#=1)
		recuse_depth=recuse_depth+1
		
		chiname$=EntityName(h)
		DebugLog "Recursing "+chiname+" Childs="+CountChildren(h)+" Depth="+recuse_depth
		If chiname="" Or Instr(chiname,"NoName") chiname="NoName"+MilliSecs()
		DebugLog chiname
		
;		mesh=CopyEntity(h)
;		EntityParent mesh,0
		mesh=h

		WriteLine XE_XF,"   Frame "+ChiName$+" {"
		WriteLine XE_XF,"      FrameTransformMatrix {"
		WriteLine XE_XF,"         "+GetStringOfMatElement(mesh,0,0)+","+GetStringOfMatElement(mesh,0,1)+","+GetStringOfMatElement(mesh,0,2)+",0.000000,"
		WriteLine XE_XF,"         "+GetStringOfMatElement(mesh,1,0)+","+GetStringOfMatElement(mesh,1,1)+","+GetStringOfMatElement(mesh,1,2)+",0.000000,"
		WriteLine XE_XF,"         "+GetStringOfMatElement(mesh,2,0)+","+GetStringOfMatElement(mesh,2,1)+","+GetStringOfMatElement(mesh,2,2)+",0.000000,"
		WriteLine XE_XF,"         "+GetStringOfMatElement(mesh,3,0)+","+GetStringOfMatElement(mesh,3,1)+","+GetStringOfMatElement(mesh,3,2)+",1.000000;;"
		WriteLine XE_XF,"   }"

		
		If EntityClass$(mesh)="Mesh"
			For surfc=1 To CountSurfaces (mesh)
				surf=GetSurface(mesh,surfc)
				verts=CountVertices(surf)
				tris=CountTriangles(surf)
				;meshinfo
				WriteLine XE_XF,"      Mesh "+ChiName$+" {"
	
	
				;Number of verts;
				WriteLine XE_XF,"         "+verts+";"
	
	
				;X;Y;Z; of verts;
				For v=0 To verts-1
					If v=verts-1 Then term$=";;" Else term$=";,"
					WriteLine XE_XF,"         "+VertexX (surf,v)+";"+VertexY (surf,v)+";"+VertexZ (surf,v)+term$
				Next
	
				
				;No of tris;
				WriteLine XE_XF,"         "+tris+";"
	
	
				;Tri ordering 3;t0,t1,t2;,
				For t=0 To Tris-1
					If t=tris-1 Then term$=";;" Else term$=";,"
					WriteLine XE_XF,"         3;"+TriangleVertex(Surf,t,0)+","+TriangleVertex(Surf,t,1)+","+TriangleVertex(Surf,t,2)+term$
				Next 
	
				;Material List
				WriteLine XE_XF,"         MeshMaterialList {"
				WriteLine XE_XF,"            1;";num of materials for mesh
				WriteLine XE_XF,"            "+tris+";";number of faces/tris
				For t=0 To tris-1
					If t=tris-1 Then term$=";;" Else term$=","
					WriteLine XE_XF,"            0"+term$ ; face indexes?
				Next 
				WriteLine XE_XF,"            {dx_brush"+LookUpTindex(surf)+"}"
				WriteLine XE_XF,"         } // end of material list"
	
				;Normals List
				WriteLine XE_XF,"         MeshNormals {"
				WriteLine XE_XF,"            "+verts+";"
				For v=0 To verts-1
					If v=verts-1 Then term$=";;" Else term$=";,"
					WriteLine XE_XF,"            "+VertexNX (surf,v)+";"+VertexNY (surf,v)+";"+VertexNZ (surf,v)+term$
				Next
				WriteLine XE_XF,"            "+tris+";"
				For t=0 To Tris-1
					If t=tris-1 Then term$=";;" Else term$=";,"
					WriteLine XE_XF,"            3;"+TriangleVertex(Surf,t,0)+","+TriangleVertex(Surf,t,1)+","+TriangleVertex(Surf,t,2)+term$
				Next 
				WriteLine XE_XF,"         } // end of normal list"
	
				;Texturecoords List
				WriteLine XE_XF,"         MeshTextureCoords {"
				WriteLine XE_XF,"            "+verts+";"
				For v=0 To verts-1
					If v=verts-1 Then term$=";;" Else term$=";,"
					WriteLine XE_XF,"            "+VertexU (surf,v)+";"+VertexV (surf,v)+term$
				Next
				WriteLine XE_XF,"         } // end of Texturecoord list"
	
				;Vertexcolor List
				WriteLine XE_XF,"         MeshVertexColors {"
				WriteLine XE_XF,"            "+verts+";"
				For v=0 To verts-1
					If v=verts-1 Then term$=";;" Else term$=";,"
					vred#=VertexRed (surf,v)/256
					vgreen#=VertexGreen (surf,v)/256
					vblue#=VertexBlue (surf,v)/256
					WriteLine XE_XF,"            "+v+";"+vred+";"+vgreen+";"+vblue+";"+VertexAlpha (surf,v)+term$
				Next
				WriteLine XE_XF,"         } // end of Vertexcolor list"
	
				;End of mesh
				WriteLine XE_XF,"      } // end of mesh block for "+ChiName$
	
			Next	 
		EndIf

		;FreeEntity mesh
		
		;do all childs.. of childs etc
		DebugLog "has "+CountChildren(h)
		For cc=CountChildren(h) To 1 Step -1
			chi=GetChild (h,cc)
			RecursiveAddMesh(chi,basescaleX#,basescaleY#,basescaleZ#)
		Next 


		;close branch frame
		WriteLine XE_XF,"   } // End of frame"+ChiName$
		DebugLog "recuse_depth Depth "+recuse_depth


	recuse_depth=recuse_depth-1

End Function

Function LookUpTindex(surf)
	;look up tindex from surface handle
	For t.XE_texdata = Each XE_texdata
		If t\h=surf Return t\idx
	Next 
End Function

Function strip_path$(f$)
	 	f$=Lower$(f$) ; Full (!) Texture Path
		lastknown=0
		For p=1 To Len (f$)
			If Instr(f$,"\",p) Then lastknown=lastknown+1
		Next
		fnl=Len(f$)-lastknown
		f$=Right(f$,fnl)
 		;DebugLog "filename stripped"+ f$

		Return f$
End Function

;'user separated values

Function USV$(in$,which%=1,sep$=",")

;''pipe seprated values

	Local n% = 1

	Local offset% = 0

	Local nextoffset% = 1

	Local ValueRet$ =""

	

	While offset<Len(in$)

		nextoffset = Instr(in$,sep$,offset+1)

		If nextoffset = 0

			nextoffset = Len(in$)+1

			which = n

		End If

		valueret$ = Mid$(in$,offset+1,nextoffset-offset-1)

		If which = n	

			Return valueret	

		End If

		offset = nextoffset

		n=n+1

	Wend



	Return n-1



End Function

Comments

LamptonWorm2008
Hi,

I was trying to get this to work 'out of the box', but I don't have the 'messagebox' and 'usv' functions - please can you let me know what decls I need?

Cheers!
LW.


markcw2008
usv and messagebox appear to be custom functions, as the win32 MessageBox and MessageBoxEx don't have those parameters. In OpenGL usv stands for 'unsigned shorts void' where void indicates a pointer to an array (eg. glColor3usv) but it can't be that. It looks like it's a function to remove a given set of characters from a string.


D4NM4N2008
Messagebox help added to top.

I think i put the usv function in the codearcs somewhere.

Edit, erm, no i didnt ill do it when i get home :/

Edit2. USV function added.


markcw2008
Thanks Dan, looks like you added usv() from Firefox in Linux as the carriage returns produce an extra linefeed. I hate that bug. Here's a tidied version.
;'user separated values

Function USV$(in$,which%=1,sep$=",")
;''pipe separated values
	Local n% = 1
	Local offset% = 0
	Local nextoffset% = 1
	Local ValueRet$ =""

	While offset<Len(in$)
		nextoffset = Instr(in$,sep$,offset+1)
		If nextoffset = 0
			nextoffset = Len(in$)+1
			which = n
		End If
		valueret$ = Mid$(in$,offset+1,nextoffset-offset-1)
		If which = n
			Return valueret
		End If
		offset = nextoffset
		n=n+1
	Wend

	Return n-1

End Function



D4NM4N2008
weird, usv is actually my own code -lol :/


Code Archives Forum