Esempio n. 1
0
        private static void SerializeFace(ValveBspFile bsp, int index, VertexArray verts)
        {
            const SurfFlags ignoreFlags = SurfFlags.NODRAW | SurfFlags.LIGHT;
            const SurfFlags skyFlags    = SurfFlags.SKY2D | SurfFlags.SKY;

            var face    = bsp.FacesHdr[index];
            var texInfo = bsp.TextureInfos[face.TexInfo];
            var plane   = bsp.Planes[face.PlaneNum];

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

            if (face.DispInfo != -1)
            {
                SerializeDisplacement(bsp, index, ref face, ref plane, verts);
                return;
            }

            var texData  = bsp.TextureData[texInfo.TexData];
            var texScale = new Vector2(1f / texData.Width, 1f / texData.Height);

            verts.BeginPrimitive();

            for (int i = face.FirstEdge, iEnd = face.FirstEdge + face.NumEdges; i < iEnd; ++i)
            {
                var vert = bsp.GetVertexFromSurfEdgeId(i);
                var uv   = GetUv(vert, texInfo.TextureUAxis, texInfo.TextureVAxis) * texScale;
                var uv2  = GetLightmapUv(bsp, vert, index, ref face, ref texInfo);

                verts.AddVertex(vert, texCoord: uv, lightmapCoord: uv2);
            }

            var numPrimitives  = face.NumPrimitives & 0x7fff;
            var texStringIndex = isSky ? -1 : texData.NameStringTableId;

            if (numPrimitives == 0)
            {
                verts.CommitPrimitive(PrimitiveType.TriangleFan, texStringIndex);
                return;
            }

            if (_sIndicesBuffer == null)
            {
                _sIndicesBuffer = new List <int>();
            }

            for (int i = face.FirstPrimitive, iEnd = face.FirstPrimitive + numPrimitives; i < iEnd; ++i)
            {
                var primitive = bsp.Primitives[i];
                for (int j = primitive.FirstIndex, jEnd = primitive.FirstIndex + primitive.IndexCount; j < jEnd; ++j)
                {
                    _sIndicesBuffer.Add(bsp.PrimitiveIndices[j]);
                }

                verts.CommitPrimitive(primitive.Type, texStringIndex, _sIndicesBuffer);
                _sIndicesBuffer.Clear();
            }
        }
Esempio 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;
        }
