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 BuildPatch(Quake3Face quake3Face, BspSubmeshStreams submesh) { var width = quake3Face.sizeX; var height = quake3Face.sizeY; if (width * height != quake3Face.numOfVerts) { throw new BspFormatException("wrong patch point count"); } for (int i = 0; i < width - 1; i += 1) { for (int j = 0; j < height - 1; j += 1) { AddVertexToMesh(quake3Face.vertexIndex + (i) + (j) * width, submesh); AddVertexToMesh(quake3Face.vertexIndex + (i + 1) + (j + 1) * width, submesh); AddVertexToMesh(quake3Face.vertexIndex + (i + 1) + (j) * width, submesh); AddVertexToMesh(quake3Face.vertexIndex + (i) + (j) * width, submesh); AddVertexToMesh(quake3Face.vertexIndex + (i) + (j + 1) * width, submesh); AddVertexToMesh(quake3Face.vertexIndex + (i + 1) + (j + 1) * width, submesh); } } }
protected override void BuildScene() { this.CollectLeafsInCluster(); //BuildVisibilityList(); var node = new Node(); this.Scene.Nodes.Add(node); if (this.buildBsp) { this.Scene.Geometries.Add(streamMesh); var meshBuilder = new MeshBuilder(streamMesh, this); node.Mesh = streamMesh; var vsdNodes = new BspVsdTreeNode[this.nodes.Length]; for (int index = 0; index < this.nodes.Length; index++) { var sourceNode = this.nodes[index]; vsdNodes[index] = new BspVsdTreeNode { Min = new Float3(sourceNode.box.boxMinX, sourceNode.box.boxMinY, sourceNode.box.boxMinZ), Max = new Float3(sourceNode.box.boxMaxX, sourceNode.box.boxMaxY, sourceNode.box.boxMaxZ), PositiveNodeIndex = sourceNode.front, NegativeNodeIndex = sourceNode.back, N = this.planes[sourceNode.planenum].normal, D = this.planes[sourceNode.planenum].dist, }; if (sourceNode.face_num > 0) { //TODO: put this faces into geometry sourceNode.face_num = sourceNode.face_num; } } List<int> visibleClustersLookup = new List<int>(); List<int> visibleMeshesLookup = new List<int>(); var vsdLeaves = new BspVsdTreeLeaf[this.leaves.Length]; var vsdClusters = new BspVsdTreeCluster[this.clusters.Length]; //int nodesMeshId; //var nodesMesh = meshBuilder.EnsureSubMesh(new BspSubmeshKey(-1, new BspMaterialKey(0, 0)), out nodesMeshId); //for (int index = 0; index < this.nodes.Length; index++) //{ // for (int j = nodes[index].face_id; j < nodes[index].face_id + nodes[index].face_num;++j ) // this.BuildFace(ref this.faces[j], nodesMesh, streamMesh); //} for (int index = 0; index < this.leaves.Length; index++) { var sourceLeaf = this.leaves[index]; vsdLeaves[index] = new BspVsdTreeLeaf { Min = new Float3(sourceLeaf.box.boxMinX, sourceLeaf.box.boxMinY, sourceLeaf.box.boxMinZ), Max = new Float3(sourceLeaf.box.boxMaxX, sourceLeaf.box.boxMaxY, sourceLeaf.box.boxMaxZ), Cluster = sourceLeaf.cluster, }; } for (int index = 0; index < this.clusters.Length; index++) { Dictionary<int, bool> uniqueSubmeshes = new Dictionary<int, bool>(); var sourceCluster = this.clusters[index]; vsdClusters[index] = new BspVsdTreeCluster { VisibleClustersCount = sourceCluster.visiblity.Count, VisibleClustersOffset = visibleClustersLookup.Count, VisibleMeshesOffset = visibleMeshesLookup.Count, }; visibleClustersLookup.AddRange(sourceCluster.visiblity); Dictionary<int, bool> uniqueFaces = new Dictionary<int, bool>(); foreach (var leafIndex in sourceCluster.leaves) { var sourceLeaf = this.leaves[leafIndex]; var faceBegin = sourceLeaf.firstleafface; var faceEnd = faceBegin + sourceLeaf.numleaffaces; for (int f = faceBegin; f < faceEnd; ++f) { uniqueFaces[this.leafFaces[f]] = true; } } foreach (var uniqueFace in uniqueFaces) { int texIndex = 0; // this.texInfo[this.faces[faceIndex].texinfo].texdata; int lightmapIndex = 0; //this.faces[faceIndex].lightmap; int meshIndex; SeparateStreamsSubmesh subMesh = meshBuilder.EnsureSubMesh(new BspSubmeshKey(index, new BspMaterialKey(texIndex, lightmapIndex)), out meshIndex); if (!uniqueSubmeshes.ContainsKey(meshIndex)) { visibleMeshesLookup.Add(meshIndex); uniqueSubmeshes[meshIndex] = true; } BspSubmeshStreams submeshStreams= new BspSubmeshStreams(subMesh, meshStreams,StreamConverterFactory); this.BuildFace(ref this.faces[uniqueFace.Key], submeshStreams); } vsdClusters[index].VisibleMeshesCount = visibleMeshesLookup.Count - vsdClusters[index].VisibleMeshesOffset; } //for (int index = 0; index < usedFaces.Length; index++) //{ // if (!usedFaces[index]) // { // for (int i = 0; i < this.models.Length; i++) // { // if (this.models[i].firstface <= index && this.models[i].firstface+this.models[i].numfaces > index) // { // Trace.WriteLine(string.Format("Lost face {0} belongs to model {1}", index, i)); // break; // } // } // for (int i = 0; i < this.nodes.Length; i++) // { // if (this.nodes[i].face_id <= index && this.nodes[i].face_id + this.nodes[i].face_num > index) // { // Trace.WriteLine(string.Format("Lost face {0} belongs to node {1}", index, i)); // break; // } // } // for (int i = 0; i < this.leaves.Length; i++) // { // var begin = this.leaves[i].firstleafface; // var end = begin+this.leaves[i].numleaffaces; // while (begin<end) // { // if (leafFaces[begin] == index) // { // Trace.WriteLine(string.Format("Lost face {0} belongs to leaf {1}", index, i)); // break; // } // ++begin; // } // } // } //} this.Scene.VsdProvider = new BspVsdProvider { VisibleClustersLookupTable = visibleClustersLookup.ToArray(), VisibleMeshesLookupTable = visibleMeshesLookup.ToArray(), Clusters = vsdClusters, Leaves = vsdLeaves, Models = (from model in this.models select new BspVsdTreeModel { RootNode = model.headnode }).ToArray(), Level = streamMesh, Nodes = vsdNodes }; this.BuildAdditionalNodes(); } else { this.BuildAdditionalNodes(); node.Mesh = this.Scene.Geometries[0]; } this.BuildEntityNodes(this.entitiesInfo); }
private static void AddVertexToMesh(int index, BspSubmeshStreams subMesh) { subMesh.AddToAllStreams(index); }