// 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); }
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; }
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); } }
public TextureNode(Rectangle rect, TextureNode parent) { Parent = parent; this.Rectangle = rect; }