@ThreadSafe
public class DAELoader
extends java.lang.Object
Facility to construct a Linkage
sub-tree from a COLLADA
scenegraph.
See also DAEExporter
.
MSim reads and writes only the (valid) COLLADA 1.5.0 subset enumerated below. Other elements and attributes are ignored, and are not guaranteed to be preserved across a DAELoad/DAEExport.
There are multiple possibilities for associating an MSim linkage with different types of COLLADA structures, including:
Currently only the first (visual scene graph) is supported. None of the possible COLLADA structures natively offers sufficient representation for all MSim state, and hence any choice will require some use of COLLADA "extra" elements. COLLADA kinematics seems to come the closest, however,
The MSim linkage model corresponds to (a sub-tree of) a COLLADA visual
scene graph. The COLLADA root element for the correspondence is either a
"node" or a "visual_scene", either in a library or instanced. Instances are
automatically dereferenced; "visual_scene" is treated as a "node" with no
user widgets. The correspondence parrallels that implemented in J3DLoader
: the MSim linkage spanning tree has the same topology as the
COLLADA subtree.
Each "instance_geometry" of a COLLADA node induces a user widget on the
corresponding MSim Link
(see
vona.dae.DAEUtils.daeGeometryInstanceToWidget()
).
Unless COLLADA "extra" elements are present containing "profile=MSim"
"technique", as described in detail below, all joints
are initially inferred as Joint.Type.GENERAL
with
identity child-to-mobility and mobility transforms, and mobility-to-parent
transform set to the corresponding COLLADA "node" child-to-parent
transform.
Behavior is undefined if the COLLADA visual scene graph contains a self-referential "instance_node". Any encountered non-rigid COLLADA transforms are treated as identity.
Upon loading a COLLADA model, this loader will look for COLLADA "extra" elements that are children of COLLADA "node"s. If such an element is present and has a "technique" child with "profile" attribute equal to "MSim", then the XML contents of the technique are used to
Full details are given below.
DAEExporter
writes these "extra" elements.
This loader expects all URI in the COLLADA document to be URL fragments of the form "#IDREF". This includes
The "source" attribute of an accessor element must resolve to an array within a(ny) "source" element (yes, there are both "source" attributes and elements).
The "source" of a "vertices/input" element must resolve to a(ny) "source" element. Outside of a "vertices" element, the "source" of an "input" element with "semantic=VERTEX" must resolve to a(ny) "vertices" element, and the "source" of an "input" element with "semantic!=VERTEX" must resolve to a(ny) "source" element.
Other than URI, there is one additional type of cross reference in the COLLADA subset handled by MSim: The "material" attributes within descendants of the "geometry" referenced by an "instance_geometry" must resolve to corresponding "symbol" attributes of "instance_material" within that same "instance_geometry".
This loader must associate names to many of the MSim entities that are induced by corresponding COLLADA elements. If the COLLADA element has an "extra" child with a profile=MSim "technique" then the name is taken from the name attribute, if any, of the "msim_link", "msim_closure", or "msim_user_subframe" COLLADA element.
In the absence of a COLLADA extra element with a profile=MSim technique, or if there was no name attribute on the appropriate descendant thereof, the name is based on the content of the following COLLADA attributes, if present, in priority order: "name", "id", "sid".
If none of the above are present, a unique name is automatically generated. Otherwise, the name is sanitized by converting any characters not allowed in an MSim name to underscores, and the name is made unique within any necessary context (by appending a deterministically generated suffix). Once an MSim name has been associated to a COLLADA element, that name will be used consistently.
Following is a summary of the subset of COLLADA 1.5.0 supported in MSim. This is a valid subset in the sense that instance documents consisting only of elements and attributes in this subset validate against the official schema.
Unsupported features include:
COLLADA: xmlns=http://www.collada.org/2008/03/COLLADASchema version=1.5.0 asset {library_geometries|library_nodes|library_visual_scenes |library_materials|library_effects}* scene [instance_visual_scene]: [sid] url-to-visual-scene library_FOOs: [id] FOO+ asset created xs:dateTime modified xs:dateTime extra: [id] [type] technique+ technique: profile [xmlns] any well formed XML visual_scene: [id] node+ extra* technique: profile="MSim" msim_link|msim_closure|msim_user_subframe|msim_skip node: [id] [sid] {matrix //MSim ignores matrices with skew or non-uniform scale float4x4 |scale //msim ignores non-uniform scale float3 |rotate float4 |translate}* float3 instance_geometry*: url-to-geometry [sid] [name] [bind_material] technique_common instance_material+: url-to-target-material symbol instance_node*: [sid] url-to-node node* extra* technique: profile="MSim" msim_link|msim_closure|msim_user_subframe|msim_skip geometry: [id] mesh source+: id float_array: [id] count [digits (def 6)] [magnitude (def 38)] list of float [technique_common] accessor: count [offset] url-to-source [stride] param*: name type=float vertices: id input+: semantic url-to-source //one input must have semantic=POSITION {lines|linestrips|triangles|trifans|tristrips}*: count [material-sym] input*: offset semantic=VERTEX|POSITION|NORMAL|COLOR source //if any input then one must have semantic=VERTEX p* //at most one for lines and triangles list of uint material: [id] instance_effect: url-to-effect effect: id profile_COMMON+: technique: sid=COMMON constant|lambert|phong|blinn [emission] [ambient] [diffuse] //only in lambert, phong, and blinn [specular] [shininess] //only in phong and blinn [transparency] emission, ambient, diffuse, specular color float4 shininess, transparency float msim_link: [name] explicit_flags [mass_props]: [mass] [com_widget_scale] [com_widget_enabled] [subtree_com_widget_enabled] link_com x y z [ground_link]: [sublinkage_name] [sublinkage_disposition] [parent_joint]: [name] joint_type [mobility_inverted] [positioning_transforms_locked] [soft_goal_priority] [soft_goal_weight] explicit_flags child_to_mobility, mobility_to_parent (tx ty tz ex ey ez)|subframe_name [dof_limits] ((lower upper)|(NaN NaN))* [dof_target], [dof_posture], [dof_lock] (double|NaN)* //corresponding to joint DoF [stiffness_props]: [stiffness] [stiffness_rest] [enabled] msim_closure: same attributes as parent_joint same child elements as parent_joint plus child_link absolute msim path to child link msim_user_subframe: name [subframe_type] [connectable_subframe_types] subframe_type* [connectable_joint_types] joint_type* msim_skip: to //sidref to replacement node explicit_flags = [explictly_visible] [explicitly_hidden] [explicitly_highlighted] [explicitly_masked] joint_type = revolute|prismatic|cylindrical|spherical|planar| cartesian2|cartesian3|pin_slider|point_slider|point_plane| general sublinkage_disposition = driving|driven|simultaneous
propertyMap
s on Linkage
,
LinkageNode
, and Widget
Copyright (C) 2010 Marsette A. Vona, III
Modifier and Type | Class and Description |
---|---|
protected static class |
DAELoader.LatentClosure
record containing all needed info to construct a closure joint
|
Modifier and Type | Field and Description |
---|---|
private static java.lang.String |
cvsid |
protected static vona.dae.util.DAEUtils |
daeUtils
for now use the singleton DAEUtils
|
static int |
MAX_UNIQUE_NAME_TRIES
maximum tries to make a unique name
|
static java.lang.String |
MSIM_EXTRA_PROP
DAEObject msim property key |
static java.lang.String |
MSIM_NAME_PROP
DAEObject msim property key |
static java.lang.String |
MSIM_PARENT_JOINT_NAME_PROP
DAEObject msim property key |
static java.lang.String |
MSIM_ROOT_PROP
DAEObject msim property key |
static java.lang.String |
MSIM_RX_PROP
DAEObject msim property key |
protected static int |
nextAnonymousNameIndex
used to generate unique names for DAE elements
|
protected static int |
nextUniqueJointNameIndex
used to generate unique names for DAE elements
|
protected static int |
nextUniqueLinkNameIndex
used to generate unique names for DAE elements
|
protected static int |
nextUniqueWidgetNameIndex
used to generate unique names for DAE elements
|
protected static javax.xml.bind.Unmarshaller |
unmarshaller
unmarshaller for DAE MSim extras
|
Constructor and Description |
---|
DAELoader() |
Modifier and Type | Method and Description |
---|---|
static DAEMSimExtra |
getExtra(vona.dae.util.DAEObject obj)
Unmarshal the first
DAEMSimExtra in an DAEMSimExtra.MSIM_PROFILE DAE "technique" child of an "extra" child of
obj, if any. |
static java.lang.String |
getName(vona.dae.util.DAEObject obj)
Resolve (or create) an MSim name for obj.
|
static vona.math.RX |
getRX(vona.dae.util.DAEObject obj)
Resolve (or create) an MSim RX for obj.
|
protected static void |
loadChildFromDAE(vona.dae.jaxb.dae.NodeType source,
Link parent,
boolean loadGeoms,
java.util.List<DAELoader.LatentClosure> latentClosures)
Load a COLLADA "node" child.
|
static Link |
loadFromDAE(vona.dae.jaxb.dae.COLLADA dae)
loadFromDAE(Link, COLLADA, String, boolean) , loading
geometries, consing a new linkage root, and inferring the DAE root. |
static Link |
loadFromDAE(vona.dae.jaxb.dae.COLLADA dae,
java.lang.String daeRoot)
loadFromDAE(Link, COLLADA, String, boolean) , loading
geometries and consing a new linkage root. |
static Link |
loadFromDAE(Link linkageRoot,
vona.dae.jaxb.dae.COLLADA dae,
java.lang.String daeRoot)
loadFromDAE(Link, COLLADA, String, boolean) , loading
geometries. |
static Link |
loadFromDAE(Link linkageRoot,
vona.dae.jaxb.dae.COLLADA dae,
java.lang.String daeRoot,
boolean loadGeometries)
Load a
Linkage sub-tree from a COLLADA visual scene
graph. |
protected static Link |
loadLinkFromDAE(Link link,
vona.dae.util.DAEObject source,
Link parentLink,
boolean loadGeoms,
java.util.List<DAELoader.LatentClosure> latentClosures)
Load an MSim
Link from a DAE element. |
private static final java.lang.String cvsid
public static final java.lang.String MSIM_EXTRA_PROP
DAEObject
msim property keypublic static final java.lang.String MSIM_NAME_PROP
DAEObject
msim property keypublic static final java.lang.String MSIM_PARENT_JOINT_NAME_PROP
DAEObject
msim property keypublic static final java.lang.String MSIM_RX_PROP
DAEObject
msim property keypublic static final java.lang.String MSIM_ROOT_PROP
DAEObject
msim property keypublic static final int MAX_UNIQUE_NAME_TRIES
protected static final vona.dae.util.DAEUtils daeUtils
protected static final javax.xml.bind.Unmarshaller unmarshaller
protected static int nextAnonymousNameIndex
protected static int nextUniqueLinkNameIndex
protected static int nextUniqueJointNameIndex
protected static int nextUniqueWidgetNameIndex
public static Link loadFromDAE(Link linkageRoot, vona.dae.jaxb.dae.COLLADA dae, java.lang.String daeRoot, boolean loadGeometries)
Load a Linkage
sub-tree from a COLLADA visual scene
graph.
The COLLADA scene graph could have been umarshalled via a call to
DAEUtils.unmarshalDAE(URL)
.
See MSim-COLLADA Model Correspondence in the class header doc for details of how the COLLADA structure is mapped to an MSim Linkage. The particular COLLADA structure that is loaded is identified by daeRoot, which if non-null must be one of the following:
linkageRoot is the MSim Link
that will correspond to
daeRoot. A warning will be issued and nothing will be loaded if
any of the following hold:
LinkageNode
is currently immutable)linkageRoot
- the attach point for the new sub-tree, or null to
create a new root Link
in the top-level Linkage
dae
- the root node of the COLLADA document, not nulldaeRoot
- see aboveloadGeometries
- whether to map COLLADA geometries to
Link
user Widget
s, if not they are ignoredpublic static Link loadFromDAE(Link linkageRoot, vona.dae.jaxb.dae.COLLADA dae, java.lang.String daeRoot)
loadFromDAE(Link, COLLADA, String, boolean)
, loading
geometries.
public static Link loadFromDAE(vona.dae.jaxb.dae.COLLADA dae, java.lang.String daeRoot)
loadFromDAE(Link, COLLADA, String, boolean)
, loading
geometries and consing a new linkage root.
public static Link loadFromDAE(vona.dae.jaxb.dae.COLLADA dae)
loadFromDAE(Link, COLLADA, String, boolean)
, loading
geometries, consing a new linkage root, and inferring the DAE root.
protected static Link loadLinkFromDAE(Link link, vona.dae.util.DAEObject source, Link parentLink, boolean loadGeoms, java.util.List<DAELoader.LatentClosure> latentClosures)
Load an MSim Link
from a DAE element.
link is consed (unless passed as non-null) and configured to match source. The parent joint of link is also consed if necessary according to the following rules:
DAEMSimLink
"extra" is present, and link is not
the root of the MSim-DAE correspondence tree (which is indicated by the
presence of MSIM_ROOT_PROP
set on source), then the parent
joint is a Joint.Type.GENERAL
tree joint with identity
child-to-mobility and mobility transforms, and mobility-to-parent set
equal to the rigid part of the pose of source with respect to its
parentDAEMSimLink
"extra" is present but does not contain a
DAEMSimJoint
as DAEMSimLink.parentJoint
, then link
is a root (no parent joint other than its root joint), with the exception
that the link at the root of the MSim-DAE correspondence tree, if not
internally consed, will keep its original parent jointDAEMSimLink
"extra" is present with a non-null DAEMSimLink.parentJoint
, then a parent tree joint is consed/configured
with the indicated settings.Once link and its parent have been set up, this method recurs on
the children of link. DAE "instance_geometry" children, which are
terminal, are loaded as MSim user link widgets iff loadGeoms is
set. DAE "node" and the referents of "instance_node" children are loaded
recursively unless they contain an "extra" with a DAEMSimUserSubframe
or DAEMSimClosure
. The latter two cases,
both also terminal, induce loading of a user subframe on link or a
latent closure parented to link (and added to
latentClosures).
link
- the link to load into, or null to conssource
- the DAE element which corresponds to link, either a
DAE "node" (NodeType
) or a DAE "visual_scene"
(VisualSceneType
). If an MSim DAE "extra" is included (see
getExtra(vona.dae.util.DAEObject)
) then it must be a DAEMSimLink
. source
is considered to be the root of the MSim-DAE correspondence tree iff the
property MSIM_ROOT_PROP
is set on it, which has implications for
how the parent joint of link may be configured as described aboveparentLink
- the parent link of the parent joint of link, or
null if unknown (this could happen in the unusual case of a link
with a dangling parent joint); if null then the ground link of the linkage
containing link is usedloadGeoms
- whether to load DAE "instance_geometry" (if source
is a "node") as MSim user link widgetslatentClosures
- any closure joints induced by the DAE structure are
collected here for attachment at the end of the loading processprotected static void loadChildFromDAE(vona.dae.jaxb.dae.NodeType source, Link parent, boolean loadGeoms, java.util.List<DAELoader.LatentClosure> latentClosures)
Load a COLLADA "node" child.
source
- the child node, which will be loaded as either an MSim
Link
(if no DAEMSimExtra
is present or if the extra is a
DAEMSimLink
), and MSim link user subframe (if a DAEMSimUserSubframe
is present), or a (latent) MSim closure Joint
(if a DAEMSimClosure
is present)parent
- the MSim link corresponding to the parent of this nodeloadGeoms
- whether to load DAE "instance_geometry" as MSim user link
widgetslatentClosures
- the collection of DAELoader.LatentClosure
spublic static DAEMSimExtra getExtra(vona.dae.util.DAEObject obj)
Unmarshal the first DAEMSimExtra
in an DAEMSimExtra.MSIM_PROFILE
DAE "technique" child of an "extra" child of
obj, if any.
Current impl only checks for extra under COLLADA "node" and "visual_scene" elements (return will be null otherwise).
The set of types of MSim extra elements is read from DAEMSimExtra.MSIM_EXTRAS
.
Once unmarshalled, the extra is stored as the MSIM_EXTRA_PROP
property on obj.
public static java.lang.String getName(vona.dae.util.DAEObject obj)
Resolve (or create) an MSim name for obj.
Once computed, the name is stored as the MSIM_NAME_PROP
property on obj.
This method does not ensure the name is unique. Names are made unique as necessary when they are assigned in-context.
public static vona.math.RX getRX(vona.dae.util.DAEObject obj)
Resolve (or create) an MSim RX for obj.
The RX is identity except in the case that obj is a COLLADA "node", in which case it is the rigid part of the node's relative transform from its parent.
Once computed, the RX is stored as the MSIM_RX_PROP
property on obj.