Example #1
0
        // Writes whole tree to console provided with a random node from the tree
        public static void WriteTree(TextureNode SomeNode)
        {
            TextureNode master = SomeNode;

            // Get master node
            while (master.Parent != null)
            {
                master = master.Parent;
            }

            master.WriteNode(0);
        }
Example #2
0
        static void LoadFaces(BinaryReader br, Header header)
        {
            // Read vertexes..
            br.BaseStream.Seek(header.lumps[3].fileofs, SeekOrigin.Begin);
            int nVertexes = header.lumps[3].filelen / 12;
            Vector3[] loadedverts = new Vector3[nVertexes];
            for (int i = 0; i < nVertexes; i++)
            {
                Vector3 vec = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
                // swap z and y axis
                vec = SwapZY(vec);
                loadedverts[i] = vec;
            }

            // Reade edge lump
            br.BaseStream.Seek(header.lumps[12].fileofs, SeekOrigin.Begin);
            int nEdges = header.lumps[12].filelen / (sizeof(short) * 2);
            edge_t[] edges = new edge_t[nEdges];
            for (int i = 0; i < nEdges; i++)
            {
                edge_t edge;
                edge.v = new ushort[] { br.ReadUInt16(), br.ReadUInt16() };
                edges[i] = edge;
            }
            world.edges = edges;
            // Read surfedges
            br.BaseStream.Seek(header.lumps[13].fileofs, SeekOrigin.Begin);
            int nSurfEdges = header.lumps[13].filelen / sizeof(int);
            int[] surfEdges = new int[nSurfEdges];
            for (int i = 0; i < nSurfEdges; i++)
            {
                surfEdges[i] = br.ReadInt32();
            }
            world.surfEdges = surfEdges;

            // Read faces
            br.BaseStream.Seek(header.lumps[7].fileofs, SeekOrigin.Begin);
            int nFaces = header.lumps[7].filelen / 56;
            if (header.lumps[7].filelen % 56 > 0)
            {
                Common.Instance.Error("Weird faces lumpsize");
            }
            world.faces_t = new face_t[nFaces];
            world.faces = new Face[world.faces_t.Length];
            for (int i = 0; i < nFaces; i++)
            {
                face_t face;
                face.planenum = br.ReadUInt16();
                face.side = br.ReadByte();
                face.onNode = br.ReadByte();
                face.firstedge = br.ReadInt32();
                face.numedges = br.ReadInt16();
                face.texinfo = br.ReadInt16();
                face.dispinfo = br.ReadInt16();
                face.surfaceFogVolumeID = br.ReadInt16();
                face.styles = br.ReadBytes(4);
                face.lightlumpofs = br.ReadInt32();
                if (face.lightlumpofs > -1)
                {
                    face.lightlumpofs /= 4; // From 4byte offset to 1color offset
                }
                face.area = br.ReadSingle();
                face.LightmapTextureMinsInLuxels = new int[] { br.ReadInt32(), br.ReadInt32() };
                face.LightmapTextureSizeInLuxels = new int[] { br.ReadInt32(), br.ReadInt32() };
                face.origFace = br.ReadInt32();
                face.numPrims = br.ReadUInt16();
                face.firstPrimID = br.ReadUInt16();
                face.smoothingGroups = br.ReadUInt32();

                // Prepare Faces structure
                Face face2 = new Face();
                face.face = face2;
                face2.face_t = face;

                face2.nVerts = face.numedges;
                face2.plane_t = world.planes[face.planenum];
                face2.texinfo = world.texinfos[face.texinfo];
                if ((face2.texinfo.flags & (SurfFlags.SURF_NODRAW | SurfFlags.SURF_HINT | SurfFlags.SURF_FLOWING | SurfFlags.SURF_NOLIGHT | SurfFlags.SURF_SKIP)) == 0)
                    nVertIndex += face.numedges;
                world.faces[i] = face2;
                world.faces_t[i] = face;

                // Reverse mapping from displacement to face
                if (face.dispinfo != -1 && face.dispinfo < world.ddispinfos.Length)
                {
                    world.DispIndexToFaceIndex[face.dispinfo] = i;
                }
            }

            // Prepare lightmap texture
            Texture lightmapTexture = new Texture(Renderer.Instance.device, LightmapSize.Width, LightmapSize.Height, 1, Usage.Dynamic, Format.A16B16G16R16F, (Renderer.Instance.Is3D9Ex ? Pool.Default : Pool.Managed));
            DataRectangle textureData = lightmapTexture.LockRectangle(0, LockFlags.None);
            DataStream ds = textureData.Data;
            TextureNode texturePacker = new TextureNode(new System.Drawing.Rectangle(0, 0, LightmapSize.Width, LightmapSize.Height), null);
            TextureNode insertedNode = null; // TExtureNode result for each face

            int vertIndex = 0;
            world.verts = new List<VertexPositionNormalTexturedLightmap>();
            for (int i = 0; i < world.faces.Length; i++)
            {
                face_t face_t = world.faces[i].face_t;
                Face face = world.faces[i];

                if ((face.texinfo.flags & SurfFlags.SURF_NODRAW) > 0 ||
                    (face.texinfo.flags & SurfFlags.SURF_HINT) > 0 ||
                    (face.texinfo.flags & SurfFlags.SURF_FLOWING) > 0 ||
                    (face.texinfo.flags & SurfFlags.SURF_NOLIGHT) > 0 ||
                    (face.texinfo.flags & SurfFlags.SURF_SKIP) > 0)
                    continue; // Dont draw this

                // Add faces lightmap to lightmap texture
                int lmWidth = face_t.LightmapTextureSizeInLuxels[0] + 1;
                int lmHeight = face_t.LightmapTextureSizeInLuxels[1] + 1;
                int lmSize = lmWidth * lmHeight;
                for (int lightstyles = 0; lightstyles < 4; lightstyles++)
                {
                    if (face_t.styles[lightstyles] == 255)
                    {
                        continue;
                    }
                    if (face_t.lightlumpofs + (lmSize * lightstyles) >= world.LightData.Length || face_t.lightlumpofs == -1)
                    {
                        Common.Instance.WriteLine("WARNING: Face wants more lightdata than is available, or no offset");
                        break;
                    }
                    // Try to fit it in the texture..
                    insertedNode = texturePacker.Insert(ref world.LightData, lmWidth, lmHeight, face_t.lightlumpofs + (lmSize * lightstyles), ref ds, (face.face_t.dispinfo == -1 ? false : true));
                    if (insertedNode == null)
                        System.Console.WriteLine("Could not fit lightmap into a texture :( w:" + lmWidth + " h:" + lmHeight);
                    else// if (lightstyles == 0)
                    {
                        // Save lightmap coordinates
                        face.lightOffsetX = insertedNode.Rectangle.X;
                        face.lightOffsetY = insertedNode.Rectangle.Y;
                    }
                }

                // Build VertexPositionNormalTexturedLightmap's for face
                float s, t;
                int v;
                int pedge = face.face_t.firstedge;
                for (int j = 0;j < face.face_t.numedges; j++)
                {
                    int edge = surfEdges[pedge++];
                    if (edge < 0)
                    {
                        v = 1;
                        edge = -edge;
                    }
                    else
                        v = 0;

                    // Base Texture
                    Vector3 vert = loadedverts[edges[edge].v[v]];

                    // Texture coordinates
                    Vector3 texs = new Vector3(face.texinfo.textureVecs[0].X, face.texinfo.textureVecs[0].Y, face.texinfo.textureVecs[0].Z);
                    Vector3 text = new Vector3(face.texinfo.textureVecs[1].X, face.texinfo.textureVecs[1].Y, face.texinfo.textureVecs[1].Z);
                    s = (Vector3.Dot(vert, texs) + face.texinfo.textureVecs[0].W) / face.texinfo.texdata_t.width;
                    t = (Vector3.Dot(vert, text) + face.texinfo.textureVecs[1].W) / face.texinfo.texdata_t.height;

                    // Generate Lightmap Coordinates
                    float l_s = 0.5f, l_t = 0.5f;
                    if (face.face_t.LightmapTextureSizeInLuxels[0] != 0 && face.face_t.LightmapTextureSizeInLuxels[1] != 0)
                    {
                        //Vector3 vecs = new Vector3(face.texinfo.lightmapVecs[0].X, face.texinfo.lightmapVecs[0].Y, face.texinfo.lightmapVecs[0].Z);
                        //Vector3 vect = new Vector3(face.texinfo.lightmapVecs[1].X, face.texinfo.lightmapVecs[1].Y, face.texinfo.lightmapVecs[1].Z);

                        l_s = Vector3.Dot(vert, face.texinfo.lightmapVecs[0]) +
                            face.texinfo.lightmapVecs2[0] - face.face_t.LightmapTextureMinsInLuxels[0];
                        l_s /= face.face_t.LightmapTextureSizeInLuxels[0];

                        l_t = Vector3.Dot(vert, face.texinfo.lightmapVecs[1]) +
                            face.texinfo.lightmapVecs2[1] - face.face_t.LightmapTextureMinsInLuxels[1];
                        l_t /= face.face_t.LightmapTextureSizeInLuxels[1];

                        float divx = (float)(face.face_t.LightmapTextureSizeInLuxels[0]) / (LightmapSize.Width);
                        float startx = (float)(face.lightOffsetX + 0.5f) / (LightmapSize.Width);
                        l_s = divx * l_s + startx;

                        float divy = (float)(face.face_t.LightmapTextureSizeInLuxels[1]) / (LightmapSize.Height);
                        float starty = (float)(face.lightOffsetY + 0.5f) / (LightmapSize.Height);
                        l_t = divy * l_t + starty;
                    }

                    // Set vertex offset for face
                    if (face.VertexOffset == -1)
                        face.VertexOffset = vertIndex;

                    world.verts.Add(new VertexPositionNormalTexturedLightmap(vert, face.plane_t.normal, new Vector2(s, t), new Vector2(l_s, l_t)));
                    vertIndex++;
                }
            }

            //DispCollTree[] dispCollTrees = new DispCollTree[world.ddispinfos.Length];
            //for (int i = 0; i < dispCollTrees.Length; i++)
            //{
            //    dispCollTrees[i] = new DispCollTree();
            //}

            // Handle displacement face
            int iCurVert = 0, iCurTri = 0;
            for (int i = 0; i < world.ddispinfos.Length; i++)
            {
                int nFaceIndex = world.DispIndexToFaceIndex[i];

                // Check for missing mapping to face
                if (nFaceIndex == 0)
                    continue;

                // Get the displacement info
                ddispinfo_t currentDispInfo = world.ddispinfos[i];
                Face face = world.faces[nFaceIndex];

                //// Read in vertices
                //int nVerts = (((1 << (currentDispInfo.power)) + 1) * ((1 << (currentDispInfo.power)) + 1));
                //List<dDispVert> dispVerts = new List<dDispVert>();
                //for (int j = 0; j < nVerts; j++)
                //{
                //    dispVerts.Add(world.dispVerts[iCurVert + j]);
                //}
                //iCurVert += nVerts;

                //// Read in triangles
                //int nTris = ((1 << (currentDispInfo.power)) * (1 << (currentDispInfo.power)) * 2);
                //List<dDispTri> dispTris = new List<dDispTri>();
                //for (int j = 0; j < nTris; j++)
                //{
                //    dispTris.Add(world.dispTris[iCurTri + j]);
                //}
                //iCurTri += nTris;

                //Displacement disp = new Displacement();
                //DispSurface dispSurf = disp.Surface;
                //dispSurf.m_PointStart = currentDispInfo.startPosition;
                //dispSurf.m_Contents = currentDispInfo.contents;

                //disp.InitDispInfo(currentDispInfo.power, currentDispInfo.minTess, currentDispInfo.smoothingAngle, dispVerts, dispTris);

                //// Hook the disp surface to the face
                //dispSurf.m_Index = nFaceIndex;

                //// get points
                //if (world.faces_t[nFaceIndex].numedges > 4)
                //    continue;

                //face_t fac = world.faces_t[nFaceIndex];

                //Vector3[] surfPoints = new Vector3[4];
                //dispSurf.m_PointCount = fac.numedges;
                //int h = 0;
                //for (h = 0; h < fac.numedges; h++ )
                //{
                //    int eIndex = surfEdges[fac.firstedge + h];
                //    if (eIndex < 0)
                //    {
                //        surfPoints[h] = world.verts[edges[-eIndex].v[1]].position;
                //    }
                //    else
                //    {
                //        surfPoints[h] = world.verts[edges[eIndex].v[0]].position;
                //    }
                //}

                //for (h = 0; h < 4; h++)
                //{
                //    dispSurf.m_Points[h] = surfPoints[h];
                //}

                //dispSurf.FindSurfPointStartIndex();
                //dispSurf.AdjustSurfPointData();

                ////
                //// generate the collision displacement surfaces
                ////
                //DispCollTree dispTree = dispCollTrees[i];
                //dispTree.Power = 0;

                ////
                //// check for null faces, should have been taken care of in vbsp!!!
                ////
                //int pointCount = dispSurf.m_PointCount;
                //if (pointCount != 4)
                //    continue;

                //disp.Create();

                //DispCollTree pDispTree = dispCollTrees[i];
                //pDispTree.Power = 0;
                //pDispTree.Create(disp);

                // Generate the displacement surface
                createDispSurface(face, currentDispInfo, world, nFaceIndex);
            }

            //world.dispCollTrees = dispCollTrees;
            lightmapTexture.UnlockRectangle(0);
            world.LightmapTexture = lightmapTexture;
        }
