collada: add support for lua source generation

This commit is contained in:
Zack Buhman 2026-02-23 18:40:36 +00:00
parent 4603ebcec2
commit 0f68237b73
4 changed files with 398 additions and 50 deletions

View File

@ -269,7 +269,7 @@ def render_interpolation_array(array_name, names):
def render_float_array(array_name, vectors): def render_float_array(array_name, vectors):
yield f"float const array_{array_name}[] = {{" yield f"float const array_{array_name}[] = {{"
for vector in vectors: for vector in vectors:
yield f"{vector}," yield f"{render_float_tuple(vector)},"
yield "};" yield "};"
def render_source(source_name, field_name, c_type, array_name, count, stride): def render_source(source_name, field_name, c_type, array_name, count, stride):
@ -295,7 +295,7 @@ def render_channel(target_name, sampler_name, transform_index, target_attribute)
def render_light(light_name, light_type, color): def render_light(light_name, light_type, color):
yield f"light const light_{light_name} = {{" yield f"light const light_{light_name} = {{"
yield f".type = light_type::{light_type}," yield f".type = light_type::{light_type},"
yield f".color = {{ {color} }}," yield f".color = {{ {render_float_tuple(color)} }},"
yield "};" yield "};"
def render_image(image_id, image_name, resource_name): def render_image(image_id, image_name, resource_name):

View File

