public Channel(Document doc, Model model, Document.Channel channel, Dictionary<string, Sampler> samplers) { if (!samplers.TryGetValue(channel.source.id, out sampler)) throw new ColladaException("can't find source with id " + channel.source.id + " of <channel>"); Bone bone; string targetNodeId = COLLADAUtil.GetTargetNodeId(doc, channel.target); if (!model.BonesTable.TryGetValue(targetNodeId, out bone)) throw new ColladaException("can't find target node in <channel>"); string[] tmp = channel.target.Split('/'); tmp = tmp[tmp.Length - 1].Split('.'); string targetTransformId = tmp[0]; if (tmp.Length == 1) targetTransformKey = null; else targetTransformKey = tmp[1]; if (!bone.Transforms.TryGetValue(targetTransformId, out transform)) throw new ColladaException("can't find target transformation '" + targetTransformId + "' in <channel>"); transform.AddChannel(this); }
/// <summary> /// Create a BasicMaterial from a "<material>". /// <param name="material">The "<material>" element to be converted.</param> /// <param name="context"> The current context for the COLLADA Processor</param> /// </summary> public BasicMaterial CreateBasicMaterial(Model model, Document.Material material) { Document doc = model.Doc; uint textureChannel = 0; Dictionary<string, uint> textureBinding = new Dictionary<string, uint>(); textureBindings[material.id] = textureBinding; BasicMaterial materialContent = new BasicMaterial(); Document.Effect effect = (Document.Effect)doc.dic[material.instanceEffect.Fragment]; if (effect == null) throw new Exception("cannot find effect#" + material.instanceEffect.Fragment); // search common profile with correct asset.... Document.ProfileCOMMON profile; foreach (Document.IProfile tmpProfile in effect.profiles) { if (tmpProfile is Document.ProfileCOMMON) { profile = (Document.ProfileCOMMON)tmpProfile; goto Found; } } throw new Exception("Could not find profile_COMMON in effect" + effect.ToString()); Found: // read params // Dictionary<string, string> samplerBind = new Dictionary<string, string>(); // Dictionary<string, string> imageBind = new Dictionary<string, string>(); // Read Technique Document.SimpleShader shader = ((Document.ProfileCOMMON)profile).technique.shader; materialContent.Name = material.name; // BasicShader only accept texture for the diffuse channel if (shader.diffuse is Document.Texture) { string sampler = ((Document.Texture)shader.diffuse).texture; string surface; string image; if (profile.newParams.ContainsKey(sampler)) { surface = ((Document.Sampler2D)profile.newParams[sampler].param).source; image = ((Document.Surface)profile.newParams[surface].param).initFrom; } else { image = sampler; // TODO: emit serious warning - invalid content } // now find image string imagePath = ((Document.Image)doc.dic[image]).init_from.Uri.LocalPath; // here associate 1 texture binding per texture in material textureBinding[((Document.Texture)shader.diffuse).texcoord] = textureChannel++; materialContent.Texture = imagePath; } else if (shader.diffuse is Document.Color) { Document.Color color = (Document.Color)shader.diffuse; // TODO: manage color[3] in transparency materialContent.DiffuseColor = new Vector3(color[0], color[1], color[2]); } if (shader.ambient is Document.Texture) { // Basic Material does not accept texture on ambient channel COLLADAUtil.Log("Ambient channel not supported in BasicMaterial."); /* string sampler = ((Document.Texture)shader.ambient).texture; string surface = ((Document.Sampler2D)profile.newParams[sampler].param).source; string image = ((Document.Surface)profile.newParams[surface].param).initFrom; // now find image string imagePath = ((Document.Image)doc.dic[image]).init_from.Uri.LocalPath; // here associate 1 texture binding per texture in material textureBinding[((Document.Texture)shader.ambient).texcoord] = textureChannel++; materialContent.Texture = new ExternalReference<TextureContent>(imagePath); */ } else if (shader.ambient is Document.Color) { // XNA BasicMaterial has no ambient COLLADAUtil.Log("Ambient channel not supported in BasicMaterial."); } if (shader.emission is Document.Texture) { // XNA BasicMaterial does not accept texture for emmision COLLADAUtil.Log("BasicMaterial does not accept texture for emmision."); /* string sampler = ((Document.Texture)shader.emission).texture; string surface = ((Document.Sampler2D)profile.newParams[sampler].param).source; string image = ((Document.Surface)profile.newParams[surface].param).initFrom; // now find image string imagePath = ((Document.Image)doc.dic[image]).init_from.Uri.LocalPath; // here associate 1 texture binding per texture in material textureBinding[((Document.Texture)shader.emission).texcoord] = textureChannel++; materialContent.Texture = new ExternalReference<TextureContent>(imagePath); */ } else if (shader.emission is Document.Color) { Document.Color color = (Document.Color)shader.emission; materialContent.EmissiveColor = new Vector3(color[0], color[1], color[2]); } if (shader.specular is Document.Texture) { // XNA BasicMaterial does not accept texture for specular COLLADAUtil.Log("BasicMaterial does not accept texture for specular."); /* string sampler = ((Document.Texture)shader.specular).texture; string surface = ((Document.Sampler2D)profile.newParams[sampler].param).source; string image = ((Document.Surface)profile.newParams[surface].param).initFrom; // now find image string imagePath = ((Document.Image)doc.dic[image]).init_from.Uri.LocalPath; // here associate 1 texture binding per texture in material textureBinding[((Document.Texture)shader.specular).texcoord] = textureChannel++; materialContent.Texture = new ExternalReference<TextureContent>(imagePath); */ } else if (shader.specular is Document.Color) { Document.Color color = (Document.Color)shader.specular; materialContent.SpecularColor = new Vector3(color[0], color[1], color[2]); if (shader.shininess is Document.Float) materialContent.SpecularPower = ((Document.Float)shader.shininess).theFloat; } if (shader.transparency is Document.Texture) { // XNA Basic Shader does not accept a texture for the transparency channel COLLADAUtil.Log("BasicMaterial does not accept texture for transparency channel."); /* string sampler = ((Document.Texture)shader.transparency).texture; string surface = ((Document.Sampler2D)profile.newParams[sampler].param).source; string image = ((Document.Surface)profile.newParams[surface].param).initFrom; // now find image string imagePath = ((Document.Image)doc.dic[image]).init_from.Uri.LocalPath; // here associate 1 texture binding per texture in material textureBinding[((Document.Texture)shader.transparency).texcoord] = textureChannel++; materialContent.Texture = new ExternalReference<TextureContent>(imagePath); */ } else if (shader.transparency is Document.Float) { materialContent.Alpha = ((Document.Float)shader.transparency).theFloat; } return materialContent; }
public Animation(Document doc, Model model, Document.Animation animation) { children = new List<Animation>(); samplers = new Dictionary<string, Sampler>(); channels = new List<Channel>(); if (animation.children != null) foreach (Document.Animation childAnim in animation.children) children.Add(new Animation(doc, model, childAnim)); if (animation.channels != null && animation.samplers != null) { foreach (Document.Sampler sampler in animation.samplers) samplers.Add(sampler.id, new Sampler(doc, sampler)); foreach (Document.Channel channel in animation.channels) { try { channels.Add(new Channel(doc, model, channel, samplers)); } catch (ColladaException e) { COLLADAUtil.Log(e); } } } }
// Summary: // Create a new Instance of a Mesh // Parameters: // mesh: // the ModelMesh to instance // parentBone: // the bone that will give this instance its position // materialBinding // the binding between the material name and the name in the mesh parts // // Returns: // A new instance of mesh public InstanceMesh(Model.CMesh mesh, Model.Bone parentBone, Dictionary<string, string> materialBinding) { this.mesh = mesh; this.parentBone = parentBone; this.materialBinding = materialBinding; }
public CSkinnedMesh(Model model, Document.Geometry geo, Document.Skin skin) : base(model, geo) { this.geo = geo; this.model = model; this.skin = skin; /* foreach (Document.Input input in skin.joint.inputs) { if (input.semantic == "JOINT") { Document.Source source = (Document.Source) input.source; boneCount = ((Document.Array<string>) source.array).Count; } } */ }
public CMesh(Model model, Document.Geometry geo) { this.geo = geo; Document doc = model.Doc; bool first = true; int vertexIndex = 0; List<int> indexBuffer = new List<int>(); List<float> vertexBuffer = new List<float>(); List<int> invVertexMappingList = new List<int>(); Dictionary<string, int> mapping = new Dictionary<string, int>(); List<float> tempValues = new List<float>(); foreach (Document.Primitive primitive in geo.mesh.primitives) { // Skip non-triangle primitives if (!(primitive is Document.Triangle)) { // Display a warning COLLADAUtil.Log(COLLADALogType.Warning, "Skipping part of geometry '" + geo.id + "'! Make sure all primitives are triangles."); continue; } #region vertex declaration // Take the first primitive and use its inputs to build the // vertex declaration and a dictionary to describe a mapping // of n source/p_index pairs to one index in the vertex buffer. // TODO: for now we assume that all primitives have the same // inputs in equal order. if (first) { first = false; short deltaOffset = 0; short offset = 0; short streamOffset = 0; DeclarationType vertexElementFormat; DeclarationUsage vertexElementUsage; byte usageIndex; byte texcoordUsageIndex = 0; foreach (Document.Input input in COLLADAUtil.GetAllInputs(primitive)) { switch (input.semantic) { case "POSITION": vertexElementUsage = DeclarationUsage.Position; usageIndex = 0; break; case "NORMAL": vertexElementUsage = DeclarationUsage.Normal; usageIndex = 0; break; case "COLOR": vertexElementUsage = DeclarationUsage.Color; usageIndex = 0; break; case "TEXCOORD": vertexElementUsage = DeclarationUsage.TextureCoordinate; usageIndex = texcoordUsageIndex++; break; case "TEXTANGENT": vertexElementUsage = DeclarationUsage.Tangent; usageIndex = 0; break; case "TEXBINORMAL": vertexElementUsage = DeclarationUsage.Binormal; usageIndex = 0; break; default: throw new Exception("Unexeptected vertexElementUsage=" + input.semantic); } // assuming floats !o switch (((Document.Source)input.source).accessor.ParameterCount) { case 2: vertexElementFormat = DeclarationType.Float2; deltaOffset = 2 * 4; vertexStride += 2; break; case 3: vertexElementFormat = DeclarationType.Float3; deltaOffset = 3 * 4; vertexStride += 3; break; case 4: vertexElementFormat = DeclarationType.Float4; deltaOffset = 4 * 4; vertexStride += 4; break; default: throw new Exception("Unexpected vertexElementFormat"); } vertexElements.Add(new VertexElement(streamOffset /* stream */, offset /* offset */, vertexElementFormat, DeclarationMethod.Default, vertexElementUsage, usageIndex)); offset += deltaOffset; } } #endregion // Build vertex and index array for (int v = 0; v < primitive.count * 3; v++) { int positionIndex = 0; string indexKey = ""; tempValues.Clear(); foreach (Document.Input input in COLLADAUtil.GetAllInputs(primitive)) { // Get index into source array of this input for this triangle t int index = COLLADAUtil.GetPValue(input, primitive, v); // Save index of position array for later inverse mapping if (input.semantic == "POSITION") positionIndex = index; // Build key out of all indices for later lookup indexKey += index + ","; // Get values this index is referencing float[] values = COLLADAUtil.GetSourceElement(doc, input, index); // Add the values to temporary storage tempValues.AddRange(values); } // Add this combination of inputs to the vertex buffer if (mapping.ContainsKey(indexKey)) indexBuffer.Add(mapping[indexKey]); else { mapping[indexKey] = vertexIndex; indexBuffer.Add(vertexIndex); vertexBuffer.AddRange(tempValues); // Inverse mapping of vertex buffer index to index of original array invVertexMappingList.Add(positionIndex); // Increment index of vertex buffer vertexIndex++; } } primitives.Add(primitive); faceCount += primitive.count; } vertexCount = vertexIndex; indexArray = indexBuffer.ToArray(); vertexArray = vertexBuffer.ToArray(); invVertexMapping = invVertexMappingList.ToArray(); // Reverse triangle order for DirectX for (int i = 0; i < indexArray.Length; i += 3) { int swap = indexArray[i]; indexArray[i] = indexArray[i + 2]; indexArray[i + 2] = swap; } foreach (VertexElement vertexElement in VertexElements) { // Reverse texture 'T' coordinate for DirectX if (vertexElement.Usage == DeclarationUsage.TextureCoordinate) { for (int i = 0; i < vertexCount; i++) { int offsetT = i * VertexStride + vertexElement.Offset / 4 + 1; if (offsetT < vertexArray.Length) vertexArray[offsetT] = 1.0f - vertexArray[offsetT]; else throw new IndexOutOfRangeException(); } } } FinalizeVertexDeclaration(vertexElements); }
public Camera(Model model, Document.Camera cam) { if (cam.optics.perspectiveOrOrthographic is Document.Perspective) { Document.Perspective perspective = (Document.Perspective) cam.optics.perspectiveOrOrthographic; projectionMatrix = Matrix.PerspectiveFovLH( perspective.yfov.theFloat * DegToRad, perspective.aspect_ratio.theFloat, perspective.znear.theFloat, perspective.zfar.theFloat); } else { Document.Orthographic orthographic = (Document.Orthographic) cam.optics.perspectiveOrOrthographic; projectionMatrix = Matrix.OrthoLH( orthographic.xmag.theFloat, orthographic.ymag.theFloat, orthographic.znear.theFloat, orthographic.zfar.theFloat); } }
public Bone(Model model, Bone _parent, string _name, string _nodeName, string _nodeType) { this.transforms = new Dictionary<string, Transform>(); if (model.BonesTable.ContainsKey(_name)) _name = _parent.Name + "/" + _name; model.BonesTable.Add(_name, this); this.index = model.Bones.Count-1; this.children = new List<Bone>(); name = _name; parent = _parent; nodeName = _nodeName; nodeType = _nodeType; }