示例#1
0
        public StudioModelPage GetStudioModelPage([Url] string map, [Url] int index)
        {
            var bsp = Program.GetMap(map);

            var info = IndexController.GetPageLayout(bsp, StudioModelDictionary.GetResourceCount(bsp),
                                                     StudioModelPage.VerticesPerPage,
                                                     null, i => StudioModelDictionary.GetVertexCount(bsp, i)).Skip(index).FirstOrDefault();

            var first = info?.First ?? StudioModelDictionary.GetResourceCount(bsp);
            var count = info?.Count ?? 0;

            var page = new StudioModelPage();

            StudioVertex[] vertices = null;
            int[]          indices  = null;

            for (var i = 0; i < count; ++i)
            {
                var mdlPath = StudioModelDictionary.GetResourcePath(bsp, first + i);
                var vvdPath = mdlPath.Replace(".mdl", ".vvd");
                var vtxPath = mdlPath.Replace(".mdl", ".dx90.vtx");

                var mdlFile = StudioModelFile.FromProvider(mdlPath, bsp.PakFile, Program.Resources);
                var vvdFile = ValveVertexFile.FromProvider(vvdPath, bsp.PakFile, Program.Resources);
                var vtxFile = ValveTriangleFile.FromProvider(vtxPath, mdlFile, vvdFile, bsp.PakFile, Program.Resources);

                StudioModel mdl;
                page.Models.Add(mdl = new StudioModel());

                for (var j = 0; j < mdlFile.BodyPartCount; ++j)
                {
                    SmdBodyPart smdBodyPart;
                    mdl.BodyParts.Add(smdBodyPart = new SmdBodyPart
                    {
                        Name = mdlFile.GetBodyPartName(j)
                    });

                    smdBodyPart.Models.AddRange(mdlFile.GetModels(j).Select((model, modelIndex) =>
                    {
                        var smdModel = new SmdModel();

                        smdModel.Meshes.AddRange(mdlFile.GetMeshes(ref model).Select((mesh, meshIndex) =>
                        {
                            var vertexCount = vtxFile.GetVertexCount(j, modelIndex, 0, meshIndex);
                            if (vertices == null || vertices.Length < vertexCount)
                            {
                                vertices = new StudioVertex[MathHelper.NextPowerOfTwo(vertexCount)];
                            }

                            var indexCount = vtxFile.GetIndexCount(j, modelIndex, 0, meshIndex);
                            if (indices == null || indices.Length < indexCount)
                            {
                                indices = new int[MathHelper.NextPowerOfTwo(indexCount)];
                            }

                            vtxFile.GetVertices(j, modelIndex, 0, meshIndex, vertices);
                            vtxFile.GetIndices(j, modelIndex, 0, meshIndex, indices);

                            var meshData = GetOrCreateMeshData(bsp, page,
                                                               mdlFile.GetMaterialName(mesh.Material, bsp.PakFile, Program.Resources), false);

                            var meshElem = new MeshElement
                            {
                                Mode         = PrimitiveType.Triangles,
                                IndexOffset  = meshData.Indices.Count,
                                VertexOffset = meshData.Vertices.Count
                            };

                            var smdMesh = new SmdMesh
                            {
                                MeshId   = mesh.MeshId,
                                Material = meshData.MaterialIndex,
                                Element  = meshData.Elements.Count
                            };

                            meshData.BeginPrimitive();

                            for (var k = 0; k < vertexCount; ++k)
                            {
                                var vertex = vertices[k];

                                meshData.VertexAttribute(VertexAttribute.Position, vertex.Position);
                                meshData.VertexAttribute(VertexAttribute.Normal, vertex.Normal);
                                meshData.VertexAttribute(VertexAttribute.Uv, new Vector2(vertex.TexCoordX, vertex.TexCoordY));
                                meshData.CommitVertex();
                            }

                            meshData.CommitPrimitive(PrimitiveType.Triangles, indices.Take(indexCount));

                            meshElem.IndexCount  = meshData.Indices.Count - meshElem.IndexOffset;
                            meshElem.VertexCount = meshData.Vertices.Count - meshElem.VertexOffset;

                            meshData.Elements.Add(meshElem);

                            return(smdMesh);
                        }));

                        return(smdModel);
                    }));
                }
            }

            return(page);
        }
示例#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;
        }