@ -14,7 +14,8 @@ from collada import parse
from collada import types from collada import types
from collada.generate import renderer from collada.generate import renderer
from collada import buffer from collada import buffer
from collada import cpp_header
lang_header = None
@dataclass @dataclass
class State: class State:
@ -139,7 +140,7 @@ def render_input_elements(state, collada, geometry_name, offset_tables):
continue continue
state.emitted_input_elements_arrays[key_name] = (i, key) state.emitted_input_elements_arrays[key_name] = (i, key)
yield from cpp_header.render_input_elements(key_name, key) yield from lang_header.render_input_elements(key_name, key)
def render_triangles(state, collada, geometry_name, primitive_elements, mesh_buffer_state): def render_triangles(state, collada, geometry_name, primitive_elements, mesh_buffer_state):
yield from render_input_elements(state, collada, geometry_name, mesh_buffer_state.offset_tables) yield from render_input_elements(state, collada, geometry_name, mesh_buffer_state.offset_tables)
@ -154,7 +155,7 @@ def render_triangles(state, collada, geometry_name, primitive_elements, mesh_buf
yield triangles.count, mesh_buffer_state.index_buffer_offsets[i], index yield triangles.count, mesh_buffer_state.index_buffer_offsets[i], index
yield from cpp_header.render_triangles(geometry_name, items()) yield from lang_header.render_triangles(geometry_name, items())
def render_geometry(state, collada, geometry): def render_geometry(state, collada, geometry):
geometry_name = sanitize_name(state, geometry.id, geometry) geometry_name = sanitize_name(state, geometry.id, geometry)
@ -178,7 +179,7 @@ def render_geometry(state, collada, geometry):
triangles_count = len(mesh.primitive_elements) triangles_count = len(mesh.primitive_elements)
yield from cpp_header.render_geometry(geometry_name, yield from lang_header.render_geometry(geometry_name,
triangles_count, triangles_count,
vertex_buffer_offset, vertex_buffer_offset,
vertex_buffer_size, vertex_buffer_size,
@ -200,26 +201,26 @@ def render_library_geometries(state, collada):
geometry_name = sanitize_name(state, geometry.id, geometry) geometry_name = sanitize_name(state, geometry.id, geometry)
yield geometry_name yield geometry_name
yield from cpp_header.render_library_geometries(geometry_names()) yield from lang_header.render_library_geometries(geometry_names())
def render_node_transforms(state, collada, node_name, transformation_elements): def render_node_transforms(state, collada, node_name, transformation_elements):
def render_transform(transform): def render_transform(transform):
if type(transform) is types.Lookat: if type(transform) is types.Lookat:
yield from cpp_header.render_transform_lookat(transform.eye, transform.at, transform.up) yield from lang_header.render_transform_lookat(transform.eye, transform.at, transform.up)
elif type(transform) is types.Matrix: elif type(transform) is types.Matrix:
yield from cpp_header.render_transform_matrix(matrix_transpose(transform.values)) yield from lang_header.render_transform_matrix(matrix_transpose(transform.values))
elif type(transform) is types.Rotate: elif type(transform) is types.Rotate:
yield from cpp_header.render_transform_rotate(transform.rotate) yield from lang_header.render_transform_rotate(transform.rotate)
elif type(transform) is types.Scale: elif type(transform) is types.Scale:
yield from cpp_header.render_transform_scale(transform.scale) yield from lang_header.render_transform_scale(transform.scale)
elif type(transform) is types.Skew: elif type(transform) is types.Skew:
yield from cpp_header.render_transform_skew(transform.skew) yield from lang_header.render_transform_skew(transform.skew)
elif type(transform) is types.Translate: elif type(transform) is types.Translate:
yield from cpp_header.render_transform_translate(transform.translate) yield from lang_header.render_transform_translate(transform.translate)
else: else:
assert False, type(transform) assert False, type(transform)
yield from cpp_header.render_node_transforms(node_name, transformation_elements, render_transform) yield from lang_header.render_node_transforms(node_name, transformation_elements, render_transform)
def find_material_symbol(geometry, material_symbol): def find_material_symbol(geometry, material_symbol):
assert material_symbol is not None assert material_symbol is not None
@ -279,7 +280,7 @@ def render_node_geometry_instance_materials(state, collada, prefix, node_name, i
specular_input_set = shader_to_input_set(channel_to_input_set, shader, attrgetter("specular")) specular_input_set = shader_to_input_set(channel_to_input_set, shader, attrgetter("specular"))
yield element_index, material_name, emission_input_set, ambient_input_set, diffuse_input_set, specular_input_set yield element_index, material_name, emission_input_set, ambient_input_set, diffuse_input_set, specular_input_set
yield from cpp_header.render_node_geometry_instance_materials(prefix, node_name, i, items()) yield from lang_header.render_node_geometry_instance_materials(prefix, node_name, i, items())
def get_instance_materials(instance_geometry): def get_instance_materials(instance_geometry):
return instance_geometry.bind_material.technique_common.materials if instance_geometry.bind_material is not None else [] return instance_geometry.bind_material.technique_common.materials if instance_geometry.bind_material is not None else []
@ -300,7 +301,7 @@ def render_node_instance_geometries(state, collada, node_name, instance_geometri
yield geometry_name, i, instance_materials_count yield geometry_name, i, instance_materials_count
yield from cpp_header.render_node_instance_geometries(node_name, items()) yield from lang_header.render_node_instance_geometries(node_name, items())
def get_node_name_id(node): def get_node_name_id(node):
name = node.id if node.id is not None else f"node-{node.name}" name = node.id if node.id is not None else f"node-{node.name}"
@ -318,10 +319,10 @@ def get_node_name_id(node):
def render_node_channels(state, collada, node, node_name): def render_node_channels(state, collada, node, node_name):
if node.id is None: if node.id is None:
# nodes with no ID can't have channels # nodes with no ID can't have channels
yield from cpp_header.render_node_channels(node_name, []) yield from lang_header.render_node_channels(node_name, [])
else: else:
target_names = state.node_animation_channels[node.id] target_names = state.node_animation_channels[node.id]
yield from cpp_header.render_node_channels(node_name, target_names) yield from lang_header.render_node_channels(node_name, target_names)
def render_node_instance_lights(state, collada, node_name, instance_lights): def render_node_instance_lights(state, collada, node_name, instance_lights):
def light_names(): def light_names():
@ -330,7 +331,7 @@ def render_node_instance_lights(state, collada, node_name, instance_lights):
light_name = sanitize_name(state, light.id, light) light_name = sanitize_name(state, light.id, light)
yield light_name yield light_name
yield from cpp_header.render_node_instance_lights(node_name, light_names()) yield from lang_header.render_node_instance_lights(node_name, light_names())
def find_node_by_sid(root_node, sid): def find_node_by_sid(root_node, sid):
if sid == root_node.sid: if sid == root_node.sid:
@ -365,7 +366,7 @@ def render_joint_node_indices(state, collada, skin, node_name, controller_name,
joint_node_name = sanitize_name(state, joint_node_name_id, joint_node) joint_node_name = sanitize_name(state, joint_node_name_id, joint_node)
yield joint_node_index, node_sid, joint_node_name yield joint_node_index, node_sid, joint_node_name
yield from cpp_header.render_joint_node_indices(node_name, controller_name, items()) yield from lang_header.render_joint_node_indices(node_name, controller_name, items())
def render_node_instance_controller_joint_node_indices(state, collada, node_name, instance_controller): def render_node_instance_controller_joint_node_indices(state, collada, node_name, instance_controller):
controller = collada.lookup(instance_controller.url, types.Controller) controller = collada.lookup(instance_controller.url, types.Controller)
@ -395,7 +396,7 @@ def render_node_instance_controllers(state, collada, node_name, instance_control
yield controller_name, i, instance_materials_count yield controller_name, i, instance_materials_count
yield from cpp_header.render_node_instance_controllers(node_name, items()) yield from lang_header.render_node_instance_controllers(node_name, items())
def render_node(state, collada, node, node_index): def render_node(state, collada, node, node_index):
node_name_id = get_node_name_id(node) node_name_id = get_node_name_id(node)
@ -419,7 +420,7 @@ def render_node(state, collada, node, node_index):
instance_lights_count = len(node.instance_lights) instance_lights_count = len(node.instance_lights)
channels_count = len(state.node_animation_channels[node.id]) channels_count = len(state.node_animation_channels[node.id])
yield from cpp_header.render_node(node_name, parent_index, type, yield from lang_header.render_node(node_name, parent_index, type,
transforms_count, transforms_count,
instance_geometries_count, instance_geometries_count,
instance_controllers_count, instance_controllers_count,
@ -453,7 +454,7 @@ def render_library_visual_scenes(state, collada):
node_name = sanitize_name(state, node_name_id, node) node_name = sanitize_name(state, node_name_id, node)
yield node_name, node_index yield node_name, node_index
yield from cpp_header.render_library_visual_scenes(items()) yield from lang_header.render_library_visual_scenes(items())
def render_opt_texture(state, profile_common, field_name, texture): def render_opt_texture(state, profile_common, field_name, texture):
sampler_sid = texture.texture sampler_sid = texture.texture
@ -469,10 +470,10 @@ def render_opt_texture(state, profile_common, field_name, texture):
image_id = surface.parameter_type.init_from.uri image_id = surface.parameter_type.init_from.uri
image_index = state.image_indices[image_id] image_index = state.image_indices[image_id]
yield from cpp_header.render_opt_texture(field_name, image_index, image_id) yield from lang_header.render_opt_texture(field_name, image_index, image_id)
def render_opt_color(field_name, color): def render_opt_color(field_name, color):
yield from cpp_header.render_opt_color(field_name, color) yield from lang_header.render_opt_color(field_name, color)
def render_opt_color_or_texture(state, profile_common, field_name, color_or_texture): def render_opt_color_or_texture(state, profile_common, field_name, color_or_texture):
if color_or_texture is None: if color_or_texture is None:
@ -490,12 +491,12 @@ def render_opt_color_or_texture(state, profile_common, field_name, color_or_text
else: else:
assert False, color_or_texture assert False, color_or_texture
yield from cpp_header.render_opt_color_or_texture(field_name, opt_type, render_body) yield from lang_header.render_opt_color_or_texture(field_name, opt_type, render_body)
def render_opt_float(field_name, f): def render_opt_float(field_name, f):
if f is None: if f is None:
f = types.Float(value=0.0) f = types.Float(value=0.0)
yield from cpp_header.render_opt_float(field_name, float(f.value)) yield from lang_header.render_opt_float(field_name, float(f.value))
def render_effect(state, collada, effect): def render_effect(state, collada, effect):
profile_common, = effect.profile_common profile_common, = effect.profile_common
@ -556,7 +557,7 @@ def render_effect(state, collada, effect):
else: else:
assert False, type(shader) assert False, type(shader)
yield from cpp_header.render_effect(effect_name, type_name, field_name, render_body) yield from lang_header.render_effect(effect_name, type_name, field_name, render_body)
def render_library_effects(state, collada): def render_library_effects(state, collada):
for library_effects in collada.library_effects: for library_effects in collada.library_effects:
@ -569,21 +570,21 @@ def render_library_materials(state, collada):
effect = collada.lookup(material.instance_effect.url, types.Effect) effect = collada.lookup(material.instance_effect.url, types.Effect)
material_name = sanitize_name(state, material.id, material) material_name = sanitize_name(state, material.id, material)
effect_name = sanitize_name(state, effect.id, effect) effect_name = sanitize_name(state, effect.id, effect)
yield from cpp_header.render_library_material(material_name, effect_name) yield from lang_header.render_library_material(material_name, effect_name)
def render_input_elements_list(state): def render_input_elements_list(state):
def items(): def items():
for key_name, (index, key) in state.emitted_input_elements_arrays.items(): for key_name, (index, key) in state.emitted_input_elements_arrays.items():
elements_count = len(key) elements_count = len(key)
yield key_name, elements_count yield key_name, elements_count
yield from cpp_header.render_input_elements_list(items()) yield from lang_header.render_input_elements_list(items())
def render_animation_children(state, collada, animation_name, animations): def render_animation_children(state, collada, animation_name, animations):
def items(): def items():
for animation in animations: for animation in animations:
animation_name = sanitize_name(state, animation.id, animation) animation_name = sanitize_name(state, animation.id, animation)
yield animation_name yield animation_name
yield from cpp_header.render_animation_children(animation_name, items()) yield from lang_header.render_animation_children(animation_name, items())
def render_array(state, collada, accessor, array): def render_array(state, collada, accessor, array):
array_name = sanitize_name(state, array.id, array) array_name = sanitize_name(state, array.id, array)
@ -596,14 +597,14 @@ def render_array(state, collada, accessor, array):
for name in array.names: for name in array.names:
assert name in {"BEZIER", "LINEAR"}, name assert name in {"BEZIER", "LINEAR"}, name
yield name yield name
yield from cpp_header.render_interpolation_array(array_name, names()) yield from lang_header.render_interpolation_array(array_name, names())
elif type(array) is types.FloatArray: elif type(array) is types.FloatArray:
def vectors(): def vectors():
it = iter(array.floats) it = iter(array.floats)
for i in range(accessor.count): for i in range(accessor.count):
vector = ", ".join(f"{float(f)}f" for f in islice(it, accessor.stride)) vector = list(islice(it, accessor.stride))
yield vector yield vector
yield from cpp_header.render_float_array(array_name, vectors()) yield from lang_header.render_float_array(array_name, vectors())
else: else:
assert False, type(array) assert False, type(array)
@ -612,7 +613,7 @@ def render_source(state, collada, field_name, source):
c_type = "interpolation" if type(source.array_element) is types.NameArray else "float" c_type = "interpolation" if type(source.array_element) is types.NameArray else "float"
source_name = sanitize_name(state, source.id, source) source_name = sanitize_name(state, source.id, source)
yield from cpp_header.render_source(source_name, yield from lang_header.render_source(source_name,
field_name, field_name,
c_type, c_type,
array_name, array_name,
@ -656,7 +657,7 @@ def render_sampler(state, collada, sampler):
source = collada.lookup(input.source, types.SourceCore) source = collada.lookup(input.source, types.SourceCore)
field_name = input.semantic.lower() field_name = input.semantic.lower()
yield from render_source(state, collada, field_name, source) yield from render_source(state, collada, field_name, source)
yield from cpp_header.render_sampler(sampler_name, render_body) yield from lang_header.render_sampler(sampler_name, render_body)
target_attributes = { target_attributes = {
"A", "ANGLE", "B", "G", "P", "Q", "R", "S", "T", "TIME", "U", "V", "W", "X", "Y", "Z", "ALL" "A", "ANGLE", "B", "G", "P", "Q", "R", "S", "T", "TIME", "U", "V", "W", "X", "Y", "Z", "ALL"
@ -703,7 +704,7 @@ def render_channel(state, collada, channel):
assert target_name not in state.node_animation_channels[node.id] assert target_name not in state.node_animation_channels[node.id]
state.node_animation_channels[node.id].add(target_name) state.node_animation_channels[node.id].add(target_name)
yield from cpp_header.render_channel(target_name, sampler_name, transform_index, target_attribute) yield from lang_header.render_channel(target_name, sampler_name, transform_index, target_attribute)
def render_animation(state, collada, animation_name, animation): def render_animation(state, collada, animation_name, animation):
# render children first # render children first
@ -751,9 +752,9 @@ def render_light_type(technique_common: types.TechniqueCommon_Light):
def render_light(state, collada, light): def render_light(state, collada, light):
technique_common = light.technique_common technique_common = light.technique_common
light_name = sanitize_name(state, light.id, light) light_name = sanitize_name(state, light.id, light)
color = ", ".join(f"{float(f)}f" for f in technique_common.light.color) color = technique_common.light.color
light_type = render_light_type(technique_common) light_type = render_light_type(technique_common)
yield from cpp_header.render_light(light_name, light_type, color) yield from lang_header.render_light(light_name, light_type, color)
def render_library_lights(state, collada): def render_library_lights(state, collada):
for library_lights in collada.library_lights: for library_lights in collada.library_lights:
@ -785,7 +786,7 @@ def render_image(state, collada, image, image_index):
resource_name = image_resource_name(state, image.image_source.uri) resource_name = image_resource_name(state, image.image_source.uri)
image_name = sanitize_name(state, image.id, image) image_name = sanitize_name(state, image.id, image)
yield from cpp_header.render_image(image.id, image_name, resource_name) yield from lang_header.render_image(image.id, image_name, resource_name)
def render_library_images(state, collada): def render_library_images(state, collada):
image_index = 0 image_index = 0
@ -799,7 +800,7 @@ def render_library_images(state, collada):
for image in library_images.images: for image in library_images.images:
image_name = sanitize_name(state, image.id, image) image_name = sanitize_name(state, image.id, image)
yield image_name yield image_name
yield from cpp_header.render_library_images(image_names()) yield from lang_header.render_library_images(image_names())
def render_inverse_bind_matrices(collada, skin, controller_name): def render_inverse_bind_matrices(collada, skin, controller_name):
inverse_bind_matrix_input, = find_semantics(skin.joints.inputs, "INV_BIND_MATRIX") inverse_bind_matrix_input, = find_semantics(skin.joints.inputs, "INV_BIND_MATRIX")
@ -817,7 +818,7 @@ def render_inverse_bind_matrices(collada, skin, controller_name):
offset = stride * i offset = stride * i
matrix = matrix_transpose(array.floats[offset:offset+stride]) matrix = matrix_transpose(array.floats[offset:offset+stride])
yield matrix yield matrix
yield from cpp_header.render_inverse_bind_matrices(controller_name, matrices()) yield from lang_header.render_inverse_bind_matrices(controller_name, matrices())
def renderbin_any(f, elems): def renderbin_any(f, elems):
fmt = { fmt = {
@ -847,7 +848,7 @@ def render_controller(state, collada, controller):
yield from render_inverse_bind_matrices(collada, skin, controller_name) yield from render_inverse_bind_matrices(collada, skin, controller_name)
yield from cpp_header.render_controller(controller_name, geometry_name, vertex_buffer_offset, vertex_buffer_size) yield from lang_header.render_controller(controller_name, geometry_name, vertex_buffer_offset, vertex_buffer_size)
def render_library_controllers(state, collada): def render_library_controllers(state, collada):
for library_controllers in collada.library_controllers: for library_controllers in collada.library_controllers:
@ -864,7 +865,7 @@ def render_camera(state, collada, camera):
else: else:
return f return f
yield from cpp_header.render_camera(camera_name, yield from lang_header.render_camera(camera_name,
nf(perspective.xfov), nf(perspective.xfov),
nf(perspective.yfov), nf(perspective.yfov),
nf(perspective.znear), nf(perspective.znear),
@ -879,7 +880,7 @@ def render_library_cameras(state, collada):
def render_all(collada, namespace, input_filename): def render_all(collada, namespace, input_filename):
state = State(input_filename) state = State(input_filename)
render, out = renderer() render, out = renderer()
render(cpp_header.render_prelude(namespace)) render(lang_header.render_prelude(namespace))
render(render_library_cameras(state, collada)) render(render_library_cameras(state, collada))
render(render_library_lights(state, collada)) render(render_library_lights(state, collada))
render(render_library_animations(state, collada)) render(render_library_animations(state, collada))
@ -892,13 +893,13 @@ def render_all(collada, namespace, input_filename):
# root elements # root elements
render(render_library_visual_scenes(state, collada)) render(render_library_visual_scenes(state, collada))
render(render_input_elements_list(state)) render(render_input_elements_list(state))
render(cpp_header.render_descriptor(namespace)) render(lang_header.render_descriptor(namespace))
render(cpp_header.render_prologue()) render(lang_header.render_prologue())
return state, out return state, out
def render_all_hpp(namespace): def render_all_hpp(namespace):
render, out = renderer() render, out = renderer()
render(cpp_header.render_hpp(namespace)) render(lang_header.render_hpp(namespace))
return out return out
if __name__ == "__main__": if __name__ == "__main__":

338
collada/lua_header.py Normal file
View File

@ -0,0 +1,338 @@
from itertools import islice
from collada import types
def render_input_elements(key_name, semantic__semantic_index__stride):
yield f"local input_elements_{key_name} = {{"
for semantic, semantic_index, stride in semantic__semantic_index__stride:
yield "{"
yield f'semantic = "{semantic}",'
yield f"semantic_index = {semantic_index},"
yield f"format = collada_types.input_format.FLOAT{stride},"
yield "},"
yield "}"
def render_triangles(geometry_name, items):
yield f"local triangles_{geometry_name} = {{"
for count, index_offset, inputs_index in items:
yield "{"
yield f"count = {count}, -- triangles"
yield f"index_offset = {index_offset}, -- indices"
yield f"inputs_index = {inputs_index}, -- index into inputs_list"
yield "},"
yield "}"
def render_geometry(geometry_name,
triangles_count,
vertex_buffer_offset, vertex_buffer_size,
index_buffer_offset, index_buffer_size):
yield f"local geometry_{geometry_name} = {{"
yield "mesh = {"
yield f"triangles = triangles_{geometry_name},"
yield f"triangles_count = {triangles_count},"
yield ""
yield f"vertex_buffer_offset = {vertex_buffer_offset},"
yield f"vertex_buffer_size = {vertex_buffer_size},"
yield ""
yield f"index_buffer_offset = {index_buffer_offset},"
yield f"index_buffer_size = {index_buffer_size},"
yield "}"
yield "}"
def render_library_geometries(geometry_names):
yield "local geometries = {"
for geometry_name in geometry_names:
yield f"geometry_{geometry_name},"
yield "}"
def render_float_tuple(t):
s = ", ".join((f"{float(f)}" for f in t))
return f"{{{s}}}"
def render_lookat(eye, at, up):
yield "type = collada_types.transform_type.LOOKAT,"
yield "lookat = {"
yield f"eye = {render_float_tuple(eye)}",
yield f"at = {render_float_tuple(at)}",
yield f"up = {render_float_tuple(up)}",
yield "},"
def render_matrix(fs):
fsi = iter(fs)
for i in range(4):
s = ", ".join(f"{f}" for f in islice(fsi, 4))
yield f"{s},"
def render_transform_matrix(matrix):
yield "type = collada_types.transform_type.MATRIX,"
yield f"matrix = {render_float_tuple(matrix)},"
def render_transform_rotate(rotate):
yield "type = collada_types.transform_type.ROTATE,"
yield f"rotate = {render_float_tuple(rotate)},"
def render_transform_scale(scale):
yield "type = collada_types.transform_type.SCALE,"
yield f"scale = {render_float_tuple(scale)},"
def render_transform_skew(skew):
yield "type = collada_types.transform_type.SKEW,"
yield f"skew = {render_float_tuple(skew)},"
def render_transform_translate(translate):
yield "type = collada_types.transform_type.TRANSLATE,"
yield f"translate = {render_float_tuple(translate)},"
def render_node_transforms(node_name, transformation_elements, render_transform):
yield f"local transforms_{node_name} = {{"
for transform in transformation_elements:
yield "{"
yield from render_transform(transform)
yield "},"
yield "}"
def render_node_geometry_instance_materials(prefix, node_name, i,
items):
yield f"local {prefix}_instance_materials_{node_name}_{i} = {{"
for element_index, material_name, emission_input_set, ambient_input_set, diffuse_input_set, specular_input_set in items:
yield "{"
yield f"element_index = {element_index}, -- an index into mesh.triangles"
yield f"material = material_{material_name},"
yield ""
yield f"emission = {{ input_set = {emission_input_set} }},"
yield f"ambient = {{ input_set = {ambient_input_set} }},"
yield f"diffuse = {{ input_set = {diffuse_input_set} }},"
yield f"specular = {{ input_set = {specular_input_set} }},"
yield "},"
yield "}"
def render_node_instance_geometries(node_name, items):
yield f"local instance_geometries_{node_name} = {{"
for geometry_name, i, instance_materials_count in items:
yield "{"
yield f"geometry = geometry_{geometry_name},"
yield ""
yield f"instance_materials = instance_geometry_instance_materials_{node_name}_{i},"
yield f"instance_materials_count = {instance_materials_count},"
yield "},"
yield "}"
def render_node_channels(node_name, target_names):
yield f"local node_channels_{node_name} = {{"
for target_name in target_names:
yield f"node_channel_{target_name},"
yield "}"
def render_node_instance_lights(node_name, light_names):
yield f"local instance_lights_{node_name} = {{"
for light_name in light_names:
yield "{"
yield f"light = light_{light_name},"
yield "}"
yield "}"
def render_joint_node_indices(node_name, controller_name, items):
yield f"local joint_node_indices_{node_name}_{controller_name} = {{"
for joint_node_index, node_sid, joint_node_name in items:
yield f"{joint_node_index}, -- {node_sid} {joint_node_name}"
yield "}"
def render_node_instance_controllers(node_name, items):
yield f"local instance_controllers_{node_name} = {{"
for controller_name, i, instance_materials_count in items:
yield "{"
yield f"controller = controller_{controller_name},"
yield ""
yield f"joint_node_indices = joint_node_indices_{node_name}_{controller_name},"
yield f"joint_count = #joint_node_indices_{node_name}_{controller_name},"
yield ""
yield f"instance_materials = instance_controller_instance_materials_{node_name}_{i},"
yield f"instance_materials_count = {instance_materials_count},"
yield "},"
yield "}"
def render_node(node_name, parent_index, type,
transforms_count,
instance_geometries_count,
instance_controllers_count,
instance_lights_count,
channels_count):
yield f"local node_{node_name} = {{"
yield f"parent_index = {parent_index},"
yield ""
yield f"type = collada_types.node_type.{type},"
yield ""
yield f"transforms = transforms_{node_name},"
yield f"transforms_count = {transforms_count},"
yield ""
yield f"instance_geometries = instance_geometries_{node_name},"
yield f"instance_geometries_count = {instance_geometries_count},"
yield ""
yield f"instance_controllers = instance_controllers_{node_name},"
yield f"instance_controllers_count = {instance_controllers_count},"
yield ""
yield f"instance_lights = instance_lights_{node_name},"
yield f"instance_lights_count = {instance_lights_count},"
yield ""
yield f"channels = node_channels_{node_name},"
yield f"channels_count = {channels_count},"
#yield ""
#yield f"nodes = node_children_{node_name},"
#yield f"nodes_count = {len(node.nodes)},"
yield "}"
def render_library_visual_scenes(items):
yield "local nodes = {"
for node_name, node_index in items:
yield f"node_{node_name}, -- {node_index}"
yield "}"
def render_opt_color(field_name, color):
yield f"{field_name} = {render_float_tuple(color.value)},"
def render_opt_texture(field_name, image_index, image_id):
yield f"{field_name} = {{ .image_index = {image_index} }}, -- {image_id}"
def render_opt_color_or_texture(field_name, opt_type, render_body):
yield f"{field_name} = {{"
yield f"type = collada_types.color_or_texture_type.{opt_type},"
yield from render_body()
yield "},"
def render_opt_float(field_name, value):
yield f"{field_name} = {value},"
def render_effect(effect_name, type_name, field_name, render_body):
yield f"local effect_{effect_name} = {{"
yield f"type = collada_types.effect_type.{type_name},"
yield f"{field_name} = {{"
yield from render_body()
yield "}"
yield "}"
def render_library_material(material_name, effect_name):
yield f"local material_{material_name} = {{"
yield f"effect = effect_{effect_name},"
yield "}"
def render_input_elements_list(items):
yield "local inputs_list = {"
for key_name, elements_count in items:
yield "{"
yield f"elements = input_elements_{key_name},"
yield f"elements_count = {elements_count},"
yield "},"
yield "}"
def render_descriptor(namespace):
yield "local descriptor = {"
yield "nodes = nodes,"
yield "nodes_count = #nodes,"
yield ""
yield "inputs_list = inputs_list,"
yield "inputs_list_count = #inputs_list,"
yield ""
yield "images = images,"
yield "images_count = #images,"
yield ""
#yield f'position_normal_texture_buffer = L"RES_SCENES_{namespace.upper()}_VTX",'
#yield f'joint_weight_buffer = L"RES_SCENES_{namespace.upper()}_VJW",'
#yield f'index_buffer = L"RES_SCENES_{namespace.upper()}_IDX",'
yield "}"
def render_prelude(namespace):
yield "local collada_types = require 'collada_types'"
yield ''
def render_prologue():
yield ""
yield "return {"
yield "descriptor = descriptor"
yield "}"
def render_animation_children(anomation_name, items):
yield f"local animation_children_{animation_name} = {{"
for animation_name in items:
yield "animation_{animation_name},"
yield "}"
def render_interpolation_array(array_name, names):
yield f"local array_{array_name} = {{"
for name in names:
yield f"collada_types.interpolation.{name},"
yield "}"
def render_float_array(array_name, vectors):
yield f"local array_{array_name} = {{"
for vector in vectors:
yield f"{render_float_tuple(vector)},"
yield "}"
def render_source(source_name, field_name, c_type, array_name, count, stride):
yield f"-- {source_name}"
yield f"{field_name} = {{"
yield f"{c_type}_array = array_{array_name},"
yield f"count = {count},"
yield f"stride = {stride},"
yield "},"
def render_sampler(sampler_name, render_body):
yield f"local sampler_{sampler_name} = {{"
yield from render_body()
yield "}"
def render_channel(target_name, sampler_name, transform_index, target_attribute):
yield f"local node_channel_{target_name} = {{"
yield f"source_sampler = sampler_{sampler_name},"
yield f"target_transform_index = {transform_index},"
yield f"target_attribute = collada_types.target_attribute.{target_attribute},"
yield "}"
def render_light(light_name, light_type, color):
yield f"local light_{light_name} = {{"
yield f"type = collada_types.light_type.{light_type},"
yield f"color = {render_float_tuple(color)},"
yield "}"
def render_image(image_id, image_name, resource_name):
yield f"-- {image.id}"
yield f"local image_{image_name} = {{"
yield f'resource_name = L"{resource_name}",'
yield "}"
def render_library_images(image_names):
yield "local images = {"
for image_name in image_names:
yield f"image_{image_name},"
yield "}"
def render_inverse_bind_matrices(controller_name, matrices):
yield f"local inverse_bind_matrices_{controller_name} = {{"
for matrix in matrices:
yield "{"
yield from render_matrix(matrix)
yield "},"
yield "}"
def render_controller(controller_name, geometry_name, vertex_buffer_offset, vertex_buffer_size):
yield f"local controller_{controller_name} = {{"
yield "skin = {"
yield f"geometry = geometry_{geometry_name},"
yield ""
yield f"inverse_bind_matrices = inverse_bind_matrices_{controller_name},"
yield ""
yield f"vertex_buffer_offset = {vertex_buffer_offset},"
yield f"vertex_buffer_size = {vertex_buffer_size},"
yield "}"
yield "}"
def render_camera(camera_name, xfov, yfov, znear, zfar, aspect_ratio):
yield f"local camera_{camera_name} = {{"
yield f"xfov = {xfov}f,"
yield f"yfov = {yfov}f,"
yield f"znear = {znear}f,"
yield f"zfar = {zfar}f,"
yield f"aspect_ratio = {aspect_ratio}f,"
yield "}"

View File

@ -3,6 +3,8 @@ import os.path
from collada import parse from collada import parse
from collada import header from collada import header
from collada import cpp_header
from collada import lua_header
def usage(): def usage():
name = sys.argv[0] name = sys.argv[0]
@ -60,7 +62,7 @@ def main():
output_resource = sys.argv[6] output_resource = sys.argv[6]
output_makefile = sys.argv[7] output_makefile = sys.argv[7]
assert input_collada.lower().endswith(".dae") assert input_collada.lower().endswith(".dae")
assert output_source.lower().endswith(".cpp") assert output_source.lower().endswith(".cpp") or output_source.lower().endswith(".lua")
assert output_position_normal_texture.lower().endswith(".vtx") assert output_position_normal_texture.lower().endswith(".vtx")
assert output_joint_weight.lower().endswith(".vjw") assert output_joint_weight.lower().endswith(".vjw")
assert output_index.lower().endswith(".idx") assert output_index.lower().endswith(".idx")
@ -71,6 +73,13 @@ def main():
collada = parse.parse_collada_file(input_collada) collada = parse.parse_collada_file(input_collada)
namespace = parse_namespace(input_collada) namespace = parse_namespace(input_collada)
if output_source.lower().endswith(".cpp"):
header.lang_header = cpp_header
elif output_source.lower().endswith(".lua"):
header.lang_header = lua_header
else:
assert False
state, out_source = header.render_all(collada, namespace, input_collada) state, out_source = header.render_all(collada, namespace, input_collada)
with open(output_source, 'wb') as f: with open(output_source, 'wb') as f: