Code archives/3D Graphics - Mesh/Load/Save Anim .b3d

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

Download source code

Load/Save Anim .b3d by Ricky Smith2006
This is the function from the first version of PaceMaker to load and save animated .b3d files.
It uses type structures to store the info. This was based on the b3d2Xml code by Peter Scheutz.
;--------------------------------------------------------------
; 
; B3d importer
; Adapted for PaceMaker by Ricky Smith
; Based on code by M Sibley & Peter Sheultz
; 
;
;--------------------------------------------------------------

Include "b3dfile.bb" 	; get this file from www.blitzbasic.com -> 
				; Community  -> Specs And utils -> Sample Blitz code
				
;OSB:	in b3dfile.bb change "Function b3dReadFloat()" to "Function b3dReadFloat#()"			
				
Global mesh
Dim PMK_tex_id%(255,255)
Const PMK_ERROR_NONE=True
Const PMK_ERROR_NOFILE=-1
Const PMK_ERROR_FILENOTVALID =-2
Const PMK_ERROR_WRONGVERSION =-3


Const PMK_FLAG_StripTexturePaths=1
Const PMK_FLAG_StripBrushPaths=2
Const PMK_FLAG_StripNodePaths=4
Const PMK_FLAG_SkipVertices=8
Const PMK_FLAG_SkipTriangles=16
Const PMK_FLAG_SkipKeys=32
Const PMK_FLAG_SkipWeights=64


Const PMK_MAX_KEYS = 5000
Const PMK_MAX_VRTS = 50000
Const PMK_MAX_TRIS = 20000
Const PMK_MAX_TEXS = 255
Const PMK_MAX_BRUS = 255

Global PMK_emf
Global PMK_xml$
Global PMK_xmlpos
Global PMK_xmlpos2
Global PMK_xmlpos3
Global PMK_kflags
Global PMK_brushtexcount
Global PMK_vflags
Global PMK_vtexsets
Global PMK_vtexsize
;Global cname$
.types
Type  NodeChunk
	Field name$
	Field x_pos#				
	Field y_pos#
	Field z_pos#
	Field x_scl#
	Field y_scl#
	Field z_scl#
	Field w_rot#
	Field x_rot#
	Field y_rot#
	Field z_rot#
	Field gui_id%
	Field joint
	Field geo
	;Field bone.ray
	Field prename$
	Field class$
	Field xrot#
	Field yrot#
	Field zrot#
	Field norm=0
	;Field bp.bodypoint
	Field newborn=0
	Field Parent
	;Field rb.ODEGeom
	;Field loangle#=-Pi*0.25;-45 degrees
	;Field hiangle#=Pi*0.25;-45 degrees
	;Field Axis1=1
	;Field Axis2=2
	;Field joint_type% = 2
	;Field max_force#=0.0
	;Field vel#=0.0
	;Field angulardamp#=0.5
	;Field lineardamp#=0.5
	;Field fixed=False
	;Field nproxy
	Field anim_flags%,Num_Frames%,FramesPS#



	Field mesh_brush_id 
	

; VrtsChunk
	Field vrts_count%,vrts_flags%,texturecoordsets%,texturecoordsize%
	;fieldrS#[PMK_MAX_VRTS],gS#[PMK_MAX_VRTS],bS#[PMK_MAX_VRTS]
	Field vrts_index%[PMK_MAX_VRTS],x#[PMK_MAX_VRTS],y#[PMK_MAX_VRTS],z#[PMK_MAX_VRTS]
	Field u0#[PMK_MAX_VRTS],v0#[PMK_MAX_VRTS],w0#[PMK_MAX_VRTS];UVW coords
	Field u1#[PMK_MAX_VRTS],v1#[PMK_MAX_VRTS],w1#[PMK_MAX_VRTS];2nd UVW coords
	Field nx#[PMK_MAX_VRTS],ny#[PMK_MAX_VRTS],nz#[PMK_MAX_VRTS]
	Field r#[PMK_MAX_VRTS],g#[PMK_MAX_VRTS],b#[PMK_MAX_VRTS],a#[PMK_MAX_VRTS]
	Field vrts_ent%[PMK_MAX_VRTS],joint1%[PMK_MAX_VRTS],joint2%[PMK_MAX_VRTS],joint3%[PMK_MAX_VRTS],joint4%[PMK_MAX_VRTS]
	Field weight1#[PMK_MAX_VRTS],weight2#[PMK_MAX_VRTS],weight3#[PMK_MAX_VRTS],weight4#[PMK_MAX_VRTS]
	Field Frontfacing[PMK_MAX_VRTS]
;End 






; BoneChunk
	Field weight_count%,vert_target%[PMK_MAX_VRTS],weight#[PMK_MAX_VRTS]
;End 



; KeysChunk
	Field keys_flag%,keys_count%,moved=0
	Field frame%[PMK_MAX_KEYS],frameP%[PMK_MAX_KEYS],frameS%[PMK_MAX_KEYS],frameR%[PMK_MAX_KEYS]
	Field key_px#[PMK_MAX_KEYS],key_py#[PMK_MAX_KEYS],key_pz#[PMK_MAX_KEYS]
	Field key_sx#[PMK_MAX_KEYS],key_sy#[PMK_MAX_KEYS],key_sz#[PMK_MAX_KEYS]
	Field key_rw#[PMK_MAX_KEYS],key_rx#[PMK_MAX_KEYS],key_ry#[PMK_MAX_KEYS],key_rz#[PMK_MAX_KEYS]
	;Field key_qrw#[PMK_MAX_KEYS],key_qrx#[PMK_MAX_KEYS],key_qry#[PMK_MAX_KEYS],key_qrz#[PMK_MAX_KEYS]
	;Field key_brw#[PMK_MAX_KEYS],key_brx#[PMK_MAX_KEYS],key_bry#[PMK_MAX_KEYS],key_brz#[PMK_MAX_KEYS]
	;Field key_pitch#[PMK_MAX_KEYS],key_yaw#[PMK_MAX_KEYS],key_roll#[PMK_MAX_KEYS]
	;Field bone_w#,bone_x#,bone_y#,bone_z#
	
