save animated mesh

Miscellaneous Forums/Blitz Showcase/save animated mesh

This saves the animated ball from the B3D AddAnimSeq example and loads it back.
;-----------------------------------------------------------------------------------------------------
; 											SaveAnimMesh
;-----------------------------------------------------------------------------------------------------

Type iObj
	Field m
End Type


Global 	dindex
Global 	orgmesh 

;-----------------------------------------------------------------------------------------------------
;											AddAnimSeq Example					
;-----------------------------------------------------------------------------------------------------

;Create 3d animation example 

;Set up a simple nice looking level 
Graphics3D 640,480,0,2
camera=CreateCamera() 
PositionEntity camera,0,12,-12 
RotateEntity camera,35,0,0 
light=CreateLight(2) 
PositionEntity light,1000,1000,-1000 
ground=CreatePlane(2) 
EntityAlpha ground,0.5 
EntityColor ground,0,0,255 
mirror=CreateMirror() 

;Lets make a bouncing ball that squashes on impact with the floor. 
ball=CreateSphere(16) 
EntityShininess ball,1 
EntityColor ball,255,0,0 

; Lets animate him and "record" the 3D animation for later playback 
bloat#=0 : flatten#=0 : ypos#=10 

For frame=1 To 10 
;Drop the ball from height 10 to 2 
ypos = ypos - spd# 
spd#=spd#+.2 
PositionEntity ball,0,ypos,0 
ScaleEntity ball,1+bloat,1+flatten,1+bloat 

;If the ball is low enough make it look increasingly squashed 
If frame>8 
bloat=bloat+1.5 
flatten=flatten-.25 
Else 
flatten=flatten+.05 
EndIf 

;Record the frame! 
SetAnimKey ball,frame 
Next 

;Now we need to add the frames we've just made to the sequence of "film"! 
seq = AddAnimSeq(ball,frame-1) ; total number of frames 
Animate ball,2,0.15

SaveAnimMesh ball, "tester.x"
FreeEntity ball
ball = iLoadAnimMesh ("tester.x")

;Play it back ping-pong! 
Animate ball,2,0.15 
While Not KeyHit(1) 
UpdateWorld 
RenderWorld 
Flip 
Wend 
End 

;-----------------------------------------------------------------------------------------------------
;												SaveAnimMesh()
;-----------------------------------------------------------------------------------------------------
;saves an animated mesh
Function SaveAnimMesh(mesh, filename$)

	orgmesh = mesh
		
	maxframe = AnimLength(mesh)
	ff = WriteFile(filename$)
	
	WriteLine ff, "xof 0302txt 0064"
	WriteLine ff, " "
	WriteLine ff, "Header {"
	WriteLine ff, " 1;"
	WriteLine ff, " 0;"
	WriteLine ff, " 1;"
	WriteLine ff, "}"
	WriteLine ff, " "

	FindChildren(mesh)
	
	For i.iObj = Each iObj
		SaveAnimObject(ff, i\m, maxframe)
	Next
	
	Delete Each iObj
	
	WriteLine ff, "AnimationSequences {"
	WriteLine ff, "1; 0; 0;"
	WriteLine ff, "2; 0; " + maxframe + ";"
	WriteLine ff, "}"
	WriteLine ff, " "
	
	CloseFile ff	
	
End Function

