public void RefreshVertexList() { //Vertex 리스트가 Mesh의 Vert 리스트와 동기화가 되었는지 확인한다. //동기화되지 않았다면 ID, 순서를 모두 다시 맞춰준다. bool isVertChanged = false; if (_meshTransform_ID < 0) { _weightedVerts.Clear(); return; } if (_meshTransform == null || _meshTransform._mesh == null) { return; } List <apVertex> srcVerts = _meshTransform._mesh._vertexData; int nVerts = srcVerts.Count; if (srcVerts.Count != _weightedVerts.Count) { isVertChanged = true; } else { for (int i = 0; i < nVerts; i++) { if (srcVerts[i]._uniqueID != _weightedVerts[i]._uniqueID) { isVertChanged = true; break; } } } if (isVertChanged) { List <WeightedVertex> nextVerts = new List <WeightedVertex>(); //Vertex가 동기화되지 않았다. //기존에 있는 값은 그대로 쓰고, 없는건 새로 만들자 for (int i = 0; i < nVerts; i++) { int curUniqueID = srcVerts[i]._uniqueID; WeightedVertex existVert = GetWeightedVert(curUniqueID); if (existVert != null) { existVert._vertIndex = i; //<<인덱스는 바꾸고.. nextVerts.Add(existVert); } else { nextVerts.Add(new WeightedVertex(curUniqueID, i)); } } _weightedVerts.Clear(); for (int i = 0; i < nVerts; i++) { _weightedVerts.Add(nextVerts[i]); } } }
public override IntermediateModel Process(IntermediateModelDef input, ContentProcessorContext context) { Scale = Scale == 0.0f ? 1.0f : Scale; model = new IntermediateModel(); String prefix = context.OutputDirectory; String wholeName = context.OutputFilename; String partialName = wholeName.Substring(prefix.Length); String modelName = partialName.Replace("\\\\", "\\"); modelName = modelName.Replace(".xnb", "").Replace(".XNB", ""); // Get the custom data associated with the model model.CustomData = ProcessCustomData(context); var scaleCustomData = model.CustomData["Scale"]; if (scaleCustomData != null) { Scale = Convert.ToSingle(scaleCustomData.Value); } List <IntermediateModelMesh> imms = new List <IntermediateModelMesh>(); for (int i = 0; i < input.ModelMeshes.Count; ++i) { var modelMesh = input.ModelMeshes[i]; IntermediateModelMesh imm = new IntermediateModelMesh(); ModelMeshVertex[] vertices = new ModelMeshVertex[modelMesh.Vertices.Length]; WeightedVertex[] origVertices = new WeightedVertex[modelMesh.Vertices.Length]; //DebugNow(); for (int j = 0; j < modelMesh.Vertices.Length; ++j) { if (input.HasSkinningData) { var intermediateWeightedVertex = input.WeightedVertices[modelMesh.Vertices[j].WeightedVertexIndex]; vertices[j].Position = Vector3.Transform(intermediateWeightedVertex.Position.ToVector3(), Matrix.CreateScale(Scale)); origVertices[j].Weight0 = new Core.Graphics.Primitives.BoneWeight(); origVertices[j].Weight0.BoneIndex = intermediateWeightedVertex.JointWeights[0].JointIndex; origVertices[j].Weight0.Weight = intermediateWeightedVertex.JointWeights[0].Weight; origVertices[j].Weight1 = new Core.Graphics.Primitives.BoneWeight(); origVertices[j].Weight1.BoneIndex = intermediateWeightedVertex.JointWeights[1].JointIndex; origVertices[j].Weight1.Weight = intermediateWeightedVertex.JointWeights[1].Weight; origVertices[j].Weight2 = new Core.Graphics.Primitives.BoneWeight(); origVertices[j].Weight2.BoneIndex = intermediateWeightedVertex.JointWeights[2].JointIndex; origVertices[j].Weight2.Weight = intermediateWeightedVertex.JointWeights[2].Weight; origVertices[j].Weight3 = new Core.Graphics.Primitives.BoneWeight(); origVertices[j].Weight3.BoneIndex = intermediateWeightedVertex.JointWeights[3].JointIndex; origVertices[j].Weight3.Weight = intermediateWeightedVertex.JointWeights[3].Weight; } else { vertices[j].Position = Vector3.Transform(modelMesh.Vertices[j].Position.ToVector3(), Matrix.CreateScale(Scale)); } vertices[j].Normal = Vector3.TransformNormal(modelMesh.Vertices[j].Normal.ToVector3(), Matrix.CreateScale(Scale)); vertices[j].TextureCoordinate0 = modelMesh.Vertices[j].TextureCoordinate0.ToVector2(); vertices[j].Tangent = modelMesh.Vertices[j].Tangent.ToVector3(); vertices[j].Binormal = modelMesh.Vertices[j].Binormal.ToVector3(); } OpaqueDataDictionary settings = new OpaqueDataDictionary(); settings["GenerateMipmaps"] = true; IntermediateMaterial im = new IntermediateMaterial(); im.Name = modelMesh.Material.Name; im.DiffuseColor = modelMesh.Material.DiffuseColor.ToVector3(); im.SpecularColor = modelMesh.Material.SpecularColor.ToVector3(); im.SpecularExp = modelMesh.Material.CosinePower.AsSingle(); im.Transparency = modelMesh.Material.Transparency.AsSingle(); im.UseAlpha = modelMesh.Material.UseAlpha.AsBoolean(); im.DrawBackfaces = modelMesh.Material.DrawBackfaces.AsBoolean(); im.Reflectivity = modelMesh.Material.Reflectivity.AsSingle(); //DebugNow(); im.DiffuseMapName = modelMesh.Material.DiffuseMapFilename.AsString(); if (!String.IsNullOrEmpty(im.DiffuseMapName)) { //im.DiffuseMapReference = context.BuildAsset<TextureContent, TextureContent>( // new ExternalReference<TextureContent>( // Path.Combine(Path.GetDirectoryName(input.Path), im.DiffuseMapName)), "TextureProcessor", settings, null, null); } im.NormalMapName = modelMesh.Material.NormalMapFilename.AsString(); if (!String.IsNullOrEmpty(im.NormalMapName)) { //im.BumpMapReference = context.BuildAsset<TextureContent, TextureContent>( // new ExternalReference<TextureContent>( // Path.Combine(Path.GetDirectoryName(input.Path), im.BumpMapName)), "TextureProcessor", settings, null, null); } im.SpecularMapName = modelMesh.Material.SpecularMapFilename.AsString(); if (!String.IsNullOrEmpty(im.SpecularMapName)) { //im.SpecularMapReference = context.BuildAsset<TextureContent, TextureContent>( // new ExternalReference<TextureContent>( // Path.Combine(Path.GetDirectoryName(input.Path), im.SpecularMapName)), "TextureProcessor", settings, null, null); } imm.Indices = modelMesh.Indices.ToInt32Array(); for (int k = 0; k <= imm.Indices.Length - 3; k += 3) { var temp = imm.Indices[k]; imm.Indices[k] = imm.Indices[k + 2]; imm.Indices[k + 2] = temp; } imm.Vertices = vertices; imm.OriginalVertices = origVertices; imm.BoundingSphere = BoundingSphere.CreateFromPoints(vertices.Select(v => v.Position)); imm.BoundingBox = BoundingBox.CreateFromPoints(vertices.Select(v => v.Position)); imm.Material = im; imms.Add(imm); } // Animation stuff List <Matrix> bindPose = new List <Matrix>(); List <Matrix> inverseBindPose = new List <Matrix>(); List <int> skeletonHierarchy = new List <int>(); IDictionary <string, int> boneMap = new Dictionary <string, int>(); IList <String> boneNames = new List <String>(input.BindPose.Count); for (int i = 0; i < input.BindPose.Count; boneNames.Add(String.Empty), ++i) { ; } //DebugNow(); foreach (var joint in input.BindPose) { Matrix transform = Matrix.CreateFromQuaternion(joint.Rotation.ToQuaternion()) * joint.Position.ToTranslationMatrix(); transform.Translation *= Scale; Matrix absoluteTransform = Matrix.CreateFromQuaternion(joint.AbsoluteRotation.ToQuaternion()) * joint.AbsolutePosition.ToTranslationMatrix(); absoluteTransform.Translation *= Scale; bindPose.Add(transform); inverseBindPose.Add(Matrix.Invert(absoluteTransform)); skeletonHierarchy.Add(joint.ParentIndex); boneNames[joint.Index] = joint.Name; boneMap.Add(joint.Name, joint.Index); } var animationClips = ProcessAnimations(input.AnimationKeyframes, input.BindPose, boneNames); var skinningData = new SkinningData(bindPose, inverseBindPose, skeletonHierarchy, boneMap, boneNames, modelName); var animations = PrepareAnimations(animationClips, skinningData, context); model.ModelMeshes = imms.ToArray(); model.AnimationMap = animations; model.SkinningData = skinningData; model.BoundingSphere = BoundingSphere.CreateFromPoints(imms.SelectMany(m => m.Vertices.Select(v => v.Position))); model.BoundingBox = BoundingBox.CreateFromPoints(imms.SelectMany(m => m.Vertices.Select(v => v.Position))); return(model); }
public void CopyFrom(WeightedVertex vertex) { Weight = vertex.Weight; VertexIndex = vertex.VertexIndex; }
/// <summary> /// Imports an FBX file. /// </summary> /// <param name="stream">The FBX stream.</param> /// <param name="settings">An import settings object.</param> /// <param name="format">The filetype of the mesh.</param> /// <param name="filePath">The path to the file.</param> /// <returns>An <see cref="ImportResult" /> object.</returns> public static ImportResult Import(Stream stream, ImportSettings settings, string format, string filePath) { var sceneName = Path.GetFileNameWithoutExtension(filePath); Debug.Assert(sceneName != null, "sceneName != null"); var steps = PostProcessSteps.ValidateDataStructure | PostProcessSteps.GenerateUVCoords | PostProcessSteps.Triangulate | PostProcessSteps.SortByPrimitiveType | PostProcessSteps.FlipUVs | PostProcessSteps.FlipWindingOrder | PostProcessSteps.LimitBoneWeights | PostProcessSteps.ImproveCacheLocality | PostProcessSteps.RemoveComponent | PostProcessSteps.RemoveRedundantMaterials; if (!settings.KeepOverlappingVertices) { steps |= PostProcessSteps.JoinIdenticalVertices; } if (!settings.ImportAsSkeletal) { steps |= PostProcessSteps.Debone; } if (settings.MergeMeshes) { steps |= PostProcessSteps.OptimizeMeshes; } switch (settings.NormalImportMethod) { case NormalImportMethod.ComputeNormals: steps |= PostProcessSteps.GenerateNormals; steps |= PostProcessSteps.CalculateTangentSpace; break; case NormalImportMethod.ComputeNormalsSmooth: steps |= PostProcessSteps.GenerateSmoothNormals; steps |= PostProcessSteps.CalculateTangentSpace; break; case NormalImportMethod.ImportNormals: steps |= PostProcessSteps.CalculateTangentSpace; break; case NormalImportMethod.ImportNormalsAndTangents: break; default: throw new ArgumentOutOfRangeException(); } var scene = ContentProvider.AssimpContext.ImportFileFromStream(stream, steps, format); Skeleton skeleton = null; var importedSkeleton = false; var importedAnimation = false; var importedMesh = false; var importedMaterials = false; var geometries = new Dictionary <string, Geometry>(scene.MeshCount); var animations = new AnimationData[scene.AnimationCount]; var materials = new Material[scene.MaterialCount]; var textures = new Data.Texture[scene.TextureCount]; if (settings.ImportAsSkeletal) { if (settings.Skeleton == null) { SkeletonNodeData nodeData; if (!FindSkeleton(ref scene, out nodeData)) { throw new InvalidOperationException("Could not import skeleton."); } skeleton = ImportSkeleton(ref nodeData); importedSkeleton = true; } else { skeleton = settings.Skeleton; } } if (scene.HasMaterials) { importedMaterials = true; if (filePath != null) { var fileFolder = Path.GetDirectoryName(filePath); for (var i = 0; i < scene.MaterialCount; i++) { var mat = scene.Materials[i]; var material = new Material(); materials[i] = material; } } } for (var i = 0; i < scene.MeshCount; i++) { var mesh = scene.Meshes[i]; var meshName = string.IsNullOrWhiteSpace(mesh.Name) ? $"{sceneName} ({i})" : mesh.Name; var vertices = new Vertex[mesh.VertexCount]; WeightedVertex[] weights = null; if (mesh.HasBones && settings.ImportAsSkeletal) { weights = new WeightedVertex[mesh.VertexCount]; } for (var j = 0; j < mesh.VertexCount; j++) { var texCoordChannel = mesh.HasTextureCoords(0) ? mesh.TextureCoordinateChannels[0][j] : new Vector3D(0, 0, 0); var vertexColourChannel = mesh.HasVertexColors(0) ? mesh.VertexColorChannels[0][j] : new Color4D(0, 0, 0, 1); var tangent = mesh.HasTangentBasis ? mesh.Tangents[j] : new Vector3D(0, 0, 0); var bitangent = mesh.HasTangentBasis ? mesh.Tangents[j] : new Vector3D(0, 0, 0); vertices[j] = new Vertex { Position = (Vector3)mesh.Vertices[j], Normal = (Vector3)mesh.Normals[j], Colour = vertexColourChannel, TexCoord = new Vector2(texCoordChannel.X, texCoordChannel.Y), Tangent = (Vector3)tangent, BiTangent = (Vector3)bitangent }; // TODO: add bone data } importedMesh = true; geometries[mesh.Name] = new Geometry(meshName, vertices.ToArray(), mesh.GetIndices(), weights?.ToArray(), PrimitiveTopology.TriangleList) { MaterialIndex = mesh.MaterialIndex }; } if (settings.MergeMeshes && !settings.ImportAsSkeletal) { var vertices = new Vertex[0]; var weights = new WeightedVertex[0]; var indices = new int[0]; foreach (var mesh in geometries.Values) { var lastVertices = vertices; vertices = new Vertex[lastVertices.Length + mesh.Vertices.Length]; lastVertices.CopyTo(vertices, 0); mesh.Vertices.CopyTo(vertices, lastVertices.Length); var lastWeights = weights; weights = new WeightedVertex[lastWeights.Length + (mesh.Weights?.Length ?? 0)]; lastWeights.CopyTo(weights, 0); mesh.Weights?.CopyTo(weights, lastWeights.Length); var lastIndices = indices; indices = new int[indices.Length + mesh.Indices.Length]; lastIndices.CopyTo(indices, 0); mesh.Indices.Select(i => i + lastVertices.Length).ToArray().CopyTo(indices, lastIndices.Length); mesh.Dispose(); } geometries.Clear(); geometries[sceneName] = new Geometry(sceneName, vertices, indices, weights); } for (var i = 0; i < scene.AnimationCount; i++) { var animation = scene.Animations[i]; animations[i] = new AnimationData(); importedAnimation = true; // TODO: import animations } string path; if (settings.ContentPath == null) { path = Path.Combine(Engine.TempPath, Guid.NewGuid().ToString("N")); Directory.CreateDirectory(path); } else { path = settings.ContentPath; } #region File Creation foreach (var material in materials) { var materialPath = Path.Combine(path, $"{material.Name}.material"); if (materialPath == null) { continue; } using (var file = File.Create(materialPath)) { Inst.Serialize(material, file); } } foreach (var geo in geometries.Values) { var meshPath = GetFilePath(sceneName, path, settings); if (meshPath == null) { continue; } using (var file = File.Create(meshPath)) { geo.Material = materials[geo.MaterialIndex]; geo.Save(file); } } if (importedSkeleton) { var skeletonPath = GetFilePath(sceneName, path, settings); if (skeletonPath != null) { using (var file = File.Create(skeletonPath)) { Inst.Serialize(skeleton, file); } } } foreach (var animation in animations) { var animPath = GetFilePath(sceneName, path, settings); if (animPath == null) { continue; } using (var file = File.Create(animPath)) { animation.Save(file); } } #endregion if (settings.ContentPath != null) { foreach (var file in Directory.GetFiles(path)) { File.Move(file, Path.Combine(settings.ContentPath, Path.GetFileName(file))); } } return(new ImportResult(geometries, animations, materials, skeleton, importedSkeleton, importedAnimation, importedMesh, importedMaterials)); }