diff --git a/collada/header.py b/collada/header.py index 037dcd9..9547f74 100644 --- a/collada/header.py +++ b/collada/header.py @@ -41,6 +41,10 @@ class State: # channel nodes: node_id to list of sanitized target names node_animation_channels: Dict[str, set] + # linearized_nodes + linearized_nodes: List[types.Node] + node_parents: Dict[int, int] + def __init__(self): self.vertex_buffer = BytesIO() self.index_buffer = BytesIO() @@ -50,6 +54,8 @@ class State: self.symbol_names = {} self.emitted_input_elements_arrays = {} self.node_animation_channels = defaultdict(set) + self.linearized_nodes = [] + self.node_parents = {} def sanitize_name(state, name, value, *, allow_slash=False): assert name is not None, value @@ -284,13 +290,13 @@ def get_node_name_id(node): assert name is not None, node return name -def render_node_children(state, collada, node_name, nodes): - yield f"node const * const node_children_{node_name}[] = {{" - for node in nodes: - node_name_id = get_node_name_id(node) - node_name = sanitize_name(state, node_name_id, node) - yield "&node_{node_name}," - yield "};" +#def render_node_children(state, collada, node_name, nodes): +# yield f"node const * const node_children_{node_name}[] = {{" +# for node in nodes: +# node_name_id = get_node_name_id(node) +# node_name = sanitize_name(state, node_name_id, node) +# yield "&node_{node_name}," +# yield "};" def render_node_channels(state, collada, node, node_name): if node.id is None: @@ -304,14 +310,10 @@ def render_node_channels(state, collada, node, node_name): yield f"&node_channel_{target_name}," yield "};" -def render_node(state, collada, node): - # render children first - for child_node in node.nodes: - yield from render_node(state, collada, child_node) - +def render_node(state, collada, node, node_index): node_name_id = get_node_name_id(node) node_name = sanitize_name(state, node_name_id, node) - yield from render_node_children(state, collada, node_name, node.nodes) + #yield from render_node_children(state, collada, node_name, node.nodes) yield from render_node_transforms(state, collada, node_name, node.transformation_elements) yield from render_node_instance_geometries(state, collada, node_name, node.instance_geometries) yield from render_node_channels(state, collada, node, node_name) @@ -322,6 +324,8 @@ def render_node(state, collada, node): }[node.type] yield f"node const node_{node_name} = {{" + yield f".parent_index = {state.node_parents[node_index]}," + yield "" yield f".type = node_type::{type}," yield "" yield f".transforms = transforms_{node_name}," @@ -332,22 +336,34 @@ def render_node(state, collada, node): yield "" yield f".channels = node_channels_{node_name}," yield f".channels_count = {len(state.node_animation_channels[node.id])}," - yield "" - yield f".nodes = node_children_{node_name}," - yield f".nodes_count = {len(node.nodes)}," + #yield "" + #yield f".nodes = node_children_{node_name}," + #yield f".nodes_count = {len(node.nodes)}," yield "};" -def linear_nodes(collada): +def traverse_node(state, parent_node_index, node): + assert parent_node_index < len(state.linearized_nodes) + node_index = len(state.linearized_nodes) + state.linearized_nodes.append(node) + assert node_index not in state.node_parents + state.node_parents[node_index] = parent_node_index + for child_node in node.nodes: + traverse_node(state, node_index, child_node) + +def linearize_nodes(state, collada): for library_visual_scenes in collada.library_visual_scenes: for visual_scene in library_visual_scenes.visual_scenes: for node in visual_scene.nodes: - yield node + traverse_node(state, -1, node) def render_library_visual_scenes(state, collada): - for node in linear_nodes(collada): - yield from render_node(state, collada, node) + linearize_nodes(state, collada) + + for node_index, node in enumerate(state.linearized_nodes): + yield from render_node(state, collada, node, node_index) + yield "node const * const nodes[] = {" - for node in linear_nodes(collada): + for node_index, node in enumerate(state.linearized_nodes): node_name_id = get_node_name_id(node) node_name = sanitize_name(state, node_name_id, node) yield f"&node_{node_name}," diff --git a/include/collada_scene.hpp b/include/collada_scene.hpp index 1246aa6..c02f6db 100644 --- a/include/collada_scene.hpp +++ b/include/collada_scene.hpp @@ -43,17 +43,9 @@ namespace collada_scene { HRESULT load_scene(collada::descriptor const * const descriptor); void render(); - typedef void (collada_scene::scene_state::* const apply_node_func_t)(collada::node const * const node, - node_instance * node_instance); - private: HRESULT load_layouts(); void allocate_node_instances(); - node_instance * apply_node_instances1(collada::node const * const node, - node_instance * node_instance, - apply_node_func_t func); - void apply_node_instances(apply_node_func_t func); - void allocate_node_instance(collada::node const * const node, node_instance * node_instance); diff --git a/include/collada_types.hpp b/include/collada_types.hpp index 33de4d6..071078d 100644 --- a/include/collada_types.hpp +++ b/include/collada_types.hpp @@ -277,6 +277,8 @@ namespace collada { ////////////////////////////////////////////////////////////////////// struct node { + int const parent_index; + node_type const type; transform const * const transforms; @@ -288,8 +290,8 @@ namespace collada { channel const * const * const channels; int const channels_count; - node const * const * const nodes; - int const nodes_count; + //node const * const * const nodes; + //int const nodes_count; }; struct descriptor { diff --git a/include/scenes/curve_interpolation.hpp b/include/scenes/curve_interpolation.hpp index dcce592..6da641d 100644 --- a/include/scenes/curve_interpolation.hpp +++ b/include/scenes/curve_interpolation.hpp @@ -510,9 +510,6 @@ geometry const * const geometries[] = { &geometry_geom_plane001, }; -node const * const node_children_node_environmentambientlight[] = { -}; - transform const transforms_node_environmentambientlight[] = { }; @@ -532,12 +529,6 @@ node const node_node_environmentambientlight = { .channels = node_channels_node_environmentambientlight, .channels_count = 0, - - .nodes = node_children_node_environmentambientlight, - .nodes_count = 0, -}; - -node const * const node_children_node_cube[] = { }; transform const transforms_node_cube[] = { @@ -583,8 +574,8 @@ instance_geometry const instance_geometries_node_cube[] = { }; channel const * const node_channels_node_cube[] = { - &node_channel_node_cube_translation_y, &node_channel_node_cube_translation_x, + &node_channel_node_cube_translation_y, }; node const node_node_cube = { @@ -598,12 +589,6 @@ node const node_node_cube = { .channels = node_channels_node_cube, .channels_count = 2, - - .nodes = node_children_node_cube, - .nodes_count = 0, -}; - -node const * const node_children_node_cylinder001[] = { }; transform const transforms_node_cylinder001[] = { @@ -638,12 +623,6 @@ node const node_node_cylinder001 = { .channels = node_channels_node_cylinder001, .channels_count = 0, - - .nodes = node_children_node_cylinder001, - .nodes_count = 0, -}; - -node const * const node_children_node_plane001[] = { }; transform const transforms_node_plane001[] = { @@ -686,9 +665,6 @@ node const node_node_plane001 = { .channels = node_channels_node_plane001, .channels_count = 0, - - .nodes = node_children_node_plane001, - .nodes_count = 0, }; node const * const nodes[] = { diff --git a/src/collada_scene.cpp b/src/collada_scene.cpp index 07af7f1..9b1bb46 100644 --- a/src/collada_scene.cpp +++ b/src/collada_scene.cpp @@ -67,15 +67,6 @@ namespace collada_scene { return S_OK; } - static int count_nodes(node const * const node) - { - int count = 1; - for (int i = 0; i < node->nodes_count; i++) { - count += count_nodes(node->nodes[i]); - } - return count; - } - static void initialize_node_transforms(node const * const node, node_instance * node_instance) { @@ -113,38 +104,13 @@ namespace collada_scene { initialize_node_transforms(node, node_instance); } - node_instance * scene_state::apply_node_instances1(node const * const node, - node_instance * node_instance, - apply_node_func_t func) - { - (this->*func)(node, node_instance); - node_instance = &node_instance[1]; - - for (int i = 0; i < node->nodes_count; i++) { - node_instance = apply_node_instances1(node->nodes[i], node_instance, func); - } - - return node_instance; - } - - void scene_state::apply_node_instances(apply_node_func_t func) - { - node_instance * node_instance = m_nodeInstances; - for (int i = 0; i < m_descriptor->nodes_count; i++) { - node_instance = apply_node_instances1(m_descriptor->nodes[i], node_instance, func); - } - } - void scene_state::allocate_node_instances() { - int count = 0; + m_nodeInstances = New(m_descriptor->nodes_count); + for (int i = 0; i < m_descriptor->nodes_count; i++) { - count += count_nodes(m_descriptor->nodes[i]); + allocate_node_instance(m_descriptor->nodes[i], &m_nodeInstances[i]); } - - m_nodeInstances = New(count); - - apply_node_instances(&scene_state::allocate_node_instance); } HRESULT scene_state::load_scene(collada::descriptor const * const descriptor) @@ -383,7 +349,6 @@ namespace collada_scene { for (int i = 0; i < m_descriptor->nodes_count; i++) { node const& node = *m_descriptor->nodes[i]; - assert(node.nodes_count == 0); if (node.type != node_type::NODE) continue;