Example #3
0
        public TextureNode Insert(ref Color3[] lightData, int width, int height, int offset, ref DataStream ds, bool flipY)
        {
            if (!leaf)
            {
                if (Child[0].Rectangle.Width >= width && Child[0].Rectangle.Height >= height)
                {
                    TextureNode newnode = Child[0].Insert(ref lightData, width, height, offset, ref ds, flipY);
                    if (newnode != null) return newnode;
                }

                if (Child[1].Rectangle.Width >= width && Child[1].Rectangle.Height >= height)
                    return Child[1].Insert(ref lightData, width, height, offset, ref ds, flipY);
                else
                    return null;
            }
            else
            {
                // allready used?
                if(Used)
                {
                    return null;
                }

                // not a fit?
                if(Rectangle.Width < width || Rectangle.Height < height)
                {
                    return null;
                }

                // perfect fit?
                if((Rectangle.Width == width && Rectangle.Height == height))
                {

                    for (int j = 0; j < (width*height); j++)
                    {
                        int x = Rectangle.X + ((j) % (width));
                        int y = Rectangle.Y + ((j) / (width));
                        long pos = (y * 1024L * 8L) + (x * 8L);
                        if(ds.Position != pos)
                            ds.Seek(pos, System.IO.SeekOrigin.Begin);
                        Half[] half =  Half.ConvertToHalf(new float[] {lightData[offset + j].Red, lightData[offset + j].Green, lightData[offset + j] .Blue});
                        ds.Write<Half3>(new Half3(half[0], half[1], half[2]));
                    }
                    this.Used = true;

                    return this;
                }

                // Else split up and make this a node
                int dw = Rectangle.Width - width;
                int dh = Rectangle.Height - height;

                if (dw > dh)
                {
                    Rectangle rect0 = new Rectangle(Rectangle.Left, Rectangle.Top, width , Rectangle.Height);
                    Rectangle rect1 = new Rectangle(Rectangle.Left + width, Rectangle.Top, Rectangle.Width-width, Rectangle.Height);

                    Child[0] = new TextureNode(rect0, this);
                    Child[1] = new TextureNode(rect1, this);
                }
                else
                {
                    Rectangle rect0 = new Rectangle(Rectangle.Left, Rectangle.Top, Rectangle.Width, height);
                    Rectangle rect1 = new Rectangle(Rectangle.Left, Rectangle.Top+height, Rectangle.Width, Rectangle.Height-height);
                    Child[0] = new TextureNode(rect0, this);
                    Child[1] = new TextureNode(rect1, this);
                }
                leaf = false;
                Used = true;
                return Child[0].Insert(ref lightData, width, height, offset, ref ds, flipY);
            }
        }
Example #4
0
 public TextureNode(Rectangle rect, TextureNode parent)
 {
     Parent = parent;
     this.Rectangle = rect;
 }