コード例 #1
0
        FoamMesh LoadMesh(BinaryReader Reader, DPMMesh Msh)
        {
            FoamVertex3[]  Verts = new FoamVertex3[Msh.num_verts];
            FoamBoneInfo[] Info  = new FoamBoneInfo[Verts.Length];
            ushort[]       Inds  = new ushort[Msh.num_tris * 3];

            Reader.Seek(Msh.ofs_verts);
            for (int i = 0; i < Verts.Length; i++)
            {
                DPMVertex V = Reader.ReadStructReverse <DPMVertex>();


                for (int j = 0; j < V.numbones; j++)
                {
                    DPMBoneVert BoneVert = Reader.ReadStructReverse <DPMBoneVert>();
                }
            }

            return(new FoamMesh(Verts, Inds, Info, Msh.GetShaderName(), 0));
        }
コード例 #2
0
        static void UpdateModel(FoamModel Model, int FrameIndex)
        {
            if (Model.Animations == null)
            {
                return;
            }

            //Matrix4x4 ParentRotMat = Matrix4x4.CreateFromYawPitchRoll(0, -Pi / 2, 0);

            foreach (var Msh in Model.Meshes)
            {
                List <Vertex3> Verts = new List <Vertex3>();
                if (Msh.BoneInformation == null)
                {
                    continue;
                }

                foreach (var Index in Msh.Indices)
                {
                    FoamVertex3  Vert  = Msh.Vertices[Index];
                    FoamBoneInfo Info  = Msh.BoneInformation[Index];
                    FoamBone     Bone1 = Model.Bones[Info.Bone1];

                    // TODO: Weights
                    Matrix4x4 BindWorld  = Bone1.BindMatrix;
                    Matrix4x4 WorldTrans = Model.CalcWorldTransform(0, FrameIndex, Info.Bone1);
                    Vector3   Pos        = Vector3.Transform(Vert.Position, BindWorld * WorldTrans);

                    // TODO: Flip?
                    Verts.Add(new Vertex3(Pos, Vert.UV));
                }

                Mesh *RayMesh = ((Model)Msh.Userdata).meshes;
                Raylib.UnloadMesh(*RayMesh);
                *RayMesh = Raylib.GenMeshRaw(Verts.ToArray());
            }
        }
