Ejemplo n.º 1
0
        private MeshData GetOrCreateMeshData(ValveBspFile bsp, GeometryPage page, string matPath, bool cacheVertices = true)
        {
            MaterialGroup matGroup;

            var matDictIndex = MaterialDictionary.GetResourceIndex(bsp, matPath);

            if (!page.MaterialIndices.TryGetValue(matDictIndex, out int matIndex))
            {
                var vmt = ValveMaterialFile.FromProvider(MaterialDictionary.GetResourcePath(bsp, matDictIndex), bsp.PakFile, Program.Resources);

                matGroup = new MaterialGroup(matIndex = page.Materials.Count, cacheVertices)
                {
                    Material = matDictIndex
                };
                page.MaterialIndices.Add(matDictIndex, matIndex);
                page.Materials.Add(matGroup);

                FindMaterialAttributes(vmt, matGroup.MeshData.Attributes);
            }
            else
            {
                matGroup = page.Materials[matIndex];
            }

            return(matGroup.MeshData);
        }
Ejemplo n.º 2
0
        private void WriteFace(ValveBspFile bsp, int faceIndex, GeometryPage page, List <Face> outFaces)
        {
            const SurfFlags ignoreFlags = SurfFlags.NODRAW | SurfFlags.LIGHT | SurfFlags.SKY | SurfFlags.SKY2D;

            var faceInfo = bsp.Faces[faceIndex];
            var texInfo  = bsp.TextureInfos[faceInfo.TexInfo];

            if ((texInfo.Flags & ignoreFlags) != 0 || texInfo.TexData < 0)
            {
                return;
            }

            var texData = bsp.TextureData[texInfo.TexData];

            var matPath  = bsp.GetTextureString(texData.NameStringTableId);
            var meshData = GetOrCreateMeshData(bsp, page, matPath);

            if (Skip)
            {
                return;
            }

            MeshElement elem;
            Face        face;

            var leafFaceIndex = outFaces.FindIndex(x => x.Material == meshData.MaterialIndex);

            if (leafFaceIndex != -1)
            {
                face = outFaces[leafFaceIndex];
                elem = meshData.Elements[face.Element];
            }
            else
            {
                elem = new MeshElement
                {
                    Mode        = PrimitiveType.Triangles,
                    Material    = 0,
                    IndexOffset = meshData.Indices.Count
                };

                face = new Face
                {
                    Material = meshData.MaterialIndex,
                    Element  = meshData.Elements.Count
                };

                outFaces.Add(face);
                meshData.Elements.Add(elem);
            }

            var texScale = new Vector2(1f / Math.Max(texData.Width, 1), 1f / Math.Max(texData.Height, 1));

            Vector2 lmMin, lmSize;

            bsp.LightmapLayout.GetUvs(faceIndex, out lmMin, out lmSize);

            if (faceInfo.DispInfo != -1)
            {
                var disp = bsp.DisplacementManager[faceInfo.DispInfo];

                SourceUtils.Vector3 c0, c1, c2, c3;
                disp.GetCorners(out c0, out c1, out c2, out c3);

                var uv00 = GetUv(c0, texInfo.TextureUAxis, texInfo.TextureVAxis) * texScale;
                var uv10 = GetUv(c3, texInfo.TextureUAxis, texInfo.TextureVAxis) * texScale;
                var uv01 = GetUv(c1, texInfo.TextureUAxis, texInfo.TextureVAxis) * texScale;
                var uv11 = GetUv(c2, texInfo.TextureUAxis, texInfo.TextureVAxis) * texScale;

                var subDivMul = 1f / disp.Subdivisions;

                for (var y = 0; y < disp.Subdivisions; ++y)
                {
                    meshData.BeginPrimitive();
                    var v0 = (y + 0) * subDivMul;
                    var v1 = (y + 1) * subDivMul;

                    for (var x = 0; x < disp.Size; ++x)
                    {
                        var u = x * subDivMul;

                        meshData.VertexAttribute(VertexAttribute.Position, disp.GetPosition(x, y + 0));
                        meshData.VertexAttribute(VertexAttribute.Normal, disp.GetNormal(x, y + 0));
                        meshData.VertexAttribute(VertexAttribute.Uv,
                                                 (uv00 * (1f - u) + uv10 * u) * (1f - v0) + (uv01 * (1f - u) + uv11 * u) * v0);
                        meshData.VertexAttribute(VertexAttribute.Uv2, new Vector2(u, v0) * lmSize + lmMin);
                        meshData.VertexAttribute(VertexAttribute.Alpha, disp.GetAlpha(x, y + 0));
                        meshData.CommitVertex();

                        meshData.VertexAttribute(VertexAttribute.Position, disp.GetPosition(x, y + 1));
                        meshData.VertexAttribute(VertexAttribute.Normal, disp.GetNormal(x, y + 1));
                        meshData.VertexAttribute(VertexAttribute.Uv,
                                                 (uv00 * (1f - u) + uv10 * u) * (1f - v1) + (uv01 * (1f - u) + uv11 * u) * v1);
                        meshData.VertexAttribute(VertexAttribute.Uv2, new Vector2(u, v1) * lmSize + lmMin);
                        meshData.VertexAttribute(VertexAttribute.Alpha, disp.GetAlpha(x, y + 1));
                        meshData.CommitVertex();
                    }

                    meshData.CommitPrimitive(PrimitiveType.TriangleStrip);
                }
            }
            else
            {
                meshData.BeginPrimitive();

                var plane = bsp.Planes[faceInfo.PlaneNum];

                for (int k = faceInfo.FirstEdge, kEnd = faceInfo.FirstEdge + faceInfo.NumEdges; k < kEnd; ++k)
                {
                    var vert = bsp.GetVertexFromSurfEdgeId(k);
                    var uv   = GetUv(vert, texInfo.TextureUAxis, texInfo.TextureVAxis);
                    var uv2  = GetUv(vert, texInfo.LightmapUAxis, texInfo.LightmapVAxis);

                    uv2.X -= faceInfo.LightMapOffsetX;
                    uv2.Y -= faceInfo.LightMapOffsetY;
                    uv2.X /= Math.Max(faceInfo.LightMapSizeX, 1);
                    uv2.Y /= Math.Max(faceInfo.LightMapSizeY, 1);

                    uv2 *= lmSize;
                    uv2 += lmMin;

                    meshData.VertexAttribute(VertexAttribute.Position, vert);
                    meshData.VertexAttribute(VertexAttribute.Normal, plane.Normal);
                    meshData.VertexAttribute(VertexAttribute.Uv, uv * texScale);
                    meshData.VertexAttribute(VertexAttribute.Uv2, uv2);

                    meshData.CommitVertex();
                }

                var numPrimitives = faceInfo.NumPrimitives & 0x7fff;

                if (numPrimitives == 0)
                {
                    meshData.CommitPrimitive(PrimitiveType.TriangleFan);
                }
                else
                {
                    if (_sIndexBuffer == null)
                    {
                        _sIndexBuffer = new List <int>();
                    }
                    else
                    {
                        _sIndexBuffer.Clear();
                    }

                    var indices = _sIndexBuffer;

                    for (int k = faceInfo.FirstPrimitive, kEnd = faceInfo.FirstPrimitive + numPrimitives;
                         k < kEnd;
                         ++k)
                    {
                        var primitive = bsp.Primitives[k];
                        for (int l = primitive.FirstIndex, lEnd = primitive.FirstIndex + primitive.IndexCount;
                             l < lEnd;
                             ++l)
                        {
                            indices.Add(bsp.PrimitiveIndices[l]);
                        }

                        PrimitiveType mode;
                        switch (primitive.Type)
                        {
                        case ValveBsp.PrimitiveType.TriangleStrip:
                            mode = PrimitiveType.TriangleStrip;
                            break;

                        case ValveBsp.PrimitiveType.TriangleFan:
                            mode = PrimitiveType.TriangleFan;
                            break;

                        case ValveBsp.PrimitiveType.TriangleList:
                            mode = PrimitiveType.Triangles;
                            break;

                        default:
                            throw new NotImplementedException();
                        }

                        meshData.CommitPrimitive(mode, indices);
                        indices.Clear();
                    }
                }
            }

            elem.IndexCount = meshData.Indices.Count - elem.IndexOffset;
        }