End Type

Type Texs
			Field mesh
			Field name$[PMK_MAX_TEXS]
			Field flags%[PMK_MAX_TEXS]
			Field blend%[PMK_MAX_TEXS]
			Field xpos#[PMK_MAX_TEXS]
			Field ypos#[PMK_MAX_TEXS]
			Field xscale#[PMK_MAX_TEXS]
			Field yscale#[PMK_MAX_TEXS]
			Field rot#[PMK_MAX_TEXS]
			Field texs_count%
End Type


Type Brus
			Field 	name$[PMK_MAX_BRUS]
			Field 	red#[PMK_MAX_BRUS]
			Field	grn#[PMK_MAX_BRUS]
			Field	blu#[PMK_MAX_BRUS]
			Field	alp#[PMK_MAX_BRUS]
			Field 	shi#[PMK_MAX_BRUS]
			Field 	blend%[PMK_MAX_BRUS]
			Field 	fx%[PMK_MAX_BRUS]
		;	Field   tex_id%[PMK_MAX_TEXS]
			Field   brus_count%
			Field   brus_tex_count%
End Type

Type TrisChunk
	Field mesh,tris_count%,tris_brush_id%,tv0%[PMK_MAX_TRIS],tv1%[PMK_MAX_TRIS],tv2%[PMK_MAX_TRIS]
End Type




Global b3dbrush.brus
Global b3dtex.texs
Global b3dnode.NodeChunk
Global b3dmesh.NodeChunk
Global b3dtris.trischunk
;Global b3dseq.sequence
Global Cnode.NodeChunk
Global DoneRefKey=False
Global retval


;Dim leaf(100)
Global NodeCount=0
Global NewJointNo=0
;Dim Joint(100)
Global level









Function b3d2pmk(b3dfile$,dumpflags=0)
	mesh=LoadAnimMesh(b3dfile$)
	Local file


	file=ReadFile( b3dfile$)
	If Not file Return PMK_ERROR_NOFILE
	
	b3dSetFile( file )
	
	If b3dReadChunk$()<>"BB3D"  Return PMK_ERROR_FILENOTVALID ;RuntimeError "Invalid b3d file"
	
	version=b3dReadInt()
	
	If version/100>0 Return  PMK_ERROR_WRONGVERSION ;RuntimeError "Invalid b3d file version"
	
	
	
	
	
	
	
	
	
	DumpChunks(dumpflags,"*")
	
	b3dExitChunk()
	
	
	
	
	CloseFile file


	Return PMK_ERROR_NONE

End Function



Function DumpChunks(dumpflags, tab$="",level%=0)
	tt$=tab$
	tab$=tab$+"  "
	level%=level%+1
			While b3dChunkSize()
		chunk$=b3dReadChunk$()
		
.anim		
		Select chunk$
		Case "SEQS"
			
		;	b3dseq.sequence=New sequence
		;	b3dseq\name$=b3dReadString()
		;	b3dseq\fstart%=b3dReadInt()
		;	b3dseq\fend%=b3dReadInt()
		;	b3dseq\seq%=ExtractAnimSeq (mesh,b3dseq\fstart%,b3dseq\fend%)
		;	b3dseq\gui_id=AddListBoxItem( lstSeq, 0, b3dseq\seq% + " - " + b3dseq\name$)
		Case "PHYS"
		;	b3dnode\joint_type=b3dReadInt()
		;	b3dnode\loangle#=b3dReadFloat() 
		;	b3dnode\hiangle#=b3dReadFloat() 
		;	b3dnode\Axis1=b3dReadInt() 
		;	b3dnode\Axis2=b3dReadInt() 	
			
			
		Case "ANIM"
	
			flags=b3dReadInt()
			n_frames=b3dReadInt()
			fps=b3dReadFloat()			
						
			AnimFrames%=n_frames
		;	DebugLog "Anim Frames :" + AnimFrames
			AnimFPS#=fps
			
			;___________________________________
			
			b3dnode\anim_flags%=flags
			b3dnode\Num_Frames%=n_frames
			b3dnode\FramesPS#=fps
			;_____________________________________
