예제 #1
0
        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;
        }
예제 #2
0
        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);
        }
예제 #3
0
#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);
                }
            }
        }