I have an old export script that worked in Blender 2.5. Now I wanted to update it to 2.9. My export uses vertex based animation as the MD2 file format uses it, so I need the vertex per animation frame position.
It works, but the mesh is not animated. I only get the vertex positions from the non-animated mesh, repeated for each frame.
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
bl_info = {
"name": "GLBasic dda",
"author": "Gernot Frisch",
"version": (1,2),
"blender": (2, 80, 0),
"location": "File > Import/Export > GLBasic dda ",
"description": "Export GLBasic DDA 3D mesh with animation (.dda format)",
"warning": "",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"
"Scripts/File_I-O/GLBasic",
"tracker_url": "https://projects.blender.org/tracker/index.php?"
"func=detail&aid=21733&group_id=153&atid=469",
"category": "Import/Export"
}
if "bpy" in locals():
import importlib
if "export_dda" in locals():
importlib.reload(export_dda)
import os
import bpy
from bpy.types import Operator, TOPBAR_MT_file_export
from bpy.props import BoolProperty, EnumProperty, FloatProperty,
FloatVectorProperty, StringProperty
from bpy_extras.io_utils import ExportHelper
def export_dda(filename, context):
try:
file = open(filename, 'w')
except:
# error = "IOError #%s: %s" % (errno, strerror)
# REPORT_DATA['errors'].append("Saving failed - %s." % error)
# ERROR_MSG = "Couldn't save file!%%t|%s" % error
print ("Exception during open out file")
raise
print ("--------------------\nEXPORT v1.2\n---------------------------\n")
scene = context.scene
scene.frame_set(1)
mesh_obj = context.object
mesh = mesh_obj.data
mesh.calc_loop_triangles()
file.write("DDDA 1.1\n")
# (1) UV coordinates for each polygon
UVCoordinates = None
for UV in mesh.uv_layers:
if UV.active_render:
UVCoordinates = UV.data
break
# build uv-dictionary
tex_list = {}
tex_count=0
for uvcoo in UVCoordinates:
uv_key = (uvcoo.uv[0], uvcoo.uv[1] )
if not (uv_key in tex_list): # .has_key(tex_key):
tex_list[ uv_key ]=tex_count
tex_count=tex_count+1
file.write("%d # tex count\n" % tex_count)
file.write("# id u v\n")
for i in range(0, tex_count):
for coord in tex_list:
if tex_list[coord] == i:
file.write("%.3f %.3f # uv\n" % (coord[0], (1.0-coord[1]) ) )
# file.write("%d # tex count\n" % len(UVCoordinates))
# file.write("# id u v\n")
# for i in range(0, len(UVCoordinates)):
# coord = UVCoordinates[i].uv
# file.write("%.3f %.3f # uv\n" % (coord[0], (1.0-coord[1]) ) )
# (2) polygon node indices
file.write("%d # num_faces\n" % (len(mesh.loop_triangles)) )
file.write("# r g b / npts / id1 id2 id3 ... iduv1 iduv2 ...\n")
iface=-1
for face in mesh.loop_triangles:
iface=iface+1
vert_in_face = len(face.loops)
if face.material_index<len(mesh.materials):
mat = mesh.materials[face.material_index]
# print "rgb=" ,mat.R, mat.G, mat.B
file.write("%d %d %d #col\n" % ( (int)(mat.diffuse_color[0]*255), (int)(mat.diffuse_color[1]*255), (int)(mat.diffuse_color[2]*255) ))
else:
print ("no material")
file.write("255 255 255 # no mat color\n")
file.write("%d " % vert_in_face) # == 3
# print("face:")
# for each vertex of that face
for i in range (vert_in_face-1, -1, -1): # reverse faces
# find the x,y,z node index
vert_index=face.vertices[i]
# print("node " + str(vert_index))
file.write("%d " % (vert_index))
# find the uv coord index for that vertex
if (len(UVCoordinates) > iface):
u = UVCoordinates[i].uv[0]
v = UVCoordinates[i].uv[1]
uvkey = (u, v)
if not (uvkey in tex_list):
file.write("0 ")
else:
file.write("%d " % tex_list[uv_key]);
else:
file.write("0 ")
file.write("\n")
# (3) per frame vertex coordinates
"""
#We only have to do this once:
ob = bpy.context.active_object #getting the object we want.
dg = bpy.context.evaluated_depsgraph_get() #getting the dependency graph
#This has to be done every time the object updates:
ob = ob.evaluated_get(dg) #this gives us the evaluated version of the object. Aka with all modifiers and deformations applied.
me = ob.to_mesh() #turn it into the mesh data block we want.
"""
graph = bpy.context.evaluated_depsgraph_get() #getting the dependency graph
startFrame = scene.frame_start
endFrame = scene.frame_end
file.write("%d #n keyframes\n" % (endFrame-startFrame+1))
file.write("# vertices: x y z nx ny nz\n")
vert_count = len(mesh.vertices);
for frameIndex in range(startFrame, endFrame+1):
file.write("# frame %d\n" % frameIndex)
#update the mesh objects vertex positions for the animation
#set blender to the correct frame
scene.frame_set(frameIndex)
mesh_obj.evaluated_get(graph)
mesh = mesh_obj.to_mesh()
# get the vertices modified by the animation
# animesh= mesh_obj.create_mesh(scene, True, 'PREVIEW') # FAILS
# animesh.calc_normals()
file.write("%d # nvertices, keyframe %d\n" % (vert_count, frameIndex))
#now for the vertices
for vert_counter in range(0, vert_count):
#XYZ
# vecpos = animesh.vertices[vert_counter].co * mesh_obj.matrix_world.transpose()
vecpos = mesh.vertices[vert_counter].co # * mesh_obj.matrix_world.transpose()
#Normal
# vecnor = animesh.vertices[vert_counter].normal # * mesh_obj.matrix_world.transpose()
vecnor = mesh.vertices[vert_counter].normal
# vecnor = unify_vec3 (mesh_obj.matrix_world.invert().transpose()*vecnor)
new_x=-vecpos[1]
new_y= vecpos[2] # swap y/z
new_z=-vecpos[0]
nor_x= -vecnor[1]
nor_y= vecnor[2] # swap y/z
nor_z= -vecnor[0]
file.write("%.3f %.3f %.3f %.3f %.3f %.3f\n" % (new_x, new_y, new_z, nor_x, nor_y, nor_z))
file.flush()
file.close()
print ("done.\n\n")
class ddaExporter(bpy.types.Operator, ExportHelper):
"""Save GLBasic 3D model""" # Tooltip
bl_idname = "export_scene.id_export_dda"
bl_label = "Export .dda"
filename_ext = '.dda'
filepath = StringProperty(name="File Path", description="Filepath used for exporting the dda file", maxlen= 1024, default= "")
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
def execute(self, context):
export_dda(str(self.filepath), context)
return {'FINISHED'}
def menu_func_export(self, context):
from io_glbasic import export_dda
import os
default_path = str(os.path.splitext(bpy.data.filepath)[0] + ".dda")
self.layout.operator(export_dda.ddaExporter.bl_idname, text='GLBasic dda (.dda)')
def register():
bpy.utils.register_class(ddaExporter)
TOPBAR_MT_file_export.append(menu_func_export)
def unregister():
bpy.utils.unregister_class(ddaExporter)
TOPBAR_MT_file_export.remove(menu_func_export)
if name == "main":
register()
mesh_obj.evaluated_get(graph)returns a new object, it doesn't changemesh_obj. So you need to callto_mesh()on the object it returns, not onmesh_obj. See if that fixes it. – scurest Nov 10 '21 at 17:14