.keys
		Case "KEYS"
				
			;For mark=0 To PMK_MAX_KEYS;b3dmesh\Num_Frames%
			;			b3dnode\frame%[mark]=-1
			;			b3dnode\frameP%[mark]=-1
			;			b3dnode\frameS%[mark]=-1
			;			b3dnode\frameR%[mark]=-1
		;	Next 
			flags=b3dReadInt()

						
			
			
			b3dnode\keys_flag%=flags
			

			sz=4
			If flags And 1 sz=sz+12
			If flags And 2 sz=sz+12
			If flags And 4 sz=sz+16
			n_keys=b3dChunkSize()/sz
			b3dnode\keys_count%=n_keys
									
				
			
			If n_keys*sz=b3dChunkSize() 
			
				While b3dChunkSize()
					frame=b3dReadInt()
						
					
					
					b3dnode\frame%[frame]=frame
					
					
					If flags And 1
						b3dnode\frameP%[frame]=frame
						key_px#=b3dReadFloat()
						key_py#=b3dReadFloat()
						key_pz#=b3dReadFloat()
						
							
						
						b3dnode\key_px#[frame]=key_px#
						b3dnode\key_py#[frame]=key_py#
						b3dnode\key_pz#[frame]=key_pz#			
						
					EndIf
					
					If flags And 2
						b3dnode\frameS%[frame]=frame
						key_sx#=b3dReadFloat()
						key_sy#=b3dReadFloat()
						key_sz#=b3dReadFloat()

						
						
						b3dnode\key_sx#[frame]=key_sx#
						b3dnode\key_sy#[frame]=key_sy#
						b3dnode\key_sz#[frame]=key_sz#

					EndIf
					
					If flags And 4
						b3dnode\frameR%[frame]=frame
						key_rw#=b3dReadFloat()
						key_rx#=b3dReadFloat()
						key_ry#=b3dReadFloat()
						key_rz#=b3dReadFloat()

					
						
						b3dnode\key_rw#[frame]=key_rw#
						b3dnode\key_rx#[frame]=key_rx#
						b3dnode\key_ry#[frame]=key_ry#
						b3dnode\key_rz#[frame]=key_rz#

					EndIf
					
								
				;	If frame  > highframe Then highframe=frame						
					
				Wend
			Else
				;;;DebugLog tab$+"***** Illegal number of keys *****"
			EndIf
		Case "TEXS"
			b3dtex.texs=New texs
			index=0
			While b3dChunkSize()
				name$=b3dReadString$()
				flags=b3dReadInt()
				blend=b3dReadInt()
				x_pos#=b3dReadFloat()
				y_pos#=b3dReadFloat()
				x_scl#=b3dReadFloat()
				y_scl#=b3dReadFloat()
				rot#=b3dReadFloat()



				If dumpflags And PMK_FLAG_StripTexturePaths Then  name$=StripPath(name$)

			
				
				
				
				b3dtex\name$[index]=name$
				b3dtex\flags%[index]=flags
				b3dtex\blend%[index]=blend
				b3dtex\xpos#[index]=x_pos#
				b3dtex\ypos#[index]=y_pos#
				b3dtex\xscale#[index]=x_scl#
				b3dtex\yscale#[index]=y_scl#
				b3dtex\rot#[index]=rot#
			
			index=index+1	
			Wend
			b3dtex\texs_count%=index
.brus
		Case "BRUS"
			b3dbrush.brus=New brus
			n_texs=b3dReadInt()
			b3dbrush\brus_tex_count%=n_texs

							
			
			index=0
			;read all brushes in chunk...
			While b3dChunkSize()
				name$=b3dReadString$()
				red#=b3dReadFloat()
				grn#=b3dReadFloat()
				blu#=b3dReadFloat()
				alp#=b3dReadFloat()
				shi#=b3dReadFloat()
				blend=b3dReadInt()
				fx=b3dReadInt()
				
				
				
			b3dbrush\name$[index]=name$
			b3dbrush\red#[index]=red#
			b3dbrush\grn#[index]=grn#
			b3dbrush\blu#[index]=blu#
			b3dbrush\alp#[index]=alp#
			b3dbrush\shi#[index]=shi#
			b3dbrush\blend%[index]=blend
			b3dbrush\fx%[index]=fx
		



				
				If dumpflags And PMK_FLAG_StripBrushPaths Then  name$=StripPath(name$)
				
				
				
					
				For k=0 To n_texs-1
					tex_id=b3dReadInt()
					
				    PMK_tex_id%(index,k)=tex_id
				Next
				
					
			index=index+1
			Wend
			b3dbrush\brus_count%=index



.verts				
		Case "VRTS"
			flags=b3dReadInt()
			tc_sets=b3dReadInt()
			tc_size=b3dReadInt()
			sz=12+tc_sets*tc_size*4
			If flags And 1 Then sz=sz+12
			If flags And 2 Then sz=sz+16
			n_verts=b3dChunkSize()/sz
			
			
				
			
		

			
			
			b3dnode\vrts_count%=n_verts		
			b3dnode\vrts_flags%=flags
			b3dnode\texturecoordsets%=tc_sets
			b3dnode\texturecoordsize%=tc_size
			
			
			
			
		
		
			If n_verts*sz=b3dChunkSize() 
				index%=0
				;read all verts in chunk
				While b3dChunkSize()
					
					
					b3dnode\vrts_index%[index]=0; Used for Selection !
					
									
					x#=b3dReadFloat()
					y#=b3dReadFloat()
					z#=b3dReadFloat()
					
					
					
					b3dnode\x#[index]=x#
					b3dnode\y#[index]=y#
					b3dnode\z#[index]=z#






					
					
					
									
					
					
					
					If flags And 1
						nx#=b3dReadFloat()
						ny#=b3dReadFloat()
						nz#=b3dReadFloat()
						
						
						
						b3dnode\nx#[index]=nx#
						b3dnode\ny#[index]=ny#
						b3dnode\nz#[index]=nz#
					
												
					EndIf
					If flags And 2
						r#=b3dReadFloat()
						g#=b3dReadFloat()
						b#=b3dReadFloat()
						a#=b3dReadFloat()
						
						
						
						
						b3dnode\r#[index]=r#
						b3dnode\g#[index]=g#
						b3dnode\b#[index]=b#
						b3dnode\a#[index]=a#

						
					EndIf
