Beispiel #1
0
    public texinfo_t[] GetTextureInfo()
    {
        lump_t lump = lumps[6];

        texinfo_t[] textureInfo = new texinfo_t[lump.filelen / 72];
        stream.Position = lump.fileofs;

        for (int i = 0; i < textureInfo.Length; i++)
        {
            textureInfo[i].textureVecs    = new float[2][];
            textureInfo[i].textureVecs[0] = new float[4] {
                FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream)
            };
            textureInfo[i].textureVecs[1] = new float[4] {
                FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream)
            };
            textureInfo[i].lightmapVecs    = new float[2][];
            textureInfo[i].lightmapVecs[0] = new float[4] {
                FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream)
            };
            textureInfo[i].lightmapVecs[1] = new float[4] {
                FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream)
            };
            textureInfo[i].flags   = FileReader.readInt(stream);
            textureInfo[i].texdata = FileReader.readInt(stream);
        }

        lumpData[6] = textureInfo;
        return(textureInfo);
    }
        public void LoadBSP(BinaryReader br)
        {
            int cnt;

            this.header = new dheader_t(br);
            //Loading planes
            cnt    = (this.header.lumps [(int)lumpTypes.LUMP_PLANES].filelen) / STRUCT_PLANE_SIZE;
            planes = new dplane_t[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_PLANES].fileofs, SeekOrigin.Begin);
            for (int i = 0; i < cnt; i++)
            {
                planes [i] = new dplane_t(br);
            }
            //Loading BSP nodes
            cnt      = (this.header.lumps [(int)lumpTypes.LUMP_NODES].filelen) / STRUCT_BSPNODE_SIZE;
            bspnodes = new dnode_t[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_NODES].fileofs, SeekOrigin.Begin);
            for (int i = 0; i < cnt; i++)
            {
                bspnodes [i] = new dnode_t(br);
            }
            //Loading BSP leaves
            cnt       = (this.header.lumps [(int)lumpTypes.LUMP_LEAFS].filelen) / STRUCT_BSPLEAF_SIZE;
            bspleaves = new dleaf_t[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_LEAFS].fileofs, SeekOrigin.Begin);
            for (int i = 0; i < cnt; i++)
            {
                bspleaves [i] = new dleaf_t(br);
            }
            //Loading texinfo
            cnt      = (this.header.lumps [(int)lumpTypes.LUMP_TEXINFO].filelen) / STRUCT_TEXINFO_SIZE;
            texinfos = new texinfo_t[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_TEXINFO].fileofs, SeekOrigin.Begin);
            for (int i = 0; i < cnt; i++)
            {
                texinfos [i] = new texinfo_t(br);
            }

            //Loading texdata
            cnt     = (this.header.lumps [(int)lumpTypes.LUMP_TEXDATA].filelen) / STRUCT_TEXDATA_SIZE;
            texdata = new dtexdata_t[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_TEXDATA].fileofs, SeekOrigin.Begin);
            for (int i = 0; i < cnt; i++)
            {
                texdata [i] = new dtexdata_t(br);
            }
            //Loading TexdataStringTable
            cnt = (this.header.lumps [(int)lumpTypes.LUMP_TEXDATA_STRING_TABLE].filelen) / 4;
            TexdataStringTable = new int[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_TEXDATA_STRING_TABLE].fileofs, SeekOrigin.Begin);
            for (int i = 0; i < cnt; i++)
            {
                TexdataStringTable [i] = br.ReadInt32();
            }
            //Loading TexdataStringData
            cnt = (this.header.lumps [(int)lumpTypes.LUMP_TEXDATA_STRING_DATA].filelen) / 1;
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_TEXDATA_STRING_DATA].fileofs, SeekOrigin.Begin);
            TexdataStringData = br.ReadChars(cnt);
        }
