public void ExpandLibraryNode( LibraryNode lnode, string referrerId, Matrix4 localTransform, Matrix4 transform, ColladaMeshInfo meshInfo ) { // recurse through any child nodes int childNo = 0; foreach( LibraryNode child in lnode.children ) ExpandLibraryNode( child, referrerId + "." + (childNo++).ToString(), localTransform, transform, meshInfo ); // expand geometry_instance references int instNo = 0; foreach( string geoInstanceId in lnode.geoInstanceIds ) { GeometryInstance geoInstance = new GeometryInstance( referrerId + "." + (instNo++).ToString(), null, localTransform, transform ); if( meshInfo.Geometries.ContainsKey( geoInstanceId ) ) { // this was an instance_geometry instead of an instance_controller in 1.4 terms geoInstance.controller = null; geoInstance.geoSet = meshInfo.Geometries[ geoInstanceId ].Clone( geoInstance.name ); meshInfo.GeoInstances.Add( geoInstance ); } } }
public void ReadWeaklyTypedArray( DataSource source, XmlNode node, ColladaMeshInfo meshInfo ) { string type = "string"; if( node.Attributes[ "type" ] != null ) type = node.Attributes[ "type" ].Value; switch( type ) { case "float": ReadFloatArray( source, node, meshInfo ); break; case "string": case "Name": ReadStringArray( source, node, meshInfo ); break; default: log.WarnFormat( "Unhandled array type: {0}", type ); break; } }
/// <summary> /// Import into the mesh, using the skeleton provided, and /// assigning the animation data to a new animation. /// </summary> /// <param name="transform">the world transform to apply to this object</param> /// <param name="mesh">the mesh we will populate</param> /// <param name="skeleton">the skeleton to which we will add animations (or null if we are creating one)</param> /// <param name="animationName">the name that will be used for the animation</param> /// <param name="materialNamespace">namespace used for generation of material names</param> public void Import( Matrix4 transform, Mesh mesh, Skeleton skeleton, string animationName, string materialNamespace ) { ColladaMeshReader reader = null; XmlDocument document = new XmlDocument(); document.Load( m_Stream ); XmlElement rootElement = document.DocumentElement; // This is slightly weird. The client calls this method on this object, // but then we determine which version of collada we're actually looking // at, and create a new instances of a derived collada reader. As an // outcome, we have to copy fields from the factory-created instance // back to this instance. // TODO: Need a static factory method on the base class to create the // collada reader instance, then call that instance from the client; // that way we'll only have one instance in the first place. reader = GetColladaParser( rootElement ); reader.m_ColladaRootNode = rootElement; reader.m_Document = document; reader.m_MaterialBuilder = new MaterialScriptBuilder( materialNamespace ); ColladaMeshInfo meshInfo = new ColladaMeshInfo( mesh ); reader.ReadCollada( rootElement, meshInfo ); meshInfo.NoRiggingCulling = NoRiggingCulling; meshInfo.Process( transform, skeleton, m_BaseFile, animationName ); this.m_MaterialBuilder = reader.MaterialBuilder; }
public virtual void ReadMesh( string geometryName, XmlNode node, ColladaMeshInfo meshInfo ) { Dictionary<int, List<InputSourceCollection>> inputSources = new Dictionary<int, List<InputSourceCollection>>(); Dictionary<string, VertexSet> vertexSets = new Dictionary<string, VertexSet>(); foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "source": ReadSource( null, childNode, meshInfo ); break; case "vertices": // Read in inputs and vertex sets that should apply to all // the sub-portions of this geometry. ReadVertices( vertexSets, childNode, meshInfo ); break; case "lines": case "linestrips": case "triangles": case "trifans": case "tristrips": case "polygons": // Handle this in the second pass break; default: DebugMessage( childNode ); break; } } int submeshIndex = 0; foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "source": case "vertices": // these were handled in the first pass break; case "polygons": case "triangles": { string name = string.Format( "{0}.{1}", geometryName, submeshIndex++ ); if( !meshInfo.Geometries.ContainsKey( geometryName ) ) meshInfo.Geometries[ geometryName ] = new GeometrySet( geometryName ); GeometrySet geoSet = meshInfo.Geometries[ geometryName ]; MeshGeometry geometry = new MeshGeometry( name, geoSet ); foreach( VertexSet vertexSet in vertexSets.Values ) geometry.AddVertexSet( vertexSet ); foreach( int inputIndex in inputSources.Keys ) geometry.AddInputs( inputIndex, inputSources[ inputIndex ] ); geoSet.Add( geometry ); ReadPolygons( geometry, vertexSets, childNode, meshInfo ); break; } case "lines": case "linestrips": case "trifans": case "tristrips": default: DebugMessage( childNode ); break; } } }
public virtual void ReadMaterial( XmlNode node, ColladaMeshInfo meshInfo ) { string id = node.Attributes[ "id" ].Value; List<MaterialTechnique_13> materialTechniques = new List<MaterialTechnique_13>(); foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "shader": ReadShader( materialTechniques, childNode ); break; default: DebugMessage( childNode ); break; } } MaterialBuilder.AddTechniques( id, materialTechniques ); }
public void ReadJoints( SkinController controller, XmlNode node, ColladaMeshInfo meshInfo ) { Dictionary<int, List<InputSourceCollection>> inputSources = new Dictionary<int, List<InputSourceCollection>>(); foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "input": ReadInput( inputSources, null, childNode, meshInfo ); break; default: break; } } // process joints here InputSource jointInput = null; InputSource invBindMatrixInput = null; foreach( List<InputSourceCollection> inputs in inputSources.Values ) { foreach( InputSourceCollection tmp in inputs ) { Debug.Assert( tmp.GetSources().Count == 1 ); InputSource source = tmp.GetSources()[ 0 ]; switch( source.Semantic ) { case "JOINT": jointInput = source; break; case "INV_BIND_MATRIX": invBindMatrixInput = source; break; default: log.InfoFormat( "Unhandled joint input semantic: {0}", source.Semantic ); break; } } } Debug.Assert( jointInput != null && invBindMatrixInput != null ); string jointParam = ""; if( jointInput.Accessor.ContainsParam( "JOINT" ) ) jointParam = "JOINT"; string invBindParam = ""; if( invBindMatrixInput.Accessor.ContainsParam( "INV_BIND_MATRIX" ) ) invBindParam = "INV_BIND_MATRIX"; else if( invBindMatrixInput.Accessor.ContainsParam( "TRANSFORM" ) ) invBindParam = "TRANSFORM"; for( int ptIndex = 0; ptIndex < jointInput.Count; ++ptIndex ) { string jointName = (String) jointInput.Accessor.GetParam( jointParam, ptIndex ); Matrix4 invBindMatrix = (Matrix4) invBindMatrixInput.Accessor.GetParam( invBindParam, ptIndex ); if( controller.InverseBindMatrices.ContainsKey( jointName ) ) { string msg = string.Format( "Duplicate inverse bind matrix found in controller '{0}' for joint '{1}'; Aborting export.", controller.Name, jointName ); log.Error( msg ); throw new Exception( msg ); } // Debug.Assert(controller.InvBindTransforms[jointName] == invBindMatrix); controller.InverseBindMatrices[ jointName ] = invBindMatrix; } }
public void ReadInstanceGeometry( string nodeName, string parentBone, Matrix4 localTransform, Matrix4 transform, XmlNode node, ColladaMeshInfo meshInfo ) { string instance = UrlFragementName( node ); if( nodeName == null ) { nodeName = instance; } // It's possible that we failed to build geometries referenced by the // a geometry instance (e.g. if the geometry only contains 'line' // primitives), so only create the instance if the geometry is present. if( meshInfo.Geometries.ContainsKey( instance ) ) { GeometryInstance geoInstance = CreateGeometryInstance( nodeName, parentBone, ref localTransform, ref transform, node, meshInfo ); geoInstance.controller = null; geoInstance.geoSet = meshInfo.Geometries[ instance ]; meshInfo.GeoInstances.Add( geoInstance ); } }
public virtual void ReadInput( Dictionary<int, List<InputSourceCollection>> inputSources, Dictionary<string, VertexSet> vertexSets, XmlNode node, ColladaMeshInfo meshInfo ) { InputSourceCollection input = null; string source = node.Attributes[ "source" ].Value; // Get the part after the '#' source = source.Substring( 1 ); string semantic = node.Attributes[ "semantic" ].Value; int inputIndex = inputSources.Count; if( node.Attributes[ "idx" ] != null ) inputIndex = int.Parse( node.Attributes[ "idx" ].Value ); if( !inputSources.ContainsKey( inputIndex ) ) inputSources[ inputIndex ] = new List<InputSourceCollection>(); if( semantic == "VERTEX" ) { VertexSet vertexSet = vertexSets[ source ]; // Dereference the vertex input and add that instead. if( inputSources != null ) { VertexInputSource vertexInput = new VertexInputSource(); foreach( InputSourceCollection tmp in vertexSet.vertexEntries ) vertexInput.AddSource( tmp ); inputSources[ inputIndex ].Add( vertexInput ); } } else { if( !Accessors.ContainsKey( source ) ) { Debug.Assert( false, "Missing accessor for source: " + source ); return; } Accessor accessor = Accessors[ source ]; if( inputSources != null ) { input = new InputSource( source, semantic, accessor ); inputSources[ inputIndex ].Add( input ); } } }
public void ReadCombiner( string currentSource, XmlNode node, ColladaMeshInfo meshInfo ) { Dictionary<int, List<InputSourceCollection>> inputSources = new Dictionary<int, List<InputSourceCollection>>(); foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "input": ReadInput( inputSources, null, childNode, meshInfo ); break; case "v": // Ignore in this pass break; default: break; } } List<CombinerComponents> combComps = new List<CombinerComponents>(); int vertexIndex = 0; foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "input": // Ignore in this pass break; case "v": { CombinerComponents cc = ReadCombinerV( vertexIndex++, inputSources, childNode ); if( cc != null ) combComps.Add( cc ); } break; default: DebugMessage( childNode ); break; } } Combiners[ currentSource ] = combComps; }
/// <summary> /// Reads bone information from the file. /// </summary> public override void ReadCollada( XmlNode node, ColladaMeshInfo meshInfo ) { foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "library": ReadLibrary( childNode, meshInfo ); break; case "asset": ReadAsset( childNode, meshInfo ); break; case "scene": ReadScene( childNode, meshInfo ); break; default: DebugMessage( childNode ); break; } } }
public virtual void ReadChannel( string parentAnimationName, string animationName, XmlNode node, ColladaMeshInfo meshInfo ) { string samplerId = node.Attributes[ "source" ].Value; string targetId = node.Attributes[ "target" ].Value; // Strip off the leading '#' samplerId = samplerId.Substring( 1 ); Sampler sampler = meshInfo.Samplers[ samplerId ]; Channel channel = new Channel( sampler, targetId, "matrix" ); channel.AnimationName = animationName; channel.ParentAnimationName = parentAnimationName; meshInfo.Channels.Add( channel ); }
public virtual void ReadAsset( XmlNode node, ColladaMeshInfo meshInfo ) { foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "unit": ReadUnit( childNode, meshInfo ); break; case "up_axis": ReadUpAxis( childNode, meshInfo ); break; default: DebugMessage( childNode ); break; } } }
private bool IsInstanceGeometry( XmlNode node, ColladaMeshInfo meshInfo ) { string instanceName = UrlFragementName( node ); if( String.Empty != instanceName ) { return meshInfo.Geometries.ContainsKey( instanceName ); } return false; }
public void ReadAnimationLibrary( XmlNode node, ColladaMeshInfo meshInfo ) { foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "animation": ReadAnimation( null, childNode, meshInfo ); break; default: DebugMessage( childNode ); break; } } }
private static GeometryInstance CreateGeometryInstance( string nodeName, string parentBone, ref Matrix4 localTransform, ref Matrix4 transform, XmlNode node, ColladaMeshInfo meshInfo ) { GeometryInstance geoInstance = new GeometryInstance( nodeName, parentBone, localTransform, transform ); #if WORKS_AS_EXPECTED XmlNode bindNode = node.SelectSingleNode( "bind_material" ); if( null != bindNode ) { geoInstance.bindMaterial = new BindMaterial( bindNode, meshInfo.materialNamespace ); } #else foreach( XmlNode child in node.ChildNodes ) { if( "bind_material" == child.Name ) { geoInstance.bindMaterial = new BindMaterial( child, MaterialScriptBuilder.MaterialNamespace ); } } #endif return geoInstance; }
public virtual void ReadImageLibrary( XmlNode node, ColladaMeshInfo meshInfo ) { foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "image": ReadImage( childNode, meshInfo ); break; default: DebugMessage( childNode ); break; } } }
public InputSourceCollection ReadInput( XmlNode node, ColladaMeshInfo meshInfo ) { string sourceId = node.Attributes[ "source" ].Value; // Get the part after the '#' sourceId = sourceId.Substring( 1 ); string semantic = node.Attributes[ "semantic" ].Value; // offset source semantic set Accessor accessor = null; if( !Accessors.ContainsKey( sourceId ) ) { if( Sources.ContainsKey( sourceId ) ) { Source source = Sources[ sourceId ]; Debug.Assert( source.Accessors.Count == 1 ); accessor = Accessors[ source.Accessors[ 0 ].AccessorId ]; return new InputSource( sourceId, semantic, accessor ); } // TODO: Check combiners as well. Debug.Assert( false, "Missing accessor for source: " + sourceId ); return null; } accessor = Accessors[ sourceId ]; return new InputSource( sourceId, semantic, accessor ); }
public virtual void ReadController( XmlNode node, ColladaMeshInfo meshInfo ) { // Set up the current geometry name string controllerName = node.Attributes[ "id" ].Value; string target = node.Attributes[ "target" ].Value; SkinController controller = new SkinController( controllerName ); controller.Target = meshInfo.Geometries[ target ]; meshInfo.Controllers[ controllerName ] = controller; foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "skin": ReadSkin( controller, childNode, meshInfo ); break; default: DebugMessage( childNode ); break; } } }
public void ReadInstanceController( string nodeName, string parentBone, Matrix4 localTransform, Matrix4 transform, XmlNode node, ColladaMeshInfo meshInfo ) { string instance = UrlFragementName( node ); if( nodeName == null ) { nodeName = instance; } if( !meshInfo.Controllers.ContainsKey( instance ) ) { log.WarnFormat( "Cannot find controller instance named '{0}'", instance ); } else { GeometryInstance geoInstance = CreateGeometryInstance( nodeName, parentBone, ref localTransform, ref transform, node, meshInfo ); geoInstance.controller = meshInfo.Controllers[ instance ]; geoInstance.geoSet = meshInfo.Controllers[ instance ].Target; meshInfo.GeoInstances.Add( geoInstance ); } }
public void ReadControllerLibrary( XmlNode node, ColladaMeshInfo meshInfo ) { #if UNORDERED foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.Name) { case "controller": ReadController(childNode, meshInfo); break; default: DebugMessage(childNode); break; } } #else XmlElement libElement = node as XmlElement; List<XmlNode> orderedControllerNodes = new List<XmlNode>(); foreach( XmlNode childNode in node.ChildNodes ) { if( IsMorphController( childNode ) ) { orderedControllerNodes.Add( childNode ); } } foreach( XmlNode childNode in node.ChildNodes ) { if( IsSkinController( childNode ) ) { orderedControllerNodes.Add( childNode ); } } foreach( XmlNode childNode in orderedControllerNodes ) { ReadController( childNode, meshInfo ); } #endif }
public void ReadIntArray( DataSource source, XmlNode node, ColladaMeshInfo meshInfo ) { string id = node.Attributes[ "id" ].Value; int count = int.Parse( node.Attributes[ "count" ].Value ); DataSources[ id ] = source; FillArray( source.IntData, node.InnerText ); Debug.Assert( source.IntData.Count == count ); }
public void ReadExtra( XmlNode node, ColladaMeshInfo meshInfo ) { foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "technique": ReadExtraTechnique( childNode, meshInfo ); break; default: DebugMessage( childNode ); break; } } }
public virtual void ReadLibrary( XmlNode node, ColladaMeshInfo meshInfo ) { string type = node.Attributes[ "type" ].Value; switch( type ) { case "IMAGE": ReadImageLibrary( node, meshInfo ); break; case "TEXTURE": ReadTextureLibrary( node, meshInfo ); break; case "MATERIAL": ReadMaterialLibrary( node, meshInfo ); break; case "GEOMETRY": ReadGeometryLibrary( node, meshInfo ); break; case "CONTROLLER": ReadControllerLibrary( node, meshInfo ); break; case "ANIMATION": ReadAnimationLibrary( node, meshInfo ); break; default: log.InfoFormat( "Ignoring unhandled library type: {0}", type ); break; } }
public void ReadExtraTechnique( XmlNode node, ColladaMeshInfo meshInfo ) { XmlAttribute attr = node.Attributes[ "profile" ]; if( attr != null && attr.Value == "MAYA" ) { log.Info( "Handling maya technique" ); foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "param": ReadExtraTechniqueParam( childNode, meshInfo ); break; default: DebugMessage( childNode ); break; } } } else { log.InfoFormat( "Skipping extra technique with unknown profile: {0}", attr ); } }
public void ReadMaterialLibrary( XmlNode node, ColladaMeshInfo meshInfo ) { foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "material": ReadMaterial( childNode, meshInfo ); break; default: DebugMessage( childNode ); break; } } }
/// <summary> /// Right now, I use this to set the layer of objects to avoid drawing controls /// </summary> /// <param name="node"></param> public void ReadExtraTechniqueParam( XmlNode node, ColladaMeshInfo meshInfo ) { XmlAttribute attr; attr = node.Attributes[ "type" ]; if( attr == null || attr.Value != "layer" ) { log.InfoFormat( "Skipping extra technique parameter with unknown type: {0}", attr ); return; } attr = node.Attributes[ "name" ]; if( attr == null || attr.Value == "" ) { log.Info( "Skipping unnamed layer in extra technique parameter" ); return; } string layer = attr.Value; // Ok, looks like these are the names of nodes that should not be displayed string[] values = node.InnerText.Split( (char[]) null, StringSplitOptions.RemoveEmptyEntries ); foreach( string val in values ) meshInfo.Layers[ val ] = layer; }
public virtual void ReadNode( List<NamedTransform> parentTransforms, string parentBone, XmlNode node, ColladaMeshInfo meshInfo ) { List<NamedTransform> transformChain = new List<NamedTransform>(); foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "rotate": { float angle = 0; Vector3 axis = Vector3.UnitY; ReadRotate( ref angle, ref axis, childNode ); transformChain.Add( new NamedRotateTransform( GetSid( childNode ), angle, axis ) ); } break; case "scale": { Vector3 scale = Vector3.UnitScale; ReadVector( ref scale, childNode ); transformChain.Add( new NamedScaleTransform( GetSid( childNode ), scale ) ); } break; case "translate": { Vector3 translation = Vector3.Zero; ReadVector( ref translation, childNode ); transformChain.Add( new NamedTranslateTransform( GetSid( childNode ), translation ) ); } break; case "skew": { // FIXME: For now, just handle skew with a matrix Matrix4 matrix = Matrix4.Identity; ReadSkewMatrix( ref matrix, childNode ); transformChain.Add( new NamedMatrixTransform( GetSid( childNode ), matrix ) ); } break; case "matrix": { Matrix4 matrix = Matrix4.Identity; ReadMatrix( ref matrix, childNode ); transformChain.Add( new NamedMatrixTransform( GetSid( childNode ), matrix ) ); } break; case "instance": case "node": case "lookat": case "perspective": case "boundingbox": case "extras": default: break; } } if( node.Attributes[ "type" ] != null && node.Attributes[ "id" ] != null ) { string nodeId = node.Attributes[ "id" ].Value; switch( node.Attributes[ "type" ].Value ) { case "JOINT": { meshInfo.JointTransformChains[ nodeId ] = transformChain; meshInfo.BoneParents[ nodeId ] = parentBone; parentBone = nodeId; } break; case "NODE": // the default break; default: DebugMessage( node ); break; } } foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "instance": { Matrix4 transform = Matrix4.Identity; foreach( NamedTransform t in transformChain ) { transform = t.Transform * transform; Debug.Assert( transform != Matrix4.Zero ); } Matrix4 localTransform = transform; foreach( NamedTransform t in parentTransforms ) { transform = t.Transform * transform; Debug.Assert( transform != Matrix4.Zero ); } if( IsInstanceGeometry( childNode, meshInfo ) ) { ReadInstanceGeometry( null, parentBone, localTransform, transform, childNode, meshInfo ); } else { ReadInstanceController( null, parentBone, localTransform, transform, childNode, meshInfo ); } break; } case "node": ReadNode( transformChain, parentBone, childNode, meshInfo ); break; case "rotate": case "scale": case "translate": case "skew": case "matrix": break; case "lookat": case "perspective": case "boundingbox": case "extras": default: DebugMessage( childNode ); break; } } }
public void ReadGeometry( XmlNode node, ColladaMeshInfo meshInfo ) { // Set up the current geometry name string geometryName = node.Attributes[ "id" ].Value; foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "mesh": ReadMesh( geometryName, childNode, meshInfo ); break; case "extra": default: DebugMessage( childNode ); break; } } }
public virtual void ReadCollada( XmlNode node, ColladaMeshInfo meshInfo ) { throw new NotImplementedException(); }
public virtual void ReadImage( XmlNode node, ColladaMeshInfo meshInfo ) { string id = node.Attributes[ "id" ].Value; string source = node.Attributes[ "source" ].Value; int slashIndex = source.LastIndexOf( '/' ); if( slashIndex >= 0 ) source = source.Substring( slashIndex + 1 ); MaterialBuilder.AddImage( id, source ); }