コード例 #3
0
ファイル: IQM.cs プロジェクト: sbarisic/Foam
        public FoamModel Load(Stream S, string IQMFile)
        {
            int NumFrames = 0;

            ushort[] FrameData = null;

            Vector3[]         Position     = null;
            Vector2[]         Texcoord     = null;
            Vector3[]         Normal       = null;
            Vector4[]         Tangent      = null;
            IQMBlendIndices[] BlendIndexes = null;
            IQMBlendWeights[] BlendWeights = null;
            FoamColor[]       Color        = null;
            byte[]            Text         = null;
            byte[]            Comment      = null;
            IQMTriangle[]     Triangles    = null;
            IQMMesh[]         Meshes       = null;
            IQMJoint[]        Joints       = null;
            IQMPose[]         Poses        = null;
            IQMAnim[]         Anims        = null;

            FoamVertex3[]  FoamVertices = null;
            FoamBoneInfo[] FoamBoneInfo = null;

            using (BinaryReader Reader = new BinaryReader(S, Encoding.UTF8, true)) {
                IQMHeader Header = Reader.ReadStruct <IQMHeader>();
                NumFrames = (int)Header.num_frames;

                if (Header.GetMagic() != "INTERQUAKEMODEL")
                {
                    throw new Exception("Invalid magic in IQM file");
                }

                if (Header.Version != 2)
                {
                    throw new Exception("Only IQM version 2 supported");
                }

                // Text
                if (Header.ofs_text != 0)
                {
                    Reader.Seek(Header.ofs_text);
                    //Text = Encoding.ASCII.GetString(Reader.ReadBytes((int)Header.num_text)).Split(new char[] { (char)0 });
                    Text = Reader.ReadBytes((int)Header.num_text);
                }

                // Comments
                if (Header.ofs_comment != 0)
                {
                    Reader.Seek(Header.ofs_comment);
                    Comment = Reader.ReadBytes((int)Header.num_comment);
                }

                // Vertex arrays
                Reader.Seek(Header.ofs_vertexarrays);
                IQMVertexArray[] VertArrays = new IQMVertexArray[Header.num_vertexarrays];
                for (int i = 0; i < VertArrays.Length; i++)
                {
                    VertArrays[i] = Reader.ReadStruct <IQMVertexArray>();
                }

                for (int i = 0; i < VertArrays.Length; i++)
                {
                    ref IQMVertexArray VA = ref VertArrays[i];
                    Reader.Seek(VA.offset);

                    switch (VA.type)
                    {
                    case IQMVertexArrayType.IQM_POSITION:
                        if (VA.format != IQMVertexArrayFormat.IQM_FLOAT && VA.size != 3)
                        {
                            throw new NotImplementedException();
                        }

                        Position = Reader.ReadStructArray <Vector3>((uint)(Header.num_vertexes * Marshal.SizeOf <Vector3>()));
                        break;

                    case IQMVertexArrayType.IQM_TEXCOORD:
                        if (VA.format != IQMVertexArrayFormat.IQM_FLOAT && VA.size != 2)
                        {
                            throw new NotImplementedException();
                        }

                        Texcoord = Reader.ReadStructArray <Vector2>((uint)(Header.num_vertexes * Marshal.SizeOf <Vector2>()));
                        break;

                    case IQMVertexArrayType.IQM_NORMAL:
                        if (VA.format != IQMVertexArrayFormat.IQM_FLOAT && VA.size != 3)
                        {
                            throw new NotImplementedException();
                        }

                        Normal = Reader.ReadStructArray <Vector3>((uint)(Header.num_vertexes * Marshal.SizeOf <Vector3>()));
                        break;

                    case IQMVertexArrayType.IQM_TANGENT:
                        if (VA.format != IQMVertexArrayFormat.IQM_FLOAT && VA.size != 4)
                        {
                            throw new NotImplementedException();
                        }

                        Tangent = Reader.ReadStructArray <Vector4>((uint)(Header.num_vertexes * Marshal.SizeOf <Vector4>()));
                        break;

                    case IQMVertexArrayType.IQM_BLENDINDEXES:
                        if (VA.format != IQMVertexArrayFormat.IQM_UBYTE && VA.size != 4)
                        {
                            throw new NotImplementedException();
                        }

                        BlendIndexes = Reader.ReadStructArray <IQMBlendIndices>((uint)(Header.num_vertexes * Marshal.SizeOf <IQMBlendIndices>()));
                        break;

                    case IQMVertexArrayType.IQM_BLENDWEIGHTS:
                        if (VA.format != IQMVertexArrayFormat.IQM_UBYTE && VA.size != 4)
                        {
                            throw new NotImplementedException();
                        }

                        BlendWeights = Reader.ReadStructArray <IQMBlendWeights>((uint)(Header.num_vertexes * Marshal.SizeOf <IQMBlendWeights>()));
                        break;

                    case IQMVertexArrayType.IQM_COLOR:
                        if (VA.format != IQMVertexArrayFormat.IQM_UBYTE && VA.size != 4)
                        {
                            throw new NotImplementedException();
                        }

                        Color = Reader.ReadStructArray <FoamColor>((uint)(Header.num_vertexes * Marshal.SizeOf <FoamColor>()));
                        break;

                    case IQMVertexArrayType.IQM_CUSTOM:
                    default:
                        throw new NotImplementedException();
                    }
                }

                // Triangles
                Reader.Seek(Header.ofs_triangles);
                Triangles = Reader.ReadStructArray <IQMTriangle>((uint)(Header.num_triangles * sizeof(IQMTriangle)));

                // Meshes
                Reader.Seek(Header.ofs_meshes);
                Meshes = Reader.ReadStructArray <IQMMesh>((uint)(Header.num_meshes * sizeof(IQMMesh)));

                // Joints
                Reader.Seek(Header.ofs_joints);
                Joints = Reader.ReadStructArray <IQMJoint>((uint)(Header.num_joints * sizeof(IQMJoint)));

                // Poses
                Reader.Seek(Header.ofs_poses);
                Poses = Reader.ReadStructArray <IQMPose>((uint)(Header.num_poses * sizeof(IQMPose)));

                // Anims
                Reader.Seek(Header.ofs_anims);
                Anims = Reader.ReadStructArray <IQMAnim>((uint)(Header.num_anims * sizeof(IQMAnim)));

                // Frames
                Reader.Seek(Header.ofs_frames);
                FrameData = Reader.ReadStructArray <ushort>((uint)(CountFrameDataLength(NumFrames, Poses) * sizeof(ushort)));

                // Foam vertices
                FoamVertices = new FoamVertex3[Header.num_vertexes];
                for (int i = 0; i < FoamVertices.Length; i++)
                {
                    FoamVertices[i] = BuildVertex(i, Tangent, Normal, Position, Texcoord, Color);
                }

                // Foam bone info
                FoamBoneInfo = new FoamBoneInfo[FoamVertices.Length];
                for (int i = 0; i < FoamBoneInfo.Length; i++)
                {
                    FoamBoneInfo Info = new FoamBoneInfo();

                    if (BlendIndexes != null && BlendWeights != null)
                    {
                        IQMBlendIndices BInd = BlendIndexes[i];
                        IQMBlendWeights BWgt = BlendWeights[i];

                        Info.Bone1 = BInd.BlendIndex1;
                        Info.Bone2 = BInd.BlendIndex2;
                        Info.Bone3 = BInd.BlendIndex3;
                        Info.Bone4 = BInd.BlendIndex4;

                        const float WeightDividend = 255.0f;
                        Info.Weight1 = BWgt.BlendWeight1 / WeightDividend;
                        Info.Weight2 = BWgt.BlendWeight2 / WeightDividend;
                        Info.Weight3 = BWgt.BlendWeight3 / WeightDividend;
                        Info.Weight4 = BWgt.BlendWeight4 / WeightDividend;
                    }

                    FoamBoneInfo[i] = Info;
                }
            }
コード例 #4
0
ファイル: FoamCompile.cs プロジェクト: sbarisic/Foam
        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()));
            }
        }