Beispiel #3
0
        public virtual void Mod_LoadTexinfo(lump_t l)
        {
            texinfo_t in_renamed;

            mtexinfo_t[] out_renamed;
            mtexinfo_t   step;
            Int32        i, count;
            Int32        next;
            String       name;

            if ((l.filelen % texinfo_t.SIZE) != 0)
            {
                Com.Error(Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name);
            }
            count       = l.filelen / texinfo_t.SIZE;
            out_renamed = new mtexinfo_t[count];
            for (i = 0; i < count; i++)
            {
                out_renamed[i] = new mtexinfo_t();
            }

            loadmodel.texinfo    = out_renamed;
            loadmodel.numtexinfo = count;
            ByteBuffer bb = ByteBuffer.Wrap(mod_base, l.fileofs, l.filelen);

            bb.Order = ByteOrder.LittleEndian;
            for (i = 0; i < count; i++)
            {
                in_renamed           = new texinfo_t(bb);
                out_renamed[i].vecs  = in_renamed.vecs;
                out_renamed[i].flags = in_renamed.flags;
                next = in_renamed.nexttexinfo;
                if (next > 0)
                {
                    out_renamed[i].next = loadmodel.texinfo[next];
                }
                else
                {
                    out_renamed[i].next = null;
                }
                name = "textures/" + in_renamed.texture + ".wal";
                out_renamed[i].image = GL_FindImage(name, it_wall);
                if (out_renamed[i].image == null)
                {
                    VID.Printf(Defines.PRINT_ALL, "Couldn't load " + name + '\\');
                    out_renamed[i].image = r_notexture;
                }
            }

            for (i = 0; i < count; i++)
            {
                out_renamed[i].numframes = 1;
                for (step = out_renamed[i].next; (step != null) && (step != out_renamed[i]); step = step.next)
                {
                    out_renamed[i].numframes++;
                }
            }
        }
        static void CreateFaces()
        {
            BSP_CFaces = new Face[BSP_Faces.Length];

            for (Int32 Index = 0; Index < BSP_Faces.Length; Index++)
            {
                dface_t CFace = BSP_Faces[Index];

                Vector3[] FaceVertices = new Vector3[CFace.NumEdges];
                Vector2[] TextureUV    = new Vector2[CFace.NumEdges], LightmapUV = new Vector2[CFace.NumEdges];

                Color32[] VertColors = new Color32[CFace.NumEdges];

                texinfo_t  CTexinfo = BSP_TexInfo[CFace.TexInfo];
                dtexdata_t CTexdata = BSP_TexData[CTexinfo.TexData];

                for (Int32 i = CFace.FirstEdge, k = 0; i < CFace.FirstEdge + CFace.NumEdges; i++, k++)
                {
                    FaceVertices[k] = BSP_Surfedges[i] > 0 ? BSP_Vertices[BSP_Edges[Mathf.Abs(BSP_Surfedges[i])].V[0]] : BSP_Vertices[BSP_Edges[Mathf.Abs(BSP_Surfedges[i])].V[1]];
                    VertColors[k]   = new Color32(0, 0, 0, 0);
                }

                Int32[] FaceIndices = new int[(FaceVertices.Length - 1) * 3];
                for (Int32 i = 1, k = 0; i < FaceVertices.Length - 1; i++, k += 3)
                {
                    FaceIndices[k]     = 0;
                    FaceIndices[k + 1] = i;
                    FaceIndices[k + 2] = i + 1;
                }

                Vector3 tS = new Vector3(-CTexinfo.TextureVecs[0].x, CTexinfo.TextureVecs[0].z, -CTexinfo.TextureVecs[0].y);
                Vector3 tT = new Vector3(-CTexinfo.TextureVecs[1].x, CTexinfo.TextureVecs[1].z, -CTexinfo.TextureVecs[1].y);

                /*for (Int32 i = 0; i < FaceVertices.Length; i++)
                 * {
                 *  Single DecalS = (Vector3.Dot(FaceVertices[i], tS) + CTexinfo.TextureVecs[0].w * Configuration.WorldScale) / (CTexdata.View_Width * Configuration.WorldScale);
                 *  Single DecalT = (Vector3.Dot(FaceVertices[i], tT) + CTexinfo.TextureVecs[1].w * Configuration.WorldScale) / (CTexdata.View_Height * Configuration.WorldScale);
                 *  TextureUV[i] = new Vector2(DecalS, DecalT);
                 * }*/


                for (Int32 i = 0; i < FaceVertices.Length; i++)
                {
                    Single NODRAWS = (Vector3.Dot(FaceVertices[i], tS) + CTexinfo.TextureVecs[0].w * ConfigLoader.WorldScale) / (CTexdata.View_Width * ConfigLoader.WorldScale);
                    Single NODRAWT = (Vector3.Dot(FaceVertices[i], tT) + CTexinfo.TextureVecs[1].w * ConfigLoader.WorldScale) / (CTexdata.View_Height * ConfigLoader.WorldScale);
                    TextureUV[i] = new Vector2(NODRAWS, NODRAWT);
                }

                Vector3 lS = new Vector3(-CTexinfo.LightmapVecs[0].x, CTexinfo.LightmapVecs[0].z, -CTexinfo.LightmapVecs[0].y);
                Vector3 lT = new Vector3(-CTexinfo.LightmapVecs[1].x, CTexinfo.LightmapVecs[1].z, -CTexinfo.LightmapVecs[1].y);

                for (Int32 i = 0; i < FaceVertices.Length; i++)
                {
                    Single DecalS = (Vector3.Dot(FaceVertices[i], lS) + (CTexinfo.LightmapVecs[0].w + 0.5f - CFace.LightmapTextureMinsInLuxels[0]) * ConfigLoader.WorldScale) / ((CFace.LightmapTextureSizeInLuxels[0] + 1) * ConfigLoader.WorldScale);
                    Single DecalT = (Vector3.Dot(FaceVertices[i], lT) + (CTexinfo.LightmapVecs[1].w + 0.5f - CFace.LightmapTextureMinsInLuxels[1]) * ConfigLoader.WorldScale) / ((CFace.LightmapTextureSizeInLuxels[1] + 1) * ConfigLoader.WorldScale);
                    LightmapUV[i] = new Vector2(DecalS, DecalT);
                }

                BSP_CFaces[Index] = new Face
                {
                    TexInfo = CTexinfo,
                    TexData = CTexdata,

                    Vertices  = FaceVertices,
                    Triangles = FaceIndices,
                    Colors    = VertColors,

                    UV  = TextureUV,
                    UV2 = LightmapUV,

                    LightOfs = CFace.LightOfs,

                    LightMapW = CFace.LightmapTextureSizeInLuxels[0] + 1,
                    LightMapH = CFace.LightmapTextureSizeInLuxels[1] + 1
                };
            }
        }
