collada: partial support for cameras
This commit is contained in:
parent
d7183c1b39
commit
fcbaf7ab66
@ -61,7 +61,11 @@ class State:
|
|||||||
# effect_textures_by_texcoord: (effect_id, channel): [sampler_sid]
|
# effect_textures_by_texcoord: (effect_id, channel): [sampler_sid]
|
||||||
effect_textures_by_texcoord: Dict[Tuple[str, str], list]
|
effect_textures_by_texcoord: Dict[Tuple[str, str], list]
|
||||||
|
|
||||||
def __init__(self):
|
# input_filename
|
||||||
|
input_filename: str
|
||||||
|
relative_path: bool
|
||||||
|
|
||||||
|
def __init__(self, input_filename):
|
||||||
self.vertex_buffer = BytesIO()
|
self.vertex_buffer = BytesIO()
|
||||||
self.index_buffer = BytesIO()
|
self.index_buffer = BytesIO()
|
||||||
self.joints_weights_vertex_buffer = BytesIO()
|
self.joints_weights_vertex_buffer = BytesIO()
|
||||||
@ -76,6 +80,8 @@ class State:
|
|||||||
self.image_indices = {}
|
self.image_indices = {}
|
||||||
self.resource_names = {}
|
self.resource_names = {}
|
||||||
self.effect_textures_by_texcoord = defaultdict(list)
|
self.effect_textures_by_texcoord = defaultdict(list)
|
||||||
|
self.input_filename = input_filename
|
||||||
|
self.relative_path = False
|
||||||
|
|
||||||
def _sanitize(name):
|
def _sanitize(name):
|
||||||
return name.replace(' ', '_').replace('-', '_').replace('.', '_').replace('/', '_')
|
return name.replace(' ', '_').replace('-', '_').replace('.', '_').replace('/', '_')
|
||||||
@ -228,7 +234,7 @@ def render_node_transforms(state, collada, node_name, transformation_elements):
|
|||||||
yield "},"
|
yield "},"
|
||||||
elif type(transform) is types.Matrix:
|
elif type(transform) is types.Matrix:
|
||||||
yield ".type = transform_type::MATRIX,"
|
yield ".type = transform_type::MATRIX,"
|
||||||
yield f".matrix = {render_float_tuple(matrix_transpose(transform.matrix))},"
|
yield f".matrix = {render_float_tuple(matrix_transpose(transform.values))},"
|
||||||
elif type(transform) is types.Rotate:
|
elif type(transform) is types.Rotate:
|
||||||
yield ".type = transform_type::ROTATE,"
|
yield ".type = transform_type::ROTATE,"
|
||||||
yield f".rotate = {render_float_tuple(transform.rotate)},"
|
yield f".rotate = {render_float_tuple(transform.rotate)},"
|
||||||
@ -507,7 +513,7 @@ def render_library_visual_scenes(state, collada):
|
|||||||
for node_index, node in enumerate(state.linearized_nodes):
|
for node_index, node in enumerate(state.linearized_nodes):
|
||||||
node_name_id = get_node_name_id(node)
|
node_name_id = get_node_name_id(node)
|
||||||
node_name = sanitize_name(state, node_name_id, node)
|
node_name = sanitize_name(state, node_name_id, node)
|
||||||
yield f"&node_{node_name},"
|
yield f"&node_{node_name}, // {node_index}"
|
||||||
yield "};"
|
yield "};"
|
||||||
|
|
||||||
def render_header(namespace):
|
def render_header(namespace):
|
||||||
@ -852,9 +858,11 @@ def render_library_lights(state, collada):
|
|||||||
|
|
||||||
def image_resource_name(state, uri):
|
def image_resource_name(state, uri):
|
||||||
uri = unquote(uri)
|
uri = unquote(uri)
|
||||||
prefix = "file:///"
|
file_prefix = "file:///"
|
||||||
assert uri.startswith(prefix), uri
|
path = uri[len(file_prefix):] if uri.startswith(file_prefix) else uri
|
||||||
path = uri[len(prefix):]
|
if not os.path.isabs(path) and not os.path.exists(path):
|
||||||
|
path = os.path.join(os.path.dirname(state.input_filename), path)
|
||||||
|
state.relative_path = True
|
||||||
assert os.path.exists(path), path
|
assert os.path.exists(path), path
|
||||||
image_extensions = {".png", ".jpg", ".bmp", ".jpeg", ".tiff"}
|
image_extensions = {".png", ".jpg", ".bmp", ".jpeg", ".tiff"}
|
||||||
assert os.path.splitext(path)[1].lower() in image_extensions, path
|
assert os.path.splitext(path)[1].lower() in image_extensions, path
|
||||||
@ -959,14 +967,38 @@ def render_controller(state, collada, controller):
|
|||||||
yield "};"
|
yield "};"
|
||||||
|
|
||||||
def render_library_controllers(state, collada):
|
def render_library_controllers(state, collada):
|
||||||
for library_controller in collada.library_controllers:
|
for library_controllers in collada.library_controllers:
|
||||||
for controller in library_controller.controllers:
|
for controller in library_controllers.controllers:
|
||||||
yield from render_controller(state, collada, controller)
|
yield from render_controller(state, collada, controller)
|
||||||
|
|
||||||
def render_all(collada, namespace):
|
def render_camera(state, collada, camera):
|
||||||
state = State()
|
camera_name = sanitize_name(state, camera.id, camera)
|
||||||
|
perspective = camera.optics.technique_common.projection_type
|
||||||
|
assert type(perspective) is types.Perspective
|
||||||
|
def nf(f):
|
||||||
|
if f is None:
|
||||||
|
return float(0)
|
||||||
|
else:
|
||||||
|
return f
|
||||||
|
|
||||||
|
yield f"camera const camera_{camera_name} = {{"
|
||||||
|
yield f".xfov = {nf(perspective.xfov)}f,"
|
||||||
|
yield f".yfov = {nf(perspective.yfov)}f,"
|
||||||
|
yield f".znear = {nf(perspective.znear)}f,"
|
||||||
|
yield f".zfar = {nf(perspective.zfar)}f,"
|
||||||
|
yield f".aspect_ratio = {nf(perspective.aspect_ratio)}f,"
|
||||||
|
yield "};"
|
||||||
|
|
||||||
|
def render_library_cameras(state, collada):
|
||||||
|
for library_cameras in collada.library_cameras:
|
||||||
|
for camera in library_cameras.cameras:
|
||||||
|
yield from render_camera(state, collada, camera)
|
||||||
|
|
||||||
|
def render_all(collada, namespace, input_filename):
|
||||||
|
state = State(input_filename)
|
||||||
render, out = renderer()
|
render, out = renderer()
|
||||||
render(render_header(namespace))
|
render(render_header(namespace))
|
||||||
|
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))
|
||||||
render(render_library_images(state, collada))
|
render(render_library_images(state, collada))
|
||||||
@ -996,5 +1028,5 @@ if __name__ == "__main__":
|
|||||||
import sys
|
import sys
|
||||||
collada = parse.parse_collada_file(sys.argv[1])
|
collada = parse.parse_collada_file(sys.argv[1])
|
||||||
|
|
||||||
state, out = render_all(collada, "test")
|
state, out = render_all(collada, "test", "./test.DAE")
|
||||||
print(out.getvalue())
|
print(out.getvalue())
|
||||||
|
|||||||
@ -65,7 +65,7 @@ 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)
|
||||||
state, out_source = header.render_all(collada, namespace)
|
state, out_source = header.render_all(collada, namespace, input_collada)
|
||||||
|
|
||||||
with open(output_source, 'wb') as f:
|
with open(output_source, 'wb') as f:
|
||||||
source_buf = out_source.getvalue()
|
source_buf = out_source.getvalue()
|
||||||
|
|||||||
@ -649,12 +649,7 @@ def parse_matrix(lookup, sid_lookup, root):
|
|||||||
values = [float(i) for i in root.text.strip().split()]
|
values = [float(i) for i in root.text.strip().split()]
|
||||||
assert len(values) == 16
|
assert len(values) == 16
|
||||||
|
|
||||||
r0 = tuple(values[0:4])
|
matrix = types.Matrix(sid, values)
|
||||||
r1 = tuple(values[4:8])
|
|
||||||
r2 = tuple(values[8:12])
|
|
||||||
r3 = tuple(values[12:16])
|
|
||||||
|
|
||||||
matrix = types.Matrix(sid, tuple([r0, r1, r2, r3]))
|
|
||||||
lookup_add(sid_lookup, sid, matrix)
|
lookup_add(sid_lookup, sid, matrix)
|
||||||
return matrix
|
return matrix
|
||||||
|
|
||||||
@ -1022,6 +1017,85 @@ def parse_library_controllers(lookup, root):
|
|||||||
lookup_add(lookup, id, library_controllers)
|
lookup_add(lookup, id, library_controllers)
|
||||||
return library_controllers
|
return library_controllers
|
||||||
|
|
||||||
|
def parse_perspective(lookup, root):
|
||||||
|
xfov = None
|
||||||
|
yfov = None
|
||||||
|
znear = None
|
||||||
|
zfar = None
|
||||||
|
aspect_ratio = None
|
||||||
|
for child in root.getchildren():
|
||||||
|
assert len(child.getchildren()) == 0
|
||||||
|
if child.tag == tag("xfov"):
|
||||||
|
assert xfov is None
|
||||||
|
xfov = float(child.text.strip())
|
||||||
|
if child.tag == tag("yfov"):
|
||||||
|
assert yfov is None
|
||||||
|
yfov = float(child.text.strip())
|
||||||
|
if child.tag == tag("znear"):
|
||||||
|
assert znear is None
|
||||||
|
znear = float(child.text.strip())
|
||||||
|
if child.tag == tag("zfar"):
|
||||||
|
assert zfar is None
|
||||||
|
zfar = float(child.text.strip())
|
||||||
|
if child.tag == tag("aspect_ratio"):
|
||||||
|
assert aspect_ratio is None
|
||||||
|
aspect_ratio = float(child.text.strip())
|
||||||
|
perspective = types.Perspective(xfov, yfov, znear, zfar, aspect_ratio)
|
||||||
|
return perspective
|
||||||
|
|
||||||
|
def parse_technique_common_optics(lookup, root):
|
||||||
|
projection_type = None
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("perspective"):
|
||||||
|
assert projection_type is None
|
||||||
|
projection_type = parse_perspective(lookup, child)
|
||||||
|
if child.tag == tag("orthographic"):
|
||||||
|
assert projection_type is None
|
||||||
|
assert False, child.tag
|
||||||
|
assert projection_type is not None
|
||||||
|
optics = types.TechniqueCommon_Optics(projection_type)
|
||||||
|
return optics
|
||||||
|
|
||||||
|
def parse_optics(lookup, root):
|
||||||
|
technique_common = None
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("technique_common"):
|
||||||
|
assert technique_common is None
|
||||||
|
technique_common = parse_technique_common_optics(lookup, child)
|
||||||
|
assert technique_common is not None
|
||||||
|
optics = types.Optics(technique_common)
|
||||||
|
return optics
|
||||||
|
|
||||||
|
def parse_camera(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
|
||||||
|
optics = None
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("optics"):
|
||||||
|
assert optics is None
|
||||||
|
optics = parse_optics(lookup, child)
|
||||||
|
|
||||||
|
assert optics is not None
|
||||||
|
camera = types.Camera(id, name, optics)
|
||||||
|
lookup_add(lookup, id, camera)
|
||||||
|
return camera
|
||||||
|
|
||||||
|
def parse_library_cameras(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
|
||||||
|
cameras = []
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("camera"):
|
||||||
|
cameras.append(parse_camera(lookup, child))
|
||||||
|
|
||||||
|
assert len(cameras) >= 1
|
||||||
|
|
||||||
|
library_cameras = types.LibraryCameras(id, name, cameras)
|
||||||
|
lookup_add(lookup, id, library_cameras)
|
||||||
|
return library_cameras
|
||||||
|
|
||||||
def parse_collada(tree):
|
def parse_collada(tree):
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
assert root.tag == tag("COLLADA")
|
assert root.tag == tag("COLLADA")
|
||||||
@ -1030,6 +1104,8 @@ def parse_collada(tree):
|
|||||||
lookup = {}
|
lookup = {}
|
||||||
|
|
||||||
for child in root.getchildren():
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("library_cameras"):
|
||||||
|
collada.library_cameras.append(parse_library_cameras(lookup, child))
|
||||||
if child.tag == tag("library_animations"):
|
if child.tag == tag("library_animations"):
|
||||||
collada.library_animations.append(parse_library_animations(lookup, child))
|
collada.library_animations.append(parse_library_animations(lookup, child))
|
||||||
if child.tag == tag("library_controllers"):
|
if child.tag == tag("library_controllers"):
|
||||||
|
|||||||
@ -519,8 +519,39 @@ class LibraryAnimations:
|
|||||||
|
|
||||||
animations: List[Animation] # 1 or more
|
animations: List[Animation] # 1 or more
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Perspective:
|
||||||
|
xfov: float
|
||||||
|
yfov: float
|
||||||
|
znear: float
|
||||||
|
zfar: float
|
||||||
|
aspect_ratio: float
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class TechniqueCommon_Optics:
|
||||||
|
projection_type: Union[Perspective]
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Optics:
|
||||||
|
technique_common: TechniqueCommon_Optics
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class Camera:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
optics: Optics
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class LibraryCameras:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
cameras: List[Camera] # 1 or more
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Collada:
|
class Collada:
|
||||||
|
library_cameras: List[LibraryCameras]
|
||||||
library_animations: List[LibraryAnimations]
|
library_animations: List[LibraryAnimations]
|
||||||
library_controllers: List[LibraryControllers]
|
library_controllers: List[LibraryControllers]
|
||||||
library_effects: List[LibraryEffects]
|
library_effects: List[LibraryEffects]
|
||||||
@ -533,6 +564,7 @@ class Collada:
|
|||||||
_lookup: dict = field(repr=False)
|
_lookup: dict = field(repr=False)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.library_cameras = []
|
||||||
self.library_animations = []
|
self.library_animations = []
|
||||||
self.library_controllers = []
|
self.library_controllers = []
|
||||||
self.library_effects = []
|
self.library_effects = []
|
||||||
|
|||||||
@ -349,6 +349,14 @@ namespace collada {
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct camera {
|
||||||
|
float xfov;
|
||||||
|
float yfov;
|
||||||
|
float znear;
|
||||||
|
float zfar;
|
||||||
|
float aspect_ratio;
|
||||||
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// scene
|
// scene
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -543,15 +543,15 @@ float const array_node_bone002_rotationz_angle_input_array[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
float const array_node_bone002_rotationz_angle_output_array[] = {
|
float const array_node_bone002_rotationz_angle_output_array[] = {
|
||||||
180.0f + 180.0f,
|
180.0f,
|
||||||
230.0f + 180.0f,
|
230.0f,
|
||||||
180.0f + 180.0f,
|
180.0f,
|
||||||
130.0f + 180.0f,
|
130.0f,
|
||||||
180.0f + 180.0f,
|
180.0f,
|
||||||
230.0f + 180.0f,
|
230.0f,
|
||||||
180.0f + 180.0f,
|
180.0f,
|
||||||
130.0f + 180.0f,
|
130.0f,
|
||||||
180.0f + 180.0f,
|
180.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
float const array_node_bone002_rotationz_angle_intangent_array[] = {
|
float const array_node_bone002_rotationz_angle_intangent_array[] = {
|
||||||
@ -1660,6 +1660,15 @@ instance_material const instance_geometry_instance_materials_node_cube_0[] = {
|
|||||||
.diffuse = { .input_set = -1 },
|
.diffuse = { .input_set = -1 },
|
||||||
.specular = { .input_set = -1 },
|
.specular = { .input_set = -1 },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.element_index = 5, // an index into mesh.triangles
|
||||||
|
.material = &material_material__17_material,
|
||||||
|
|
||||||
|
.emission = { .input_set = -1 },
|
||||||
|
.ambient = { .input_set = -1 },
|
||||||
|
.diffuse = { .input_set = -1 },
|
||||||
|
.specular = { .input_set = -1 },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.element_index = 0, // an index into mesh.triangles
|
.element_index = 0, // an index into mesh.triangles
|
||||||
.material = &material_material__16_material,
|
.material = &material_material__16_material,
|
||||||
@ -1678,15 +1687,6 @@ instance_material const instance_geometry_instance_materials_node_cube_0[] = {
|
|||||||
.diffuse = { .input_set = -1 },
|
.diffuse = { .input_set = -1 },
|
||||||
.specular = { .input_set = -1 },
|
.specular = { .input_set = -1 },
|
||||||
},
|
},
|
||||||
{
|
|
||||||
.element_index = 5, // an index into mesh.triangles
|
|
||||||
.material = &material_material__17_material,
|
|
||||||
|
|
||||||
.emission = { .input_set = -1 },
|
|
||||||
.ambient = { .input_set = -1 },
|
|
||||||
.diffuse = { .input_set = -1 },
|
|
||||||
.specular = { .input_set = -1 },
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
.element_index = 2, // an index into mesh.triangles
|
.element_index = 2, // an index into mesh.triangles
|
||||||
.material = &material_material__19_material,
|
.material = &material_material__19_material,
|
||||||
@ -2044,8 +2044,8 @@ instance_light const instance_lights_node_light[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
channel const * const node_channels_node_light[] = {
|
channel const * const node_channels_node_light[] = {
|
||||||
&node_channel_node_light_translation_y,
|
|
||||||
&node_channel_node_light_translation_x,
|
&node_channel_node_light_translation_x,
|
||||||
|
&node_channel_node_light_translation_y,
|
||||||
};
|
};
|
||||||
|
|
||||||
node const node_node_light = {
|
node const node_node_light = {
|
||||||
@ -2139,15 +2139,6 @@ int const joint_node_indices_node_box001_geom_box001_skin1[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
instance_material const instance_controller_instance_materials_node_box001_0[] = {
|
instance_material const instance_controller_instance_materials_node_box001_0[] = {
|
||||||
{
|
|
||||||
.element_index = 0, // an index into mesh.triangles
|
|
||||||
.material = &material_material__14_material,
|
|
||||||
|
|
||||||
.emission = { .input_set = -1 },
|
|
||||||
.ambient = { .input_set = -1 },
|
|
||||||
.diffuse = { .input_set = -1 },
|
|
||||||
.specular = { .input_set = -1 },
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
.element_index = 1, // an index into mesh.triangles
|
.element_index = 1, // an index into mesh.triangles
|
||||||
.material = &material_material__13_material,
|
.material = &material_material__13_material,
|
||||||
@ -2166,6 +2157,15 @@ instance_material const instance_controller_instance_materials_node_box001_0[] =
|
|||||||
.diffuse = { .input_set = -1 },
|
.diffuse = { .input_set = -1 },
|
||||||
.specular = { .input_set = -1 },
|
.specular = { .input_set = -1 },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.element_index = 0, // an index into mesh.triangles
|
||||||
|
.material = &material_material__14_material,
|
||||||
|
|
||||||
|
.emission = { .input_set = -1 },
|
||||||
|
.ambient = { .input_set = -1 },
|
||||||
|
.diffuse = { .input_set = -1 },
|
||||||
|
.specular = { .input_set = -1 },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.element_index = 3, // an index into mesh.triangles
|
.element_index = 3, // an index into mesh.triangles
|
||||||
.material = &material_material__16_1_material,
|
.material = &material_material__16_1_material,
|
||||||
@ -2328,17 +2328,17 @@ node const node_node_bone002 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
node const * const nodes[] = {
|
node const * const nodes[] = {
|
||||||
&node_node_environmentambientlight,
|
&node_node_environmentambientlight, // 0
|
||||||
&node_node_cube,
|
&node_node_cube, // 1
|
||||||
&node_node_torus,
|
&node_node_torus, // 2
|
||||||
&node_node_cylinder,
|
&node_node_cylinder, // 3
|
||||||
&node_node_plane,
|
&node_node_plane, // 4
|
||||||
&node_node_geosphere,
|
&node_node_geosphere, // 5
|
||||||
&node_node_light,
|
&node_node_light, // 6
|
||||||
&node_node_lightindicator,
|
&node_node_lightindicator, // 7
|
||||||
&node_node_box001,
|
&node_node_box001, // 8
|
||||||
&node_node_bone001,
|
&node_node_bone001, // 9
|
||||||
&node_node_bone002,
|
&node_node_bone002, // 10
|
||||||
};
|
};
|
||||||
|
|
||||||
inputs const inputs_list[] = {
|
inputs const inputs_list[] = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user