collada: incomplete collada file parser
This commit is contained in:
parent
add3facb88
commit
bccb3632ae
2
.gitignore
vendored
2
.gitignore
vendored
@ -7,3 +7,5 @@
|
|||||||
*.obj
|
*.obj
|
||||||
*.res
|
*.res
|
||||||
*.aps
|
*.aps
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
1
Makefile
1
Makefile
@ -24,6 +24,7 @@ CFLAGS += -Wno-unknown-pragmas
|
|||||||
CFLAGS += -I./include
|
CFLAGS += -I./include
|
||||||
CFLAGS += -municode
|
CFLAGS += -municode
|
||||||
LDFLAGS += -municode
|
LDFLAGS += -municode
|
||||||
|
LDFLAGS += -static-libgcc
|
||||||
|
|
||||||
CXXFLAGS += -fno-exceptions
|
CXXFLAGS += -fno-exceptions
|
||||||
|
|
||||||
|
|||||||
435
collada/collada_types.py
Normal file
435
collada/collada_types.py
Normal file
@ -0,0 +1,435 @@
|
|||||||
|
from dataclasses import dataclass, field
|
||||||
|
from enum import Enum, auto
|
||||||
|
from typing import Optional, Union, List, Tuple
|
||||||
|
|
||||||
|
URI = str
|
||||||
|
ID = str
|
||||||
|
|
||||||
|
Float3 = Tuple[float, float, float]
|
||||||
|
Float4 = Tuple[float, float, float, float]
|
||||||
|
Float7 = Tuple[float, float, float, float, float, float, float]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Lookat:
|
||||||
|
sid: Optional[str]
|
||||||
|
eye: Float3
|
||||||
|
at: Float3
|
||||||
|
up: Float3
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Matrix:
|
||||||
|
# collada is the transpose of a directx matrix
|
||||||
|
# 1.0 0.0 0.0 0.0
|
||||||
|
# 0.0 1.0 0.0 0.0
|
||||||
|
# 0.0 0.0 1.0 0.0
|
||||||
|
# 2.0 3.0 4.0 1.0
|
||||||
|
sid: Optional[str]
|
||||||
|
values: Tuple[Float4, Float4, Float4, Float4]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Rotate:
|
||||||
|
# x y z w ; quaternion
|
||||||
|
sid: Optional[str]
|
||||||
|
rotate: Float4
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Scale:
|
||||||
|
sid: Optional[str]
|
||||||
|
scale: Float3
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Skew:
|
||||||
|
sid: Optional[str]
|
||||||
|
skew: Float7
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Translate:
|
||||||
|
sid: Optional[str]
|
||||||
|
translate: Float3
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Param:
|
||||||
|
name: Optional[str]
|
||||||
|
sid: Optional[str]
|
||||||
|
type: str
|
||||||
|
semantic: Optional[str]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Accessor:
|
||||||
|
count: int
|
||||||
|
offset: Optional[int]
|
||||||
|
source: URI
|
||||||
|
stride: Optional[int]
|
||||||
|
|
||||||
|
params: List[Param]
|
||||||
|
|
||||||
|
sid_lookup: dict = field(repr=False)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TechniqueCommon_SourceCore:
|
||||||
|
accessor: Accessor
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Ambient:
|
||||||
|
color: Float3
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Directional:
|
||||||
|
color: Float3
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Point:
|
||||||
|
color: Float3
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Spot:
|
||||||
|
color: Float3
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BindVertexInput:
|
||||||
|
semantic: str
|
||||||
|
input_semantic: str
|
||||||
|
input_set: int
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InstanceMaterial:
|
||||||
|
sid: Optional[str]
|
||||||
|
name: Optional[str]
|
||||||
|
target: URI
|
||||||
|
symbol: str
|
||||||
|
|
||||||
|
bind_vertex_inputs: List[BindVertexInput]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TechniqueCommon_BindMaterial:
|
||||||
|
materials: List[InstanceMaterial] # one or more
|
||||||
|
|
||||||
|
sid_lookup: dict = field(repr=False)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BindMaterial:
|
||||||
|
technique_common: TechniqueCommon_BindMaterial
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InstanceGeometry:
|
||||||
|
sid: Optional[str]
|
||||||
|
name: Optional[str]
|
||||||
|
url: URI
|
||||||
|
|
||||||
|
# child element
|
||||||
|
bind_material: Optional[BindMaterial]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InstanceLight:
|
||||||
|
sid: Optional[str]
|
||||||
|
name: Optional[str]
|
||||||
|
url: URI
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InstanceVisualScene:
|
||||||
|
sid: Optional[str]
|
||||||
|
name: Optional[str]
|
||||||
|
url: URI
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Scene:
|
||||||
|
instance_visual_scene: InstanceVisualScene
|
||||||
|
|
||||||
|
sid_lookup: dict = field(repr=False)
|
||||||
|
|
||||||
|
class FxSurfaceType(Enum):
|
||||||
|
UNTYPED = auto()
|
||||||
|
_1D = auto()
|
||||||
|
_2D = auto()
|
||||||
|
_3D = auto()
|
||||||
|
CUBE = auto()
|
||||||
|
DEPTH = auto()
|
||||||
|
RECT = auto()
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InitFrom:
|
||||||
|
uri: str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Surface:
|
||||||
|
type: FxSurfaceType
|
||||||
|
|
||||||
|
init_from: InitFrom
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SourceFX:
|
||||||
|
sid: ID
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Sampler2D:
|
||||||
|
source: SourceFX
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Newparam:
|
||||||
|
sid: str # required
|
||||||
|
parameter_type: Union[Surface, Sampler2D]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Color:
|
||||||
|
value: Float4
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Float:
|
||||||
|
value: float
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Texture:
|
||||||
|
texture: str
|
||||||
|
texcoord: str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Blinn:
|
||||||
|
emission: Optional[Union[Color, Texture]]
|
||||||
|
ambient: Optional[Union[Color, Texture]]
|
||||||
|
diffuse: Optional[Union[Color, Texture]]
|
||||||
|
specular: Optional[Union[Color, Texture]]
|
||||||
|
shininess: Optional[Float]
|
||||||
|
reflective: Optional[Union[Color, Texture]]
|
||||||
|
reflectivity: Optional[Float]
|
||||||
|
transparent: Optional[Union[Color, Texture]]
|
||||||
|
transparency: Optional[Float]
|
||||||
|
index_of_refraction: Optional[Float]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Lambert:
|
||||||
|
emission: Optional[Union[Color, Texture]]
|
||||||
|
ambient: Optional[Union[Color, Texture]]
|
||||||
|
diffuse: Optional[Union[Color, Texture]]
|
||||||
|
reflective: Optional[Union[Color, Texture]]
|
||||||
|
reflectivity: Optional[Float]
|
||||||
|
transparent: Optional[Union[Color, Texture]]
|
||||||
|
transparency: Optional[Float]
|
||||||
|
index_of_refraction: Optional[Float]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Phong:
|
||||||
|
emission: Optional[Union[Color, Texture]]
|
||||||
|
ambient: Optional[Union[Color, Texture]]
|
||||||
|
diffuse: Optional[Union[Color, Texture]]
|
||||||
|
specular: Optional[Union[Color, Texture]]
|
||||||
|
shininess: Optional[Float]
|
||||||
|
reflective: Optional[Union[Color, Texture]]
|
||||||
|
reflectivity: Optional[Float]
|
||||||
|
transparent: Optional[Union[Color, Texture]]
|
||||||
|
transparency: Optional[Float]
|
||||||
|
index_of_refraction: Optional[Float]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Constant:
|
||||||
|
emission: Optional[Color]
|
||||||
|
reflective: Optional[Union[Color, Texture]]
|
||||||
|
reflectivity: Optional[Float]
|
||||||
|
transparent: Optional[Union[Color, Texture]]
|
||||||
|
transparency: Optional[Float]
|
||||||
|
index_of_refraction: Optional[Float]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TechniqueFX:
|
||||||
|
id: Optional[ID]
|
||||||
|
sid: str # required
|
||||||
|
shader: Union[Blinn, Lambert, Phong, Constant]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ProfileCommon:
|
||||||
|
newparam: List[Newparam]
|
||||||
|
technique: TechniqueFX
|
||||||
|
|
||||||
|
sid_lookup: dict = field(repr=False)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Effect:
|
||||||
|
id: str
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
profile_common: List[ProfileCommon]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LibraryEffects:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
effects: List[Effect]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InstanceEffect:
|
||||||
|
sid: Optional[str]
|
||||||
|
name: Optional[str]
|
||||||
|
url: URI
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Material:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
instance_effect: InstanceEffect
|
||||||
|
|
||||||
|
sid_lookup: dict = field(repr=False)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LibraryMaterials:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
materials: List[Material]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class FloatArray:
|
||||||
|
count: int
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
digits: Optional[str]
|
||||||
|
magnitude: Optional[str]
|
||||||
|
|
||||||
|
floats: List[float]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SourceCore:
|
||||||
|
id: ID
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
array_element: Union[FloatArray]
|
||||||
|
technique_common: TechniqueCommon_SourceCore
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InputShared:
|
||||||
|
offset: int
|
||||||
|
semantic: str
|
||||||
|
source: URI
|
||||||
|
set: Optional[int]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Triangles:
|
||||||
|
name: Optional[str]
|
||||||
|
count: int
|
||||||
|
material: Optional[str]
|
||||||
|
inputs: List[InputShared]
|
||||||
|
p: List[int]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InputUnshared:
|
||||||
|
semantic: str
|
||||||
|
source: URI
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Vertices:
|
||||||
|
id: ID
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
input: List[InputUnshared]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Mesh:
|
||||||
|
sources: List[SourceCore]
|
||||||
|
vertices: Vertices
|
||||||
|
primitive_elements: List[Union[Triangles]]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Geometry:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
geometric_element: Union[Mesh]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LibraryGeometries:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
geometries: List[Geometry]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TechniqueCommon_Light:
|
||||||
|
light: Union[Ambient, Directional, Point, Spot]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Light:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
technique_common: TechniqueCommon_Light
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LibraryLights:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
lights: List[Light]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Image:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
format: Optional[str]
|
||||||
|
height: Optional[int]
|
||||||
|
width: Optional[int]
|
||||||
|
depth: Optional[int]
|
||||||
|
|
||||||
|
image_source: Union[InitFrom]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LibraryImages:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
images: List[Image]
|
||||||
|
|
||||||
|
class NodeType(Enum):
|
||||||
|
JOINT = auto()
|
||||||
|
NODE = auto()
|
||||||
|
|
||||||
|
TransformationElements = Union[Lookat, Matrix, Rotate, Scale, Skew, Translate]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Node:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
sid: Optional[str]
|
||||||
|
type: NodeType
|
||||||
|
layer: List[str]
|
||||||
|
|
||||||
|
transformation_elements: List[TransformationElements]
|
||||||
|
instance_geometries: List[InstanceGeometry]
|
||||||
|
instance_lights: List[InstanceLight]
|
||||||
|
nodes: List['Node']
|
||||||
|
|
||||||
|
sid_lookup: dict = field(repr=False)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class VisualScene:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
nodes: List[Node]
|
||||||
|
|
||||||
|
sid_lookup: dict = field(repr=False)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LibraryVisualScenes:
|
||||||
|
id: Optional[ID]
|
||||||
|
name: Optional[str]
|
||||||
|
|
||||||
|
visual_scenes: List[VisualScene]
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Collada:
|
||||||
|
library_effects: List[LibraryEffects]
|
||||||
|
library_materials: List[LibraryMaterials]
|
||||||
|
library_geometries: List[LibraryGeometries]
|
||||||
|
library_lights: List[LibraryLights]
|
||||||
|
library_images: List[LibraryImages]
|
||||||
|
library_visual_scenes: List[LibraryVisualScenes]
|
||||||
|
scenes: List[Scene]
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.library_effects = []
|
||||||
|
self.library_materials = []
|
||||||
|
self.library_geometries = []
|
||||||
|
self.library_lights = []
|
||||||
|
self.library_images = []
|
||||||
|
self.library_visual_scenes = []
|
||||||
|
self.scenes = []
|
||||||
770
collada/parse.py
Normal file
770
collada/parse.py
Normal file
@ -0,0 +1,770 @@
|
|||||||
|
from lxml import etree
|
||||||
|
import collada_types as types
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
with open("cube_material.DAE") as f:
|
||||||
|
tree = etree.parse(f)
|
||||||
|
|
||||||
|
xml_namespace = "http://www.collada.org/2005/11/COLLADASchema"
|
||||||
|
|
||||||
|
def tag(s):
|
||||||
|
return f"{{{xml_namespace}}}{s}"
|
||||||
|
|
||||||
|
def lookup_add(lookup, name, value):
|
||||||
|
if name is None:
|
||||||
|
return
|
||||||
|
assert name not in lookup
|
||||||
|
lookup[name] = value
|
||||||
|
|
||||||
|
def parse_init_from(lookup, root):
|
||||||
|
return types.InitFrom(root.text.strip())
|
||||||
|
|
||||||
|
def parse_surface_type(s):
|
||||||
|
if s == "UNTYPED":
|
||||||
|
return types.FxSurfaceType.UNTYPED
|
||||||
|
if s == "1D":
|
||||||
|
return types.FxSurfaceType._1D
|
||||||
|
if s == "2D":
|
||||||
|
return types.FxSurfaceType._2D
|
||||||
|
if s == "3D":
|
||||||
|
return types.FxSurfaceType._3D
|
||||||
|
if s == "CUBE":
|
||||||
|
return types.FxSurfaceType.CUBE
|
||||||
|
if s == "DEPTH":
|
||||||
|
return types.FxSurfaceType.DEPTH
|
||||||
|
if s == "RECT":
|
||||||
|
return types.FxSurfaceType.RECT
|
||||||
|
assert False, s
|
||||||
|
|
||||||
|
def parse_surface(lookup, root):
|
||||||
|
type = parse_surface_type(root.attrib["type"])
|
||||||
|
|
||||||
|
init_from = None
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("init_from"):
|
||||||
|
assert init_from is None
|
||||||
|
init_from = parse_init_from(lookup, child)
|
||||||
|
|
||||||
|
surface = types.Surface(type, init_from)
|
||||||
|
return surface
|
||||||
|
|
||||||
|
def parse_source_fx(lookup, root):
|
||||||
|
return types.SourceFX(root.text.strip())
|
||||||
|
|
||||||
|
def parse_sampler2d(lookup, root):
|
||||||
|
source_fx = None
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("source"):
|
||||||
|
assert source_fx is None
|
||||||
|
source_fx = parse_source_fx(lookup, child)
|
||||||
|
|
||||||
|
assert source_fx is not None
|
||||||
|
sampler2d = types.Sampler2D(source_fx)
|
||||||
|
return sampler2d
|
||||||
|
|
||||||
|
def parse_newparam(lookup, sid_lookup, root):
|
||||||
|
sid = root.attrib["sid"]
|
||||||
|
|
||||||
|
parameter_type = None
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("surface"):
|
||||||
|
assert parameter_type is None
|
||||||
|
parameter_type = parse_surface(lookup, child)
|
||||||
|
if child.tag == tag("sampler2D"):
|
||||||
|
assert parameter_type is None
|
||||||
|
parameter_type = parse_sampler2d(lookup, child)
|
||||||
|
|
||||||
|
assert parameter_type is not None
|
||||||
|
newparam = types.Newparam(sid, parameter_type)
|
||||||
|
lookup_add(sid_lookup, sid, newparam)
|
||||||
|
return newparam
|
||||||
|
|
||||||
|
def parse_fields(lookup, root, *, cls, fields):
|
||||||
|
field_kv = {}
|
||||||
|
for child in root.getchildren():
|
||||||
|
for tag_name, parser in fields:
|
||||||
|
if child.tag == tag(tag_name):
|
||||||
|
assert tag_name not in field_kv
|
||||||
|
grandchildren = child.getchildren()
|
||||||
|
assert len(grandchildren) == 1
|
||||||
|
field_kv[tag_name] = parser(lookup, grandchildren[0])
|
||||||
|
for tag_name, _ in fields:
|
||||||
|
if tag_name not in field_kv:
|
||||||
|
field_kv[tag_name] = None
|
||||||
|
return cls(**field_kv)
|
||||||
|
|
||||||
|
def parse_color_or_texture(lookup, root):
|
||||||
|
if root.tag == tag("color"):
|
||||||
|
return types.Color(tuple(map(float, root.text.strip().split())))
|
||||||
|
if root.tag == tag("texture"):
|
||||||
|
return types.Texture(root.attrib["texture"], root.attrib["texcoord"])
|
||||||
|
assert False, (root, root.tag)
|
||||||
|
|
||||||
|
def parse_float(lookup, root):
|
||||||
|
assert root.tag == tag("float")
|
||||||
|
return types.Float(float(root.text.strip()))
|
||||||
|
|
||||||
|
blinn_phong_fields = [
|
||||||
|
("emission", parse_color_or_texture),
|
||||||
|
("ambient", parse_color_or_texture),
|
||||||
|
("diffuse", parse_color_or_texture),
|
||||||
|
("specular", parse_color_or_texture),
|
||||||
|
("shininess", parse_float),
|
||||||
|
("reflective", parse_color_or_texture),
|
||||||
|
("reflectivity", parse_float),
|
||||||
|
("transparent", parse_color_or_texture),
|
||||||
|
("transparency", parse_float),
|
||||||
|
("index_of_refraction", parse_float),
|
||||||
|
]
|
||||||
|
|
||||||
|
lambert_fields = [
|
||||||
|
("emission", parse_color_or_texture),
|
||||||
|
("ambient", parse_color_or_texture),
|
||||||
|
("diffuse", parse_color_or_texture),
|
||||||
|
("reflective", parse_color_or_texture),
|
||||||
|
("reflectivity", parse_float),
|
||||||
|
("transparent", parse_color_or_texture),
|
||||||
|
("transparency", parse_float),
|
||||||
|
("index_of_refraction", parse_float),
|
||||||
|
]
|
||||||
|
|
||||||
|
constant_fields = [
|
||||||
|
("emission", parse_color_or_texture),
|
||||||
|
("reflective", parse_color_or_texture),
|
||||||
|
("reflectivity", parse_float),
|
||||||
|
("transparent", parse_color_or_texture),
|
||||||
|
("transparency", parse_float),
|
||||||
|
("index_of_refraction", parse_float),
|
||||||
|
]
|
||||||
|
|
||||||
|
parse_blinn = partial(parse_fields, cls=types.Blinn, fields=blinn_phong_fields)
|
||||||
|
parse_phong = partial(parse_fields, cls=types.Phong, fields=blinn_phong_fields)
|
||||||
|
parse_lambert = partial(parse_fields, cls=types.Lambert, fields=lambert_fields)
|
||||||
|
parse_constant = partial(parse_fields, cls=types.Constant, fields=constant_fields)
|
||||||
|
|
||||||
|
def parse_technique_fx(lookup, sid_lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
sid = root.attrib["sid"]
|
||||||
|
|
||||||
|
shader = None
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("blinn"):
|
||||||
|
assert shader is None
|
||||||
|
shader = parse_blinn(lookup, child)
|
||||||
|
if child.tag == tag("constant"):
|
||||||
|
assert shader is None
|
||||||
|
shader = parse_constant(lookup, child)
|
||||||
|
if child.tag == tag("lambert"):
|
||||||
|
assert shader is None
|
||||||
|
shader = parse_lambert(lookup, child)
|
||||||
|
if child.tag == tag("phong"):
|
||||||
|
assert shader is None
|
||||||
|
shader = parse_phong(lookup, child)
|
||||||
|
assert shader is not None
|
||||||
|
|
||||||
|
technique = types.TechniqueFX(id, sid, shader)
|
||||||
|
lookup_add(lookup, id, technique)
|
||||||
|
lookup_add(sid_lookup, sid, technique)
|
||||||
|
return technique
|
||||||
|
|
||||||
|
def parse_profile_common(lookup, root):
|
||||||
|
newparam = []
|
||||||
|
technique_fx = None
|
||||||
|
sid_lookup = {}
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("newparam"):
|
||||||
|
newparam.append(parse_newparam(lookup, sid_lookup, child))
|
||||||
|
if child.tag == tag("technique"):
|
||||||
|
assert technique_fx is None
|
||||||
|
technique_fx = parse_technique_fx(lookup, sid_lookup, child)
|
||||||
|
|
||||||
|
assert technique_fx is not None
|
||||||
|
return types.ProfileCommon(newparam, technique_fx, sid_lookup)
|
||||||
|
|
||||||
|
def parse_effect(lookup, root):
|
||||||
|
id = root.attrib["id"]
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
|
||||||
|
profile_common = []
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("profile_COMMON"):
|
||||||
|
profile_common.append(parse_profile_common(lookup, child))
|
||||||
|
|
||||||
|
effect = types.Effect(id, name, profile_common)
|
||||||
|
lookup_add(lookup, id, effect)
|
||||||
|
return effect
|
||||||
|
|
||||||
|
def parse_library_effects(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
effects = []
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("effect"):
|
||||||
|
effects.append(parse_effect(lookup, child))
|
||||||
|
|
||||||
|
library_effects = types.LibraryEffects(id, name, effects)
|
||||||
|
lookup_add(lookup, id, library_effects)
|
||||||
|
return library_effects
|
||||||
|
|
||||||
|
def parse_instance_effect(lookup, sid_lookup, root):
|
||||||
|
sid = root.attrib.get("sid")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
url = root.attrib["url"]
|
||||||
|
|
||||||
|
instance_effect = types.InstanceEffect(sid, name, url)
|
||||||
|
lookup_add(sid_lookup, sid, instance_effect)
|
||||||
|
return instance_effect
|
||||||
|
|
||||||
|
def parse_material(lookup, root):
|
||||||
|
sid_lookup = {}
|
||||||
|
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
instance_effect = None
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("instance_effect"):
|
||||||
|
assert instance_effect is None
|
||||||
|
instance_effect = parse_instance_effect(lookup, sid_lookup, child)
|
||||||
|
assert instance_effect is not None
|
||||||
|
|
||||||
|
material = types.Material(id, name, instance_effect, sid_lookup)
|
||||||
|
lookup_add(lookup, id, material)
|
||||||
|
return material
|
||||||
|
|
||||||
|
def parse_library_materials(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
materials = []
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("material"):
|
||||||
|
materials.append(parse_material(lookup, child))
|
||||||
|
|
||||||
|
library_materials = types.LibraryMaterials(id, name, materials)
|
||||||
|
lookup_add(lookup, id, library_materials)
|
||||||
|
return library_materials
|
||||||
|
|
||||||
|
def parse_input_unshared(lookup, root):
|
||||||
|
semantic = root.attrib["semantic"]
|
||||||
|
source = root.attrib["source"]
|
||||||
|
return types.InputUnshared(semantic, source)
|
||||||
|
|
||||||
|
def parse_vertices(lookup, root):
|
||||||
|
id = root.attrib["id"]
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
input = []
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("input"):
|
||||||
|
input.append(parse_input_unshared(lookup, child))
|
||||||
|
|
||||||
|
assert len(input) >= 1
|
||||||
|
vertices = types.Vertices(id, name, input)
|
||||||
|
lookup_add(lookup, id, vertices)
|
||||||
|
return vertices
|
||||||
|
|
||||||
|
def parse_float_array(lookup, root):
|
||||||
|
count = int(root.attrib["count"])
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
digits = int(root.attrib.get("digits", 6))
|
||||||
|
magnitude = int(root.attrib.get("digits", 38))
|
||||||
|
|
||||||
|
assert len(root.getchildren()) == 0
|
||||||
|
floats = [float(s) for s in root.text.strip().split()]
|
||||||
|
|
||||||
|
float_array = types.FloatArray(count, id, name, digits, magnitude, floats)
|
||||||
|
lookup_add(lookup, id, float_array)
|
||||||
|
return float_array
|
||||||
|
|
||||||
|
def parse_param(lookup, sid_lookup, root):
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
sid = root.attrib.get("sid")
|
||||||
|
type = root.attrib["type"]
|
||||||
|
semantic = root.attrib.get("semantic")
|
||||||
|
|
||||||
|
param = types.Param(name, sid, type, semantic)
|
||||||
|
lookup_add(sid_lookup, sid, param)
|
||||||
|
return param
|
||||||
|
|
||||||
|
def parse_accessor(lookup, root):
|
||||||
|
count = int(root.attrib["count"])
|
||||||
|
offset = int(root.attrib.get("offset", 0))
|
||||||
|
source = root.attrib["source"]
|
||||||
|
stride = int(root.attrib.get("stride", 1))
|
||||||
|
|
||||||
|
sid_lookup = {}
|
||||||
|
|
||||||
|
params = []
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("param"):
|
||||||
|
params.append(parse_param(lookup, sid_lookup, child))
|
||||||
|
|
||||||
|
return types.Accessor(count, offset, source, stride, params, sid_lookup)
|
||||||
|
|
||||||
|
def parse_technique_common_source_core(lookup, root):
|
||||||
|
accessor = None
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("accessor"):
|
||||||
|
assert accessor is None
|
||||||
|
accessor = parse_accessor(lookup, child)
|
||||||
|
|
||||||
|
assert accessor is not None
|
||||||
|
return types.TechniqueCommon_SourceCore(accessor)
|
||||||
|
|
||||||
|
def parse_source_core(lookup, root):
|
||||||
|
id = root.attrib["id"]
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
array_element = None # 0 or 1
|
||||||
|
technique_common = None # 0 or 1
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("float_array"):
|
||||||
|
assert array_element is None
|
||||||
|
array_element = parse_float_array(lookup, child)
|
||||||
|
if child.tag == tag("technique_common"):
|
||||||
|
assert technique_common is None
|
||||||
|
technique_common = parse_technique_common_source_core(lookup, child)
|
||||||
|
|
||||||
|
source_core = types.SourceCore(id, name, array_element, technique_common)
|
||||||
|
lookup_add(lookup, id, source_core)
|
||||||
|
return source_core
|
||||||
|
|
||||||
|
def parse_input_shared(lookup, root):
|
||||||
|
offset = int(root.attrib["offset"])
|
||||||
|
semantic = root.attrib["semantic"]
|
||||||
|
source = root.attrib["source"]
|
||||||
|
set = int(root.attrib["set"]) if "set" in root.attrib else None
|
||||||
|
return types.InputShared(offset, semantic, source, set)
|
||||||
|
|
||||||
|
def parse_p(lookup, root):
|
||||||
|
assert len(root.getchildren()) == 0
|
||||||
|
return [int(i) for i in root.text.strip().split()]
|
||||||
|
|
||||||
|
def parse_triangles(lookup, root):
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
count = int(root.attrib["count"])
|
||||||
|
material = root.attrib.get("material")
|
||||||
|
|
||||||
|
inputs = []
|
||||||
|
p = None
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("input"):
|
||||||
|
inputs.append(parse_input_shared(lookup, child))
|
||||||
|
if child.tag == tag("p"):
|
||||||
|
assert p is None
|
||||||
|
p = parse_p(lookup, child)
|
||||||
|
|
||||||
|
return types.Triangles(name, count, material, inputs, p)
|
||||||
|
|
||||||
|
def parse_mesh(lookup, root):
|
||||||
|
sources = []
|
||||||
|
vertices = None
|
||||||
|
primitive_elements = []
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("source"):
|
||||||
|
sources.append(parse_source_core(lookup, child))
|
||||||
|
if child.tag == tag("vertices"):
|
||||||
|
assert vertices is None
|
||||||
|
vertices = parse_vertices(lookup, child)
|
||||||
|
if child.tag == tag("triangles"):
|
||||||
|
primitive_elements.append(parse_triangles(lookup, child))
|
||||||
|
assert vertices is not None
|
||||||
|
assert len(sources) >= 1
|
||||||
|
|
||||||
|
mesh = types.Mesh(sources, vertices, primitive_elements)
|
||||||
|
return mesh
|
||||||
|
|
||||||
|
def parse_geometry(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
|
||||||
|
geometric_element = None
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("mesh"):
|
||||||
|
assert geometric_element is None
|
||||||
|
geometric_element = parse_mesh(lookup, child)
|
||||||
|
assert geometric_element is not None
|
||||||
|
|
||||||
|
geometry = types.Geometry(id, name, geometric_element)
|
||||||
|
lookup_add(lookup, id, geometry)
|
||||||
|
return geometry
|
||||||
|
|
||||||
|
def parse_library_geometries(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
geometries = []
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("geometry"):
|
||||||
|
geometries.append(parse_geometry(lookup, child))
|
||||||
|
|
||||||
|
assert len(geometries) >= 1
|
||||||
|
library_geometries = types.LibraryGeometries(id, name, geometries)
|
||||||
|
lookup_add(lookup, id, library_geometries)
|
||||||
|
return library_geometries
|
||||||
|
|
||||||
|
def parse_light_color(lookup, root, *, cls):
|
||||||
|
color = None
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("color"):
|
||||||
|
assert color is None
|
||||||
|
color = tuple([float(i) for i in child.text.strip().split()])
|
||||||
|
assert color is not None
|
||||||
|
return cls(color)
|
||||||
|
|
||||||
|
parse_ambient = partial(parse_light_color, cls=types.Ambient)
|
||||||
|
parse_directional = partial(parse_light_color, cls=types.Directional)
|
||||||
|
parse_point = partial(parse_light_color, cls=types.Point)
|
||||||
|
parse_spot = partial(parse_light_color, cls=types.Spot)
|
||||||
|
|
||||||
|
def parse_technique_common_light(lookup, root):
|
||||||
|
light = None
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("ambient"):
|
||||||
|
assert light is None
|
||||||
|
light = parse_ambient(lookup, child)
|
||||||
|
if child.tag == tag("directional"):
|
||||||
|
assert light is None
|
||||||
|
light = parse_directional(lookup, child)
|
||||||
|
if child.tag == tag("point"):
|
||||||
|
assert light is None
|
||||||
|
light = parse_point(lookup, child)
|
||||||
|
if child.tag == tag("spot"):
|
||||||
|
assert light is None
|
||||||
|
light = parse_spot(lookup, child)
|
||||||
|
|
||||||
|
assert light is not None
|
||||||
|
|
||||||
|
return types.TechniqueCommon_Light(light)
|
||||||
|
|
||||||
|
def parse_light(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
|
||||||
|
technique_common = None
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("technique_common"):
|
||||||
|
assert technique_common is None
|
||||||
|
technique_common = parse_technique_common_light(lookup, child)
|
||||||
|
|
||||||
|
assert technique_common is not None
|
||||||
|
|
||||||
|
light = types.Light(id, name, technique_common)
|
||||||
|
lookup_add(lookup, id, light)
|
||||||
|
return light
|
||||||
|
|
||||||
|
def parse_library_lights(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
lights = []
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("light"):
|
||||||
|
lights.append(parse_light(lookup, child))
|
||||||
|
|
||||||
|
assert len(lights) >= 1
|
||||||
|
library_lights = types.LibraryLights(id, name, lights)
|
||||||
|
lookup_add(lookup, id, library_lights)
|
||||||
|
return library_lights
|
||||||
|
|
||||||
|
def parse_init_from(lookup, root):
|
||||||
|
assert len(root.getchildren()) == 0
|
||||||
|
return types.InitFrom(root.text.strip())
|
||||||
|
|
||||||
|
def parse_image(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
format = root.attrib.get("format")
|
||||||
|
height = root.attrib.get("height")
|
||||||
|
width = root.attrib.get("width")
|
||||||
|
depth = root.attrib.get("depth")
|
||||||
|
|
||||||
|
image_source = None
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("init_from"):
|
||||||
|
assert image_source is None
|
||||||
|
image_source = parse_init_from(lookup, child)
|
||||||
|
|
||||||
|
assert image_source is not None
|
||||||
|
image = types.Image(id, name, format, height, width, depth, image_source)
|
||||||
|
lookup_add(lookup, id, image)
|
||||||
|
return image
|
||||||
|
|
||||||
|
def parse_library_images(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
|
||||||
|
images = []
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("image"):
|
||||||
|
images.append(parse_image(lookup, child))
|
||||||
|
|
||||||
|
assert len(images) >= 1
|
||||||
|
|
||||||
|
library_images = types.LibraryImages(id, name, images)
|
||||||
|
lookup_add(lookup, id, library_images)
|
||||||
|
return library_images
|
||||||
|
|
||||||
|
def parse_node_type(s):
|
||||||
|
if s == "JOINT":
|
||||||
|
return types.NodeType.JOINT
|
||||||
|
if s == "NODE":
|
||||||
|
return types.NodeType.NODE
|
||||||
|
assert False, s
|
||||||
|
|
||||||
|
def parse_lookat(lookup, sid_lookup, root):
|
||||||
|
sid = root.attrib.get("sid")
|
||||||
|
|
||||||
|
assert len(root.getchildren()) == 0
|
||||||
|
values = [float(i) for i in root.text.strip().split()]
|
||||||
|
assert len(values) == 9
|
||||||
|
|
||||||
|
eye = tuple(values[0:3])
|
||||||
|
at = tuple(values[3:6])
|
||||||
|
up = tuple(values[6:9])
|
||||||
|
|
||||||
|
lookat = types.Lookat(sid, eye, at, up)
|
||||||
|
lookup_add(sid_lookup, sid, lookat)
|
||||||
|
return lookat
|
||||||
|
|
||||||
|
def parse_matrix(lookup, sid_lookup, root):
|
||||||
|
sid = root.attrib.get("sid")
|
||||||
|
|
||||||
|
assert len(root.getchildren()) == 0
|
||||||
|
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]))
|
||||||
|
lookup_add(sid_lookup, sid, matrix)
|
||||||
|
return matrix
|
||||||
|
|
||||||
|
def parse_simple_transform(lookup, sid_lookup, root, *, cls, count):
|
||||||
|
sid = root.attrib.get("sid")
|
||||||
|
|
||||||
|
assert len(root.getchildren()) == 0
|
||||||
|
values = [float(i) for i in root.text.strip().split()]
|
||||||
|
assert len(values) == count
|
||||||
|
|
||||||
|
inst = cls(sid, values)
|
||||||
|
lookup_add(sid_lookup, sid, inst)
|
||||||
|
return inst
|
||||||
|
|
||||||
|
parse_rotate = partial(parse_simple_transform, cls=types.Rotate, count=4)
|
||||||
|
parse_scale = partial(parse_simple_transform, cls=types.Scale, count=3)
|
||||||
|
parse_skew = partial(parse_simple_transform, cls=types.Skew, count=7)
|
||||||
|
parse_translate = partial(parse_simple_transform, cls=types.Translate, count=3)
|
||||||
|
|
||||||
|
def parse_bind_vertex_input(lookup, root):
|
||||||
|
semantic = root.attrib["semantic"]
|
||||||
|
input_semantic = root.attrib["input_semantic"]
|
||||||
|
input_set = root.attrib.get("input_set")
|
||||||
|
|
||||||
|
return types.BindVertexInput(semantic, input_semantic, input_set)
|
||||||
|
|
||||||
|
def parse_instance_material(lookup, sid_lookup, root):
|
||||||
|
sid = root.attrib.get("sid")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
target = root.attrib["target"]
|
||||||
|
symbol = root.attrib["symbol"]
|
||||||
|
|
||||||
|
bind_vertex_inputs = []
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("bind_vertex_input"):
|
||||||
|
bind_vertex_inputs.append(parse_bind_vertex_input(lookup, child))
|
||||||
|
|
||||||
|
inst = types.InstanceMaterial(sid, name, target, symbol, bind_vertex_inputs)
|
||||||
|
lookup_add(sid_lookup, sid, inst)
|
||||||
|
return inst
|
||||||
|
|
||||||
|
def parse_technique_common_bind_material(lookup, root):
|
||||||
|
materials = []
|
||||||
|
sid_lookup = {}
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("instance_material"):
|
||||||
|
materials.append(parse_instance_material(lookup, sid_lookup, child))
|
||||||
|
|
||||||
|
assert len(materials) >= 1
|
||||||
|
return types.TechniqueCommon_BindMaterial(materials, sid_lookup)
|
||||||
|
|
||||||
|
def parse_bind_material(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_bind_material(lookup, child)
|
||||||
|
|
||||||
|
assert technique_common is not None
|
||||||
|
return types.BindMaterial(technique_common)
|
||||||
|
|
||||||
|
def parse_instance_geometry(lookup, sid_lookup, root):
|
||||||
|
sid = root.attrib.get("sid")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
url = root.attrib["url"]
|
||||||
|
|
||||||
|
bind_material = None # optional
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("bind_material"):
|
||||||
|
assert bind_material is None
|
||||||
|
bind_material = parse_bind_material(lookup, child)
|
||||||
|
|
||||||
|
# bind_material may be none
|
||||||
|
instance_geometry = types.InstanceGeometry(sid, name, url, bind_material)
|
||||||
|
lookup_add(sid_lookup, sid, instance_geometry)
|
||||||
|
return instance_geometry
|
||||||
|
|
||||||
|
def parse_instance_light(lookup, sid_lookup, root):
|
||||||
|
sid = root.attrib.get("sid")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
url = root.attrib["url"]
|
||||||
|
|
||||||
|
instance_light = types.InstanceLight(sid, name, url)
|
||||||
|
lookup_add(sid_lookup, sid, instance_light)
|
||||||
|
return instance_light
|
||||||
|
|
||||||
|
def parse_node(lookup, sid_lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
sid = root.attrib.get("sid")
|
||||||
|
type = root.attrib["type"] if "type" in root.attrib else types.NodeType.NODE
|
||||||
|
layer = root.attrib.get("layer", "").strip().split()
|
||||||
|
|
||||||
|
transformation_elements = []
|
||||||
|
instance_geometries = []
|
||||||
|
instance_lights = []
|
||||||
|
nodes = []
|
||||||
|
|
||||||
|
child_sid_lookup = {}
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("lookat"):
|
||||||
|
transformation_elements.append(parse_lookat(lookup, child_sid_lookup, child))
|
||||||
|
if child.tag == tag("matrix"):
|
||||||
|
transformation_elements.append(parse_matrix(lookup, child_sid_lookup, child))
|
||||||
|
if child.tag == tag("rotate"):
|
||||||
|
transformation_elements.append(parse_rotate(lookup, child_sid_lookup, child))
|
||||||
|
if child.tag == tag("scale"):
|
||||||
|
transformation_elements.append(parse_scale(lookup, child_sid_lookup, child))
|
||||||
|
if child.tag == tag("skew"):
|
||||||
|
transformation_elements.append(parse_skew(lookup, child_sid_lookup, child))
|
||||||
|
if child.tag == tag("translate"):
|
||||||
|
transformation_elements.append(parse_translate(lookup, child_sid_lookup, child))
|
||||||
|
if child.tag == tag("instance_geometry"):
|
||||||
|
instance_geometries.append(parse_instance_geometry(lookup, child_sid_lookup, child))
|
||||||
|
if child.tag == tag("instance_light"):
|
||||||
|
instance_lights.append(parse_instance_light(lookup, child_sid_lookup, child))
|
||||||
|
if child.tag == tag("node"):
|
||||||
|
nodes.append(parse_node(lookup, child_sid_lookup, child))
|
||||||
|
|
||||||
|
node = types.Node(id, name, sid, type, layer,
|
||||||
|
transformation_elements,
|
||||||
|
instance_geometries,
|
||||||
|
instance_lights,
|
||||||
|
nodes,
|
||||||
|
child_sid_lookup)
|
||||||
|
|
||||||
|
lookup_add(lookup, id, node)
|
||||||
|
lookup_add(sid_lookup, sid, node)
|
||||||
|
return node
|
||||||
|
|
||||||
|
def parse_visual_scene(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
|
||||||
|
sid_lookup = {}
|
||||||
|
|
||||||
|
nodes = []
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("node"):
|
||||||
|
nodes.append(parse_node(lookup, sid_lookup, child))
|
||||||
|
|
||||||
|
assert len(nodes) >= 1
|
||||||
|
|
||||||
|
visual_scenes = types.VisualScene(id, name, nodes, sid_lookup)
|
||||||
|
lookup_add(lookup, id, visual_scenes)
|
||||||
|
return visual_scenes
|
||||||
|
|
||||||
|
def parse_library_visual_scenes(lookup, root):
|
||||||
|
id = root.attrib.get("id")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
|
||||||
|
visual_scenes = []
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("visual_scene"):
|
||||||
|
visual_scenes.append(parse_visual_scene(lookup, child))
|
||||||
|
|
||||||
|
assert len(visual_scenes) >= 1
|
||||||
|
|
||||||
|
library_visual_scenes = types.LibraryVisualScenes(id, name, visual_scenes)
|
||||||
|
lookup_add(lookup, id, library_visual_scenes)
|
||||||
|
return library_visual_scenes
|
||||||
|
|
||||||
|
def parse_instance_visual_scene(lookup, sid_lookup, root):
|
||||||
|
sid = root.attrib.get("sid")
|
||||||
|
name = root.attrib.get("name")
|
||||||
|
url = root.attrib["url"]
|
||||||
|
|
||||||
|
instance_visual_scene = types.InstanceVisualScene(sid, name, url)
|
||||||
|
lookup_add(sid_lookup, sid, instance_visual_scene)
|
||||||
|
return instance_visual_scene
|
||||||
|
|
||||||
|
def parse_scene(lookup, root):
|
||||||
|
instance_visual_scene = None
|
||||||
|
sid_lookup = {}
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("instance_visual_scene"):
|
||||||
|
instance_visual_scene = parse_instance_visual_scene(lookup, sid_lookup, child)
|
||||||
|
|
||||||
|
# instance_visual_scene may be none
|
||||||
|
return types.Scene(instance_visual_scene, sid_lookup)
|
||||||
|
|
||||||
|
def parse_collada(tree):
|
||||||
|
root = tree.getroot()
|
||||||
|
assert root.tag == tag("COLLADA")
|
||||||
|
|
||||||
|
collada = types.Collada()
|
||||||
|
lookup = {}
|
||||||
|
|
||||||
|
for child in root.getchildren():
|
||||||
|
if child.tag == tag("library_effects"):
|
||||||
|
collada.library_effects.append(parse_library_effects(lookup, child))
|
||||||
|
if child.tag == tag("library_materials"):
|
||||||
|
collada.library_materials.append(parse_library_materials(lookup, child))
|
||||||
|
if child.tag == tag("library_geometries"):
|
||||||
|
collada.library_geometries.append(parse_library_geometries(lookup, child))
|
||||||
|
if child.tag == tag("library_lights"):
|
||||||
|
collada.library_lights.append(parse_library_lights(lookup, child))
|
||||||
|
if child.tag == tag("library_images"):
|
||||||
|
collada.library_images.append(parse_library_images(lookup, child))
|
||||||
|
if child.tag == tag("library_visual_scenes"):
|
||||||
|
collada.library_visual_scenes.append(parse_library_visual_scenes(lookup, child))
|
||||||
|
if child.tag == tag("scene"):
|
||||||
|
collada.scenes.append(parse_scene(lookup, child))
|
||||||
|
|
||||||
|
return collada
|
||||||
|
|
||||||
|
collada = parse_collada(tree)
|
||||||
|
from prettyprinter import pprint, install_extras
|
||||||
|
install_extras(include=["dataclasses"])
|
||||||
|
pprint(collada, width=120)
|
||||||
Loading…
x
Reference in New Issue
Block a user