protected override IEnumerable <string> OnFindResourcePaths(ValveBspFile bsp) { for (var i = 0; i < bsp.TextureStringTable.Length; ++i) { yield return(bsp.GetTextureString(i)); } for (var i = 0; i < bsp.StaticProps.ModelCount; ++i) { var modelName = bsp.StaticProps.GetModelName(i); var mdl = StudioModelFile.FromProvider(modelName, bsp.PakFile, Program.Resources); if (mdl == null) { continue; } for (var j = 0; j < mdl.MaterialCount; ++j) { yield return(mdl.GetMaterialName(j, bsp.PakFile, Program.Resources)); } } foreach (var entity in bsp.Entities) { switch (entity.ClassName) { case "move_rope": case "keyframe_rope": yield return(entity["RopeMaterial"]); break; } } }
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; }