Esempio n. 3
0
        private MeshGroup GenerateMesh(MeshBuilder meshGen, IEnumerable <int> faceIndices)
        {
            var mesh             = new Mesh();
            var primitiveIndices = new List <int>();

            const SurfFlags ignoreFlags = SurfFlags.NODRAW | SurfFlags.SKIP | SurfFlags.SKY | SurfFlags.SKY2D | SurfFlags.HINT | SurfFlags.TRIGGER;

            var corners  = new Vector3[4];
            var lightmap = GetLightmap();

            using (Profiler.Begin("GenerateMesh"))
            {
                foreach (var faceIndex in faceIndices)
                {
                    var face  = FacesHdr[faceIndex];
                    var plane = Planes[face.PlaneNum];
                    var tex   = TexInfos[face.TexInfo];

                    if ((tex.Flags & ignoreFlags) != 0 || tex.TexData < 0)
                    {
                        continue;
                    }
                    var texData = TexData[tex.TexData];
                    var uvScale = new Vector2(1f / texData.Width, 1f / texData.Height);
                    var matName = GetTexdataString(texData.NameStringTableId) + ".vmt";
                    var mat     = World.Resources.LoadVmt(matName).GetMaterial(World.Resources);
                    mat.SetTexture("_LightMap", lightmap);

                    Rect lightmapRect;
                    if (!_lightmapRects.TryGetValue(faceIndex, out lightmapRect))
                    {
                        lightmapRect = new Rect(0f, 0f, 1f, 1f);
                    }

                    if (face.DispInfo != -1)
                    {
                        Debug.Assert(face.NumEdges == 4);

                        var disp             = DispInfos[face.DispInfo];
                        var size             = 1 << disp.Power;
                        var firstCorner      = 0;
                        var firstCornerDist2 = float.MaxValue;

                        for (var surfId = face.FirstEdge; surfId < face.FirstEdge + face.NumEdges; ++surfId)
                        {
                            var surfEdge  = SurfEdges[surfId];
                            var edgeIndex = Math.Abs(surfEdge);
                            var edge      = Edges[edgeIndex];
                            var vert      = Vertices[surfEdge >= 0 ? edge.A : edge.B];

                            corners[surfId - face.FirstEdge] = vert;

                            var dist2 = ((Vector3)disp.StartPosition - vert).sqrMagnitude;
                            if (dist2 < firstCornerDist2)
                            {
                                firstCorner      = surfId - face.FirstEdge;
                                firstCornerDist2 = dist2;
                            }
                        }

                        for (var x = 0; x < size; ++x)
                        {
                            for (var y = 0; y < size; ++y)
                            {
                                var a = GetDisplacementVertex(disp.DispVertStart, x, y, size, corners, firstCorner);
                                var b = GetDisplacementVertex(disp.DispVertStart, x, y + 1, size, corners, firstCorner);
                                var c = GetDisplacementVertex(disp.DispVertStart, x + 1, y + 1, size, corners, firstCorner);
                                var d = GetDisplacementVertex(disp.DispVertStart, x + 1, y, size, corners, firstCorner);

                                meshGen.StartFace(mat);
                                meshGen.AddVertex(a * SourceToUnityUnits, plane.Normal, Vector2.zero, GetLightmapUv(x, y, size, face, lightmapRect));
                                meshGen.AddVertex(b * SourceToUnityUnits, plane.Normal, Vector2.zero, GetLightmapUv(x, y + 1, size, face, lightmapRect));
                                meshGen.AddVertex(c * SourceToUnityUnits, plane.Normal, Vector2.zero, GetLightmapUv(x + 1, y + 1, size, face, lightmapRect));
                                meshGen.AddVertex(d * SourceToUnityUnits, plane.Normal, Vector2.zero, GetLightmapUv(x + 1, y, size, face, lightmapRect));
                                meshGen.AddPrimitive(PrimitiveType.TriangleStrip);
                                meshGen.EndFace();
                            }
                        }

                        continue;
                    }

                    meshGen.StartFace(mat);

                    for (var surfId = face.FirstEdge; surfId < face.FirstEdge + face.NumEdges; ++surfId)
                    {
                        var surfEdge   = SurfEdges[surfId];
                        var edgeIndex  = Math.Abs(surfEdge);
                        var edge       = Edges[edgeIndex];
                        var vert       = Vertices[surfEdge >= 0 ? edge.A : edge.B];
                        var textureUv  = Vector2.Scale(GetUv(vert, tex.TextureUAxis, tex.TextureVAxis), uvScale);
                        var lightmapUv = GetLightmapUv(vert, face, tex, lightmapRect);

                        meshGen.AddVertex((Vector3)vert * SourceToUnityUnits, plane.Normal, textureUv, lightmapUv);
                    }

                    if (face.NumPrimitives == 0 || face.NumPrimitives >= 0x8000)
                    {
                        meshGen.AddPrimitive(PrimitiveType.TriangleStrip);
                        meshGen.EndFace();
                        continue;
                    }

                    for (var primId = face.FirstPrimitive; primId < face.FirstPrimitive + face.NumPrimitives; ++primId)
                    {
                        var primitive = Primitives[primId];
                        for (var indexId = primitive.FirstIndex;
                             indexId < primitive.FirstIndex + primitive.IndexCount;
                             ++indexId)
                        {
                            primitiveIndices.Add(PrimitiveIndices[indexId]);
                        }

                        meshGen.AddPrimitive(primitive.Type, primitiveIndices);

                        primitiveIndices.Clear();
                    }

                    meshGen.EndFace();
                }
            }

            meshGen.CopyToMesh(mesh);

            return(new MeshGroup(mesh, meshGen.GetMaterials()));
        }