Newer
Older
# ##### 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 #####
"name": "Export Pointcache Format(.pc2)",
"location": "File > Export > Pointcache (.pc2)",
"description": "Export mesh Pointcache data (.pc2)",
"doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/pc2.html",
"category": "Import-Export",
}
CoDEmanX
committed
Related links:
https://developer.blender.org/T34456
https://developer.blender.org/T25408
Usage Notes:
in Maya Mel:
cacheFile -pc2 1 -pcf "<insert filepath of source>" -f "<insert target filename w/o extension>" -dir "<insert directory path for target>" -format "OneFile";
Bastien Montagne
committed
from bpy.props import BoolProperty, IntProperty, EnumProperty
import mathutils
from bpy_extras.io_utils import ExportHelper
Bastien Montagne
committed
import math
import struct
Bastien Montagne
committed
def get_sampled_frames(start, end, sampling):
return [math.modf(start + x * sampling) for x in range(int((end - start) / sampling) + 1)]
def do_export(context, props, filepath):
mat_x90 = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
ob = context.active_object
sc = context.scene
start = props.range_start
end = props.range_end
sampling = float(props.sampling)
apply_modifiers = props.apply_modifiers
depsgraph = None
if apply_modifiers:
depsgraph = context.evaluated_depsgraph_get()
me = ob.evaluated_get(depsgraph).to_mesh()
else:
me = ob.to_mesh()
Bastien Montagne
committed
sampletimes = get_sampled_frames(start, end, sampling)
CoDEmanX
committed
headerStr = struct.pack(headerFormat, b'POINTCACHE2\0',
1, vertCount, start, sampling, sampleCount)
file = open(filepath, "wb")
file.write(headerStr)
CoDEmanX
committed
# stupid modf() gives decimal part first!
sc.frame_set(int(frame[1]), subframe=frame[0])
if apply_modifiers:
me = ob.evaluated_get(depsgraph).to_mesh()
else:
me = ob.to_mesh()
CoDEmanX
committed
bpy.data.meshes.remove(me, do_unlink=True)
file.close()
try:
remove(filepath)
except:
empty = open(filepath, 'w')
empty.write('DUMMIFILE - export failed\n')
empty.close()
print('Export failed. Vertexcount of Object is not constant')
return False
CoDEmanX
committed
if props.world_space:
me.transform(ob.matrix_world)
if props.rot_x90:
me.transform(mat_x90)
CoDEmanX
committed
for v in me.vertices:
thisVertex = struct.pack('<fff', float(v.co[0]),
CoDEmanX
committed
if apply_modifiers:
ob.evaluated_get(depsgraph).to_mesh_clear()
else:
me = ob.to_mesh_clear()
file.flush()
file.close()
return True
"""Export the active Object as a .pc2 Pointcache file"""
bl_idname = "export_shape.pc2"
bl_label = "Export Pointcache (.pc2)"
filename_ext = ".pc2"
CoDEmanX
committed
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
rot_x90: BoolProperty(
name="Convert to Y-up",
description="Rotate 90 degrees around X to convert to y-up",
default=True,)
world_space: BoolProperty(
name="Export into Worldspace",
description="Transform the Vertexcoordinates into Worldspace",
default=False,)
apply_modifiers: BoolProperty(
name="Apply Modifiers",
description="Applies the Modifiers",
default=True,)
range_start: IntProperty(
name='Start Frame',
description='First frame to use for Export',
default=1,)
range_end: IntProperty(
name='End Frame',
description='Last frame to use for Export',
default=250,)
sampling: EnumProperty(
name='Sampling',
description='Sampling --> frames per sample (0.1 yields 10 samples per frame)',
items=(('0.01', '0.01', ''),
('0.05', '0.05', ''),
('0.1', '0.1', ''),
('0.2', '0.2', ''),
('0.25', '0.25', ''),
('0.5', '0.5', ''),
('1', '1', ''),
('2', '2', ''),
('3', '3', ''),
('4', '4', ''),
('5', '5', ''),
('10', '10', ''),
),
default='1',
)
CoDEmanX
committed
obj is not None
and obj.type in {'MESH', 'CURVE', 'SURFACE', 'FONT'}
def execute(self, context):
start_time = time.time()
print('\n_____START_____')
props = self.properties
filepath = self.filepath
filepath = bpy.path.ensure_ext(filepath, self.filename_ext)
exported = do_export(context, props, filepath)
CoDEmanX
committed
print('finished export in %s seconds' %
((time.time() - start_time)))
CoDEmanX
committed
return {'FINISHED'}
def invoke(self, context, event):
wm = context.window_manager
if True:
# File selector
return {'RUNNING_MODAL'}
elif True:
# search the enum
wm.invoke_search_popup(self)
return {'RUNNING_MODAL'}
elif False:
# Redo popup
return wm.invoke_props_popup(self, event)
self.layout.operator(Export_pc2.bl_idname, text="Pointcache (.pc2)")
for cls in classes:
bpy.utils.register_class(cls)
bpy.types.TOPBAR_MT_file_export.append(menu_func_export_button)
#bpy.types.VIEW3D_PT_tools_objectmode.prepend(menu_func_export_button)
Campbell Barton
committed
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export_button)
#bpy.types.VIEW3D_PT_tools_objectmode.remove(menu_func_export_button)
for cls in classes:
bpy.utils.unregister_class(cls)
Campbell Barton
committed
CoDEmanX
committed