;-----------------------------------------------------------------------------------------------------
;												SaveAnimObject()
;-----------------------------------------------------------------------------------------------------
;writes a single object to the file
Function SaveAnimObject(ff, mesh, maxframe)

	If CountSurfaces(mesh) > 0 Then 

		x = CountSurfaces(mesh)
		UpdateNormals mesh
				
		For surfindex = 1 To CountSurfaces(mesh)
		
		objectname$ = "Object" + dindex
		dindex = dindex + 1
		
		;start mesh
		WriteLine ff, "Frame frm_" + objectname$ + " {"
		WriteLine ff, " "
		WriteLine ff, " FrameTransformMatrix { "
		WriteLine ff, " 1.000000,0.000000,0.000000,0.000000,"
		WriteLine ff, " 0.000000,1.000000,0.000000,0.000000,"
		WriteLine ff, " 0.000000,0.000000,1.000000,0.000000,"
		WriteLine ff, " 0.000000,0.000000,0.000000,1.000000;"
		WriteLine ff, "}"
		WriteLine ff, " "
	
		;get surface
		surf 		= GetSurface(mesh, surfindex)
		numVert  	= CountVertices(surf)
		numTris 	= CountTriangles(surf)
		
		;get texname
		brush 		= GetSurfaceBrush(surf)
		tex			= GetBrushTexture(brush)
		texname$	= TextureName$(tex)
		If Instr(texname$, "") > 0 Then
			test = 1
			For i = Len(texname$) To 1 Step -1
				 If Mid$(texname$, i, 1) = "" Then test = i: Exit
			Next
			texname$ = Mid$(texname$, test + 1, Len(texname$))
		End If
		FreeTexture tex
		FreeBrush brush
		
		WriteLine 	ff, " Mesh " + objectname$ + " { "
			
		;write vertices
		WriteLine 	ff, " " + numVert + ";"
		
		For i = 0 To numVert - 1
			xx# = VertexX(surf, i)
			yy# = VertexY(surf, i)
			zz# = VertexZ(surf, i)
			WriteLine ff, xx# + ";" + yy# + ";" + zz# + ";,"
		Next
	
		;write triangles	
		WriteLine ff, " " + numTris + ";"
		
		For i = 0 To numTris - 1
			aa = TriangleVertex(surf, i, 0)
			bb = TriangleVertex(surf, i, 1)
			cc = TriangleVertex(surf, i, 2)
			If i = numTris - 1 Then st$ = ";" Else st$ = ","
			WriteLine ff, "3;" + aa + "," + bb + "," + cc + ";" + st$
		Next
	
		;write material properties	
		WriteLine ff, " "
		WriteLine ff, "MeshMaterialList {"
		WriteLine ff, "1;"
		WriteLine ff, "1;"
		WriteLine ff, "0;;"
		WriteLine ff, " "
			
		WriteLine ff, "Material {"
		WriteLine ff, " 1.000000,1.000000,1.000000,1.000000;;"
		WriteLine ff, " 1.000000;"
		WriteLine ff, " 0.500000,0.500000,0.500000;;"
		WriteLine ff, " 0.000000,0.000000,0.000000;;"
		
		;write texture file name	
		If FileType(texname$) = 1 Then
			WriteLine ff, "      TextureFilename {"
			WriteLine ff, "        " + Chr$(34) + texname$ + Chr$(34) + "; }"
		End If
		
		;close material block		
		WriteLine ff, "}"
		WriteLine ff, "}"
		WriteLine ff, " "
	
		;write normals	
		WriteLine ff, "MeshNormals {"	
		WriteLine ff, " " + numVert + ";"
		
		;write normal vertices
		For i = 0 To numVert - 1
			xx# 		= VertexNX(surf, i)
			yy# 		= VertexNY(surf, i)
			zz# 		= VertexNZ(surf, i)
			WriteLine 	ff, xx# + ";" + yy# + ";" + zz# + ";,"
		Next
		
		;write normal triangles
		WriteLine ff, " " + numTris + ";"
		For i = 0 To numTris - 1
			aa 			= TriangleVertex(surf, i, 0)
			bb 			= TriangleVertex(surf, i, 1)
			cc 			= TriangleVertex(surf, i, 2)
			If ( i = numTris - 1 ) Then st$ = ";" Else st$ = ","
			WriteLine 	ff, "3;" + aa + "," + bb + "," + cc + ";" + st$
		Next
	
		;close normals block	
		WriteLine ff, 	"}"
		WriteLine ff, 	" "
		
		;write texture coordinates U,V
		WriteLine ff, 	"MeshTextureCoords {"	
		WriteLine ff, 	" " + numVert + ";"
		
		For i = 0 To numVert - 1
			If ( i = numVert - 1 ) Then st$ = ";" Else st$ = ","
			uu# 		= VertexU(surf, i)
			vv# 		= VertexV(surf, i)
			WriteLine 	ff, uu# + ";" + vv# + ";" + st$
		Next
	
		WriteLine ff, "  }"
	
		;close mesh block	
		WriteLine ff, " }"
		WriteLine ff, " "
		WriteLine ff, "}"
		WriteLine ff, " "
	
		;start animation block
		WriteLine ff, "AnimationSet set_" + objectname$ + " {"
		WriteLine ff, "Animation ani_" + objectname$ + " {"
		WriteLine ff, "{frm_" + objectname$ + "} "
		WriteLine ff, " "
	
			;write position data
			WriteLine ff, "AnimationKey {"
			WriteLine ff, "2;"
			WriteLine ff, (maxframe + 0) + ";"
				For i = 1 To maxframe
					oldp = GetParent(mesh)
					iSetAnimTime orgmesh, i
					EntityParent mesh, 0
					WriteLine ff, PositionToString(i, EntityX(mesh), EntityY(mesh), EntityZ(mesh))
					EntityParent mesh, oldp
				Next
			WriteLine ff, "}"
			WriteLine ff, " "
			
			;write rotation data
			WriteLine ff, "AnimationKey {"
			WriteLine ff, "0;"
			WriteLine ff, (maxframe + 0) + ";"
				For i = 1 To maxframe
					oldp = GetParent(mesh)
					iSetAnimTime orgmesh, i
					EntityParent mesh, 0
					WriteLine ff, RotationToString(i, EntityPitch(mesh), EntityYaw(mesh), EntityRoll(mesh))
					EntityParent mesh, oldp
				Next	
			WriteLine ff, "}"
			WriteLine ff, " "
			
			;write scaling data
			WriteLine ff, "AnimationKey {"
			WriteLine ff, "1;"
			WriteLine ff, (maxframe + 0) + ";"
				For i = 1 To maxframe
					oldp = GetParent(mesh)
					iSetAnimTime orgmesh, i
					EntityParent mesh, 0
					WriteLine ff, ScalingToString(i, EntityWidth(mesh), EntityHeight(mesh), EntityDepth(mesh))
					EntityParent mesh, oldp
				Next
			WriteLine ff, "}"
			WriteLine ff, " "
		
		;write animation options
		WriteLine ff, "AnimationOptions {"
		WriteLine ff , "1;"		;0 = closed (default)  1 = open
		WriteLine ff , "1; }"	;0 = splines  1 = linear
		
		;close animation block
		WriteLine ff, "}"
		WriteLine ff, "}"
		WriteLine ff, " "
		
		Next

	End If
			
