Skip to content

Instantly share code, notes, and snippets.

@joncardasis
Last active November 3, 2024 09:41
Show Gist options
  • Save joncardasis/e815ec69f81ed767389aa7a878f3deb6 to your computer and use it in GitHub Desktop.
Save joncardasis/e815ec69f81ed767389aa7a878f3deb6 to your computer and use it in GitHub Desktop.
Convert Collada (.DAE) animation files for Xcode Scenekit Animation use by removing unnecessary data.
#!/usr/local/bin/python
# Jonathan Cardasis, 2018
#
# Cleans up a collada `dae` file removing all unnessasary data
# only leaving animations and bone structures behind.
# Combines multiple animation sequences into a single animation
# sequence for Xcode to use.
import sys
import os
import re
import subprocess
def print_usage(app_name):
print 'Usage:'
print ' {} [path(s) to collada file(s)...]'.format(app_name)
print ''
def xml_is_collada(xml_string):
return bool(re.search('(<COLLADA).*(>)', xml_string))
################
## MAIN ##
################
DAE_TAGS_TO_STRIP = ['library_geometries', 'library_materials', 'library_images']
if len(sys.argv) < 2:
app_name = os.path.basename(sys.argv[0])
print_usage(app_name)
sys.exit(1)
print 'Stripping collada files of non-animation essential features...'
failed_file_conversions = 0
for file_path in sys.argv[1:]:
try:
print 'Stripping {} ...'.format(file_path)
dae_filename = os.path.basename(file_path)
renamed_dae_path = file_path + '.old'
dae = open(file_path, 'r')
xml_string = dae.read().strip()
dae.close()
# Ensure is a collada file
if not xml_is_collada(xml_string):
raise Exception('Not a proper Collada file.')
# Strip tags
for tag in DAE_TAGS_TO_STRIP:
xml_string = re.sub('(?:<{tag}>)([\s\S]+?)(?:</{tag}>)'.format(tag=tag), '', xml_string)
# Combine animation keys into single key:
# 1. Remove all <animation> tags.
# 2. Add leading and trailing <library_animation> tags with single <animation> tag between.
xml_string = re.sub(r'\s*(<animation[^>]*>)\s*', '\n', xml_string)
xml_string = re.sub(r'\s*(<\/animation\s*>.*)\s*', '', xml_string)
xml_string = re.sub(r'\s*(<library_animations>)\s*', '<library_animations>\n<animation>\n', xml_string)
xml_string = re.sub(r'\s*(<\/library_animations>)\s*', '\n</animation>\n</library_animations>', xml_string)
# Rename original and dump xml to previous file location
os.rename(file_path, renamed_dae_path)
with open(file_path, 'w') as new_dae:
new_dae.write(xml_string)
print 'Finished processing {}. Old file can be found at {}.\n'.format(file_path, renamed_dae_path)
except Exception as e:
print '[!] Failed to correctly parse {}: {}'.format(file_path, e)
failed_file_conversions += 1
if failed_file_conversions > 0:
print '\nFailed {} conversion(s).'.format(failed_file_conversions)
sys.exit(1)
@8secz-johndpope
Copy link

8secz-johndpope commented May 29, 2020

Is this to achieve smaller file size?
I arrived here from stack overflow - but I'm wanting to get clarity around if I have the (mixamo samba style) dances in FBX
can I some how import this animation (500kb) and have the usdz or dae model apply the fbx dance?
or do I need to spit out a new dae file with the skeleton /body / mesh ? ~ 20mb or can I import / export it? then apply it? (https://www.reddit.com/r/gamedev/comments/4jb68g/anyone_still_got_the_whole_mixamo_pack/ - talking about the giant animations 4.5gb here)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment