Skip to content

Commit

Permalink
Merge branch 'main' into animation_refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
julienduroure committed Feb 16, 2023
2 parents 405df21 + be5c0ce commit 144169f
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
env:
CI: true
BLENDER_MAJOR: 3
BLENDER_MINOR: 5
BLENDER_MINOR: 6

jobs:
build:
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ Notes:
* 3.4 is the current stable release. Check the `blender-v3.4-release` branch.
* 2.80 - 3.3 are previous stable releases.
* 3.3.2 is the current Blender LTS release. Check the `blender-v3.3-release` branch (and `3.3.2` tag)
* main branch of this addon is mirrored in [Blender Addons main](https://projects.blender.org/blender/blender-addons/src/branch/main/io_scene_gltf2), that will become Blender 3.5.
* `blender-v3.5-release` branch will be the next stable version.
* main branch of this addon is mirrored in [Blender Addons main](https://projects.blender.org/blender/blender-addons/src/branch/main/io_scene_gltf2), that will become Blender 3.6.

### Legacy 2.79 Support

Expand Down
23 changes: 23 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
- [X] frame_step to be tested correctly
- [X] remove export_keys file
- [ ] check fbx simplify curve
- [X] replace some gltf_selected by gltf_baked_animation
- [X] At import, both SK and TRS anim are active. Shouldn't active only the first anim in gltf file?
- [X] Make a system to bake any property (for future KHR_animation_pointer)
- [X] Cut animation when negative frame is not really possible when not sampled... --> force to_be_sampled?
- [X] names : baked/sampled
- [X] do we need to bake sk? Are drivers on sk detected as animation or not? If driver is the only case ???
- [X] cache system merge between bone/object/sk/drivers
- [ ] check @cache on functions
- [X] Rename gather_object_bake_animation_sampler to gather_object_sampled_animation_sampler
- [X] nom des fichiers _samplers ou _sampler
- [ ] Optim option for SK?
- [X] fcurve on armature itself + bones : One or 2 animation created in master? --> Only 1
- [X] animation generate_extras
- [X] restore drivers
- [ ] slide for fcurve ??? (negative frame & looping animation)
- [X] TODOCACHEANIM -> resetting cache
- [X] TODOEXTENSIONANIM -> all hooks
- [ ] Reset SK values when not keys
- [ ] Reset bone to default values
- [X] Export multiple action on same track --> Not doing it
2 changes: 1 addition & 1 deletion addons/io_scene_gltf2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
"version": (3, 5, 27),
"version": (3, 6, 1),
'blender': (3, 5, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',
Expand Down
63 changes: 36 additions & 27 deletions addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ def __init__(self, export_settings):

self.tree_troncated = False

self.axis_basis_change = Matrix.Identity(4)
if self.export_settings['gltf_yup']:
self.axis_basis_change = Matrix(
((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))

def add_node(self, node):
self.nodes[node.uuid] = node

Expand All @@ -110,9 +115,9 @@ def construct(self, blender_scene):

scene_eval = blender_scene.evaluated_get(depsgraph=depsgraph)
for blender_object in [obj.original for obj in scene_eval.objects if obj.parent is None]:
self.recursive_node_traverse(blender_object, None, None, Matrix.Identity(4), blender_children)
self.recursive_node_traverse(blender_object, None, None, Matrix.Identity(4), False, blender_children)

def recursive_node_traverse(self, blender_object, blender_bone, parent_uuid, parent_coll_matrix_world, blender_children, armature_uuid=None, dupli_world_matrix=None):
def recursive_node_traverse(self, blender_object, blender_bone, parent_uuid, parent_coll_matrix_world, delta, blender_children, armature_uuid=None, dupli_world_matrix=None):
node = VExportNode()
node.uuid = str(uuid.uuid4())
node.parent_uuid = parent_uuid
Expand Down Expand Up @@ -169,6 +174,11 @@ def recursive_node_traverse(self, blender_object, blender_bone, parent_uuid, par
node.parent_bone_uuid = parent_uuid

# World Matrix

# Delta is used when rest transforms are used for armatures
# Any children of objects parented to bones must have this delta (for grandchildren, etc...)
new_delta = False

# Store World Matrix for objects
if dupli_world_matrix is not None:
node.matrix_world = dupli_world_matrix
Expand All @@ -177,11 +187,16 @@ def recursive_node_traverse(self, blender_object, blender_bone, parent_uuid, par
# So real world matrix is collection world_matrix @ "world_matrix" of object
node.matrix_world = parent_coll_matrix_world @ blender_object.matrix_world.copy()

# If object is parented to bone, and Rest pose is used for Armature, we need to keep the world matrix transformed relative
# Of the bone rest pose, not the current world matrix
# If object is parented to bone, and Rest pose is used for Armature, we need to keep the world matrix transformed relative relative to rest pose,
# not the current world matrix (relation to pose)
if parent_uuid and self.nodes[parent_uuid].blender_type == VExportNode.BONE and self.export_settings['gltf_rest_position_armature'] is True:
_blender_bone = self.nodes[parent_uuid].blender_bone
node.matrix_world = (_blender_bone.matrix @ _blender_bone.bone.matrix_local.inverted_safe()).inverted_safe() @ node.matrix_world
_pose = self.nodes[self.nodes[parent_uuid].armature].matrix_world @ _blender_bone.matrix @ self.axis_basis_change
_rest = self.nodes[self.nodes[parent_uuid].armature].matrix_world @ _blender_bone.bone.matrix_local @ self.axis_basis_change
_delta = _pose.inverted_safe() @ node.matrix_world
node.original_matrix_world = node.matrix_world.copy()
node.matrix_world = _rest @ _delta
new_delta = True

if node.blender_type == VExportNode.CAMERA and self.export_settings['gltf_cameras']:
if self.export_settings['gltf_yup']:
Expand All @@ -202,11 +217,14 @@ def recursive_node_traverse(self, blender_object, blender_bone, parent_uuid, par
else:
# Use edit bone for TRS --> REST pose will be used
node.matrix_world = self.nodes[node.armature].matrix_world @ blender_bone.bone.matrix_local
axis_basis_change = Matrix.Identity(4)
if self.export_settings['gltf_yup']:
axis_basis_change = Matrix(
((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))
node.matrix_world = node.matrix_world @ axis_basis_change
node.matrix_world = node.matrix_world @ self.axis_basis_change

if delta is True:
_pose_parent = self.nodes[parent_uuid].original_matrix_world
_rest_parent = self.nodes[parent_uuid].matrix_world
_delta = _pose_parent.inverted_safe() @ node.matrix_world
node.original_matrix_world = node.matrix_world.copy()
node.matrix_world = _rest_parent @ _delta

# Force empty ?
# For duplis, if instancer is not display, we should create an empty
Expand All @@ -227,35 +245,35 @@ def recursive_node_traverse(self, blender_object, blender_bone, parent_uuid, par
continue
else:
# Classic parenting
self.recursive_node_traverse(child_object, None, node.uuid, parent_coll_matrix_world, blender_children)
self.recursive_node_traverse(child_object, None, node.uuid, parent_coll_matrix_world, new_delta or delta, blender_children)

# Collections
if blender_object.instance_type == 'COLLECTION' and blender_object.instance_collection:
for dupli_object in blender_object.instance_collection.all_objects:
if dupli_object.parent is not None:
continue
self.recursive_node_traverse(dupli_object, None, node.uuid, node.matrix_world, blender_children)
self.recursive_node_traverse(dupli_object, None, node.uuid, node.matrix_world, new_delta or delta, blender_children)

# Armature : children are bones with no parent
if blender_object.type == "ARMATURE" and blender_bone is None:
for b in [b for b in blender_object.pose.bones if b.parent is None]:
self.recursive_node_traverse(blender_object, b, node.uuid, parent_coll_matrix_world, blender_children, node.uuid)
self.recursive_node_traverse(blender_object, b, node.uuid, parent_coll_matrix_world, new_delta or delta, blender_children, node.uuid)

# Bones
if blender_object.type == "ARMATURE" and blender_bone is not None:
for b in blender_bone.children:
self.recursive_node_traverse(blender_object, b, node.uuid, parent_coll_matrix_world, blender_children, armature_uuid)
self.recursive_node_traverse(blender_object, b, node.uuid, parent_coll_matrix_world, new_delta or delta, blender_children, armature_uuid)

# Object parented to bone
if blender_bone is not None:
for child_object in [c for c in blender_children[blender_object] if c.parent_type == "BONE" and c.parent_bone is not None and c.parent_bone == blender_bone.name]:
self.recursive_node_traverse(child_object, None, node.uuid, parent_coll_matrix_world, blender_children)
self.recursive_node_traverse(child_object, None, node.uuid, parent_coll_matrix_world, new_delta or delta, blender_children)

# Duplis
if blender_object.is_instancer is True and blender_object.instance_type != 'COLLECTION':
depsgraph = bpy.context.evaluated_depsgraph_get()
for (dupl, mat) in [(dup.object.original, dup.matrix_world.copy()) for dup in depsgraph.object_instances if dup.parent and id(dup.parent.original) == id(blender_object)]:
self.recursive_node_traverse(dupl, None, node.uuid, parent_coll_matrix_world, blender_children, dupli_world_matrix=mat)
self.recursive_node_traverse(dupl, None, node.uuid, parent_coll_matrix_world, new_delta or delta, blender_children, dupli_world_matrix=mat)

def get_all_objects(self):
return [n.uuid for n in self.nodes.values() if n.blender_type != VExportNode.BONE]
Expand Down Expand Up @@ -441,11 +459,7 @@ def add_neutral_bones(self):
added_armatures.append(n.armature) # Make sure to not insert 2 times the neural bone

# First add a new node
axis_basis_change = Matrix.Identity(4)
if self.export_settings['gltf_yup']:
axis_basis_change = Matrix(((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))

trans, rot, sca = axis_basis_change.decompose()
trans, rot, sca = self.axis_basis_change.decompose()
translation, rotation, scale = (None, None, None)
if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0:
translation = [trans[0], trans[1], trans[2]]
Expand Down Expand Up @@ -476,13 +490,8 @@ def add_neutral_bones(self):
# Need to add an InverseBindMatrix
array = BinaryData.decode_accessor_internal(n.node.skin.inverse_bind_matrices)

axis_basis_change = Matrix.Identity(4)
if self.export_settings['gltf_yup']:
axis_basis_change = Matrix(
((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))

inverse_bind_matrix = (
axis_basis_change @ self.nodes[n.armature].matrix_world_armature).inverted_safe()
self.axis_basis_change @ self.nodes[n.armature].matrix_world_armature).inverted_safe()

matrix = []
for column in range(0, 4):
Expand Down
57 changes: 57 additions & 0 deletions docs/release_cycle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Repositories

- This repository, called _Khronos repo_ : [glTF-Blender-IO](https://github.com/KhronosGroup/glTF-Blender-IO)
- Blender addon repository, called _Blender repo_ : [blender-addons](https://projects.blender.org/blender/blender-addons)

# Release Cycle

This addon follow the [Blender release cycle](https://wiki.blender.org/wiki/Process/Release_Cycle).

# How to manage branches before and after Bcon3

- From Bcon1 to Bcon3:
- Branches:
- stable version is blender-vX.Y-release
- main branch is future next stable version X.Y+1 (or X+1.0)
- How to commit
- You can push commit to main branch

- From Bcon3 to release
- Branches:
- stable version is blender-vX.Y-release
- main branch is future stable version X.Y+2 (or X+1.1)
- future next stable is blender-vX.Y+1 (or blender-vX+1.0)

# To be perform at Bcon3

- update README.md to change versions
- main branch => update the version
- add new line with next stable release
- on your local clone of _Blender repo_, pull newly created branch
- Create new branch (blender-vX.Y+1-release), and push this branch
- on main branch of _Khronos repo_, bump version number to the new version, commit, push
- copy this change to main branch of _Blender repo_ (see details bellow)
- update version test config file : ci.yml

# How to commit from bcon3 to release

- _Khronos repo_ : git checkout blender-vX.Y-release
- (Merge PR from github + git pull) or (commit + push) on blender-vX.Y-release
- git pull _Blender repo_
- _Blender repo_: git checkout blender-vX.Y-release
- python tools/copy_repo -r /path/blender_repo/source/release/addons -b -w
- _Blender repo_: git add . ; git commit ; git push
- _Blender repo_: git checkout main ; git merge blender-vX.Y-release
- _Blender repo_: fix merge error (bump version on main) ; git push
- _Khronos repo_: git add . ; git commit (Bump version)
- _Khronos repo_: git checkout main ; git merge blender-vX.Y-release
- _Khronos repo_: fix merge error (bump version on main) ; git push


# At release

TODO

# Corrective release / LTS

TODO

0 comments on commit 144169f

Please sign in to comment.