;Parent vert boxes				
				;	b3dnode\vrts_ent[index]=CreateCube()
				;	NameEntity b3dnode\vrts_ent[index],index
				;	EntityColor b3dnode\vrts_ent[index],255,255,255
				;	EntityParent b3dnode\vrts_ent[index],b3dnode\joint
				;	PositionEntity b3dnode\vrts_ent[index],x,y,z,0
				;	ScaleMesh b3dnode\vrts_ent[index],.1,.1,.1
				;	b3dnode\rS#[index]=255
				;	b3dnode\gS#[index]=255
				;	b3dnode\bS#[index]=255
				;	EntityPickMode b3dnode\vrts_ent[index],2
					coordnameindex=0
					set=0
					;read tex coords...
					For j=1 To tc_sets*tc_size
						uvw#=b3dReadFloat()
						
						coordnameindex=coordnameindex + 1
						If coordnameindex>tc_size Then
							coordnameindex =1
							set=set+1
						EndIf

						If coordnameindex=1
							cn$="u"
							If Not set Then
								b3dnode\u0#[index]=uvw
							Else
								b3dnode\u1#[index]=uvw
							End If


						ElseIf coordnameindex=2
							cn$="v"
							If Not set Then
								b3dnode\v0#[index]=uvw
							Else
								b3dnode\v1#[index]=uvw
							End If



						Else
							cn$="w"
							If Not set Then
								b3dnode\w0#[index]=uvw
							Else
								b3dnode\w1#[index]=uvw
							End If



						EndIf
						
						
						
					Next

						
								
					
					index=index+1

				Wend
			Else
				;;;DebugLog tab$+"***** Illegal number of vertices *****"
			EndIf
		Case "TRIS"
			b3dtris.trischunk=New trischunk
		  	
			brush_id=b3dReadInt()
			sz=12
			n_tris=b3dChunkSize()/sz
			
				
			
			
			b3dtris\tris_count%=n_tris
			b3dtris\tris_brush_id%=brush_id	
			
.tris			
			If n_tris*sz=b3dChunkSize()
			index%=0
				;read all tris in chunk
				While b3dChunkSize()
					v0=b3dReadInt()
					v1=b3dReadInt()
					v2=b3dReadInt()

					
					b3dtris\tv0%[index]=v0
					b3dtris\tv1%[index]=v1
					b3dtris\tv2%[index]=v2
					index%=index%+1
				Wend
			Else
				;;;DebugLog tab$+"***** Illegal number of triangles *****"
			EndIf
		Case "MESH"
			brush_id=b3dReadInt()
			
			
			
			b3dnode\mesh_brush_id=brush_id
			b3dnode\class$="mesh"
			b3dmesh=b3dnode
			;HideEntity b3dmesh\geo				
.bone			
		Case "BONE"
			
		  
			sz=8
			n_weights=b3dChunkSize()/sz
			b3dnode\weight_count%=n_weights
			
			b3dnode\class$="bone"
			index%=0
			If n_weights*sz=b3dChunkSize()
				;read all weights
				While b3dChunkSize()
					vertex_id=b3dReadInt()
					weight#=b3dReadFloat()
					
			;		If weight#>b3dnode\weight#[index]
					b3dnode\vert_target%[vertex_id]=1;vertex_id
					
					b3dnode\weight#[vertex_id]=weight
					
				;	Else
					
				;	n_weights=n_weights-1
				;	End If
					
				;	For tmp.NodeChunk=Each NodeChunk
				;	EntityParent b3dmesh\vrts_ent[vertex_id],b3dnode\joint
				;	DebugLog "Parenting "+ EntityName(b3dnode\vrts_ent[vertex_id])+" to "+ b3dnode\name$
				flag=0					
				If  b3dmesh\joint1[vertex_id]=0 And flag=0 Then
						b3dmesh\joint1[vertex_id]=b3dnode\joint
						b3dmesh\weight1#[vertex_id]=weight
						flag=1
				End If
				
				If  b3dmesh\joint2[vertex_id]=0 And flag=0 Then
						b3dmesh\joint2[vertex_id]=b3dnode\joint
						b3dmesh\weight2#[vertex_id]=weight
						flag=2
				End If
				 
				If  b3dmesh\joint3[vertex_id]=0 And flag=0 Then 
						b3dmesh\joint3[vertex_id]=b3dnode\joint
						b3dmesh\weight3#[vertex_id]=weight
						flag=3
				End If
				
				If  b3dmesh\joint4[vertex_id]=0 And flag=0 Then
						b3dmesh\joint4[vertex_id]=b3dnode\joint
						b3dmesh\weight4#[vertex_id]=weight
						flag=4
				End If


						
					 
				
				
				
					
				
					index%=index%+1
				Wend
			Else
				;;;DebugLog tab$+"***** Illegal number of bone weights *****"
			EndIf
			
			
			
			