コード例 #5
0
 static Vertex3 ToVert3(FoamVertex3 V)
 {
     return(new Vertex3(V.Position, new Vector2(V.UV2.X, 1.0f - V.UV2.Y)));
 }
コード例 #6
0
ファイル: MapFoam.cs プロジェクト: sbarisic/Foam
        static void GenAtlas(string OutDir, FoamModel LevelModel, out MeshAtlasMap AtlasMap)
        {
            const bool  GenerateNewUVs = true;
            const float TextureScale   = 2;
            //const float VertexScale = 1.0f / 100;
            const float VertexScale = 1.0f;
            const int   BounceCount = 2;

            FoamMesh[] Meshes = LevelModel.Meshes;

            List <FoamMesh>    VertexMeshMap = new List <FoamMesh>();
            List <FoamVertex3> ModelVerts    = new List <FoamVertex3>();
            //ushort[] NewInds = null;

            int W;
            int H;

            {
                foreach (var Mesh in Meshes)
                {
                    IEnumerable <FoamVertex3> MeshVerts = Mesh.GetFlatVertices();

                    foreach (var V in MeshVerts)
                    {
                        VertexMeshMap.Add(Mesh);
                        ModelVerts.Add(V);
                    }

                    Mesh.Indices  = new ushort[] { };
                    Mesh.Vertices = new FoamVertex3[] { };
                }

                if (GenerateNewUVs)
                {
                    AtlasStruct *   _Atlas   = XAtlas.Create();
                    XAtlas_MeshDecl MeshDecl = new XAtlas_MeshDecl(ModelVerts.Select(V => V.Position).ToArray());
                    XAtlas.AddMesh(_Atlas, ref MeshDecl);
                    XAtlas.Generate(_Atlas, ChartOptions.CreateOptions(), null, PackOptions.CreatePackOptions());

                    XAtlasMesh *XMsh = &_Atlas->meshes[0];

                    /*NewInds = null;
                     * for (int i = 0; i < XMsh->indexCount; i++)
                     *      Utils.Append(ref NewInds, (ushort)XMsh->indexArray[i]);*/

                    W        = (int)(_Atlas->width * TextureScale);
                    H        = (int)(_Atlas->height * TextureScale);
                    AtlasMap = new MeshAtlasMap(W, H);

                    FoamVertex3[] OldModelVerts = ModelVerts.ToArray();
                    ModelVerts.Clear();

                    FoamMesh[] OldVertexMeshMap = VertexMeshMap.ToArray();
                    VertexMeshMap.Clear();

                    Vector2 AtlasSize = new Vector2((int)_Atlas->width, (int)_Atlas->height);
                    for (int i = 0; i < XMsh->vertexCount; i++)
                    {
                        XAtlasVertex *XVert   = &XMsh->vertexArray[i];
                        FoamVertex3   OldVert = OldModelVerts[(int)XVert->xref];
                        FoamMesh      OldMesh = OldVertexMeshMap[(int)XVert->xref];

                        //OldVert.UV = (XVert->UV) / AtlasSize;
                        OldVert.UV2 = (XVert->UV) / AtlasSize;

                        //OldVert.UV.X = (int)OldVert.UV.X;
                        //OldVert.UV.Y = (int)OldVert.UV.Y;

                        ModelVerts.Add(OldVert);
                        VertexMeshMap.Add(OldMesh);
                    }
                }
                else
                {
                    /*for (int i = 0; i < ModelVerts.Count; i++)
                     *      Utils.Append(ref NewInds, (ushort)i);*/
                    AtlasMap = new MeshAtlasMap(512, 512);
                }
            }


            Vector3[] RL_Pos = new Vector3[ModelVerts.Count];
            Vector2[] RL_UV  = new Vector2[ModelVerts.Count];

            // Calculate normals
            for (int i = 0; i < ModelVerts.Count; i += 3)
            {
                FoamVertex3 VA = ModelVerts[i + 0];
                FoamVertex3 VB = ModelVerts[i + 1];
                FoamVertex3 VC = ModelVerts[i + 2];

                Vector3 CB     = VC.Position - VB.Position;
                Vector3 AB     = VA.Position - VB.Position;
                Vector3 Normal = Vector3.Normalize(Vector3.Cross(CB, AB));

                VA.Normal = Normal;
                VB.Normal = Normal;
                VC.Normal = Normal;

                ModelVerts[i + 0] = VA;
                ModelVerts[i + 1] = VB;
                ModelVerts[i + 2] = VC;


                RL_Pos[i + 0] = VA.Position * VertexScale;
                RL_Pos[i + 1] = VB.Position * VertexScale;
                RL_Pos[i + 2] = VC.Position * VertexScale;

                RL_UV[i + 0] = VA.UV2;
                RL_UV[i + 1] = VB.UV2;
                RL_UV[i + 2] = VC.UV2;
            }

            Vector2 PixelsSize = new Vector2(W, H);

            Vector4[] Pixels = new Vector4[W * H];
            ApplyEmissive(Pixels, W, H, ModelVerts, VertexMeshMap, LevelModel);

            //int TriIdx = 6;
            //Vector4 TriClr = new Vector4(50.0f / 255, 100.0f / 255, 200.0f / 255, 1);
            //DrawTriangle(Pixels, W, H, TriClr, ModelVerts[TriIdx * 3 + 0].UV2 * PixelsSize, ModelVerts[TriIdx * 3 + 1].UV2 * PixelsSize, ModelVerts[TriIdx * 3 + 2].UV2 * PixelsSize);

            Lightmapper.GenerateLightmap(ref Pixels, W, H, RL_Pos, RL_UV, BounceCount);
            ApplyEmissive(Pixels, W, H, ModelVerts, VertexMeshMap, LevelModel);

            //DrawTriangle(Pixels, W, H, TriClr, ModelVerts[TriIdx * 3 + 0].UV2 * PixelsSize, ModelVerts[TriIdx * 3 + 1].UV2 * PixelsSize, ModelVerts[TriIdx * 3 + 2].UV2 * PixelsSize);


            for (int i = 0; i < Pixels.Length; i++)
            {
                int X = i % W;
                int Y = (i - X) / W;

                Vector4 Clr = Pixels[i];
                Clr = Utils.Clamp(Clr, Vector4.Zero, Vector4.One);

                AtlasMap.Atlas.SetPixel(X, Y, new FastColor((byte)(Clr.X * 255), (byte)(Clr.Y * 255), (byte)(Clr.Z * 255), 255));
            }


            for (int i = 0; i < VertexMeshMap.Count; i++)
            {
                FoamMesh CurMesh = VertexMeshMap[i];

                //Utils.Append(ref CurMesh.Indices, (ushort)(NewInds[i]));
                Utils.Append(ref CurMesh.Vertices, ModelVerts[i]);
            }

            for (int i = 0; i < Meshes.Length; i++)
            {
                int VertCount = Meshes[i].Vertices.Length;
                Meshes[i].Indices = new ushort[VertCount];

                for (int j = 0; j < VertCount; j++)
                {
                    Meshes[i].Indices[j] = (ushort)j;
                }
            }

            //Msh.Vertices = Verts.ToArray();
            //Msh.Indices = NewInds.ToArray();
        }