Code archives/3D Graphics - Mesh/saveanimmesh
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| this lib saves animated meshes in .x format update: it now saves the mesh hierarchy update: nan is removed update: the models are now compatible with LoadMesh as well I updated the Transformation Matrix, thanks to the description of DJWoodgate here: http://www.blitzbasic.com/b3ddocs/command.php?name=GetMatElement&ref=3d_a-z | |||||
;-------------------------------------------------------------------------------------------------------
; SaveAnimFile()
;-------------------------------------------------------------------------------------------------------
;save an animated mesh to the ".x" format
;the x format doesn't support vertex weight, only parenting objects to each other
;
;SYNTAX:
;
; SaveAnimFile mesh, filename$
;
; mesh - mesh handle
; filename - name of file
;
;print debug output
Const debug = False
Global frameindex
Global meshindex
Global animindex
Global orgmesh
;save animated mesh
Function SaveAnimFile(mesh, filename$)
;reset counters
frameindex = 0
meshindex = 0
animindex = 0
;open file for writing
ff = WriteFile(filename)
;write header data
WriteLine ff, "xof 0302txt 0064"
WriteLine ff, " "
WriteLine ff, "Header {"
WriteLine ff, " 1;"
WriteLine ff, " 0;"
WriteLine ff, " 1;"
WriteLine ff, "}"
WriteLine ff, " "
;save object "mesh" to file
SaveAnimObj(ff, mesh)
;save animation data to file
SaveAnimAnim(ff, mesh)
;close file
CloseFile ff
End Function
;-------------------------------------------------------------------------------------------------------
; SaveAnimObj()
;-------------------------------------------------------------------------------------------------------
;save object and children (recursive)
Function SaveAnimObj(ff, mesh)
;generate name
name$ = "Frame" + frameindex
frameindex = frameindex + 1
;start frame block
WriteLine ff, "Frame frm_" + name$ + " {"
WriteLine ff, " "
WriteLine ff, " FrameTransformMatrix { "
TFormPoint 1, 0, 0, mesh, GetParent(mesh)
xx# = TFormedX() - EntityX(mesh)
xy# = TFormedY() - EntityY(mesh)
xz# = TFormedZ() - EntityZ(mesh)
TFormPoint 0, 1, 0, mesh, GetParent(mesh)
yx# = TFormedX() - EntityX(mesh)
yy# = TFormedY() - EntityY(mesh)
yz# = TFormedZ() - EntityZ(mesh)
TFormPoint 0, 0, 1, mesh, GetParent(mesh)
zx# = TFormedX() - EntityX(mesh)
zy# = TFormedY() - EntityY(mesh)
zz# = TFormedZ() - EntityZ(mesh)
WriteLine ff, NoNan(xx) + "," + NoNan(xy) + "," + NoNan(xz) + "," + "0.000000,"
WriteLine ff, NoNan(yx) + "," + NoNan(yy) + "," + NoNan(yz) + "," + "0.000000,"
WriteLine ff, NoNan(zx) + "," + NoNan(zy) + "," + NoNan(zz) + "," + "0.000000,"
WriteLine ff, NoNan(EntityX(mesh)) + "," + NoNan(EntityY(mesh)) + "," + NoNan(EntityZ(mesh)) + "," + "1.000000;"
WriteLine ff, " }"
WriteLine ff, " "
;save children
For i = 1 To CountChildren(mesh)
g = GetChild(mesh, i)
SaveAnimObj ff, g
Next
;if entity is a mesh, then save the mesh data
If EntityClass$(mesh) = "Mesh" Then SaveAnimMesh(ff, mesh)
;end frame block
WriteLine ff, "}"
WriteLine ff, " "
End Function
;-------------------------------------------------------------------------------------------------------
; SaveAnimMesh()
;-------------------------------------------------------------------------------------------------------
;save mesh data to file
Function SaveAnimMesh(ff, mesh)
;generate name
name$ = "Mesh" + meshindex
meshindex = meshindex + 1
;debug
If debug Then Print "Mesh->Frame:" + name$
;loop through all surfaces
For surfindex = 1 To CountSurfaces(mesh)
;generate name
objectname$ = name$ + "_surface" + surfindex
;debug
If debug Then Print "Surface->Mesh:" + objectname$
;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 = 0
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
;start mesh block
WriteLine ff, " Mesh " + objectname$ + " { "
;write vertices
WriteLine ff, " " + numVert + ";"
For i = 0 To numVert - 1
If i = numVert - 1 Then st$ = ";" Else st$ = ","
xx# = VertexX(surf, i)
yy# = VertexY(surf, i)
zz# = VertexZ(surf, i)
WriteLine ff, NoNan(xx#) + ";" + NoNan(yy#) + ";" + NoNan(zz#) + ";" + st$
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;"
;----------------------------------------
;This part is not compatible with Blender
;Blender wants all triangles defined here
WriteLine ff, "1;"
WriteLine ff, "0;;"
;Besides this, Blender still complains
;about these files, at least when they
;are animated
;----------------------------------------
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 texname$ <> "" Then
WriteLine ff, " TextureFilename {"
WriteLine ff, " " + Chr$(34) + texname$ + Chr$(34) + "; }"
If debug Then Print "texture:" + texname$
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
If (i = numVert - 1) Then st$ = ";" Else st$ = ","
xx# = VertexNX(surf, i)
yy# = VertexNY(surf, i)
zz# = VertexNZ(surf, i)
WriteLine ff, NoNan(xx#) + ";" + NoNan(yy#) + ";" + NoNan(zz#) + ";" + st$
Next
;write normal triangles
WriteLine ff, " " + numTris + ";"
For i = 0 To numTris - 1
If (i = numTris - 1) Then st$ = ";" Else st$ = ","
aa = TriangleVertex(surf, i, 0)
bb = TriangleVertex(surf, i, 1)
cc = TriangleVertex(surf, i, 2)
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, NoNan(uu#) + ";" + NoNan(vv#) + ";" + st$
Next
WriteLine ff, " }"
;close mesh block
WriteLine ff, " }"
WriteLine ff, " "
Next
End Function
;-------------------------------------------------------------------------------------------------------
; SaveAnimAnim()
;-------------------------------------------------------------------------------------------------------
;save animation sequence data to file
Function SaveAnimAnim(ff, mesh)
If AnimLength(mesh) < 0 Then Return
;used for "Animate" command
orgmesh = mesh
;start animation sequence block
WriteLine ff, "AnimationSet Sequence01 {"
;save animation data
SaveAnimDat(ff, mesh, AnimLength(mesh) + 1)
;close animation sequence block
WriteLine ff, "}"
End Function
;-------------------------------------------------------------------------------------------------------
; SaveAnimDat()
;-------------------------------------------------------------------------------------------------------
;save animation data
Function SaveAnimDat(ff, mesh, maxframe)
animname$ = "ani_" + animindex
objectname$ = "Frame" + animindex
animindex = animindex + 1
If debug Then Print "Animation" + animname$
If debug Then Print "-->" + objectname$
WriteLine ff, "Animation " + animname$ + " {"
WriteLine ff, " "
WriteLine ff, "{frm_" + objectname$ + "} "
WriteLine ff, " "
;write rotation data
WriteLine ff, "AnimationKey {"
WriteLine ff, "0;"
WriteLine ff, (maxframe) + ";"
For i = 0 To maxframe
iSetAnimTime orgmesh, i
WriteLine ff, RotationToString(i, EntityPitch(mesh), EntityYaw(mesh), EntityRoll(mesh))
Next
WriteLine ff, "}"
WriteLine ff, " "
;write scaling data
WriteLine ff, "AnimationKey {"
WriteLine ff, "1;"
WriteLine ff, (maxframe) + ";"
For i = 0 To maxframe
iSetAnimTime orgmesh, i
WriteLine ff, ScalingToString(i, EntityWidth(mesh), EntityHeight(mesh), EntityDepth(mesh))
Next
WriteLine ff, "}"
WriteLine ff, " "
;write position data
WriteLine ff, "AnimationKey {"
WriteLine ff, "2;"
WriteLine ff, (maxframe) + ";"
For i = 0 To maxframe
iSetAnimTime orgmesh, i
WriteLine ff, PositionToString(i, EntityX(mesh), EntityY(mesh), EntityZ(mesh))
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, "}"
;save children
For i = 1 To CountChildren(mesh)
g = GetChild(mesh, i)
SaveAnimDat(ff, g, maxframe)
Next
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; " + NoNan(w) + "," + NoNan(x) + "," + NoNan(y) + "," + NoNan(z) + ";;;"
End Function
;-----------------------------------------------------------------------------------------------------
; PositionToString$()
;-----------------------------------------------------------------------------------------------------
;convert position information to string
Function PositionToString$(ptime, iX#, iY#, iZ#)
Return pTime + "; 3;" + NoNan(iX) + "," + NoNan(iY) + "," + NoNan(iZ) + ";;,"
End Function
;-----------------------------------------------------------------------------------------------------
; ScalingToString$()
;-----------------------------------------------------------------------------------------------------
;convert scaling information to string
Function ScalingToString$(pTime, iWidth#, iHeight#, iDepth#)
Return pTime + "; 3;" + NoNan(iWidth) + "," + NoNan(iHeight) + "," + NoNan(iDepth) + ";;,"
End Function
;-----------------------------------------------------------------------------------------------------
; EntityWidth()
;-----------------------------------------------------------------------------------------------------
;returns width of an entity
Function EntityWidth#( mesh )
If EntityClass$(mesh) <> "Mesh" Then Return 1
If MeshWidth(mesh) = 0 Then Return 1
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)
If ll = 0 Then ll = 1
Return ll
End Function
;-----------------------------------------------------------------------------------------------------
; EntityHeight()
;-----------------------------------------------------------------------------------------------------
;returns height of an entity
Function EntityHeight#( mesh )
If EntityClass$(mesh) <> "Mesh" Then Return 1
If MeshHeight(mesh) = 0 Then Return 1
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)
If ll = 0 Then ll = 1
Return ll
End Function
;-----------------------------------------------------------------------------------------------------
; EntityDepth()
;-----------------------------------------------------------------------------------------------------
;returns depth of an entity
Function EntityDepth#( mesh )
If EntityClass$(mesh) <> "Mesh" Then Return 1
If MeshDepth(mesh) = 0 Then Return 1
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)
If ll = 0 Then ll = 1
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
If debug Then If time Mod 10 = 0 Then Print "frame:" + time
End Function
;-----------------------------------------------------------------------------------------------------
; NoNan()
;-----------------------------------------------------------------------------------------------------
;avoids writing 'Nan' (not a number) to a file.
Function NoNan#(t$)
If t$ = "NaN" Then t$ = "0"
Return t$
End Function
;-----------------------------------------------------------------------------------------------------
; Test with Mak_Robotic.X
;-----------------------------------------------------------------------------------------------------
Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer()
;setup camera
camera = CreateCamera()
PositionEntity camera,0,20,-100
CreateLight()
If FileType("C:\Program Files\Blitz3D\Samples\Blitz 3D Samples\mak\anim\makbot") <> 2 Then RuntimeError "erm .. mak_robotic is not where i expected .. sorry"
;go to directory
ChangeDir "C:\Program Files\Blitz3D\Samples\Blitz 3D Samples\mak\anim\makbot"
;load anim mesh
robot = LoadAnimMesh("mak_robotic.3ds")
;animate mesh
Animate robot, 1
;save animated mesh
SaveAnimFile robot, "robot.x"
;re-apply animation
Animate robot, 1
;load saved mesh
robot2 = LoadAnimMesh("robot.x")
If AnimLength(robot2) > 0 Then Animate robot2, 1
;move meshes to the side
MoveEntity robot2, -35, 0, 0
MoveEntity robot, 20, 0, 0
;main loop
While Not KeyDown(1)
UpdateWorld
RenderWorld
Flip
Wend
;clean up saved file
DeleteFile "robot.x"
End |
Comments
| ||
| sample taken from blitzbasic doc's addanimseq |
| ||
| awsome |
| ||
| Youve just fixed my own export! I wondered why my mesh want loading in DX viewer!!! NAN! i/we need 2 add a quick file parser to replace nans for 0.0 i did it in wordpad and it worked. Thanks for bringing that to my attention:) |
| ||
I used this function to wrap any numerical output:Function NoNan#(t$) If t$ = "NaN" Then t$ = "0" Return t$ End Function So any number that is exported to the file is passed to this function first. As for Blender, I've read that the "materials" section should define a material for each face. This results in having very long files. However, you can also omit the material tag completely. He, I didn't look at your exporter yet, but maybe we can implement animation support to it ? |
Code Archives Forum