.nodes
		Case "NODE"
		
			;If level%>1
			b3dnode.NodeChunk=New NodeChunk
		;	End If
			b3dnode\class$="root"			;
			name$=b3dReadString$()
			x_pos#=b3dReadFloat()
			y_pos#=b3dReadFloat()
			z_pos#=b3dReadFloat()
			x_scl#=b3dReadFloat()
			y_scl#=b3dReadFloat()
			z_scl#=b3dReadFloat()
			w_rot#=b3dReadFloat()
			x_rot#=b3dReadFloat()
			y_rot#=b3dReadFloat()
			z_rot#=b3dReadFloat()
	;		If w_rot#<>1.0 Then b3dnode\norm=1
			
			b3dnode\joint=findchildentity(mesh,name$)
		;	DebugLog "creating "+name$ +" "+ b3dnode\joint


			b3dnode\name$=name$
			b3dnode\x_pos#=x_pos#
			b3dnode\y_pos#=y_pos#
			b3dnode\z_pos#=z_pos#
			b3dnode\x_scl#=x_scl#
			b3dnode\y_scl#=y_scl#
			b3dnode\z_scl#=z_scl#
			b3dnode\w_rot#=w_rot#
			b3dnode\x_rot#=x_rot#
			b3dnode\y_rot#=y_rot#
			b3dnode\z_rot#=z_rot#
			
			For mark=0 To PMK_MAX_KEYS;b3dmesh\Num_Frames%
						b3dnode\frame%[mark]=-1
						b3dnode\frameP%[mark]=-1
						b3dnode\frameS%[mark]=-1
						b3dnode\frameR%[mark]=-1
			Next
			;b3dnode\loangle#=-45.0;-45;-Pi*0.25;-45 degrees
			;b3dnode\hiangle#=45.0;Pi*0.25;-45 degrees
			;b3dnode\Axis1=1
			;b3dnode\Axis2=2
			;b3dnode\joint_type% = 2
			;b3dnode\max_force#=0.0
			;b3dnode\vel#=0.0
			;b3dnode\angulardamp#=0.5
			;b3dnode\lineardamp#=0.5
			;b3dnode\nproxy=CreatePivot()
		;	DebugLog  b3dnode.NodeChunk\name$

	If b3dnode\joint=0 Then
		;b3dnode\gui_id=AddTreeViewNode( treeJoints, name$ );
	;	DebugLog "adding node  :"+b3dnode\name$ +"  parent="+b3dnode\joint+"   mesh="+mesh

	Else If GetParent(b3dnode\joint)=mesh Then
			
			;b3dnode\gui_id=AddTreeViewNode( treeJoints, name$ )
			b3dnode\parent=mesh
	Else
		
		For tmp.Nodechunk=Each NodeChunk
	;	DebugLog "looking for.."+tmp\joint+"  parent   :"+GetParent (b3dnode\joint)
			If tmp\joint=GetParent (b3dnode\joint) Then
				;b3dnode\gui_id=AddTreeViewNode( tmp\gui_id, name$ )
			;	DebugLog "adding child node  :"+b3dnode\name$+"  to  "+ tmp\name$
				;dad.nodechunk=getnodechunk(GetParent (b3dnode\joint))
				;b3dnode\bone=createRay.ray(EntityX#(dad\joint,1),EntityY#(dad\joint,1),EntityZ#(dad\joint,1),EntityX#(b3dnode\joint,1),EntityY#(b3dnode\joint,1),EntityZ#(b3dnode\joint,1), punit#*0.1,dad\joint, 1)
				;EntityOrder b3dnode\bone\entity,-1
				;UpdateRay(b3dnode.nodechunk)
			Else 
				
			;b3dnode\gui_id=AddTreeViewNode( treeJoints, name$ )
			End If
		Next
				
	End If
	
	;b3dnode\geo=CreateSphere()
	hnd.NodeChunk=b3dnode.NodeChunk
	;NameEntity b3dnode\geo,"Sphere: " + name$
	;EntityPickMode b3dnode\geo,2
	;EntityAlpha b3dnode\geo,0.6
	;EntityOrder b3dnode\geo,-3
	;EntityColor b3dnode\geo,0,0,255
	;EntityParent b3dnode\geo,b3dnode\joint,0
	;EntityOrder b3dnode\geo,-1 - make optional 
	;HideEntity b3dnode\geo
	;If b3dnode\ent>0 DebugLog EntityName(b3dnode\geo) + " : " + EntityName(b3dnode\ent)
	;joint(NodeCount)=CreateSphere();
	;ScaleEntity b3dnode\geo,.1,.1,.1;
	;EntityParent joint(NodeCount),findchildentity(mesh,name$),0;
	;NodeCount=NodeCount+1;
	;NewJointNo=NewJointNo+1
	;PositionEntity ball,x_pos#,y_pos#,z_pos# ,True

			If dumpflags And PMK_FLAG_StripNodePaths Then  name$=StripPath(name$)	
			
						
			
		Default
			; OBS untested!

	;		out$=BeginTag$(chunk$)
	;		out$=AddIntegerAttrib(out$,"size",b3dChunkSize())
	;		out$ = CloseTag(out$)				
	;		emit out$
			
	;		out$="<![CDATA[" 
		
	;		While b3dChunkSize()
	;			out$=out$ + Chr$(b3dReadByte())	
	;		Wend
		
	;		out$=out$ + "]]>"
	;		emit out$
		
			
		End Select

		DumpChunks(dumpflags, tab$,level%)	;dump any subchunks
		b3dExitChunk()					;exit this chunk
	
	
	   	
		
	Wend
End Function


Function StripPath$(name$)
	Local pos

	For pos=Len(name$) To 1 Step -1
		If Mid$(name$,pos,1)="\" Or Mid$(name$,pos,1)="/" Then Exit
	Next
	Return Right$(name$,Len(name$)-pos)


End Function

;### name   : 1-call recursive child search ###
;### by     : jonathan pittock (skn3)       ###
;### contact: skn3@acsv.net                 ###
;### www    : www.acsv.net                  ###

;This value is used to size the buffer bank below. If the data needs more space,
;it will resize the bank in blocks of the amount below. (in bytes, 1k = 1024 bytes)
Const recursive_resize=1024

;This bank is used in each call to the search function. It is outside the function,
;as creating and deleting over and over from memory, can cause fragmentation, not...
;to mention slow downs.
Global recursive_bank=CreateBank(recursive_resize),recursive_size=recursive_resize

;These are misc values, having them defined as global speeds up the function as...
;they don't need to be created/destroyed each time the function is called
Global recursive_entity,recursive_parent,recursive_id,recursive_start,recursive_total,recursive_offset

;The function
;It will return the entity if found, or 0 if not.
;MyChild=findchildentity(entity,"child name")
Function findchildentity(entity,name$)
	name$=Lower$(name$)
	recursive_parent=entity
	recursive_start=1
	recursive_offset=0
	.recursive_label
		recursive_total=CountChildren(recursive_parent)
		For recursive_id=recursive_start To recursive_total
			recursive_entity=GetChild(recursive_parent,recursive_id)
			If name$=Lower$(EntityName$(recursive_entity))
				Return recursive_entity
			Else
				If recursive_offset+8 > recursive_size-1
					ResizeBank(recursive_bank,recursive_size+recursive_resize)
					recursive_size=recursive_size+recursive_resize
				End If
				PokeInt(recursive_bank,recursive_offset,recursive_id+1)
				PokeInt(recursive_bank,recursive_offset+4,recursive_parent)
				recursive_offset=recursive_offset+8
				recursive_start=1
				recursive_parent=recursive_entity
				Goto recursive_label
			End If
		Next
		If recursive_offset=0
			Return 0
		Else
			recursive_start=PeekInt(recursive_bank,recursive_offset-8)
			recursive_parent=PeekInt(recursive_bank,recursive_offset-4)
			recursive_offset=recursive_offset-8
			Goto recursive_label
		End If
End Function



;;;;;;;;;;;;;;;;;;;EXPORT FUNCTIONS:::::::::::::::::::::::::::::::::

Function pmk2b3d( f_name$,mesh )

	file=WriteFile( f_name$ )

	b3dSetFile( file )
	
	b3dBeginChunk( "BB3D" )
	DebugLog "Begin BB3d"
		b3dWriteInt( 1 )	;version
		If b3dtex.texs<>Null  Then
		b3dBeginChunk("TEXS")
		DebugLog "Begin Chunk Texs"
			For x=0 To b3dtex\texs_count%-1
				b3dWriteString b3dtex\name$[x]
				b3dWriteInt b3dtex\flags%[x]
				b3dWriteInt b3dtex\blend%[x]
				b3dWritefloat b3dtex\xpos#[x]
				b3dWritefloat b3dtex\ypos#[x]
				b3dWritefloat b3dtex\xscale#[x]
				b3dWritefloat b3dtex\yscale#[x]
				b3dWritefloat b3dtex\rot#[x]
				
			Next
			
		b3dEndChunk();TEXS
		DebugLog "End Chunk Texs"
		End If								
.brus			
		If b3dbrush.brus <> Null Then
		For tmpbrush.brus=Each brus

		b3dBeginChunk( "BRUS" )
		DebugLog "Begin Chunk Brus"
				b3dWriteInt tmpbrush\brus_tex_count%

			For x=0 To tmpbrush\brus_count%-1
																		;0 textures per brush
				b3dWriteString  tmpbrush\name$[x]		;name
				b3dWriteFloat   tmpbrush\red#[x]					;red
				b3dWriteFloat   tmpbrush\grn#[x] 					;green
				b3dWriteFloat   tmpbrush\blu#[x] 					;blue
				b3dWriteFloat   tmpbrush\alp#[x] 					;alpha
				b3dWriteFloat   tmpbrush\shi#[x] 				;shininess
				b3dWriteInt     tmpbrush\blend%[x] 					;blend
				b3dWriteInt     tmpbrush\fx%[x] 
				
				For k=0 To tmpbrush\brus_tex_count%-1
					b3dWriteInt PMK_tex_id% (x,k)
				Next
			;b3dWriteInt x

			Next	
									
		
		b3dEndChunk()	;end of BRUS chunk
		DebugLog "End Chunk Brus"
		Next
		End If
		DebugLog "Begin NODE Chunk"
			b3dBeginChunk("NODE")
				b3dWriteString b3dmesh\name$
				b3dWritefloat b3dmesh\x_pos#
				b3dWritefloat b3dmesh\y_pos#
				b3dWritefloat b3dmesh\z_pos#
				b3dWritefloat b3dmesh\x_scl#
				b3dWritefloat b3dmesh\y_scl#
				b3dWritefloat b3dmesh\z_scl#
				b3dWritefloat b3dmesh\w_rot#
				b3dWritefloat b3dmesh\x_rot#
				b3dWritefloat b3dmesh\y_rot#
				b3dWritefloat b3dmesh\z_rot#
				
			
				b3dBeginChunk("MESH")
				DebugLog tab$+"Begin Chunk Mesh"
				b3dWriteInt b3dmesh\mesh_brush_id
				
				b3dBeginChunk("VRTS")
				DebugLog tab$+"Begin Chunk Vrts"
				
							b3dWriteInt b3dmesh\vrts_flags%
							b3dWriteInt b3dmesh\texturecoordsets%
							b3dWriteInt b3dmesh\texturecoordsize%
												
														
			For x=0 To b3dmesh\vrts_count%-1
							
					
								b3dWritefloat b3dmesh\x#[x]
								b3dWritefloat b3dmesh\y#[x]
								b3dWritefloat b3dmesh\z#[x]
			
									
						
						If b3dmesh\vrts_flags% And 1
								b3dWritefloat b3dmesh\nx#[x]
								b3dWritefloat b3dmesh\ny#[x]
								b3dWritefloat b3dmesh\nz#[x]						
										
						EndIf
						If b3dmesh\vrts_flags% And 2
								b3dWritefloat b3dmesh\r#[x]
								b3dWritefloat b3dmesh\g#[x]
								b3dWritefloat b3dmesh\b#[x]
								b3dWritefloat b3dmesh\a#[x]
						EndIf


					If b3dmesh\texturecoordsets%=1 Then
				
				
						If b3dmesh\texturecoordsize%>0 Then b3dWritefloat b3dmesh\u0#[x]
						If b3dmesh\texturecoordsize%>1 Then b3dWritefloat b3dmesh\v0#[x]				
						If b3dmesh\texturecoordsize%>2 Then b3dWritefloat b3dmesh\w0#[x]
						
					End If
					
					If b3dmesh\texturecoordsets%=2 Then
				
						If b3dmesh\texturecoordsize%>0 Then b3dWritefloat b3dmesh\u0#[x]
						If b3dmesh\texturecoordsize%>1 Then b3dWritefloat b3dmesh\v0#[x]				
						If b3dmesh\texturecoordsize%>2 Then b3dWritefloat b3dmesh\w0#[x]

						If b3dmesh\texturecoordsize%>0 Then b3dWritefloat b3dmesh\u1#[x]
						If b3dmesh\texturecoordsize%>1 Then b3dWritefloat b3dmesh\v1#[x]				
						If b3dmesh\texturecoordsize%>2 Then b3dWritefloat b3dmesh\w1#[x]
						
					End If
						
				



			Next
			b3dEndChunk();VRTS
			DebugLog tab$+"End Chunk Vrts"
			For b3dtris.trischunk=Each trischunk
			
			b3dBeginChunk("TRIS")
			DebugLog tab$+"Begin Chunk Tris"
			
				b3dWriteInt b3dtris\tris_brush_id%
				
				For x = 0 To b3dtris\tris_count%-1
				
						b3dWriteInt b3dtris\tv0%[x]
						b3dWriteInt b3dtris\tv1%[x]
						b3dWriteInt b3dtris\tv2%[x]
				Next
		
			b3dEndChunk();TRIS
			
			Next
		
			DebugLog tab$+"End Chunk Tris"
			
			

		
		
			
			b3dEndChunk();MESH
			DebugLog tab$+"End Chunk Mesh"
			
			b3dBeginChunk("ANIM")
			DebugLog tab$+"Begin Chunk Anim"
			b3dWriteInt b3dmesh\anim_flags%
			b3dWriteInt b3dmesh\Num_Frames%
			b3dWriteFloat b3dmesh\FramesPS#
			b3dEndChunk();ANIM
			DebugLog tab$+"End Chunk Anim"
			
			If CountChildren(mesh)>0 Then	
				WriteNodes(mesh); write joint hierarchy
			
			End If
			
		

			
			DebugLog "End Chunk ROOT"	
			b3dEndChunk();End B3D Chunk
			
			
			CloseFile  file
			Return PMK_ERROR_NONE
			
End Function

Function WriteNodes(parent,tab$="")
		tab$=tab$+"	 "
		WriteNode (parent,tab$)
		If CountChildren(parent)>0 Then
		For a=1 To CountChildren(parent)
		 	child=GetChild(parent,a)
			fin=WriteNodes(child,tab$)
			
			
		Next
		End If
		b3dEndChunk(); end NODE chunk
		DebugLog tab$+"End Chunk NOde ***********"+ EntityName(parent)
			
		
			
	
	;If parent=mesh Then	b3dEndChunk(); end NODE chunk
	;DebugLog tab$+"End Chunk NOde"+ currname$
	

	
End Function







Function WriteNode(child,tab$)
	For tmp.NodeChunk=Each NodeChunk
		If tmp\joint=child And tmp\class$="bone" Then
				currname$=tmp\name$

				b3dBeginChunk("NODE")
				DebugLog tab$+"Begin Chunk Node  "+currname$
				b3dWriteString tmp\name$
				b3dWritefloat tmp\x_pos#
				b3dWritefloat tmp\y_pos#
				b3dWritefloat tmp\z_pos#
				b3dWritefloat tmp\x_scl#
				b3dWritefloat tmp\y_scl#
				b3dWritefloat tmp\z_scl#
				b3dWritefloat tmp\w_rot#
				b3dWritefloat tmp\x_rot#
				b3dWritefloat tmp\y_rot#
				b3dWritefloat tmp\z_rot#



					



			If tmp\class$="bone" Then
				b3dBeginChunk("BONE")
				DebugLog tab$+"Begin Chunk Bone"
			
				;If tmp\weight_count%>0
					For x=0 To b3dmesh\vrts_count%-1
						If tmp\vert_target[x]=1
						b3dWriteInt x
						b3dWriteFloat tmp\weight#[x]
					;	DebugLog tab$+"VERT "+tmp\vert_target%[x]+"  WEIGHT "+tmp\weight#[x]
						End If
					Next
				;End If
			b3dEndChunk(); end BONE Chunk
			DebugLog tab$+"End Chunk Bone"



			If tmp\keys_count%>0 Then 
				b3dBeginChunk("KEYS")
				DebugLog tab$+"Begin Chunk Keys"
				
				b3dWriteInt (1);Compressed for now....Pos and Rot only - get flag value at import
				
				For x=0 To PMK_MAX_KEYS-1;animframes;b3dmesh\Num_Frames%
					If tmp\frameP%[x]>-1 Then
					b3dWriteInt x
				
				;	If tmp\keys_flag% And 1
			
					b3dWritefloat tmp\key_px#[x]
					b3dWritefloat tmp\key_py#[x]
					b3dWritefloat tmp\key_pz#[x]
				
				;	EndIf
			
				;	If tmp\keys_flag% And 2
			
				;	b3dWritefloat (1.0);tmp\key_sx#[x]
				;	b3dWritefloat (1.0);tmp\key_sy#[x]
				;	b3dWritefloat (1.0);tmp\key_sz#[x]
			
				;	End If
			
				;	If tmp\keys_flag% And 4
				
				;	b3dWritefloat tmp\key_rw#[x]
				;	b3dWritefloat tmp\key_rx#[x]
				;	b3dWritefloat tmp\key_ry#[x]
				;	b3dWritefloat tmp\key_rz#[x]
					End If
				Next
			
			b3dEndChunk(); end KEYS chunk
			
			;b3dBeginChunk("KEYS")
			;	DebugLog tab$+"Begin Chunk Keys"
				
			;	b3dWriteInt (2);Compressed for now....Pos and Rot only - get flag value at import
				
			;	For x=0 To PMK_MAX_KEYS-1;b3dmesh\Num_Frames%
			;		If tmp\frameS%[x]>-1 Then
			;		b3dWriteInt x
				
				;	If tmp\keys_flag% And 1
			
				;	b3dWritefloat tmp\key_px#[x]
				;	b3dWritefloat tmp\key_py#[x]
				;	b3dWritefloat tmp\key_pz#[x]
				
				;	EndIf
			
				;	If tmp\keys_flag% And 2
			
			;		b3dWritefloat tmp\key_sx#[x]
			;		b3dWritefloat tmp\key_sy#[x]
			;		b3dWritefloat tmp\key_sz#[x]
			
				;	End If
			
				;	If tmp\keys_flag% And 4
				
				;	b3dWritefloat tmp\key_rw#[x]
				;	b3dWritefloat tmp\key_rx#[x]
				;	b3dWritefloat tmp\key_ry#[x]
				;	b3dWritefloat tmp\key_rz#[x]
			;		End If
			;	Next
			
		;	b3dEndChunk(); end KEYS chunk
			
			b3dBeginChunk("KEYS")
				DebugLog tab$+"Begin Chunk Keys"
				
				b3dWriteInt (4);Compressed for now....Pos and Rot only - get flag value at import
				
				For x=0 To PMK_MAX_KEYS-1;b3dmesh\Num_Frames%
					If tmp\frameR%[x]>-1 Then
					b3dWriteInt x
				
				;	If tmp\keys_flag% And 1
			
				;	b3dWritefloat tmp\key_px#[x]
				;	b3dWritefloat tmp\key_py#[x]
				;	b3dWritefloat tmp\key_pz#[x]
				
				;	EndIf
			
				;	If tmp\keys_flag% And 2
			
				;	b3dWritefloat (1.0);tmp\key_sx#[x]
				;	b3dWritefloat (1.0);tmp\key_sy#[x]
				;	b3dWritefloat (1.0);tmp\key_sz#[x]
			
				;	End If
			
				;	If tmp\keys_flag% And 4
				
					b3dWritefloat tmp\key_rw#[x]
					b3dWritefloat tmp\key_rx#[x]
					b3dWritefloat tmp\key_ry#[x]
					b3dWritefloat tmp\key_rz#[x]
					End If
				Next
			
			b3dEndChunk(); end KEYS chunk
			;PMK_write_physics_nodes(tmp.nodechunk)
			DebugLog tab$+"End Chunk Keys"
			;b3dEndChunk();End Node
			Return True
			End If
	End If
	
End If			
			
Next
Return False
End Function



;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;;;;;;;;;;;;;TEST;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;First Load and Parse File: You will end up with a  NodeChunk type for each node in the model.
; There will be a global NodeChunk type for the Mesh node - B3dmesh. This type contains the UV coords in
; B3dmesh\u0#[vert index],B3dmesh\v0#[vert index],B3dmesh\w0#[vert index] for set 1 and
; B3dmesh\u1#[vert index],B3dmesh\v1#[vert index],B3dmesh\w1#[vert index] for set 2 if exists
; Set 2 is normally used for lightmapping and so will not normally be found on animated models.
Graphics3D 800,600, 16,2
file1$="oldfile.b3d"
file2$="newfile.b3d"
retval=b3d2pmk(file1$);Load and Parse Saving all info to types
If retval=PMK_ERROR_NONE
	Repeat  
		Text 10,10,"OK - Do whatever you want here ! .
		Text 10,20,"Hit Enter to save
		Flip
	Until KeyHit(28)
	retval=pmk2b3d(file2$,mesh);Save animated model using values held in types
Else
	RuntimeError "Error loading file
End If
FreeEntity mesh 
FreeBank recursive_bank

Comments

Bnesiba2006
will this save animated .X files as well as animated .b3d?


Damien Sturdy2006
No.


ShadowTurtle2006
You can write an .X Loader for loading the data into the types and export it as (animated) b3d.


Bnesiba2006
ok, if i use loadanimmesh() and load a .x file, then run the pmk2b3d() function will it save an animated .b3d or not?


Ricky Smith2006
No, unfortunately Blitz3d only supports import of the DirectX7 animated .x file which doesn't use bones.
The file would be saved as a static mesh.
You would have to do as Shadow Turtle suggests and write a .X loader first to fill the type values then you could use the pmk2b3d() function to export as .b3d.


bytecode772006
can we access the exact vertex coords of each vertex somehow?
and if, how?


Ricky Smith2006
One way would be to keep the values in an array of some type and calculate and update the vertex positions manually when the model is animating - taking into consideration the vertex weighting. This would probably be too slow to be useful in real-time.


H. T. U.2008
Thanks, I wanted a way to edit fine details on my b3d models in-game.


jfk EO-111102010
Would be nice to have an Example that shows how to deal with the KeysChunk. Eg. how to alter some keys and save the Animesh with a new/edited animation. Some Field naes don't seem very obvious to me. Anyone?


Ricky Smith2010
b3dnode\x_pos#[x]=Position key X axis animation frame x
b3dnode\y_pos#[x]=Position key Y axis frame x
b3dnode\z_pos#[x]=Position key Z axis frame x
b3dnode\x_scl#[x]=Scale Key X frame x
b3dnode\y_scl#[x]=Scale key Y frame x
b3dnode\z_scl#[x]=Scale Key Z frame x
b3dnode\w_rot#[x]=W Quaternion(rotation) value for frame x
b3dnode\x_rot#[x]=X Quaternion(rotation) value for frame x
b3dnode\y_rot#[x]=Y Quaternion(rotation) value for frame x
b3dnode\z_rot#[x]=Z Quaternion(rotation) value for frame x

Just load the model - set these values and then save to save the animation.



Code Archives Forum