1 # SPDX-License-Identifier: GPL-2.0-or-later
4 "name": "Export Pointcache Format(.pc2)",
5 "author": "Florian Meyer (tstscr)",
8 "location": "File > Export > Pointcache (.pc2)",
9 "description": "Export mesh Pointcache data (.pc2)",
11 "doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/pc2.html",
12 "category": "Import-Export",
17 https://developer.blender.org/T34456
18 https://developer.blender.org/T25408
23 cacheFile -pc2 1 -pcf "<insert filepath of source>" -f "<insert target filename w/o extension>" -dir "<insert directory path for target>" -format "OneFile";
28 from bpy
.props
import BoolProperty
, IntProperty
, EnumProperty
30 from bpy_extras
.io_utils
import ExportHelper
38 def get_sampled_frames(start
, end
, sampling
):
39 return [math
.modf(start
+ x
* sampling
) for x
in range(int((end
- start
) / sampling
) + 1)]
42 def do_export(context
, props
, filepath
):
43 mat_x90
= mathutils
.Matrix
.Rotation(-math
.pi
/2, 4, 'X')
44 ob
= context
.active_object
46 start
= props
.range_start
48 sampling
= float(props
.sampling
)
49 apply_modifiers
= props
.apply_modifiers
52 depsgraph
= context
.evaluated_depsgraph_get()
53 me
= ob
.evaluated_get(depsgraph
).to_mesh()
56 vertCount
= len(me
.vertices
)
57 sampletimes
= get_sampled_frames(start
, end
, sampling
)
58 sampleCount
= len(sampletimes
)
61 headerFormat
= '<12siiffi'
62 headerStr
= struct
.pack(headerFormat
, b
'POINTCACHE2\0',
63 1, vertCount
, start
, sampling
, sampleCount
)
65 file = open(filepath
, "wb")
68 for frame
in sampletimes
:
69 # stupid modf() gives decimal part first!
70 sc
.frame_set(int(frame
[1]), subframe
=frame
[0])
72 me
= ob
.evaluated_get(depsgraph
).to_mesh()
76 if len(me
.vertices
) != vertCount
:
77 bpy
.data
.meshes
.remove(me
, do_unlink
=True)
82 empty
= open(filepath
, 'w')
83 empty
.write('DUMMIFILE - export failed\n')
85 print('Export failed. Vertexcount of Object is not constant')
89 me
.transform(ob
.matrix_world
)
94 thisVertex
= struct
.pack('<fff', float(v
.co
[0]),
97 file.write(thisVertex
)
100 ob
.evaluated_get(depsgraph
).to_mesh_clear()
102 me
= ob
.to_mesh_clear()
110 class Export_pc2(bpy
.types
.Operator
, ExportHelper
):
111 """Export the active Object as a .pc2 Pointcache file"""
112 bl_idname
= "export_shape.pc2"
113 bl_label
= "Export Pointcache (.pc2)"
115 filename_ext
= ".pc2"
117 rot_x90
: BoolProperty(
118 name
="Convert to Y-up",
119 description
="Rotate 90 degrees around X to convert to y-up",
121 world_space
: BoolProperty(
122 name
="Export into Worldspace",
123 description
="Transform the Vertexcoordinates into Worldspace",
125 apply_modifiers
: BoolProperty(
126 name
="Apply Modifiers",
127 description
="Applies the Modifiers",
129 range_start
: IntProperty(
131 description
='First frame to use for Export',
133 range_end
: IntProperty(
135 description
='Last frame to use for Export',
137 sampling
: EnumProperty(
139 description
='Sampling --> frames per sample (0.1 yields 10 samples per frame)',
140 items
=(('0.01', '0.01', ''),
141 ('0.05', '0.05', ''),
144 ('0.25', '0.25', ''),
157 def poll(cls
, context
):
158 obj
= context
.active_object
161 and obj
.type in {'MESH', 'CURVE', 'SURFACE', 'FONT'}
164 def execute(self
, context
):
165 start_time
= time
.time()
166 print('\n_____START_____')
167 props
= self
.properties
168 filepath
= self
.filepath
169 filepath
= bpy
.path
.ensure_ext(filepath
, self
.filename_ext
)
171 exported
= do_export(context
, props
, filepath
)
174 print('finished export in %s seconds' %
175 ((time
.time() - start_time
)))
180 def invoke(self
, context
, event
):
181 wm
= context
.window_manager
185 wm
.fileselect_add(self
) # will run self.execute()
186 return {'RUNNING_MODAL'}
189 wm
.invoke_search_popup(self
)
190 return {'RUNNING_MODAL'}
193 return wm
.invoke_props_popup(self
, event
)
195 return self
.execute(context
)
198 def menu_func_export_button(self
, context
):
199 self
.layout
.operator(Export_pc2
.bl_idname
, text
="Pointcache (.pc2)")
209 bpy
.utils
.register_class(cls
)
211 bpy
.types
.TOPBAR_MT_file_export
.append(menu_func_export_button
)
212 #bpy.types.VIEW3D_PT_tools_objectmode.prepend(menu_func_export_button)
216 bpy
.types
.TOPBAR_MT_file_export
.remove(menu_func_export_button
)
217 #bpy.types.VIEW3D_PT_tools_objectmode.remove(menu_func_export_button)
219 bpy
.utils
.unregister_class(cls
)
222 if __name__
== "__main__":