Beispiel #5
0
    public texinfo_t[] GetTextureInfo()
    {
        lump_t lump = lumps[6];
        texinfo_t[] textureInfo = new texinfo_t[lump.filelen / 72];
        stream.Position = lump.fileofs;

        for (int i = 0; i < textureInfo.Length; i++)
        {
            textureInfo[i].textureVecs = new float[2][];
            textureInfo[i].textureVecs[0] = new float[4] { FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream) };
            textureInfo[i].textureVecs[1] = new float[4] { FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream) };
            textureInfo[i].lightmapVecs = new float[2][];
            textureInfo[i].lightmapVecs[0] = new float[4] { FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream) };
            textureInfo[i].lightmapVecs[1] = new float[4] { FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream), FileReader.readFloat(stream) };
            textureInfo[i].flags = FileReader.readInt(stream);
            textureInfo[i].texdata = FileReader.readInt(stream);
        }

        lumpData[6] = textureInfo;
        return textureInfo;
    }
        public void LoadBSP(BinaryReader br)
        {
            int cnt;
            this.header = new dheader_t (br);
            //Loading planes
            cnt = (this.header.lumps [(int)lumpTypes.LUMP_PLANES].filelen) / STRUCT_PLANE_SIZE;
            planes=new dplane_t[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_PLANES].fileofs, SeekOrigin.Begin);
            for(int i=0 ; i<cnt ; i++) {
                planes [i] = new dplane_t (br);
            }
            //Loading BSP nodes
            cnt = (this.header.lumps [(int)lumpTypes.LUMP_NODES].filelen) / STRUCT_BSPNODE_SIZE;
            bspnodes=new dnode_t[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_NODES].fileofs, SeekOrigin.Begin);
            for(int i=0 ; i<cnt ; i++) {
                bspnodes [i] = new dnode_t (br);
            }
            //Loading BSP leaves
            cnt = (this.header.lumps [(int)lumpTypes.LUMP_LEAFS].filelen) / STRUCT_BSPLEAF_SIZE;
            bspleaves=new dleaf_t[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_LEAFS].fileofs, SeekOrigin.Begin);
            for(int i=0 ; i<cnt ; i++) {
                bspleaves [i] = new dleaf_t (br);
            }
            //Loading texinfo
            cnt = (this.header.lumps [(int)lumpTypes.LUMP_TEXINFO].filelen) / STRUCT_TEXINFO_SIZE;
            texinfos=new texinfo_t[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_TEXINFO].fileofs, SeekOrigin.Begin);
            for(int i=0 ; i<cnt ; i++) {
                texinfos [i] = new texinfo_t (br);
            }

            //Loading texdata
            cnt = (this.header.lumps [(int)lumpTypes.LUMP_TEXDATA].filelen) / STRUCT_TEXDATA_SIZE;
            texdata=new dtexdata_t[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_TEXDATA].fileofs, SeekOrigin.Begin);
            for(int i=0 ; i<cnt ; i++) {
                texdata [i] = new dtexdata_t (br);
            }
            //Loading TexdataStringTable
            cnt = (this.header.lumps [(int)lumpTypes.LUMP_TEXDATA_STRING_TABLE].filelen) / 4;
            TexdataStringTable=new int[cnt];
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_TEXDATA_STRING_TABLE].fileofs, SeekOrigin.Begin);
            for(int i=0 ; i<cnt ; i++) {
                TexdataStringTable [i] = br.ReadInt32();
            }
            //Loading TexdataStringData
            cnt = (this.header.lumps [(int)lumpTypes.LUMP_TEXDATA_STRING_DATA].filelen) / 1;
            br.BaseStream.Seek(this.header.lumps [(int)lumpTypes.LUMP_TEXDATA_STRING_DATA].fileofs, SeekOrigin.Begin);
            TexdataStringData=br.ReadChars(cnt);
        }
    // I'm not the author of this method. I translated it on С#.
    // http://trac.openscenegraph.org/projects/osg/browser/OpenSceneGraph/branches/OpenSceneGraph-osgWidget-dev/src/osgPlugins/bsp/VBSPGeometry.cpp?rev=9236
    private static face CreateDispSurface(int dispIndex)
    {
        List <Vector3> faceVertices = new List <Vector3>();
        List <Vector3> dispVertices = new List <Vector3>();
        List <Int32>   dispIndices  = new List <int>();

        List <Vector2> textureCoordinates = new List <Vector2>();
        // List<Vector2> lightmapCoordinates = new List<Vector2>();

        dface_t faceInfo = BSP_Faces[BSP_DispInfo[dispIndex].MapFace];
        int     minIndex = 0;

        for (int i = faceInfo.firstedge; i < (faceInfo.firstedge + faceInfo.numedges); i++)
        {
            faceVertices.Add((BSP_Surfedges[i] > 0 ? BSP_Vertices[BSP_Edges[Mathf.Abs(BSP_Surfedges[i])].v[0]] : BSP_Vertices[BSP_Edges[Mathf.Abs(BSP_Surfedges[i])].v[1]]) * WorldController.WorldScale);
        }

        float minDist = 1.0e9f;

        for (int i = 0; i < 4; i++)
        {
            float dist = (faceVertices[i] - BSP_DispInfo[dispIndex].startPosition * WorldController.WorldScale).magnitude;

            if (dist < minDist)
            {
                minDist  = dist;
                minIndex = i;
            }
        }

        for (int i = 0; i < minIndex; i++)
        {
            Vector3 temp = faceVertices[0];
            faceVertices[0] = faceVertices[1];
            faceVertices[1] = faceVertices[2];
            faceVertices[2] = faceVertices[3];
            faceVertices[3] = temp;
        }

        Vector3 leftEdge  = faceVertices[1] - faceVertices[0];
        Vector3 rightEdge = faceVertices[2] - faceVertices[3];

        int   numEdgeVertices = (1 << BSP_DispInfo[dispIndex].power) + 1;
        float subdivideScale  = 1.0f / (numEdgeVertices - 1);

        Vector3 leftEdgeStep  = leftEdge * subdivideScale;
        Vector3 rightEdgeStep = rightEdge * subdivideScale;

        for (int i = 0; i < numEdgeVertices; i++)
        {
            Vector3 leftEnd = leftEdgeStep * i;
            leftEnd += faceVertices[0];

            Vector3 rightEnd = rightEdgeStep * i;
            rightEnd += faceVertices[3];

            Vector3 leftRightSeg  = rightEnd - leftEnd;
            Vector3 leftRightStep = leftRightSeg * subdivideScale;

            for (int j = 0; j < numEdgeVertices; j++)
            {
                int dispVertIndex = BSP_DispInfo[dispIndex].DispVertStart;
                dispVertIndex += i * numEdgeVertices + j;
                dDispVert dispVertInfo = BSP_DispVerts[dispVertIndex];

                Vector3 flatVertex = leftEnd + (leftRightStep * j);
                Vector3 dispVertex = dispVertInfo.vec * (dispVertInfo.dist * WorldController.WorldScale);
                dispVertex += flatVertex;

                texinfo_t faceTexinfo = BSP_Texinfo[faceInfo.texinfo];
                float     fU          = Vector3.Dot(new Vector3(faceTexinfo.textureVecs[0].x, faceTexinfo.textureVecs[0].y, faceTexinfo.textureVecs[0].z), flatVertex) + faceTexinfo.textureVecs[0].w * WorldController.WorldScale;
                float     fV          = Vector3.Dot(new Vector3(faceTexinfo.textureVecs[1].x, faceTexinfo.textureVecs[1].y, faceTexinfo.textureVecs[1].z), flatVertex) + faceTexinfo.textureVecs[1].w * WorldController.WorldScale;

                fU /= (BSP_Texdata[faceTexinfo.texdata].width * WorldController.WorldScale);
                fV /= (BSP_Texdata[faceTexinfo.texdata].height * WorldController.WorldScale);
                textureCoordinates.Add(new Vector2(fU, fV));

                dispVertices.Add(new Vector3(-dispVertex.x, dispVertex.z, dispVertex.y));
            }
        }

        for (int i = 0; i < numEdgeVertices - 1; i++)
        {
            for (int j = 0; j < numEdgeVertices - 1; j++)
            {
                int index = i * numEdgeVertices + j;

                if ((index % 2) == 1)
                {
                    dispIndices.Add(index);
                    dispIndices.Add(index + 1);
                    dispIndices.Add(index + numEdgeVertices);
                    dispIndices.Add(index + 1);
                    dispIndices.Add(index + numEdgeVertices + 1);
                    dispIndices.Add(index + numEdgeVertices);
                }
                else
                {
                    dispIndices.Add(index);
                    dispIndices.Add(index + numEdgeVertices + 1);
                    dispIndices.Add(index + numEdgeVertices);
                    dispIndices.Add(index);
                    dispIndices.Add(index + 1);
                    dispIndices.Add(index + numEdgeVertices + 1);
                }
            }
        }

        return(new face()
        {
            index = BSP_DispInfo[dispIndex].MapFace,

            points = dispVertices.ToArray(),
            triangles = dispIndices.ToArray(),
            uv = textureCoordinates.ToArray()
        });
    }
    private static face CreateFace(int index)
    {
        List <Vector3> faceVertices        = new List <Vector3>();
        List <Vector2> textureCoordinates  = new List <Vector2>();
        List <Vector2> lightmapCoordinates = new List <Vector2>();

        int startEdgeIndex = BSP_Faces[index].firstedge;
        int edgesCount     = BSP_Faces[index].numedges;

        texinfo_t  faceTexinfo = BSP_Texinfo[BSP_Faces[index].texinfo];
        dtexdata_t faceTexdata = BSP_Texdata[faceTexinfo.texdata];

        // Get vertices for this polygon
        for (int i = startEdgeIndex; i < startEdgeIndex + edgesCount; i++)
        {
            faceVertices.Add(WorldController.SwapZY(BSP_Surfedges[i] > 0 ? BSP_Vertices[BSP_Edges[Mathf.Abs(BSP_Surfedges[i])].v[0]] : BSP_Vertices[BSP_Edges[Mathf.Abs(BSP_Surfedges[i])].v[1]]) * WorldController.WorldScale);
        }

        List <int> templist = new List <int>();

        // Generate indices for this polygon
        for (int i = 1; i < faceVertices.Count - 1; i++)
        {
            templist.Add(0);
            templist.Add(i);
            templist.Add(i + 1);
        }

        // Generate texture UV for this polygon
        for (int i = 0; i < faceVertices.Count; i++)
        {
            float tU = Vector3.Dot(WorldController.SwapZY(new Vector3(faceTexinfo.textureVecs[0].x, faceTexinfo.textureVecs[0].y, faceTexinfo.textureVecs[0].z)), faceVertices[i]) + faceTexinfo.textureVecs[0].w * WorldController.WorldScale;
            float tV = Vector3.Dot(WorldController.SwapZY(new Vector3(faceTexinfo.textureVecs[1].x, faceTexinfo.textureVecs[1].y, faceTexinfo.textureVecs[1].z)), faceVertices[i]) + faceTexinfo.textureVecs[1].w * WorldController.WorldScale;

            tU /= (faceTexdata.width * WorldController.WorldScale);
            tV /= (faceTexdata.height * WorldController.WorldScale);
            textureCoordinates.Add(new Vector2(tU, tV));
        }

        // Generate lightmap UV for this polygon
        for (int i = 0; i < faceVertices.Count; i++)
        {
            // TODO: Remove "+ 0.5f" if you don't use atlases
            float lU = Vector3.Dot(WorldController.SwapZY(new Vector3(faceTexinfo.lightmapVecs[0].x, faceTexinfo.lightmapVecs[0].y, faceTexinfo.lightmapVecs[0].z)), faceVertices[i]) + (faceTexinfo.lightmapVecs[0].w + 0.5f - BSP_Faces[index].LightmapTextureMinsInLuxels[0]) * WorldController.WorldScale;
            float lV = Vector3.Dot(WorldController.SwapZY(new Vector3(faceTexinfo.lightmapVecs[1].x, faceTexinfo.lightmapVecs[1].y, faceTexinfo.lightmapVecs[1].z)), faceVertices[i]) + (faceTexinfo.lightmapVecs[1].w + 0.5f - BSP_Faces[index].LightmapTextureMinsInLuxels[1]) * WorldController.WorldScale;

            lU /= (BSP_Faces[index].LightmapTextureSizeInLuxels[0] + 1) * WorldController.WorldScale;
            lV /= (BSP_Faces[index].LightmapTextureSizeInLuxels[1] + 1) * WorldController.WorldScale;
            lightmapCoordinates.Add(new Vector2(lU, lV));
        }

        return(new face()
        {
            index = index,

            points = faceVertices.ToArray(),
            triangles = templist.ToArray(),

            uv = textureCoordinates.ToArray(),
            uv2 = lightmapCoordinates.ToArray(),

            lightMapW = BSP_Faces[index].LightmapTextureSizeInLuxels[0] + 1,
            lightMapH = BSP_Faces[index].LightmapTextureSizeInLuxels[1] + 1
        });
    }