public BrushModel(Map map, ResourceManager resourceManager) { this.map = map; this.resourceManager = resourceManager; var rootNode = map.Lumps.GetNodes()[0]; Read(rootNode); var meshParts = new MeshPart[indicesByTexture.Count]; var modelMaterials = new SourceMaterial[indicesByTexture.Count]; var i = 0; foreach (var(materialName, indices) in indicesByTexture) { var indexPositions = new Dictionary <uint, uint>(); if (indices.Count % 3 != 0) { throw new Exception("Broken triangles"); } meshParts[i] = new MeshPart { Indices = indices.ToArray() }; modelMaterials[i] = resourceManager.Get <SourceMaterial>(materialName); i++; } Mesh = new Mesh { Vertices = vertices.ToArray(), Parts = meshParts }; Materials = modelMaterials; }
public T Get <T>(string name) where T : Resource { if (name == null) { return(null); } //Sanitize resource string name = name.Replace('\\', '/').Trim().ToLower(); if (!fileTypes.ContainsKey(typeof(T))) { throw new ArgumentException("Unsupported resource type"); } var nameWithType = name.ToLower(); var path = paths[typeof(T)]; var fileType = fileTypes[typeof(T)]; if (!nameWithType.StartsWith(path, StringComparison.Ordinal)) { nameWithType = path + nameWithType; } if (!nameWithType.EndsWith(fileType, StringComparison.Ordinal)) { nameWithType = nameWithType + fileType; } if (!resources.TryGetValue(nameWithType, out Resource resource)) { var data = ReadResourceFromDisk(nameWithType); if (data != null) { using (var reader = new BinaryReader(new MemoryStream(data))) { resource = (T)Activator.CreateInstance(typeof(T), reader, data.Length); } } else { if (typeof(T) == typeof(SourceMaterial)) { //Material not found => try to load texture and create simple material var texture = Get <SourceTexture>(name); if (texture == null) { return(null); } resource = new SourceMaterial(name); } else if (typeof(T) == typeof(SourceMeshStrip)) { return(Get <T>(name + ".dx90")); } else { return(null); } } resources[nameWithType] = resource; } if (!(resource is T)) { return(null); } return((T)resource); }
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator private void Read(Leaf leaf) { var bspVertices = map.Lumps.GetVertices(); var leafFaces = map.Lumps.GetLeafFaces(); var faces = map.Lumps.GetFaces(); var edges = map.Lumps.GetEdges(); var surfEdges = map.Lumps.GetSurfaceEdges(); var dispInfos = map.Lumps.GetDisplacementInfos(); for (var leafFaceIndex = leaf.FirstLeafFace; leafFaceIndex < leaf.FirstLeafFace + leaf.LeafFacesCount; leafFaceIndex++) { var faceIndex = leafFaces[leafFaceIndex]; var face = faces[faceIndex]; var texInfo = map.Lumps.GetTextureInfo()[face.TextureInfo]; var texData = map.Lumps.GetTextureData()[texInfo.TextureData]; var textureOffset = map.Lumps.GetTextureDataStringTable()[texData.NameStringTableId]; var textureName = map.Lumps.GetTextureDataString()[textureOffset]; uint rootVertex = 0; SourceMaterial material = resourceManager.Get <SourceMaterial>(textureName); SourceTexture texture = resourceManager.Get <SourceTexture>(material?.BaseTextureName); float texWidth = texData.Width; float texHeight = texData.Height; if (texture != null) { if (texture.Header.Width != texData.Width || texture.Header.Height != texData.Height) { texWidth = texture.Header.Width; texHeight = texture.Header.Height; } } var faceVertices = new Dictionary <uint, uint>(); //Just to make sure that there's no duplicates for (var surfEdgeIndex = face.FirstEdge; surfEdgeIndex < face.FirstEdge + face.EdgesCount; surfEdgeIndex++) { var edgeIndex = surfEdges[surfEdgeIndex]; var edge = edges[Math.Abs(edgeIndex)]; //Push the two vertices of the first edge if (surfEdgeIndex == face.FirstEdge) { if (!faceVertices.ContainsKey(edge.VertexIndex[edgeIndex > 0 ? 0 : 1])) { rootVertex = edge.VertexIndex[edgeIndex > 0 ? 0 : 1]; var position = bspVertices[rootVertex]; var vertex = new Vertex { Position = position, TextureCoord = CalculateUV(position, texInfo.TextureVecsS, texInfo.TextureVecsT, texWidth, texHeight) }; faceVertices.Add(rootVertex, (uint)vertices.Count); vertices.Add(vertex); } continue; } //Edge must not be connected to the root vertex if (edge.VertexIndex[0] == rootVertex || edge.VertexIndex[1] == rootVertex) { continue; } //Edge is on opposite side of the first edge => push the for (var i = 0; i < 2; i++) { if (!faceVertices.ContainsKey(edge.VertexIndex[i])) { var position = bspVertices[edge.VertexIndex[i]]; var vertex = new Vertex { Position = position, TextureCoord = CalculateUV(position, texInfo.TextureVecsS, texInfo.TextureVecsT, texWidth, texHeight) }; faceVertices.Add(edge.VertexIndex[i], (uint)vertices.Count); vertices.Add(vertex); } } var indices = GetIndices(textureName); indices.Add(faceVertices[rootVertex]); if (edgeIndex < 0) { indices.Add(faceVertices[edge.VertexIndex[1]]); indices.Add(faceVertices[edge.VertexIndex[0]]); } else { indices.Add(faceVertices[edge.VertexIndex[0]]); indices.Add(faceVertices[edge.VertexIndex[1]]); } } if (face.DisplacementInfo != -1) { var dispInfo = dispInfos[face.DisplacementInfo]; Read(dispInfo, texInfo); } } }