private void WriteMaterials(BinaryWriter bw, AMT_MODEL model) { List <AMT_MATERIAL> materials = model.Materials; for (int i = 0; i < materials.Count; i++) { char[] name = Tools.GetCharArray(materials[i].Name, 64); bw.Write(name); _import.ProgressText = "Exporting Materials " + materials[i].Name; WriteVector(bw, materials[i].Ambient); WriteVector(bw, materials[i].Diffuse); WriteVector(bw, materials[i].Specular); WriteVector(bw, materials[i].Emissive); bw.Write(materials[i].SpecularPower); bw.Write(materials[i].Transparency); char[] diffuseTexture = Tools.GetCharArray(materials[i].DiffuseTexture, 64); bw.Write(diffuseTexture); char[] specularTexture = Tools.GetCharArray(materials[i].SpecularTexture, 64); bw.Write(specularTexture); char[] normalTexture = Tools.GetCharArray(materials[i].NormalTexture, 64); bw.Write(normalTexture); char[] animatedTexture = Tools.GetCharArray(materials[i].AnimatedTexture, 64); bw.Write(animatedTexture); bw.Write(materials[i].Flag); } }
public static void CenterPivot(ref AMT_MODEL model) { List<Vector3> vertices = new List<Vector3>(); for (int i = 0; i < model.Vertices.Count; i++) vertices.Add(model.Vertices[i].Position); BoundingBox bb = BoundingBox.CreateFromPoints(vertices); Vector3 positionAjust = -(bb.Max + bb.Min) / 2; Matrix translation = Matrix.CreateTranslation(positionAjust); //redimensiona os vertices for (int i = 0; i < model.Vertices.Count; i++) model.Vertices[i].Position = Vector3.Transform(model.Vertices[i].Position, translation); //reposiciona tb todos os bones e os keyframes if (model.Joints != null) { for (int i = 0; i < model.Joints.Count; i++) { AMT_JOINT v = model.Joints[i]; //como ele mexeu na posicao entao mexe so no raiz if (v.Name == "Root") v.BindMatrix *= translation; if (model.Joints[i].ParentID != -1) v.MatrixAbsolute = model.Joints[i].BindMatrix * model.Joints[model.Joints[i].ParentID].MatrixAbsolute; else v.MatrixAbsolute = model.Joints[i].BindMatrix; v.InverseBindMatrix = Matrix.Invert(translation) * v.InverseBindMatrix; //mexe so no raiz if (v.Name == "Root") { for (int j = 0; j < v.KFData.Count; j++) { AMT_KF p = v.KFData[j]; p.BindMatrix *= translation; v.KFData[j] = p; } } model.Joints[i] = v; } } }
private void WriteAnimations(BinaryWriter bw, AMT_MODEL model) { List <AMT_ANIMATION> animations = model.Animations; for (int i = 0; i < animations.Count; i++) { char[] name = Tools.GetCharArray(animations[i].Name, 64); bw.Write(name); _import.ProgressText = "Exporting Bones: animation: " + animations[i].Name; bw.Write(animations[i].StartFrame); bw.Write(animations[i].EndFrame); bw.Write(animations[i].Active); } }
private void WriteAnimations(BinaryWriter bw, AMT_MODEL model) { List<AMT_ANIMATION> animations = model.Animations; for (int i = 0; i < animations.Count; i++) { char[] name = Tools.GetCharArray(animations[i].Name, 64); bw.Write(name); _import.ProgressText = "Exporting Bones: animation: " + animations[i].Name; bw.Write(animations[i].StartFrame); bw.Write(animations[i].EndFrame); bw.Write(animations[i].Active); } }
private void WriteFaces(BinaryWriter bw, AMT_MODEL model) { List<AMT_FACE> faces = model.Faces; for (int i = 0; i < faces.Count; i++) { _import.ProgressText = "Exporting Faces " + i.ToString() + "/" + faces.Count.ToString(); for (int j = 0; j < faces[i].Indices.Count; j++) bw.Write(faces[i].Indices[j]); WriteVector(bw, faces[i].Normal); bw.Write(faces[i].MeshID); bw.Write(faces[i].Flag); } }
public bool Export(AMT_MODEL model, string filePath, Import import) { _import = import; using (BinaryWriter bw = new BinaryWriter(File.Open(filePath, FileMode.Create))) { WriteHead(bw, model); WriteVertices(bw, model); WriteFaces(bw, model); WriteMeshes(bw, model); WriteMaterials(bw, model); WriteJoints(bw, model); WriteAnimations(bw, model); bw.Close(); } return(true); }
private void WriteHead(BinaryWriter bw, AMT_MODEL model) { _import.ProgressText = "Exporting Head"; AMT_HEAD head = model.Head; bw.Write(head.Version); bw.Write(head.NumVertices); bw.Write(head.NumIndices); bw.Write(head.NumFaces); bw.Write(head.NumMeshes); bw.Write(head.NumMaterials); bw.Write(head.NumJoints); bw.Write(head.AnimationFPS); bw.Write(head.CurrentTime); bw.Write(head.NumFrames); bw.Write(head.NumAnimations); bw.Write(head.HasSkeleton); }
public bool Export(AMT_MODEL model, string filePath, Import import) { _import = import; using (BinaryWriter bw = new BinaryWriter(File.Open(filePath, FileMode.Create))) { WriteHead(bw, model); WriteVertices(bw, model); WriteFaces(bw, model); WriteMeshes(bw, model); WriteMaterials(bw, model); WriteJoints(bw, model); WriteAnimations(bw, model); bw.Close(); } return true; }
void AddAnimations(ref AMT_MODEL? amtModel) { List<AMT_ANIMATION> animations = new List<AMT_ANIMATION>(); for (int i = 0; i < animationsData.Rows.Count; i++) { var animation = new AMT_ANIMATION() { StartFrame = (uint)animationsData.Rows[i]["Start"], EndFrame = (uint)animationsData.Rows[i]["End"], Name = animationsData.Rows[i]["Name"].ToString() }; animations.Add(animation); } AMT_MODEL im = amtModel.Value; im.Animations = animations; im.Head.NumAnimations = (uint)animations.Count; amtModel = im; }
private void WriteFaces(BinaryWriter bw, AMT_MODEL model) { List <AMT_FACE> faces = model.Faces; for (int i = 0; i < faces.Count; i++) { _import.ProgressText = "Exporting Faces " + i.ToString() + "/" + faces.Count.ToString(); for (int j = 0; j < faces[i].Indices.Count; j++) { bw.Write(faces[i].Indices[j]); } WriteVector(bw, faces[i].Normal); bw.Write(faces[i].MeshID); bw.Write(faces[i].Flag); } }
private void WriteMeshes(BinaryWriter bw, AMT_MODEL model) { List <AMT_MESH> meshes = model.Meshes; for (int i = 0; i < meshes.Count; i++) { char[] name = Tools.GetCharArray(meshes[i].Name, 64); bw.Write(name); _import.ProgressText = "Exporting Mesh " + meshes[i].Name; bw.Write(meshes[i].NumFaces); for (int j = 0; j < meshes[i].FaceIndices.Count; j++) { bw.Write(meshes[i].FaceIndices[j]); } bw.Write(meshes[i].MaterialID); bw.Write(meshes[i].Flag); } }
private void WriteJoints(BinaryWriter bw, AMT_MODEL model) { List <AMT_JOINT> joints = model.Joints; for (int i = 0; i < joints.Count; i++) { char[] name = Tools.GetCharArray(joints[i].Name, 64); bw.Write(name); _import.ProgressText = "Exporting Bones: name: " + joints[i].Name; bw.Write(joints[i].ID); bw.Write(joints[i].ParentID); //grava os ids dos filhos bw.Write(joints[i].NumChildren); if (joints[i].NumChildren > 0) { foreach (var item in joints[i].JointChildren) { bw.Write(item); } } //grava todos os keyframes desse joint bw.Write(joints[i].NumKF); if (joints[i].NumKF > 0) { WriteKFData(bw, joints[i].KFData); } bw.Write(joints[i].IsAnimated); bw.Write(joints[i].Flag); WriteMatrix(bw, joints[i].BindMatrix); WriteMatrix(bw, joints[i].MatrixAbsolute); WriteMatrix(bw, joints[i].InverseBindMatrix); } }
private void WriteVertices(BinaryWriter bw, AMT_MODEL model) { List <AMT_VERTEX> vertices = model.Vertices; for (int i = 0; i < vertices.Count; i++) { _import.ProgressText = "Exporting Vertices " + i.ToString() + "/" + vertices.Count.ToString(); WriteVector(bw, vertices[i].Position); WriteVector(bw, vertices[i].TexCoord1); WriteVector(bw, vertices[i].TexCoord2); WriteVector(bw, vertices[i].Normal); for (int j = 0; j < 4; j++) { bw.Write(vertices[i].BoneIndices[j]); bw.Write(vertices[i].BoneWeights[j]); } bw.Write(vertices[i].Flag); } }
public AMT_MODEL ConvertCollada(Stream stream) { var amtModel = new AMT_MODEL(); var doc = XDocument.Load(stream); var colladaNode = doc.Root; Namespace = doc.Root.Name.Namespace.NamespaceName; //ReadGeometries(new XElement(XName.Get("library_geometries", Namespace)), ref amtModel); //_effects = ReadEffects(colladaNode.Element(XName.Get("library_effects", COLLADAConverter.Namespace))); //_materials = ReadMaterials(colladaNode.Element(XName.Get("library_materials", COLLADAConverter.Namespace))); ////Lê os layers //var geometryNodes = colladaNode.Element(XName.Get("library_geometries", COLLADAConverter.Namespace)); //if (geometryNodes != null) // pmobDoc.Layers = ReadLayers(geometryNodes.Elements()); //ReadLibraryNodes(colladaNode.Element(XName.Get("library_nodes", COLLADAConverter.Namespace))); //var scenesElement = colladaNode.Element(XName.Get("library_visual_scenes", COLLADAConverter.Namespace)); //if (scenesElement != null) //{ // var nodes = ReadNodes(scenesElement.Element(XName.Get("visual_scene", COLLADAConverter.Namespace))); // var rootNode = new Node("root", "root", nodes); // pmobDoc.Primitive = CreatePrimitive(rootNode); //} ////Gira o objeto dependendo do up //var assetNode = colladaNode.Element(XName.Get("asset", COLLADAConverter.Namespace)); //if (assetNode != null) //{ // var upAxis = assetNode.Elements(XName.Get("up_axis", COLLADAConverter.Namespace)); //} return amtModel; }
private void WriteVertices(BinaryWriter bw, AMT_MODEL model) { List<AMT_VERTEX> vertices = model.Vertices; for (int i = 0; i < vertices.Count; i++) { _import.ProgressText = "Exporting Vertices " + i.ToString() + "/" + vertices.Count.ToString(); WriteVector(bw, vertices[i].Position); WriteVector(bw, vertices[i].TexCoord1); WriteVector(bw, vertices[i].TexCoord2); WriteVector(bw, vertices[i].Normal); for (int j = 0; j < 4; j++) { bw.Write(vertices[i].BoneIndices[j]); bw.Write(vertices[i].BoneWeights[j]); } bw.Write(vertices[i].Flag); } }
private void ConvertMesh(XElement meshElement, XElement triangles, ref AMT_MODEL amtModel) { //pega o mesh atual uint meshID = (uint)amtModel.Meshes.Count - 1; AMT_MESH mesh = amtModel.Meshes[amtModel.Meshes.Count - 1]; //ja armazena o numero de faces do mesh mesh.NumFaces = int.Parse(triangles.Attribute("count").Value); //pega os inputs vertex, normal, texcoord etc List<XElement> inputs = triangles.Elements(XName.Get("input", Namespace)).ToList(); XElement vertex = inputs.Find(item => { return item.Attribute("semantic").Value == "VERTEX"; }); XElement normal = inputs.Find(item => { return item.Attribute("semantic").Value == "NORMAL"; }); XElement texcoord = inputs.Find(item => { return item.Attribute("semantic").Value == "TEXCOORD"; }); //elementos que tem na tag vertices, procurar o id = vertex.source List<XElement> verticesElements = meshElement.Elements(XName.Get("vertices", Namespace)).ToList(); XElement verticeElement = verticesElements.Find(item => { return item.Attribute("id").Value == vertex.Attribute("source").Value.Substring(1); }); //agora com o vertice certo pega o position List<XElement> inputsVerticesElement = verticeElement.Elements(XName.Get("input", Namespace)).ToList(); XElement position = inputsVerticesElement.Find(item => { return item.Attribute("semantic").Value == "POSITION"; }); //agora é so carregar os dados dos sources conforme os id dos inputs position, normal, texcoord List<XElement> sources = meshElement.Elements(XName.Get("source", Namespace)).ToList(); XElement sourcePosition = sources.Find(item => { return item.Attribute("id").Value == position.Attribute("source").Value.Substring(1); }); XElement sourceNormal = sources.Find(item => { return item.Attribute("id").Value == normal.Attribute("source").Value.Substring(1); }); XElement sourceTexcoord = sources.Find(item => { return item.Attribute("id").Value == texcoord.Attribute("source").Value.Substring(1); }); //pega os indices e junta tudo em um unico string List<XElement> ps = triangles.Elements(XName.Get("p", Namespace)).ToList(); string indices = null; foreach (var item in ps) indices += ' ' + item.Value; //separa todos os indices usando os offsets string[] strIndices = indices.Replace('\n', ' ').Trim().Split(' '); List<int> positionIndices = new List<int>(); int positionOffset = int.Parse(vertex.Attribute("offset").Value); List<int> normalIndices = new List<int>(); int normalOffset = int.Parse(normal.Attribute("offset").Value); List<int> texcoordIndices = new List<int>(); int texcoordOffset = int.Parse(texcoord.Attribute("offset").Value); for (int i = 0; i < strIndices.Length; i += sources.Count) { positionIndices.Add(int.Parse(strIndices[i + positionOffset])); normalIndices.Add(int.Parse(strIndices[i + normalOffset])); texcoordIndices.Add(int.Parse(strIndices[i + texcoordOffset])); } //vertices reais List<Vector3> positions = GetPositions(sourcePosition); List<Vector3> normals = GetNormals(sourceNormal); List<Vector2> texcoords = GetTexCoords(sourceTexcoord); //agora é so pegar os indices e vincular com os arrays pra criar os vertices q vao para o amt for (int i = 0; i < positionIndices.Count; i++) { AMT_VERTEX v = new AMT_VERTEX(); v.SID = positionIndices[i]; //utilizado para encontrar esses vertices depois quando for atualizar o peso dos bones v.Position = positions[positionIndices[i]]; v.Normal = normals[normalIndices[i]]; v.TexCoord1 = texcoords[texcoordIndices[i]]; v.TexCoord1.Y = -v.TexCoord1.Y; //Inverto o Y pq o exportador do max usa as coordenadas do opengl amtModel.Vertices.Add(v); } //carrega as faces for (int i = 0; i < amtModel.Vertices.Count; i += 3) { AMT_FACE f = new AMT_FACE(); f.MeshID = meshID; f.Indices = new List<int>(); f.Indices.Add(i); f.Indices.Add(i + 1); f.Indices.Add(i + 2); f.Normal = Tools.GetNormal(amtModel.Vertices[i].Position, amtModel.Vertices[i + 1].Position, amtModel.Vertices[i + 2].Position); amtModel.Faces.Add(f); mesh.FaceIndices.Add(amtModel.Faces.Count - 1); } //finalmente seta o mesh atual amtModel.Meshes[amtModel.Meshes.Count - 1] = mesh; }
private void ConvertBones(XElement rootElement, ref AMT_MODEL amtModel) { //primeiro eu encontro o library_visual_scenes XElement libraryVisualScenes = rootElement.Element(XName.Get("library_visual_scenes", Namespace)); XElement visualScene = libraryVisualScenes.Element(XName.Get("visual_scene", Namespace)); //se tem o nodo skeleton XElement rootNode = FindRootSkeletonNodeId(visualScene); amtModel.Joints = new List<AMT_JOINT>(); //Começo a percorrer os nodes procurando pela hierarquia de bones if (rootNode != null) { //adiciona o bone raiz Matrix matrix = Matrix.Identity; string sid = rootNode.Attribute("sid").Value; string boneId = rootNode.Attribute("id").Value; XElement matrixElement = rootNode.Element(XName.Get("matrix", Namespace)); string matrixSID = null; if (matrixElement.Attribute("sid") != null) matrixSID = matrixElement.Attribute("sid").Value; //uso nas animacoes para achar o bone id/sid matrix = Tools.ConvertStringToMatrix(matrixElement.Value, 0); AMT_JOINT newBone = new AMT_JOINT(); newBone.SID = sid; newBone.TARGET = boneId + "/" + matrixSID; newBone.ID = 0; newBone.ParentID = -1; //nao tem pai newBone.Name = "Root"; newBone.NumChildren = 0; newBone.JointChildren = new List<uint>(); newBone.NumKF = 0; newBone.KFData = new List<AMT_KF>(); //se nao tem sid entao ele nao é animado newBone.IsAnimated = (uint)(string.IsNullOrEmpty(matrixSID)? 0 : 1); newBone.Flag = 0; newBone.BindMatrix = matrix; newBone.MatrixAbsolute = matrix; newBone.InverseBindMatrix = Matrix.Invert(matrix); amtModel.Joints.Add(newBone); FillBoneNodes(ref newBone, rootNode, ref amtModel); } }
private void WriteJoints(BinaryWriter bw, AMT_MODEL model) { List<AMT_JOINT> joints = model.Joints; for (int i = 0; i < joints.Count; i++) { char[] name = Tools.GetCharArray(joints[i].Name, 64); bw.Write(name); _import.ProgressText = "Exporting Bones: name: " + joints[i].Name; bw.Write(joints[i].ID); bw.Write(joints[i].ParentID); //grava os ids dos filhos bw.Write(joints[i].NumChildren); if (joints[i].NumChildren > 0) foreach (var item in joints[i].JointChildren) bw.Write(item); //grava todos os keyframes desse joint bw.Write(joints[i].NumKF); if (joints[i].NumKF > 0) WriteKFData(bw, joints[i].KFData); bw.Write(joints[i].IsAnimated); bw.Write(joints[i].Flag); WriteMatrix(bw, joints[i].BindMatrix); WriteMatrix(bw, joints[i].MatrixAbsolute); WriteMatrix(bw, joints[i].InverseBindMatrix); } }
private AMT_MODEL ConvertDAEtoAMT(XElement rootElement) { AMT_MODEL amtModel = new AMT_MODEL(); amtModel.Vertices = new List<AMT_VERTEX>(); ConvertGeometries(rootElement, ref amtModel); ConvertBones(rootElement, ref amtModel); ConvertAnimations(rootElement, ref amtModel); ConvertController(rootElement, ref amtModel); ConvertHead(ref amtModel); Optimize(ref amtModel); return amtModel; }
private void ConvertController(XElement rootElement, ref AMT_MODEL amtModel) { XElement libraryController = rootElement.Element(XName.Get("library_controllers", Namespace)); if (libraryController == null) return; List<XElement> controllers = libraryController.Elements(XName.Get("controller", Namespace)).ToList(); foreach (XElement controller in controllers) { XElement skin = controller.Element(XName.Get("skin", Namespace)); //joints elements XElement jointsElements = skin.Element(XName.Get("joints", Namespace)); List<XElement> inputJointsElements = jointsElements.Elements(XName.Get("input", Namespace)).ToList(); XElement inverseBindMatrixElement = inputJointsElements.Find(item => { return item.Attribute("semantic").Value == "INV_BIND_MATRIX"; }); string inverseBindMatrixName = inverseBindMatrixElement.Attribute("source").Value.Substring(1); //pega o nome do source XElement vWeightsElement = skin.Element(XName.Get("vertex_weights", Namespace)); int numberOfWeights = int.Parse(vWeightsElement.Attribute("count").Value); //pego o numero de bones q influenciam cada vertice string vCount = vWeightsElement.Element(XName.Get("vcount", Namespace)).Value; //par (indice do bone seguido do indice do peso) string v = vWeightsElement.Element(XName.Get("v", Namespace)).Value; List<XElement> inputElements = vWeightsElement.Elements(XName.Get("input", Namespace)).ToList(); //procura o source joint XElement jointInputElement = inputElements.Find(item => { return item.Attribute("semantic").Value == "JOINT"; }); string jointSourceName = jointInputElement.Attribute("source").Value.Substring(1); //procura o source weight XElement weightInputElement = inputElements.Find(item => { return item.Attribute("semantic").Value == "WEIGHT"; }); string weightSourceName = weightInputElement.Attribute("source").Value.Substring(1); //pega o bindmatrix (utilizado para rotacionar o bone) string bindShapeMatrix = skin.Element(XName.Get("bind_shape_matrix", Namespace)).Value; Matrix bindMatrix = Tools.ConvertStringToMatrix(bindShapeMatrix, 0); foreach (var item in amtModel.Joints) { if (item.Name == "Root") item.BindMatrix *= bindMatrix; } //vai no source Joint descoberto e pega a lista de joints e weights List<XElement> sourceElements = skin.Elements(XName.Get("source", Namespace)).ToList(); //pega todas as matrizes inversas XElement invBindMatSourceElement = sourceElements.Find(item => { return item.Attribute("id").Value == inverseBindMatrixName; }); XElement floatArrayInvBind = invBindMatSourceElement.Element(XName.Get("float_array", Namespace)); int numberOfFloats = int.Parse(floatArrayInvBind.Attribute("count").Value); string invBindMatFloats = floatArrayInvBind.Value; invBindMatFloats = invBindMatFloats.Replace('\n', ' ').Trim(); Matrix[] invBindMat = new Matrix[numberOfFloats / 16]; for (int i = 0, j = 0; i < numberOfFloats; i+=16, j++) invBindMat[j] = Tools.ConvertStringToMatrix(invBindMatFloats, i); //pega a lista de nomes de bones na ordem XElement jointSourceElement = sourceElements.Find(item => { return item.Attribute("id").Value == jointSourceName; }); string jointNames = jointSourceElement.Element(XName.Get("Name_array", Namespace)).Value; //pega a lista de weights XElement weightSourceElement = sourceElements.Find(item => { return item.Attribute("id").Value == weightSourceName; }); string weightValues = weightSourceElement.Element(XName.Get("float_array", Namespace)).Value; //joga pra o array as influencias string[] jointsOnSkin = jointNames.Trim().Split(' '); string[] weights = weightValues.Replace('\n', ' ').Trim().Split(' '); string[] influenceNumber = vCount.Trim().Split(' '); string[] boneIndexWeight = v.Trim().Split(' '); //construo um de para, dos indices que estao na lista de joints do amtmodel List<uint> _from = new List<uint>(); List<uint> _to = new List<uint>(); //converto os indices dos bones q estao no <v> para os indices da lista que ja esta na lista for (uint i = 0; i < amtModel.Joints.Count; i++) { for (uint j = 0; j < jointsOnSkin.Length; j++) { //procuro o joint na lista ja salva if (amtModel.Joints[(int)i].SID == jointsOnSkin[j]) { _from.Add(j); _to.Add(i); //seta a invesa da matrix amtModel.Joints[(int)i].InverseBindMatrix = invBindMat[j]; } } } //atribui para os vertices o id dos joints e tb os pesos int vIndex = 0; for (int i = 0; i < influenceNumber.Length; i++) { //primeira coisa encontrar todos os vertices da lista q ja existe com o SID = i List<int> finalVertexListIndices = new List<int>(); for (int vi = 0; vi < amtModel.Vertices.Count; vi++) { if (amtModel.Vertices[vi].SID == i) finalVertexListIndices.Add(vi); } //pega o primeiro vertices na lista ai de cima e atualiza os pesos e os indices AMT_VERTEX firstVertex = amtModel.Vertices[finalVertexListIndices[0]]; uint numInfluence = uint.Parse(influenceNumber[i]); uint[] boneIndices = new uint[numInfluence]; float[] boneWeights = new float[numInfluence]; #region PROCURA OS PESOS E INDICES PRO PRIMEIRO VERTICES DA LISTA for (int d = 0; d < numInfluence; d++) { //seleciona o indice do bone na lista <v> e procura do de-para para achar o indice no amtmodel uint boneIndex = uint.Parse(boneIndexWeight[vIndex++]); for (int j = 0; j < _from.Count; j++) { if (_from[j] == boneIndex) { boneIndex = _to[j]; break; } } uint weightIndex = uint.Parse(boneIndexWeight[vIndex++]); //seta o indice e o peso do bone no vertice atual boneIndices[d] = boneIndex; boneWeights[d] = System.Convert.ToSingle(weights[weightIndex], CultureInfo.InvariantCulture); } //ele carrega o numero de influencias q tem no arquivo, pode ser mais ou menos q 4 mas eu preciso gravar 4 no arquivo //entao se for menos coloco zero se for mais somo tudo no ultimo ate completar 1 q se foda firstVertex.BoneIndices = new uint[4]; firstVertex.BoneWeights = new float[4]; for (int d = 0; d < numInfluence; d++) { if (d > 3) firstVertex.BoneWeights[3] += boneWeights[d]; else { firstVertex.BoneIndices[d] = boneIndices[d]; firstVertex.BoneWeights[d] = boneWeights[d]; } } #endregion //depois de achar os pesos e indices do primeiro vertice da finalVertexListIndices entao ele so copia para os outros da lista for (int vi = 1; vi < finalVertexListIndices.Count; vi++) { AMT_VERTEX vertex = amtModel.Vertices[finalVertexListIndices[vi]]; vertex.BoneIndices = new uint[4]; vertex.BoneWeights = new float[4]; for (int d = 0; d < 4; d++) { vertex.BoneIndices[d] = firstVertex.BoneIndices[d]; vertex.BoneWeights[d] = firstVertex.BoneWeights[d]; } } } } }
private void ConvertHead(ref AMT_MODEL amtModel) { amtModel.Head.Version = 1; amtModel.Head.NumFaces = (uint)amtModel.Faces.Count; amtModel.Head.NumIndices = (uint)amtModel.Faces.Count * 3; amtModel.Head.NumMeshes = (uint)amtModel.Meshes.Count; amtModel.Head.NumVertices = (uint)amtModel.Vertices.Count; amtModel.Head.NumMaterials = (uint)amtModel.Materials.Count; amtModel.Head.NumJoints = (uint)amtModel.Joints.Count; //o numero de animacaoes nao esta aqui }
private void ConvertGeometries(XElement rootElement, ref AMT_MODEL amtModel) { //pega a tag principal das geometrias XElement libraryGeometries = rootElement.Element(XName.Get("library_geometries", Namespace)); List<XElement> geometries = libraryGeometries.Elements(XName.Get("geometry", Namespace)).ToList(); if (geometries.Count > 0) { amtModel.Meshes = new List<AMT_MESH>(); amtModel.Faces = new List<AMT_FACE>(); amtModel.Materials = new List<AMT_MATERIAL>(); amtModel.Head = new AMT_HEAD(); foreach (XElement geometry in geometries) { XElement meshElement = geometry.Element(XName.Get("mesh", Namespace)); //resgata os triangulos, se for uma versao anterior a 1.4.1 o nome é polygons XElement triangles = meshElement.Element(XName.Get("triangles", Namespace)); if (triangles == null) triangles = meshElement.Element(XName.Get("polygons", Namespace)); //se existe uma tag triangles entao ele vai pra frente if (triangles != null) { AMT_MESH mesh = new AMT_MESH(); mesh.Name = geometry.Attribute("name").Value; mesh.FaceIndices = new List<int>(); amtModel.Meshes.Add(mesh); //converte o mesh, pega todos os vertices, indices e faces e ja armazena no model amt ConvertMesh(meshElement, triangles, ref amtModel); //carrega o material //pega no visual scene o nome do material XElement libraryVisualScene = rootElement.Element(XName.Get("library_visual_scenes", Namespace)); XElement visualSceneElement = libraryVisualScene.Element(XName.Get("visual_scene", Namespace)); List<XElement> visualSceneNodes = visualSceneElement.Elements(XName.Get("node", Namespace)).ToList(); XElement geometryScene = visualSceneNodes.Find(item => { return item.Attribute("name").Value == mesh.Name; }); XElement instanceGeometry = geometryScene.Element(XName.Get("instance_geometry", Namespace)); //se existe a instancia geometry entao ele pega senao ele tem skin ai vai pelo controller XElement materialScene; if (instanceGeometry != null) { XElement bindMaterial = instanceGeometry.Element(XName.Get("bind_material", Namespace)); XElement techniqueCommon = bindMaterial.Element(XName.Get("technique_common", Namespace)); List<XElement> materialsScene = techniqueCommon.Elements(XName.Get("instance_material", Namespace)).ToList(); materialScene = materialsScene.Find(item => { return item.Attribute("symbol").Value == triangles.Attribute("material").Value; }); } else { XElement controller = geometryScene.Element(XName.Get("instance_controller", Namespace)); string skeletonName = controller.Element(XName.Get("skeleton", Namespace)).Value.Substring(1); if (skeletonName != null) amtModel.Head.HasSkeleton = 1; XElement bindMaterial = controller.Element(XName.Get("bind_material", Namespace)); XElement techniqueCommon = bindMaterial.Element(XName.Get("technique_common", Namespace)); List<XElement> materialsScene = techniqueCommon.Elements(XName.Get("instance_material", Namespace)).ToList(); materialScene = materialsScene.Find(item => { return item.Attribute("symbol").Value == triangles.Attribute("material").Value; }); } string materialID = materialScene.Attribute("target").Value.Substring(1); if (materialID != null) { //carrega a tag de materiais XElement libraryMaterials = rootElement.Element(XName.Get("library_materials", Namespace)); List<XElement> materials = libraryMaterials.Elements(XName.Get("material", Namespace)).ToList(); //carrega a tag de imagens XElement libraryImages = rootElement.Element(XName.Get("library_images", Namespace)); List<XElement> images = null; if (libraryImages != null) images = libraryImages.Elements(XName.Get("image", Namespace)).ToList(); //carrega os atributos do primeiro effect XElement libraryEffect = rootElement.Element(XName.Get("library_effects", Namespace)); List<XElement> effectElements = libraryEffect.Elements(XName.Get("effect", Namespace)).ToList(); XElement materialElement = materials.Find(item => { return item.Attribute("id").Value == materialID; }); if (materialElement != null) { AMT_MATERIAL material = ConvertMaterial(materialElement, effectElements, images); amtModel.Materials.Add(material); //seta o id do material q ta na estrutura principal mesh.MaterialID = (uint)amtModel.Materials.Count() - 1; } } } } } }
//deixa todos os modelos com tamanho 1 para serem redimensionados no editor public static void UniformScale(ref AMT_MODEL model) { List<Vector3> vertices = new List<Vector3>(); for (int i = 0; i < model.Vertices.Count; i++) vertices.Add(model.Vertices[i].Position); BoundingSphere sphere = BoundingSphere.CreateFromPoints(vertices); //redimensiona os vertices float scalefactor = 1.0f / sphere.Radius; //redimensiona tb todos os bones e os keyframes Matrix scale = Matrix.CreateScale(scalefactor); for (int i = 0; i < model.Vertices.Count; i++) { model.Vertices[i].Position = Vector3.Transform(model.Vertices[i].Position, scale); model.Vertices[i].Normal = Vector3.TransformNormal(model.Vertices[i].Normal, scale); } if (model.Joints != null) { for (int i = 0; i < model.Joints.Count; i++) { AMT_JOINT v = model.Joints[i]; //como ele mexeu na posicao entao mexe so no raiz if (v.Name == "Root") v.BindMatrix *= scale; if (model.Joints[i].ParentID != -1) v.MatrixAbsolute = model.Joints[i].BindMatrix * model.Joints[model.Joints[i].ParentID].MatrixAbsolute; else v.MatrixAbsolute = model.Joints[i].BindMatrix; v.InverseBindMatrix = Matrix.Invert(scale) * v.InverseBindMatrix; if (v.Name == "Root") { for (int j = 0; j < v.KFData.Count; j++) { AMT_KF p = v.KFData[j]; p.BindMatrix *= scale; v.KFData[j] = p; } } model.Joints[i] = v; } } }
public static void SetYUp(ref AMT_MODEL model, Vector3 upVector) { if (upVector == Vector3.UnitY) return; //aplica a rotacao Matrix rotation; if (upVector == Vector3.UnitX) rotation = Matrix.CreateRotationZ(-MathHelper.PiOver2); else rotation = Matrix.CreateRotationX(-MathHelper.PiOver2); List<Vector3> vertices = new List<Vector3>(); for (int i = 0; i < model.Vertices.Count; i++) { AMT_VERTEX v = model.Vertices[i]; Vector3.Transform(ref v.Position, ref rotation, out v.Position); Vector3.TransformNormal(ref v.Normal, ref rotation, out v.Normal); } if (model.Joints != null) { for (int i = 0; i < model.Joints.Count; i++) { AMT_JOINT v = model.Joints[i]; //como ele mexeu na posicao entao mexe so no raiz if (v.Name == "Root") v.BindMatrix *= rotation; if (model.Joints[i].ParentID != -1) v.MatrixAbsolute = model.Joints[i].BindMatrix * model.Joints[model.Joints[i].ParentID].MatrixAbsolute; else v.MatrixAbsolute = model.Joints[i].BindMatrix; v.InverseBindMatrix = Matrix.Invert(rotation) * v.InverseBindMatrix; //mexe so no raiz if (v.Name == "Root") { for (int j = 0; j < v.KFData.Count; j++) { AMT_KF p = v.KFData[j]; p.BindMatrix *= rotation; v.KFData[j] = p; } } model.Joints[i] = v; } } }
private void ConvertAnimations(XElement rootElement, ref AMT_MODEL amtModel) { XElement libraryAnimations = rootElement.Element(XName.Get("library_animations", Namespace)); if (libraryAnimations == null) return; List<XElement> animations = libraryAnimations.Elements(XName.Get("animation", Namespace)).ToList(); foreach (XElement animation in animations) { //pego os channels primeiro e percoro List<XElement> channels = animation.Elements(XName.Get("channel", Namespace)).ToList(); foreach (XElement channel in channels) { //pego o source do channel para achar o sampler e o terget string source = channel.Attribute("source").Value.Substring(1); string target = channel.Attribute("target").Value; List<XElement> samplers = animation.Elements(XName.Get("sampler", Namespace)).ToList(); XElement samplerElement = samplers.Find(item => { return item.Attribute("id").Value == source; }); //pego o nome do input source e tb do output source string inputSourceName = samplerElement.Elements(XName.Get("input", Namespace)) .ToList() .Find(item => { return item.Attribute("semantic").Value == "INPUT"; }).Attribute("source").Value.Substring(1); string outputSourceName = samplerElement.Elements(XName.Get("input", Namespace)) .ToList() .Find(item => { return item.Attribute("semantic").Value == "OUTPUT"; }).Attribute("source").Value.Substring(1); //pego os elementos inputsource e outputsource List<XElement> sourceElements = animation.Elements(XName.Get("source", Namespace)).ToList(); XElement inputSourceElement = sourceElements.Find(item => { return item.Attribute("id").Value == inputSourceName; }); XElement outputSourceElement = sourceElements.Find(item => { return item.Attribute("id").Value == outputSourceName; }); //agora vo atras do float_array do sourceinput e sourceoutput XElement faInput = inputSourceElement.Element(XName.Get("float_array", Namespace)); amtModel.Head.NumFrames = System.Convert.ToUInt32(faInput.Attribute("count").Value); string kfTimeValues = faInput.Value; string[] kfTimes = kfTimeValues.Replace('\n', ' ').Trim().Split(' '); uint numberOfMatrixFloats = amtModel.Head.NumFrames * 16; string kfTransformValues = outputSourceElement.Element(XName.Get("float_array", Namespace)).Value.Replace('\n', ' ').Trim(); Matrix[] keyFramesMatrizes = new Matrix[amtModel.Head.NumFrames]; for (int i = 0, j = 0; i < numberOfMatrixFloats; i += 16, j++) keyFramesMatrizes[j] = Tools.ConvertStringToMatrix(kfTransformValues, i); //agora q tenho a lista de tempos e matrizes eu procuro qual o bone do momento e crio um kf foreach (var joint in amtModel.Joints) { if (joint.TARGET == target) { joint.NumKF = (uint)kfTimes.Length; for (int i = 0; i < joint.NumKF; i++) { joint.KFData.Add(new AMT_KF() { Time = System.Convert.ToSingle(kfTimes[i], CultureInfo.InvariantCulture), BindMatrix = keyFramesMatrizes[i] }); } } } } } }
private void Optimize(ref AMT_MODEL amtModel) { List<AMT_VERTEX> vertices = new List<AMT_VERTEX>(); vertices.AddRange(amtModel.Vertices); amtModel.Vertices.Clear(); //grava os vertices agora na ordem certa triangulados int currentVertices = (int)amtModel.Head.NumVertices; // optimazacao dor vertices for (int i = 0; i < amtModel.Head.NumVertices; i++) { _import.ProgressText = "Importing Faces, recompute vertices " + i.ToString() + "/" + amtModel.Head.NumVertices.ToString(); // se o flag for 42 ele vai para o proximo if (vertices[i].Flag == 42) continue; for (int j = 0; j < amtModel.Head.NumVertices; j++) if ((i != j) && vertices[i] == vertices[j]) { //desliga o vertice pq esta duplicado AMT_VERTEX v = vertices[j]; v.Flag = 42; vertices[j] = v; currentVertices--; } } // Copia os vertices para o array da estrutura for (int i = 0; i < amtModel.Head.NumVertices; i++) { // todos q nao sao 42 if (vertices[i].Flag != 42) amtModel.Vertices.Add(vertices[i]); } //percorre o array de indices para procurar os vertices q estao na mesma posicao, se estiverem entao ele deixa os indices iguais for (ulong i = 0; i < amtModel.Head.NumFaces; i++) { _import.ProgressText = "Importing Faces, recompute indices " + i.ToString() + "/" + amtModel.Head.NumFaces.ToString(); AMT_FACE f = amtModel.Faces[(int)i]; for (int n = 0; n < 3; n++) { for (int j = 0; j < (int)currentVertices; j++) { if (AMT_VERTEX.EqualsWithoutFlagTest(vertices[f.Indices[n]], amtModel.Vertices[j])) { f.Indices[n] = j; } } } amtModel.Faces[(int)i] = f; } //calcula as normais das faces for (ulong i = 0; i < amtModel.Head.NumFaces; i++) { _import.ProgressText = "Importing Faces, recompute normals " + i.ToString() + "/" + amtModel.Head.NumFaces.ToString(); Vector3 v1 = amtModel.Vertices[amtModel.Faces[(int)i].Indices[0]].Position; Vector3 v2 = amtModel.Vertices[amtModel.Faces[(int)i].Indices[1]].Position; Vector3 v3 = amtModel.Vertices[amtModel.Faces[(int)i].Indices[2]].Position; AMT_FACE face = amtModel.Faces[(int)i]; face.Normal = Tools.GetNormal(v1, v2, v3); amtModel.Faces[(int)i] = face; } amtModel.Head.NumVertices = (uint)currentVertices; }
private void WriteMeshes(BinaryWriter bw, AMT_MODEL model) { List<AMT_MESH> meshes = model.Meshes; for (int i = 0; i < meshes.Count; i++) { char[] name = Tools.GetCharArray(meshes[i].Name, 64); bw.Write(name); _import.ProgressText = "Exporting Mesh " + meshes[i].Name; bw.Write(meshes[i].NumFaces); for (int j = 0; j < meshes[i].FaceIndices.Count; j++) bw.Write(meshes[i].FaceIndices[j]); bw.Write(meshes[i].MaterialID); bw.Write(meshes[i].Flag); } }
private void FillBoneNodes(ref AMT_JOINT parentBone, XElement boneNode, ref AMT_MODEL amtModel) { //pego todos os nodes List<XElement> nodes = boneNode.Elements(XName.Get("node", Namespace)).ToList(); foreach (var node in nodes) { //se é um bone if (node.Attribute("type") != null && node.Attribute("type").Value.Contains("JOINT")) { Matrix matrix = Matrix.Identity; //pega o nome e a matrix do bone string boneName = node.Attribute("name").Value; string boneId = node.Attribute("id").Value; string sid = node.Attribute("sid").Value; XElement matrixElement = node.Element(XName.Get("matrix", Namespace)); string matrixSID = null; if (matrixElement.Attribute("sid") != null) matrixSID = matrixElement.Attribute("sid").Value; //uso nas animacoes para achar o bone id/sid matrix = Tools.ConvertStringToMatrix(matrixElement.Value, 0); // Create this node, use the current number of bones as number. AMT_JOINT newBone = new AMT_JOINT(); newBone.SID = sid; newBone.TARGET = boneId + "/" + matrixSID; newBone.ID = (uint)amtModel.Joints.Count(); newBone.ParentID = (int)parentBone.ID; newBone.Name = boneName; newBone.NumChildren = 0; newBone.JointChildren = new List<uint>(); newBone.NumKF = 0; newBone.KFData = new List<AMT_KF>(); newBone.IsAnimated = (uint)(string.IsNullOrEmpty(matrixSID) ? 0 : 1); newBone.Flag = 0; //atualiza o bone pai parentBone.NumChildren++; parentBone.JointChildren.Add(newBone.ID); //matrix relativa newBone.BindMatrix = matrix; //absoluta = relativa do atual * absoluta do pai newBone.MatrixAbsolute = matrix * parentBone.MatrixAbsolute; //inversa da matriz relativa newBone.InverseBindMatrix = Matrix.Invert(newBone.MatrixAbsolute); amtModel.Joints.Add(newBone); // vai para os filhos FillBoneNodes(ref newBone, node, ref amtModel); } } }
private void WriteMaterials(BinaryWriter bw, AMT_MODEL model) { List<AMT_MATERIAL> materials = model.Materials; for (int i = 0; i < materials.Count; i++) { char[] name = Tools.GetCharArray(materials[i].Name, 64); bw.Write(name); _import.ProgressText = "Exporting Materials " + materials[i].Name; WriteVector(bw, materials[i].Ambient); WriteVector(bw, materials[i].Diffuse); WriteVector(bw, materials[i].Specular); WriteVector(bw, materials[i].Emissive); bw.Write(materials[i].SpecularPower); bw.Write(materials[i].Transparency); char[] diffuseTexture = Tools.GetCharArray(materials[i].DiffuseTexture, 64); bw.Write(diffuseTexture); char[] specularTexture = Tools.GetCharArray(materials[i].SpecularTexture, 64); bw.Write(specularTexture); char[] normalTexture = Tools.GetCharArray(materials[i].NormalTexture, 64); bw.Write(normalTexture); char[] animatedTexture = Tools.GetCharArray(materials[i].AnimatedTexture, 64); bw.Write(animatedTexture); bw.Write(materials[i].Flag); } }