End Function

;-----------------------------------------------------------------------------------------------------
;											iLoadAnimMesh()	
;-----------------------------------------------------------------------------------------------------
;loads animated mesh and loads "AnimationSequences" block 
Function iLoadAnimMesh( f$ )

	If FileType(f$) <> 1 Then Return 0
	
	mesh = LoadAnimMesh(f$)
	
	file = ReadFile( f$ )
	
	Repeat
	
		;scan (text) .x file for the term "animationsequences"
		ll$ = ReadLine$( file )
		If Instr(ll$, "AnimationSequences") > 0 Then
			;read from { to }
			While (Instr(ll$, "}") < 1) 
				ll$ = ReadLine$( file )
				If Eof(file) Then Exit
				If Instr(ll$, ";") > 0 Then
					cc = Instr(ll$, ";")
					ll$ = Mid$(ll$, cc + 1, Len(ll$))

					cc = Instr(ll$, ";")
					v1 = Left$(ll$, cc - 1)
					v2 = Mid$(ll$, cc + 1, Len(ll$))
					index = ExtractAnimSeq (mesh, v1, v2)
					
				End If
			Wend
		End If

	If Eof(file) Then Exit
	
	Until Eof(file)
	
	CloseFile file
		
	Return mesh
	
End Function

;-----------------------------------------------------------------------------------------------------
; 										    RotationToString$()
;-----------------------------------------------------------------------------------------------------
;convert rotation information to string
Function RotationToString$(ptime, iPitch#, iYaw#, iRoll#)	

	;this code was written by LeadWerks
	;http://www.blitzbasic.com/Community/posts.php?topic=51579
	sp# = Sin(iYaw   / 2)
	cp# = Cos(iYaw   / 2)
	sy# = Sin(iRoll  / 2)
	cy# = Cos(iRoll  / 2)
	sr# = Sin(iPitch / 2)
	cr# = Cos(iPitch / 2)
	
	w# = + (cr * cp * cy - sr * sp * sy)
	x# = - (sr * cp * cy - cr * sp * sy)
	y# = + (cr * sp * cy + sr * cp * sy)
	z# = - (sr * sp * cy + cr * cp * sy)
	
	Return ptime + "; 4; " + w + "," + x + "," + y + "," + z + ";;;"
	
End Function

;-----------------------------------------------------------------------------------------------------
;											 PositionToString$()
;-----------------------------------------------------------------------------------------------------
;convert position information to string
Function PositionToString$(ptime, iX#, iY#, iZ#)
	
	Return pTime + "; 3;" + iX + "," + iY + "," + iZ + ";;,"
	
End Function

;-----------------------------------------------------------------------------------------------------
;											ScalingToString$()
;-----------------------------------------------------------------------------------------------------
;convert scaling information to string
Function ScalingToString$(pTime, iWidth#, iHeight#, iDepth#)
	
	Return pTime + "; 3;" + iWidth + "," + iHeight + "," + iDepth + ";;,"
	
End Function

;-----------------------------------------------------------------------------------------------------
;											EntityWidth()
;-----------------------------------------------------------------------------------------------------
;returns width of an entity
Function EntityWidth#( mesh )

	If MeshWidth(mesh) = 0 Then Return 0

	TFormPoint MeshWidth(mesh), 0, 0, mesh, 0	
	xx# = TFormedX()
	yy# = TFormedY()
	zz# = TFormedZ()
	TFormPoint 0, 0, 0, mesh, 0	
	xx# = TFormedX()-xx
	yy# = TFormedY()-yy
	zz# = TFormedZ()-zz	
	ll# = Sqr(xx * xx + yy * yy + zz * zz) / MeshWidth(mesh)
	
	Return ll
	
End Function

;-----------------------------------------------------------------------------------------------------
;											EntityHeight()
;-----------------------------------------------------------------------------------------------------
;returns height of an entity
Function EntityHeight#( mesh )

	If MeshHeight(mesh) = 0 Then Return 0
	
	TFormPoint 0, MeshHeight(mesh), 0, mesh, 0
	xx# = TFormedX()
	yy# = TFormedY()
	zz# = TFormedZ()
	TFormPoint 0, 0, 0, mesh, 0
	xx# = TFormedX()-xx
	yy# = TFormedY()-yy
	zz# = TFormedZ()-zz
	ll# = Sqr(xx * xx + yy * yy + zz * zz) / MeshHeight(mesh)
	
	Return ll
	
End Function

;-----------------------------------------------------------------------------------------------------
;											EntityDepth()
;-----------------------------------------------------------------------------------------------------
;returns depth of an entity
Function EntityDepth#( mesh )

	If MeshDepth(mesh) = 0 Then Return 0
	
	TFormPoint 0, 0, MeshDepth(mesh), mesh, 0	
	xx# = TFormedX()
	yy# = TFormedY()
	zz# = TFormedZ()
	TFormPoint 0, 0, 0, mesh, 0
	xx# = TFormedX()-xx
	yy# = TFormedY()-yy
	zz# = TFormedZ()-zz
	
	ll# = Sqr(xx * xx + yy * yy + zz * zz) / MeshDepth(mesh)
	
	Return ll
		
End Function

;-----------------------------------------------------------------------------------------------------
;											iSetAnimTime()
;-----------------------------------------------------------------------------------------------------
;user defined SetAnimTime
Function iSetAnimTime( mesh, time# )
	If time >= AnimLength(mesh) Then time = AnimLength(mesh) - 0.01
	SetAnimTime mesh, time
End Function

	
;-----------------------------------------------------------------------------------------------------
;											iEntityPitch()
;-----------------------------------------------------------------------------------------------------
;get entity's pitch
Function iEntityPitch#(mesh)

	imesh 	= mesh
	pivot	= CreatePivot()

	pt# = 0	
	Repeat	
		TurnEntity pivot, EntityPitch(imesh), EntityYaw(imesh), EntityRoll(imesh), 1
		imesh = GetParent(imesh)
		If imesh = 0 Then Exit
	Forever

	pt# = EntityPitch(pivot, 0)		
	FreeEntity pivot
	Return pt#

End Function

;-----------------------------------------------------------------------------------------------------
;											iEntityYaw()
;-----------------------------------------------------------------------------------------------------
;get entity's yaw
Function iEntityYaw#(mesh)

	imesh 	= mesh
	pivot	= CreatePivot()

	Repeat	
		TurnEntity pivot, EntityPitch(imesh), EntityYaw(imesh), EntityRoll(imesh), 1
		imesh = GetParent(imesh)
		If imesh = 0 Then Exit
	Forever

	yw# = EntityYaw(pivot, 0)
	FreeEntity pivot
	Return yw#

End Function

;-----------------------------------------------------------------------------------------------------
;											iEntityRoll()
;-----------------------------------------------------------------------------------------------------
;get entity's roll
Function iEntityRoll#(mesh)

	imesh 	= mesh
	pivot	= CreatePivot()

	Repeat	
		TurnEntity pivot, EntityPitch(imesh), EntityYaw(imesh), EntityRoll(imesh), 1
		imesh = GetParent(imesh)
		If imesh = 0 Then Exit
	Forever

	rl# = EntityRoll(pivot, 0)
	FreeEntity pivot
	Return rl#

End Function


;-----------------------------------------------------------------------------------------------------
;											FindChildren()
;-----------------------------------------------------------------------------------------------------
;store all children to iObj instances
Function FindChildren(mesh)

	i.iObj = New iObj
	i\m = mesh
	
	If CountChildren(mesh) < 1 Then Return
	
	For ij = 1 To CountChildren(mesh)
		g = GetChild(mesh, ij)
		FindChildren(g)
	Next
	
End Function


Looks great! I'll need to give this a whirl :o)

Very useful contribution, thanks a lot! How about to add it to the archives.

Thanks, I posted it here:
http://www.blitzbasic.com/codearcs/codearcs.php?code=1740