private void BuildFace(ref SourceFace face, BspSubmeshStreams subMesh) { Vertex[] faceVertices = new Vertex[face.numedges]; var plane = this.planes[face.planenum]; var texture_id = this.texInfo[face.texinfo].texdata; Float2 minUV0 = new Float2(float.MaxValue, float.MaxValue); Float2 minUV1 = new Float2(float.MaxValue, float.MaxValue); Float2 maxUV1 = new Float2(float.MinValue, float.MinValue); int nextShouldBe = -1; for (int index = 0; index < faceVertices.Length; index++) { var listOfEdgesIndex = face.firstedge + index; if (listOfEdgesIndex >= this.listOfEdges.Length) { throw new BspFormatException( string.Format("Edge list index {0} is out of range [0..{1}]", listOfEdgesIndex, this.listOfEdges.Length - 1)); } var edgeIndex = this.listOfEdges[listOfEdgesIndex]; if (edgeIndex >= this.edges.Length) { throw new BspFormatException( string.Format("Edge index {0} is out of range [0..{1}]", edgeIndex, this.edges.Length - 1)); } SourceEdge edge; if (edgeIndex >= 0) { edge = this.edges[edgeIndex]; } else { var flippedEdge = this.edges[-edgeIndex]; edge = new SourceEdge { vertex0 = flippedEdge.vertex1, vertex1 = flippedEdge.vertex0 }; } var edgesvertex0 = edge.vertex0; if (edgesvertex0 >= this.vertices.Length) { throw new BspFormatException( string.Format("Vertex index {0} is out of range [0..{1}]", edgesvertex0, this.vertices.Length - 1)); } var edgesvertex1 = edge.vertex1; if (edgesvertex1 >= this.vertices.Length) { throw new BspFormatException( string.Format("Vertex index {0} is out of range [0..{1}]", edgesvertex1, this.vertices.Length - 1)); } if (nextShouldBe >= 0 && nextShouldBe != edgesvertex0) { throw new BspFormatException(string.Format("Wrong edge order")); } nextShouldBe = edgesvertex1; Vertex vertex; this.BuildVertex( this.vertices[(short)edgesvertex0], plane.normal, //(face.side == 0) ? plane.normal : -plane.normal, face, ref this.texInfo[face.texinfo], out vertex); faceVertices[index] = vertex; if (minUV0.X > vertex.UV0.X) { minUV0.X = vertex.UV0.X; } if (minUV0.Y > vertex.UV0.Y) { minUV0.Y = vertex.UV0.Y; } if (minUV1.X > vertex.UV1.X) { minUV1.X = vertex.UV1.X; } if (minUV1.Y > vertex.UV1.Y) { minUV1.Y = vertex.UV1.Y; } if (maxUV1.X < vertex.UV1.X) { maxUV1.X = vertex.UV1.X; } if (maxUV1.Y < vertex.UV1.Y) { maxUV1.Y = vertex.UV1.Y; } } if (this.textures[texture_id].name == "TOOLS/TOOLSSKYBOX") { minUV0.X = 0; minUV0.Y = 0; for (int j = 0; j < (int)face.numedges; ++j) { faceVertices[j].UV0 = new Float3(0, 0, 0); } } int[] indices = new int[faceVertices.Length]; for (int j = 0; j < faceVertices.Length; ++j) { meshStreams.Positions.Add(faceVertices[j].Position); meshStreams.Normals.Add(faceVertices[j].Normal); meshStreams.Colors.Add(faceVertices[j].Color); meshStreams.TexCoord0.Add(new Float2(faceVertices[j].UV0.X, faceVertices[j].UV0.Y)); meshStreams.TexCoord1.Add(new Float2(faceVertices[j].UV1.X, faceVertices[j].UV1.Y)); } for (int j = 1; j < faceVertices.Length - 1; ++j) { subMesh.AddToAllStreams(indices[0]); subMesh.AddToAllStreams(indices[j]); subMesh.AddToAllStreams(indices[j + 1]); } }
//private void BuildSubmeshes(int maxTextures) //{ // int[] textureToMaterial = new int[maxTextures]; // foreach (var quake3Face in this.faces) // { // ++textureToMaterial[this.texInfo[quake3Face.texinfo].texdata]; // } // for (int i = 0; i < maxTextures; ++i) // { // if (textureToMaterial[i] > 0) // { // int index = this.Scene.Materials.Count; // var baseFileName = this.GetMaterialFileName(i); // var imagePath = baseFileName; // var texture = new FileReferenceImage { Path = imagePath }; // this.Scene.Images.Add(texture); // var effect = new SceneEffect // { // //Diffuse = new ImageColorSource { Image = texture } // }; // this.Scene.Effects.Add(effect); // var sceneMaterial = new SceneMaterial { Effect = effect }; // this.Scene.Materials.Add(sceneMaterial); // submeshes[i].Material = sceneMaterial; // textureToMaterial[i] = index; // } // } //} //private void BuildVisibilityList() //{ // for (int i = 0; i < leaves.Length; ++i) // { // Dictionary<int, bool> map = new Dictionary<int, bool>(); // if (leaves[i].cluster >= 0) // foreach (var c in clusters[leaves[i].cluster].visiblity) // foreach (var l in clusters[c].lists) // map[l] = true; // leaves[i].VisibleLeaves = new List<int>(); // foreach (var j in map.Keys) // if (i != j) // leaves[i].VisibleLeaves.Add(j); // } //} private void BuildVertex(Float3 vector3, Float3 n, SourceFace f, ref SourceTexInfo surf, out Vertex res) { res = new Vertex { Position = vector3, Normal = n, Color = Color.White, UV0 = new Float3( Float3.Dot(surf.vectorS, vector3) + surf.distS, Float3.Dot(surf.vectorT, vector3) + surf.distT, 0.0f), UV1 = new Float3( Float3.Dot(surf.lm_vectorS, vector3) + surf.lm_distS - f.LightmapTextureMinsInLuxels[0], Float3.Dot(surf.lm_vectorT, vector3) + surf.lm_distT - f.LightmapTextureMinsInLuxels[1], 0.0f) }; //if (f.LightmapTextureSizeInLuxels[0] == 0) res.UV1.X = (res.UV1.X + this.safeOffset) / (f.LightmapTextureSizeInLuxels[0] + 1.0f + this.safeBorderWidth); res.UV1.Y = (res.UV1.Y + this.safeOffset) / (f.LightmapTextureSizeInLuxels[1] + 1.0f + this.safeBorderWidth); SourceTexData tex = this.textures[surf.texdata]; res.UV0 = new Float3( res.UV0.X / ((tex.width != 0) ? tex.width : 256.0f), res.UV0.Y / ((tex.height != 0) ? tex.height : 256.0f), 0.0f); }
protected virtual void ReadFace(ref SourceFace face) { this.Stream.ReadUInt32(); //source.ReadBytes(4); face.planenum = this.Stream.ReadUInt16(); // the plane number face.side = (byte)this.Stream.ReadByte(); // faces opposite to the node's plane direction face.onNode = (byte)this.Stream.ReadByte(); // 1 of on node, 0 if in leaf face.firstedge = this.Stream.ReadInt32(); // index into surfedges face.numedges = this.Stream.ReadInt16(); // number of surfedges face.texinfo = this.Stream.ReadInt16(); // texture info face.dispinfo = this.Stream.ReadInt16(); // displacement info this.Stream.ReadBytes(50); face.origFace = this.Stream.ReadInt32(); // original face this was split from face.smoothingGroups = this.Stream.ReadUInt32(); // lightmap smoothing group }