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: 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.index_buffer = BytesIO()
|
||||
self.joints_weights_vertex_buffer = BytesIO()
|
||||
@ -76,6 +80,8 @@ class State:
|
||||
self.image_indices = {}
|
||||
self.resource_names = {}
|
||||
self.effect_textures_by_texcoord = defaultdict(list)
|
||||
self.input_filename = input_filename
|
||||
self.relative_path = False
|
||||
|
||||
def _sanitize(name):
|
||||
return name.replace(' ', '_').replace('-', '_').replace('.', '_').replace('/', '_')
|
||||
@ -228,7 +234,7 @@ def render_node_transforms(state, collada, node_name, transformation_elements):
|
||||
yield "},"
|
||||
elif type(transform) is types.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:
|
||||
yield ".type = transform_type::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):
|
||||
node_name_id = get_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 "};"
|
||||
|
||||
def render_header(namespace):
|
||||
@ -852,9 +858,11 @@ def render_library_lights(state, collada):
|
||||
|
||||
def image_resource_name(state, uri):
|
||||
uri = unquote(uri)
|
||||
prefix = "file:///"
|
||||
assert uri.startswith(prefix), uri
|
||||
path = uri[len(prefix):]
|
||||
file_prefix = "file:///"
|
||||
path = uri[len(file_prefix):] if uri.startswith(file_prefix) else uri
|
||||
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
|
||||
image_extensions = {".png", ".jpg", ".bmp", ".jpeg", ".tiff"}
|
||||
assert os.path.splitext(path)[1].lower() in image_extensions, path
|
||||
@ -959,14 +967,38 @@ def render_controller(state, collada, controller):
|
||||
yield "};"
|
||||
|
||||
def render_library_controllers(state, collada):
|
||||
for library_controller in collada.library_controllers:
|
||||
for controller in library_controller.controllers:
|
||||
for library_controllers in collada.library_controllers:
|
||||
for controller in library_controllers.controllers:
|
||||
yield from render_controller(state, collada, controller)
|
||||
|
||||
def render_all(collada, namespace):
|
||||
state = State()
|
||||
def render_camera(state, collada, camera):
|
||||
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(render_header(namespace))
|
||||
render(render_library_cameras(state, collada))
|
||||
render(render_library_lights(state, collada))
|
||||
render(render_library_animations(state, collada))
|
||||
render(render_library_images(state, collada))
|
||||
@ -996,5 +1028,5 @@ if __name__ == "__main__":
|
||||
import sys
|
||||
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())
|
||||
|
||||
@ -65,7 +65,7 @@ def main():
|
||||
|
||||
collada = parse.parse_collada_file(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:
|
||||
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()]
|
||||
assert len(values) == 16
|
||||
|
||||
r0 = tuple(values[0:4])
|
||||
r1 = tuple(values[4:8])
|
||||
r2 = tuple(values[8:12])
|
||||
r3 = tuple(values[12:16])
|
||||
|
||||
matrix = types.Matrix(sid, tuple([r0, r1, r2, r3]))
|
||||
matrix = types.Matrix(sid, values)
|
||||
lookup_add(sid_lookup, sid, matrix)
|
||||
return matrix
|
||||
|
||||
@ -1022,6 +1017,85 @@ def parse_library_controllers(lookup, root):
|
||||
lookup_add(lookup, id, 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):
|
||||
root = tree.getroot()
|
||||
assert root.tag == tag("COLLADA")
|
||||
@ -1030,6 +1104,8 @@ def parse_collada(tree):
|
||||
lookup = {}
|
||||
|
||||
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"):
|
||||
collada.library_animations.append(parse_library_animations(lookup, child))
|
||||
if child.tag == tag("library_controllers"):
|
||||
|
||||
@ -519,8 +519,39 @@ class LibraryAnimations:
|
||||
|
||||
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
|
||||
class Collada:
|
||||
library_cameras: List[LibraryCameras]
|
||||
library_animations: List[LibraryAnimations]
|
||||
library_controllers: List[LibraryControllers]
|
||||
library_effects: List[LibraryEffects]
|
||||
@ -533,6 +564,7 @@ class Collada:
|
||||
_lookup: dict = field(repr=False)
|
||||
|
||||
def __init__(self):
|
||||
self.library_cameras = []
|
||||
self.library_animations = []
|
||||
self.library_controllers = []
|
||||
self.library_effects = []
|
||||
|
||||
@ -349,6 +349,14 @@ namespace collada {
|
||||
};
|
||||
*/
|
||||
|
||||
struct camera {
|
||||
float xfov;
|
||||
float yfov;
|
||||
float znear;
|
||||
float zfar;
|
||||
float aspect_ratio;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// scene
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -543,15 +543,15 @@ float const array_node_bone002_rotationz_angle_input_array[] = {
|
||||
};
|
||||
|
||||
float const array_node_bone002_rotationz_angle_output_array[] = {
|
||||
180.0f + 180.0f,
|
||||
230.0f + 180.0f,
|
||||
180.0f + 180.0f,
|
||||
130.0f + 180.0f,
|
||||
180.0f + 180.0f,
|
||||
230.0f + 180.0f,
|
||||
180.0f + 180.0f,
|
||||
130.0f + 180.0f,
|
||||
180.0f + 180.0f,
|
||||
180.0f,
|
||||
230.0f,
|
||||
180.0f,
|
||||
130.0f,
|
||||
180.0f,
|
||||
230.0f,
|
||||
180.0f,
|
||||
130.0f,
|
||||
180.0f,
|
||||
};
|
||||
|
||||
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 },
|
||||
.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
|
||||
.material = &material_material__16_material,
|
||||
@ -1678,15 +1687,6 @@ instance_material const instance_geometry_instance_materials_node_cube_0[] = {
|
||||
.diffuse = { .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
|
||||
.material = &material_material__19_material,
|
||||
@ -2044,8 +2044,8 @@ instance_light const instance_lights_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_y,
|
||||
};
|
||||
|
||||
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[] = {
|
||||
{
|
||||
.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
|
||||
.material = &material_material__13_material,
|
||||
@ -2166,6 +2157,15 @@ instance_material const instance_controller_instance_materials_node_box001_0[] =
|
||||
.diffuse = { .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
|
||||
.material = &material_material__16_1_material,
|
||||
@ -2328,17 +2328,17 @@ node const node_node_bone002 = {
|
||||
};
|
||||
|
||||
node const * const nodes[] = {
|
||||
&node_node_environmentambientlight,
|
||||
&node_node_cube,
|
||||
&node_node_torus,
|
||||
&node_node_cylinder,
|
||||
&node_node_plane,
|
||||
&node_node_geosphere,
|
||||
&node_node_light,
|
||||
&node_node_lightindicator,
|
||||
&node_node_box001,
|
||||
&node_node_bone001,
|
||||
&node_node_bone002,
|
||||
&node_node_environmentambientlight, // 0
|
||||
&node_node_cube, // 1
|
||||
&node_node_torus, // 2
|
||||
&node_node_cylinder, // 3
|
||||
&node_node_plane, // 4
|
||||
&node_node_geosphere, // 5
|
||||
&node_node_light, // 6
|
||||
&node_node_lightindicator, // 7
|
||||
&node_node_box001, // 8
|
||||
&node_node_bone001, // 9
|
||||
&node_node_bone002, // 10
|
||||
};
|
||||
|
||||
inputs const inputs_list[] = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user