public virtual void Mod_LoadLeafs(lump_t l) { qfiles.dleaf_t in_renamed; mleaf_t[] out_renamed; Int32 i, j, count; if ((l.filelen % qfiles.dleaf_t.SIZE) != 0) { Com.Error(Defines.ERR_DROP, "MOD_LoadBmodel: funny lump size in " + loadmodel.name); } count = l.filelen / qfiles.dleaf_t.SIZE; out_renamed = new mleaf_t[count]; loadmodel.leafs = out_renamed; loadmodel.numleafs = count; ByteBuffer bb = ByteBuffer.Wrap(mod_base, l.fileofs, l.filelen); bb.Order = ByteOrder.LittleEndian; for (i = 0; i < count; i++) { in_renamed = new dleaf_t(bb); out_renamed[i] = new mleaf_t(); for (j = 0; j < 3; j++) { out_renamed[i].mins[j] = in_renamed.mins[j]; out_renamed[i].maxs[j] = in_renamed.maxs[j]; } out_renamed[i].contents = in_renamed.contents; out_renamed[i].cluster = in_renamed.cluster; out_renamed[i].area = in_renamed.area; out_renamed[i].SetMarkSurface(in_renamed.firstleafface, loadmodel.marksurfaces); out_renamed[i].nummarksurfaces = in_renamed.numleaffaces; } }
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); }
int FindIntersectionSurfaceAtLeaf(dleaf_t leaf, float start, float end, ref Vector3 c, LightVecState state) { int clostestSurf = -1; for (int i = 0; i < leaf.numleaffaces; i++) { int surfid = world.leafFaces[leaf.firstleafface + i]; face_t face = world.faces_t[surfid]; // Don't add surfaces that have displacement; they are handled above // In fact, don't even set the vis frame; we need it unset for translucent // displacement code if (face.dispinfo != -1) continue; if ((face.face.texinfo.flags & SurfFlags.SURF_NODRAW) == SurfFlags.SURF_NODRAW) continue; cplane_t plane = face.face.plane_t; // Backface cull... if (Vector3.Dot(plane.normal, (state.end - state.start)) > 0.0f) continue; float startdotn = Vector3.Dot(state.start, plane.normal); float deltadotn = Vector3.Dot((state.end - state.start), plane.normal); float front = startdotn + start * deltadotn - plane.dist; float back = startdotn + end * deltadotn - plane.dist; bool side = front < 0.0f; // Blow it off if it doesn't split the plane... if ((back < 0.0f) == side) continue; // Don't test a surface that is farther away from the closest found intersection float frac = front / (front - back); if (frac >= state.hitFrac) continue; float mid = start * (1.0f - frac) + end * frac; // Check this surface to see if there's an intersection if (FindIntersectionAtSurface(surfid, mid, ref c, state)) { clostestSurf = surfid; } } // Return the closest surface hit return clostestSurf; }
static void LoadNodesAndLeafs(BinaryReader br, Header header) { // Read nodes br.BaseStream.Seek(header.lumps[5].fileofs, SeekOrigin.Begin); int nNodes = header.lumps[5].filelen / 32; if (header.lumps[5].filelen % 32 > 0) { Common.Instance.Error("LoadNodesAndLeafs: Weird node lumpsize"); } world.nodes = new dnode_t[nNodes]; for (int i = 0; i < nNodes; i++) { dnode_t node = new dnode_t(); node.planenum = br.ReadInt32(); node.children = new int[] { br.ReadInt32(), br.ReadInt32() }; node.mins = SourceParser.SwapZY(new Vector3(br.ReadInt16(), br.ReadInt16(), br.ReadInt16())); // 3 For frustrum culling node.maxs = SourceParser.SwapZY(new Vector3(br.ReadInt16(), br.ReadInt16(), br.ReadInt16())); // 3 node.firstface = br.ReadUInt16(); // index into face array node.numfaces = br.ReadUInt16(); ; // counting both sides node.area = br.ReadInt16(); ; // If all leaves below this node are in the same area, then // this is the area index. If not, this is -1. node.paddding = br.ReadInt16(); ; // pad to 32 bytes length node.plane = world.planes[node.planenum]; world.nodes[i] = node; } // Determine size int leafSize = 56; if (header.version == 20 || header.version == 17) { if (header.lumps[10].filelen % 32 == 0) leafSize = 32; else System.Console.WriteLine("Problem reading leafs.."); } world.numLeafs = header.lumps[10].filelen / leafSize; world.leafs = new dleaf_t[world.numLeafs]; br.BaseStream.Seek(header.lumps[10].fileofs, SeekOrigin.Begin); for (int i = 0; i < world.numLeafs; i++) { // dleaf_t leaf = new dleaf_t(); leaf.contents = br.ReadInt32(); leaf.cluster = br.ReadInt16(); if (leaf.cluster > world.numClusters) world.numClusters = leaf.cluster + 1; ushort packed = br.ReadUInt16(); leaf.area = (short)((ushort)(packed << 7) >> 7); leaf.flags = (short)(packed >> 9); if (packed > 0) { int test = 2; } leaf.mins = SourceParser.SwapZY(new Vector3(br.ReadInt16(), br.ReadInt16(), br.ReadInt16())); // 3 For frustrum culling leaf.maxs = SourceParser.SwapZY(new Vector3(br.ReadInt16(), br.ReadInt16(), br.ReadInt16())); // 3 leaf.firstleafface = br.ReadUInt16(); leaf.numleaffaces = br.ReadUInt16(); leaf.firstleafbrush = br.ReadUInt16(); leaf.numleafbrushes = br.ReadUInt16(); leaf.leafWaterDataID = br.ReadInt16(); leaf.ambientLighting = new CompressedLightCube(); if (leafSize > 32) { leaf.ambientLighting.Color = new Vector3[6]; for (int j = 0; j < 6; j++) { RGBExp color = new RGBExp(); color.r = br.ReadByte(); color.g = br.ReadByte(); color.b = br.ReadByte(); color.exp = br.ReadSByte(); float r = SourceParser.TexLightToLinear((int)color.r, color.exp); float g = SourceParser.TexLightToLinear((int)color.g, color.exp); float b = SourceParser.TexLightToLinear((int)color.b, color.exp); leaf.ambientLighting.Color[j] = new Vector3(r, g, b); } } else { if (world.LightGrid != null && world.LightGrid.Length > i) leaf.ambientLighting = world.LightGrid[i]; } leaf.padding = br.ReadInt16(); leaf.staticProps = new List<SourceProp>(); world.leafs[i] = leaf; } }
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); }
public void Render(Device device) { // Get current leaf & cluster if (!LockPVS) { VisCount++; CurrentLeafID = FindLeaf(Renderer.Instance.Camera.position); CurrentLeaf = world.leafs[CurrentLeafID]; CurrentCluster = CurrentLeaf.cluster; //if (Renderer.Instance.window != null) // Renderer.Instance.window.CurrentCluster.Text = CurrentCluster.ToString(); } if (skybox != null) skybox.Render(); if (skybox3d != null) skybox3d.Render(); bboxVerts.Clear(); Camera cam = Renderer.Instance.Camera; // Update visibility if new position if (CurrentCluster != LastCluster || !cam.position.Equals(lastPosition)) { // save position lastPosition = cam.position; // Clear last runs visible renderitems foreach (List<RenderItem> itlist in visibleRenderItems.Values) { itlist.Clear(); } visibleProps.Clear(); // Mark visible leafs and nodes MarkVisible(CurrentCluster, VisCount); // Move though BSP tree RecursiveWorldNode(0); // Always show displacements //foreach (RenderItem item in dispRenderItems) // visibleRenderItems[item.material.MaterialID].Add(item); List<DynamicItem> dynItems = new List<DynamicItem>(); List<KeyValuePair<ulong, RenderDelegate>> calls = new List<KeyValuePair<ulong, RenderDelegate>>(); ushort dist = 0; SortItem.Translucency trans = SortItem.Translucency.OPAQUE; DynamicItem dynItem = new DynamicItem(); uint min = 9999999, max = 0; int dynoffset = 0; // Group items that needs to be batched Dictionary<int, List<RenderItem>> renderItems = visibleRenderItems; for (int itemPass = 0; itemPass < 2; itemPass++) { if (itemPass == 1) { if (skybox3d != null) renderItems = skybox3d.visibleRenderItems; else break; } foreach (List<RenderItem> grouplist in renderItems.Values) { // Create new batch dynItem = new DynamicItem(); dynItem.vb = this.vb; dynItem.ib = batchIB; dynItem.IndiceStartIndex = dynoffset; trans = SortItem.Translucency.OPAQUE; dist = 0; min = 9999999; max = 0; // Add items to batch foreach (RenderItem item in grouplist) { if (item.face.HasDisplacement) { int test = 2; } if (item.indices.Count == 0 || item.nVerts == 0) continue; // Not too sure about how alpha batching should be handled.. Maybe sort before batching? if (item.material.Alpha) { trans = SortItem.Translucency.NORMAL; dist = item.depth; } dynItem.material = item.material; dynItem.Type = item.Type; if (item.IndiceMin < min) min = item.IndiceMin; if (item.IndiceMax > max) max = item.IndiceMax; // Append to current batch dynItem.nIndices += item.indices.Count; dynItem.nVerts += item.nVerts; // Ensure dynamic array is big enough if (dynoffset + item.indices.Count > dynamicIndices.Length) { uint[] newlist = new uint[dynamicIndices.Length * 2]; dynamicIndices.CopyTo(newlist, 0); dynamicIndices = newlist; } // Copy indices into the indice buffer item.indices.CopyTo(0, dynamicIndices, dynoffset, item.indices.Count); dynoffset += item.indices.Count; } // Add drawcall for batch if (dynItem.nIndices > 0) { // Important for ATI cards dynItem.nVerts = (int)max - (int)min + 1; dynItem.lowestIndiceValue = (int)min; // Complete current batch if (itemPass != 0) { int test = 1; } ulong k = SortItem.GenerateBits(SortItem.FSLayer.GAME, SortItem.Viewport.DYNAMIC, itemPass==0?SortItem.VPLayer.WORLD:SortItem.VPLayer.SKYBOX3D, trans, dynItem.material.MaterialID, dist, batchIB.IndexBufferID, vb.VertexBufferID); RenderDelegate v = new RenderDelegate(dynItem.Render); calls.Add(new KeyValuePair<ulong, RenderDelegate>(k, v)); } } } // Set IB data for batches batchIB.SetIB<uint>(dynamicIndices, dynoffset * sizeof(uint), Usage.WriteOnly | Usage.Dynamic, false, Pool.Default, dynoffset); Dictionary<string, List<SourceProp>> propList = new Dictionary<string, List<SourceProp>>(); // Group up props for instancing foreach (SourceProp prop in visibleProps) { if (propList.ContainsKey(prop.prop_t.PropName)) propList[prop.prop_t.PropName].Add(prop); else propList.Add(prop.prop_t.PropName, new List<SourceProp>(new SourceProp[] { prop })); } int propVBOffset = 0; int totalBytes = 0; int lightcubeid = 0; List<VertexPropInstance> verts = new List<VertexPropInstance>(); // Create InstanceItems foreach (List<SourceProp> props in propList.Values) { //Dictionary<ushort, KeyValuePair<int, CompressedLightCube>> lightcubes = new Dictionary<ushort, KeyValuePair<int, CompressedLightCube>>(); ////if (props.Count == 0 || !props[0].prop_t.PropName.Contains("models/props/cs_office/Vending_machine.mdl") ||!props[0].prop_t.PropName.Contains("Light")) //// continue; //if (props[0].srcModel == null) // continue; //InstanceItem instItem = new InstanceItem(); //// Add mesh //instItem.Parts = props[0].srcModel.BodyParts; //instItem.InstanceBufferOffset = propVertexBufferOffset + (verts.Count * VertexPropInstance.SizeInBytes); //int propInstanceCount = 0; // Generate Instance vert for every prop in this group foreach (SourceProp prop in props) { ///ushort propLeaf = prop.prop_t.lastVisibleLeaf; //int lightid = 0; //// Grap lightcube id if already added //if (lightcubes.ContainsKey(propLeaf) ) //{ // lightid = lightcubes[propLeaf].Key; //} //// else add it now //else if (true) // //{ // lightid = lightcubeid++; // //leafs[propLeaf].ambientLighting.Color[0]. // //Matrix matrix = new Matrix(); // //matrix.set_Rows(0, leafs[propLeaf].ambientLighting.Color[0].ToVector4()); // //matrix.set_Rows(1, leafs[propLeaf].ambientLighting.Color[1].ToVector4()); // //matrix.set_Rows(2, leafs[propLeaf].ambientLighting.Color[2].ToVector4()); // //instItem.lightcubearr.Add(matrix); // //matrix = new Matrix(); // //matrix.set_Rows(0, leafs[propLeaf].ambientLighting.Color[3].ToVector4()); // //matrix.set_Rows(1, leafs[propLeaf].ambientLighting.Color[4].ToVector4()); // //matrix.set_Rows(2, leafs[propLeaf].ambientLighting.Color[5].ToVector4()); // //instItem.lightcubearr.Add(matrix); // //for (int j = 0; j < 6; j++) // //{ // // Vector3 val = leafs[propLeaf].ambientLighting.Color[j].ToVector3(); // // float redval = 1f; // // if (lightid % 2 == 0) // // redval = 5f; // // instItem.lightcubearr.AddRange(new float[] { redval, 0f, 0f }); // // //for (int veci = 0; veci < 3; veci++) // // //{ // // // instItem.lightcubearr.Add(val[veci]); // // //} // // //lightcubearr.Add(redCube.Color[j].ToVector4()); // //} // lightcubes.Add(propLeaf, new KeyValuePair<int, CompressedLightCube>(lightid, leafs[propLeaf].ambientLighting)); //} //else //{ // lightid = 63; // for (int i = 0; i < 6; i++) // { // Vector3 val = redCube.Color[i].ToVector3(); // for (int veci = 0; veci < 3; veci++) // { // instItem.lightcubearr.Add(val[veci]); // } // } //} //float pitch, roll, yaw; //pitch = prop.prop_t.Angles.Z * (float)(Math.PI / 180f); //roll = prop.prop_t.Angles.Y * (float)(Math.PI / 180f); //yaw = prop.prop_t.Angles.X * (float)(Math.PI / 180f); //// Order of multiplication very important //Matrix modelMatrix = Matrix.RotationYawPitchRoll(yaw, -pitch, roll) * Matrix.Translation(prop.prop_t.Origin); //VertexPropInstance instvert = new VertexPropInstance(modelMatrix, world.leafs[propLeaf].ambientLighting); //verts.Add(instvert); //instItem.nInstances++; //propInstanceCount++; ulong callkey = SortItem.GenerateBits(SortItem.FSLayer.GAME, SortItem.Viewport.FOUR, SortItem.VPLayer.WORLD, SortItem.Translucency.OPAQUE, 0, 0, 0, 0); RenderDelegate callvalue = new RenderDelegate(prop.Render); calls.Add(new KeyValuePair<ulong, RenderDelegate>(callkey, callvalue)); } // Create instance vertexbuffer //instItem.vb = propVertexBuffer; //totalBytes += propInstanceCount * VertexPropInstance.SizeInBytes; // Create rendercall to this instanceitem //ulong callkey = SortItem.GenerateBits(SortItem.FSLayer.GAME, SortItem.Viewport.INSTANCED, SortItem.VPLayer.WORLD, SortItem.Translucency.OPAQUE, 0, 0, 0, 0); //RenderDelegate callvalue = new RenderDelegate(instItem.Render); //calls.Add(new KeyValuePair<ulong, RenderDelegate>(callkey, callvalue)); } //propVertexBuffer.SetVB<VertexPropInstance>(verts.ToArray(), totalBytes, VertexPropInstance.Format, Usage.Dynamic | Usage.WriteOnly, propVertexBufferOffset); //if (propVertexBufferOffset > 0) // propVertexBufferOffset = 0; //else // propVertexBufferOffset = totalBytes; //List<Vector4> lightcubearr = new List<Vector4>(); //foreach (KeyValuePair<int, CompressedLightCube> kv in lightcubes.Values) //{ // // Write 6 * 4 * floats // CompressedLightCube cube = kv.Value; // for (int j = 0; j < 6; j++) // { // lightcubearr.Add(cube.Color[j].ToVector4()); // //lightcubearr.Add(redCube.Color[j].ToVector4()); // } // if (lightcubearr.Count == 31 * 6) // break; // //ds.Seek((long)(y * 1024L * 8L) + (long)(x * 8L), System.IO.SeekOrigin.Begin); // // for (int j = 0; j < 6; j++) // // { // // Half[] half = Half.ConvertToHalf(new float[] { cube.Color[j].Red, cube.Color[j].Green, cube.Color[j].Blue }); // // ds.Write<Half4>(new Half4(half[0], half[1], half[2], new Half())); // // } //} // ambientLightTexture.UnlockRectangle(0); //if (lightcubearr.Count <= 32*6 && lightcubearr.Count > 0) // Renderer.Instance.effect.SetValue<Vector4>("ambientLight", lightcubearr.ToArray()); //RenderItem thatone = null; //foreach (SourceModel chl in prop.items) //{ // foreach (BodyPart item in chl.BodyParts) // { // foreach (Model mdl in item.Models) // { // if (mdl.Meshes[0].items[0].vb != null) // { // thatone = mdl.Meshes[0].items[0]; // break; // } // } // } //} //if (thatone != null) //{ // ushort ibid; // if (thatone.ib == null) // ibid = 0; // else // ibid = thatone.ib.IndexBufferID; // ulong callkey = SortItem.GenerateBits(SortItem.FSLayer.GAME, SortItem.Viewport.STATIC, SortItem.VPLayer.WORLD, SortItem.Translucency.NORMAL, thatone.material.MaterialID, 0, ibid, thatone.vb.VertexBufferID); // RenderDelegate callvalue = new RenderDelegate(thatone.Render); // calls.Add(new KeyValuePair<ulong, RenderDelegate>(callkey, callvalue)); //} // submit call to renderer renderCalls = calls; Renderer.Instance.drawCalls.AddRange(renderCalls); } else { Renderer.Instance.drawCalls.AddRange(renderCalls); } LastCluster = CurrentCluster; //VisualizeBSP(); //VisualizeCollision(); }
void ReadLeafs(Header header, BinaryReader br) { // Determine size int leafSize = 56; if (header.version == 20 || header.version == 17) { if (header.lumps[10].filelen % 32 == 0) leafSize = 32; else System.Console.WriteLine("Problem reading leafs.."); } numLeafs = header.lumps[10].filelen / leafSize; leafs = new dleaf_t[numLeafs]; for (int i = 0; i < numLeafs; i++) { br.BaseStream.Seek(header.lumps[10].fileofs + (i * leafSize), SeekOrigin.Begin); dleaf_t leaf = new dleaf_t(); leaf.contents = br.ReadInt32(); leaf.cluster = br.ReadInt16(); if (leaf.cluster > numClusters) numClusters = leaf.cluster + 1; leaf.area = 0;//br.ReadInt16(); leaf.flags = br.ReadInt16(); leaf.mins = SourceParser.SwapZY(new Vector3(br.ReadInt16(), br.ReadInt16(), br.ReadInt16())); // 3 For frustrum culling leaf.maxs = SourceParser.SwapZY(new Vector3(br.ReadInt16(), br.ReadInt16(), br.ReadInt16())); // 3 leaf.firstleafface = br.ReadUInt16(); leaf.numleaffaces = br.ReadUInt16(); leaf.firstleafbrush = br.ReadUInt16(); leaf.numleafbrushes = br.ReadUInt16(); leaf.leafWaterDataID = br.ReadInt16(); leaf.ambientLighting = new CompressedLightCube(); if (leafSize > 32) { leaf.ambientLighting.Color = new Vector3[6]; for (int j = 0; j < 6; j++) { RGBExp color = new RGBExp(); color.r = br.ReadByte(); color.g = br.ReadByte(); color.b = br.ReadByte(); color.exp = br.ReadSByte(); float r = SourceParser.TexLightToLinear((int)color.r, color.exp ) * 255; float g = SourceParser.TexLightToLinear((int)color.g, color.exp ) * 255; float b = SourceParser.TexLightToLinear((int)color.b, color.exp ) * 255; leaf.ambientLighting.Color[j] = new Vector3(r, g, b); } } //else if (map.HDRCubes != null && i < map.HDRCubes.Length) //{ // leaf.ambientLighting = map.HDRCubes[i]; //} //else if (map.LDRCubes != null && i < map.LDRCubes.Length) //{ // leaf.ambientLighting = map.LDRCubes[i]; //} //else //{ // System.Console.WriteLine("No ambient cube for this leaf :("); //} leaf.padding = 0;//br.ReadInt16(); leaf.staticProps = new List<SourceProp>(); leafs[i] = leaf; } numAreas = 0; }