static void AddTextureIfExists(bool Exists, ref FoamMaterial FoamMat, TextureSlot Texture, FoamTextureType TexType) { if (Exists) { FoamMat.AddTexture(new FoamTexture(Texture.FilePath, TexType)); } }
static void ApplyEmissive(Vector4[] Pixels, int W, int H, List <FoamVertex3> ModelVerts, List <FoamMesh> Meshes, FoamModel Model) { Vector4 ClrR = new Vector4(1, 0, 0, 1); Vector4 ClrG = new Vector4(0, 1, 0, 1); Vector4 ClrB = new Vector4(0, 0, 1, 1); Vector4 ClrW = new Vector4(1, 1, 1, 1); Vector2 Size = new Vector2(W, H); for (int i = 0; i < ModelVerts.Count; i += 3) { FoamMaterial Mat = Model.Materials[Meshes[i].MaterialIndex]; // TODO: Move somewhere else switch (Mat.MaterialName) { case "base/emissive_red": DrawTriangle(Pixels, W, H, ClrR, ModelVerts[i + 0].UV2 * Size, ModelVerts[i + 1].UV2 * Size, ModelVerts[i + 2].UV2 * Size); break; case "base/emissive_green": DrawTriangle(Pixels, W, H, ClrG, ModelVerts[i + 0].UV2 * Size, ModelVerts[i + 1].UV2 * Size, ModelVerts[i + 2].UV2 * Size); break; case "base/emissive_blue": DrawTriangle(Pixels, W, H, ClrB, ModelVerts[i + 0].UV2 * Size, ModelVerts[i + 1].UV2 * Size, ModelVerts[i + 2].UV2 * Size); break; //case "base/emissive_sky": case "base/emissive_white": DrawTriangle(Pixels, W, H, ClrW, ModelVerts[i + 0].UV2 * Size, ModelVerts[i + 1].UV2 * Size, ModelVerts[i + 2].UV2 * Size); break; default: break; } } }
public static FoamModel Load(string ObjFile, string MtlFile) { FoamMaterial[] Materials = new FoamMaterial[] { new FoamMaterial("default") }; ref FoamMaterial CurMat = ref Materials[0];
static FoamModel Load(string FileName, int MD3Frame = 0) { string Ext = Path.GetExtension(FileName).ToLower(); using (AssimpContext Importer = new AssimpContext()) { Importer.SetConfig(new MD3HandleMultiPartConfig(false)); //Importer.SetConfig(new MD5NoAnimationAutoLoadConfig(true)); Importer.SetConfig(new VertexBoneWeightLimitConfig(4)); Importer.SetConfig(new MD3KeyFrameImportConfig(MD3Frame)); PostProcessSteps ProcessSteps = PostProcessSteps.Triangulate; ProcessSteps |= PostProcessSteps.SplitLargeMeshes; ProcessSteps |= PostProcessSteps.OptimizeMeshes; ProcessSteps |= PostProcessSteps.LimitBoneWeights; ProcessSteps |= PostProcessSteps.JoinIdenticalVertices; ProcessSteps |= PostProcessSteps.ImproveCacheLocality; ProcessSteps |= PostProcessSteps.GenerateNormals; ProcessSteps |= PostProcessSteps.GenerateUVCoords; //if (Ext != ".md3") ProcessSteps |= PostProcessPreset.ConvertToLeftHanded; Scene Sc = Importer.ImportFile(FileName, ProcessSteps); List <FoamMaterial> MaterialList = new List <FoamMaterial>(); foreach (var Mat in Sc.Materials) { FoamMaterial FoamMat = new FoamMaterial(Mat.Name); AddTextureIfExists(Mat.HasTextureDiffuse, ref FoamMat, Mat.TextureDiffuse, FoamTextureType.Diffuse); AddTextureIfExists(Mat.HasTextureEmissive, ref FoamMat, Mat.TextureEmissive, FoamTextureType.Glow); AddTextureIfExists(Mat.HasTextureNormal, ref FoamMat, Mat.TextureNormal, FoamTextureType.Normal); AddTextureIfExists(Mat.HasTextureSpecular, ref FoamMat, Mat.TextureSpecular, FoamTextureType.Specular); AddTextureIfExists(Mat.HasTextureReflection, ref FoamMat, Mat.TextureReflection, FoamTextureType.Reflection); AddTextureIfExists(Mat.HasTextureHeight, ref FoamMat, Mat.TextureHeight, FoamTextureType.Height); AddTextureIfExists(Mat.HasTextureLightMap, ref FoamMat, Mat.TextureLightMap, FoamTextureType.LightMap); AddTextureIfExists(Mat.HasTextureDisplacement, ref FoamMat, Mat.TextureDisplacement, FoamTextureType.Displacement); AddTextureIfExists(Mat.HasTextureAmbient, ref FoamMat, Mat.TextureAmbient, FoamTextureType.Ambient); AddTextureIfExists(Mat.HasTextureOpacity, ref FoamMat, Mat.TextureOpacity, FoamTextureType.Opacity); MaterialList.Add(FoamMat); } FoamBone[] Bones = new FoamBone[0]; List <FoamMesh> MeshList = new List <FoamMesh>(); foreach (var Msh in Sc.Meshes) { Vector3D[] Verts = Msh.Vertices.ToArray(); Vector3D[] UVs1 = Msh.TextureCoordinateChannels[0].ToArray(); Vector3D[] UVs2 = Msh.TextureCoordinateChannels[1].ToArray(); Vector3D[] Normals = Msh.Normals.ToArray(); Vector3D[] Tangents = Msh.Tangents.ToArray(); Color4D[] Colors = Msh.VertexColorChannels[0].ToArray(); string MeshName = Msh.Name; int MaterialIndex = Msh.MaterialIndex; FoamVertex3[] FoamVertices = new FoamVertex3[Verts.Length]; for (int i = 0; i < FoamVertices.Length; i++) { Vector2 UV1 = UVs1.Length != 0 ? new Vector2(UVs1[i].X, UVs1[i].Y) : Vector2.Zero; Vector2 UV2 = UVs2.Length != 0 ? new Vector2(UVs2[i].X, UVs2[i].Y) : Vector2.Zero; Vector3 Normal = Normals.Length != 0 ? new Vector3(Normals[i].X, Normals[i].Y, Normals[i].Z) : Vector3.Zero; Vector3 Tangent = Tangents.Length != 0 ? new Vector3(Tangents[i].X, Tangents[i].Y, Tangents[i].Z) : Vector3.Zero; FoamColor Color = Colors.Length != 0 ? new FoamColor(Colors[i].R, Colors[i].G, Colors[i].B, Colors[i].A) : FoamColor.White; FoamVertex3 V = new FoamVertex3(new Vector3(Verts[i].X, Verts[i].Y, Verts[i].Z), UV1, UV2, Normal, Tangent, Color); FoamVertices[i] = V; } bool CalculateTangents = Tangents.Length == 0 && UVs1.Length != 0; //bool CalculateNormals = Normals.Length == 0; List <ushort> FoamIndices = new List <ushort>(); foreach (var F in Msh.Faces) { ushort IndexA = (ushort)F.Indices[0]; ushort IndexB = (ushort)F.Indices[1]; ushort IndexC = (ushort)F.Indices[2]; if (CalculateTangents) { FoamVertex3 V0 = FoamVertices[IndexA]; FoamVertex3 V1 = FoamVertices[IndexB]; FoamVertex3 V2 = FoamVertices[IndexC]; Vector3 DeltaPos1 = V1.Position - V0.Position; Vector3 DeltaPos2 = V2.Position - V0.Position; //if (CalculateTangents) { Vector2 DeltaUV1 = V1.UV - V0.UV; Vector2 DeltaUV2 = V2.UV - V0.UV; Vector3 Tangent = (DeltaPos1 * DeltaUV2.Y - DeltaPos2 * DeltaUV1.Y) * (1.0f / (DeltaUV1.X * DeltaUV2.Y - DeltaUV1.Y * DeltaUV2.X)); FoamVertices[IndexA].Tangent = FoamVertices[IndexB].Tangent = FoamVertices[IndexC].Tangent = Tangent; /*} * * if (CalculateNormals) * FoamVertices[IndexA].Normal = FoamVertices[IndexB].Normal = FoamVertices[IndexC].Normal = Vector3.Normalize(Vector3.Cross(DeltaPos1, DeltaPos2));*/ } FoamIndices.AddRange(F.Indices.Select(I => (ushort)I)); } FoamBoneInfo[] BoneInfo = null; if (Msh.BoneCount != 0) { BoneInfo = new FoamBoneInfo[FoamVertices.Length]; Bone[] OrigBones = Msh.Bones.ToArray(); // Convert bones for (int i = 0; i < OrigBones.Length; i++) { if (!ContainsBoneNamed(Bones, OrigBones[i].Name)) { Utils.Append(ref Bones, new FoamBone(OrigBones[i].Name, -1, ConvertMatrix(OrigBones[i].OffsetMatrix))); } } // Convert vertex bone information for (int i = 0; i < FoamVertices.Length; i++) { BoneInfo[i] = FindWeightsFor(OrigBones, Bones, i); } } MeshList.Add(new FoamMesh(FoamVertices, FoamIndices?.ToArray() ?? null, BoneInfo, MeshName, MaterialIndex)); } if (Bones.Length > 0) { Node[] NodeHierarchy = Flatten(Sc.RootNode); //Node SceneRootNode = Sc.RootNode; Node RootNode = FindRoot(FindNode(NodeHierarchy, Bones[0].Name), Bones); Utils.Prepend(ref Bones, new FoamBone(RootNode.Name, -1, ConvertMatrix(RootNode.Transform))); /*Node RootNodeTest = RootNode; * while (RootNodeTest.Parent != null) { * Bones[0].BindMatrix = Bones[0].BindMatrix * ConvertMatrix(RootNodeTest.Transform); * RootNodeTest = RootNodeTest.Parent; * }*/ /*while (RootNode.Parent != null) { * Utils.Prepend(ref Bones, new FoamBone(RootNode.Name, -1, NumMatrix4x4.Identity)); * RootNode = RootNode.Parent; * }*/ for (int i = 0; i < Bones.Length; i++) { Node BoneNode = FindNode(NodeHierarchy, Bones[i].Name); int BoneParentIndex = FindBoneIndex(Bones, BoneNode.Parent.Name); if (BoneNode != RootNode) { if (BoneParentIndex == -1) { throw new Exception("Could not find a bone"); } } Bones[i].ParentBoneIndex = BoneParentIndex; } } else { Bones = null; } // Animations FoamAnimation[] Animations = null; foreach (var Anim in Sc.Animations) { string[] BoneNames = Anim.NodeAnimationChannels.Select(C => C.NodeName).ToArray(); int FrameCount = Anim.NodeAnimationChannels[0].PositionKeyCount; FoamAnimationFrame[] Frames = new FoamAnimationFrame[FrameCount]; for (int i = 0; i < FrameCount; i++) { Frames[i] = ReadFrame(Anim.NodeAnimationChannels, BoneNames, i); } FoamAnimation Animation = new FoamAnimation(Anim.Name, Frames, BoneNames, (float)Anim.DurationInTicks, (float)Anim.TicksPerSecond); Utils.Append(ref Animations, Animation); } return(new FoamModel(Path.GetFileNameWithoutExtension(FileName), FoamFlags.Model, MeshList.ToArray(), Bones, Animations, MaterialList.ToArray())); } }
static void Run() { string ObjInput = ArgumentParser.GetSingle("obj"); string MtlInput = ArgumentParser.GetSingle("mtl"); string MapOutput = ArgumentParser.GetSingle("out"); bool EmbedTextures = ArgumentParser.Defined("e"); bool ComputeLights = !ArgumentParser.Defined("l"); string ObjName = "test"; if (ObjInput == null) { ObjInput = "sample/" + ObjName + ".obj"; MtlInput = "sample/" + ObjName + ".mtl"; MapOutput = "sample/" + ObjName + ".mapfoam"; } if (!File.Exists(ObjInput)) { throw new Exception("Obj input file not found"); } if (!File.Exists(MtlInput)) { throw new Exception("Mtl input file not found"); } string OutDir = Path.GetDirectoryName(Path.GetFullPath(MapOutput)); Console.WriteLine("obj = '{0}'", ObjInput); Console.WriteLine("mtl = '{0}'", MtlInput); Console.WriteLine("out = '{0}'", MapOutput); Console.WriteLine("Embed textures? {0}", EmbedTextures); Console.WriteLine("Compute lights? {0}", ComputeLights); FoamModel LevelModel = ObjLoader.Load(ObjInput, MtlInput); MeshAtlasMap AtlasMap; LevelModel.CalcBounds(out Vector3 Min, out Vector3 Max); Console.WriteLine("Level min = {0}; max = {1}", Min, Max); // Generate atlas { Console.WriteLine("Generating lightmap"); GenAtlas(OutDir, LevelModel, out AtlasMap); } if (ComputeLights) { Light[] Lights = new Light[] { new Light(new Vector3(-32, 104, 368), new Vector3(1, 0, 0), 10000), new Light(new Vector3(-80, 104, 704), new Vector3(0, 1, 0), 10000), new Light(new Vector3(0, 312, 304), new Vector3(0, 0, 1), 20000) }; //LightMapping.Compute(LevelModel, AtlasMap, Lights); //Vector4[] Pixels = new Vector4[1024 * 1024]; //RayLightmapper.raylight_render_scene(1024, 1024, 512, new Vector3(1, 1, 1), 0, null, 0, null, null, null, ref Pixels); { string TexName = "lightmap.png"; FoamMaterial LightmapMat = new FoamMaterial(Path.GetFileNameWithoutExtension(TexName), new[] { new FoamTexture(TexName, FoamTextureType.LightMap) }); Utils.Append(ref LevelModel.Materials, LightmapMat); foreach (var M in LevelModel.Meshes) { M.MaterialIndex = LevelModel.Materials.Length - 1; } //AtlasMap.Atlas.Resize(4); AtlasMap.Atlas.FlipY(); AtlasMap.Atlas.Save(Path.Combine(OutDir, TexName)); Utils.Append(ref LevelModel.Extensions, FoamExtension.CreateEmbeddedPng(TexName, AtlasMap.Atlas.GetImage())); } } //ObjLoader.Save(LevelModel, "sample/EXPORTED.obj"); LevelModel.SaveToFile(MapOutput); //Console.WriteLine("Done!"); //Console.ReadLine(); }