private void ReadFaces(BSPParser bspParser, VPKParser vpkParser, CancellationToken cancelToken, Action <float, string> onProgressChanged = null) { for (int i = 0; i < Mathf.RoundToInt(bspParser.faces.Length * FaceLoadPercent); i++) { if (cancelToken.IsCancellationRequested) { return; } dface_t face = bspParser.faces[i]; texflags currentTexFlags = GetFaceTextureFlags(face, bspParser); string textureLocation = GetFaceTextureLocation(face, bspParser); if (!IsUndesiredTexture(textureLocation, currentTexFlags)) { FaceMesh currentFace = new FaceMesh(); currentFace.textureFlag = currentTexFlags; currentFace.lightmapKey = bspParser.faces[i].lightofs; currentFace.faceName = textureLocation; currentFace.material = VMTData.GrabVMT(bspParser, vpkParser, textureLocation); currentFace.meshData = MakeFace(bspParser, face); AddFaceMesh(currentFace, combineMeshesWithSameTexture); } totalItemsLoaded++; onProgressChanged?.Invoke(PercentLoaded, currentMessage); } }
private void GrabDependants(BSPParser bspParser, VPKParser vpkParser) { if (!string.IsNullOrEmpty(includedVmtPath)) { includedVmt = VMTData.GrabVMT(bspParser, vpkParser, includedVmtPath); } if (!string.IsNullOrEmpty(baseTexturePath)) { baseTexture = SourceTexture.GrabTexture(bspParser, vpkParser, baseTexturePath); } if (!string.IsNullOrEmpty(bumpMapPath)) { bumpMap = SourceTexture.GrabTexture(bspParser, vpkParser, bumpMapPath); } if (!string.IsNullOrEmpty(detailMapPath)) { detailMap = SourceTexture.GrabTexture(bspParser, vpkParser, detailMapPath); } }
private void ReadFaceMeshes(MDLParser mdl, VVDParser vvd, VTXParser vtx, BSPParser bspParser, VPKParser vpkParser) { int textureIndex = 0; if (mdl.bodyParts.Length == vtx.bodyParts.Length) { for (int bodyPartIndex = 0; bodyPartIndex < mdl.bodyParts.Length; bodyPartIndex++) { for (int modelIndex = 0; modelIndex < mdl.bodyParts[bodyPartIndex].models.Length; modelIndex++) { //int currentPosition = 0; for (int meshIndex = 0; meshIndex < mdl.bodyParts[bodyPartIndex].models[modelIndex].theMeshes.Length; meshIndex++) { int rootLodIndex = mdl.header1.rootLod; //int rootLodIndex = 0; //int rootLodCount = 1; //if (mdl.header1.numAllowedRootLods == 0) // rootLodCount = vtx.header.numLODs; FaceMesh currentFace = new FaceMesh(); int verticesStartIndex = mdl.bodyParts[bodyPartIndex].models[modelIndex].theMeshes[meshIndex].vertexIndexStart; int vertexCount = 0; //int vertexCount = mdl.bodyParts[bodyPartIndex].models[modelIndex].theMeshes[meshIndex].vertexCount; //int vertexCount = mdl.bodyParts[bodyPartIndex].models[modelIndex].theMeshes[meshIndex].vertexData.lodVertexCount[rootLodIndex]; //int vertexCount = 0; //for (int i = 0; i <= rootLodIndex; i++) // vertexCount += mdl.bodyParts[bodyPartIndex].models[modelIndex].theMeshes[meshIndex].vertexData.lodVertexCount[i]; int trianglesCount = 0; for (int stripGroupIndex = 0; stripGroupIndex < vtx.bodyParts[bodyPartIndex].theVtxModels[modelIndex].theVtxModelLods[rootLodIndex].theVtxMeshes[meshIndex].stripGroupCount; stripGroupIndex++) { var currentStripGroup = vtx.bodyParts[bodyPartIndex].theVtxModels[modelIndex].theVtxModelLods[rootLodIndex].theVtxMeshes[meshIndex].theVtxStripGroups[stripGroupIndex]; for (int stripIndex = 0; stripIndex < currentStripGroup.theVtxStrips.Length; stripIndex++) { var currentStrip = currentStripGroup.theVtxStrips[stripIndex]; if (((StripHeaderFlags_t)currentStrip.flags & StripHeaderFlags_t.STRIP_IS_TRILIST) > 0) { trianglesCount += currentStrip.indexCount; } } } //List<int> triangles = new List<int>(); int[] triangles = new int[trianglesCount]; int trianglesIndex = 0; //for (int countUpLodIndex = 0; countUpLodIndex <= rootLodIndex; countUpLodIndex++) //{ for (int stripGroupIndex = 0; stripGroupIndex < vtx.bodyParts[bodyPartIndex].theVtxModels[modelIndex].theVtxModelLods[rootLodIndex].theVtxMeshes[meshIndex].stripGroupCount; stripGroupIndex++) { //var currentStripGroup = vtx.bodyParts[bodyPartIndex].theVtxModels[modelIndex].theVtxModelLods[rootLodIndex].theVtxMeshes[meshIndex].theVtxStripGroups[0]; var currentStripGroup = vtx.bodyParts[bodyPartIndex].theVtxModels[modelIndex].theVtxModelLods[rootLodIndex].theVtxMeshes[meshIndex].theVtxStripGroups[stripGroupIndex]; //int trianglesCount = currentStripGroup.theVtxIndices.Length; //int[] triangles = new int[trianglesCount]; for (int stripIndex = 0; stripIndex < currentStripGroup.theVtxStrips.Length; stripIndex++) { var currentStrip = currentStripGroup.theVtxStrips[stripIndex]; if (((StripHeaderFlags_t)currentStrip.flags & StripHeaderFlags_t.STRIP_IS_TRILIST) > 0) { for (int indexIndex = 0; indexIndex < currentStrip.indexCount; indexIndex += 3) { int vertexIndexA = verticesStartIndex + currentStripGroup.theVtxVertices[currentStripGroup.theVtxIndices[indexIndex + currentStrip.indexMeshIndex]].originalMeshVertexIndex; int vertexIndexB = verticesStartIndex + currentStripGroup.theVtxVertices[currentStripGroup.theVtxIndices[indexIndex + currentStrip.indexMeshIndex + 2]].originalMeshVertexIndex; int vertexIndexC = verticesStartIndex + currentStripGroup.theVtxVertices[currentStripGroup.theVtxIndices[indexIndex + currentStrip.indexMeshIndex + 1]].originalMeshVertexIndex; vertexCount = Mathf.Max(vertexCount, vertexIndexA, vertexIndexB, vertexIndexC); //if (vertexIndexA < vertices.Length && vertexIndexB < vertices.Length && vertexIndexC < vertices.Length) //{ triangles[trianglesIndex++] = vertexIndexA; triangles[trianglesIndex++] = vertexIndexB; triangles[trianglesIndex++] = vertexIndexC; //triangles.Add(vertexIndexA); //triangles.Add(vertexIndexB); //triangles.Add(vertexIndexC); //} } } } } //} vertexCount += 1; //vertexCount = vvd.vertices.Length; //vertexCount = vvd.header.numLODVertices[rootLodIndex]; Vector3[] vertices = new Vector3[vertexCount]; Vector3[] normals = new Vector3[vertexCount]; Vector2[] uv = new Vector2[vertexCount]; for (int verticesIndex = 0; verticesIndex < vertices.Length; verticesIndex++) { vertices[verticesIndex] = vvd.vertices[verticesIndex].m_vecPosition; normals[verticesIndex] = vvd.vertices[verticesIndex].m_vecNormal; uv[verticesIndex] = vvd.vertices[verticesIndex].m_vecTexCoord; } Debug.Assert(triangles.Length % 3 == 0, "SourceModel: Triangles not a multiple of three for " + modelPath); if (mdl.header1.includemodel_count > 0) { Debug.LogWarning("SourceModel: Include model count greater than zero (" + mdl.header1.includemodel_count + ", " + mdl.header1.includemodel_index + ") for " + modelPath); } if (vvd.header.numFixups > 0) { Debug.LogWarning("SourceModel: " + vvd.header.numFixups + " fixups found for " + modelPath); } MeshHelpers.MeshData meshData; //var outcome = MeshHelpers.GenerateConvexHull(vertices, out meshData, 0.2); //if (outcome != MIConvexHull.ConvexHullCreationResultOutcome.Success) // Debug.LogError("SourceModel: Convex hull error " + outcome + " for " + modelPath); if (decimationPercent > 0) { meshData = MeshHelpers.DecimateByTriangleCount(vertices, triangles, normals, 1 - decimationPercent); meshData.uv = new Vector2[meshData.vertices.Length]; System.Array.Copy(uv, meshData.uv, meshData.vertices.Length); } else { meshData = new MeshHelpers.MeshData(); meshData.vertices = vertices; meshData.triangles = triangles; meshData.normals = normals; meshData.uv = uv; } currentFace.meshData = meshData; string textureName = ""; string texturePath = mdl.texturePaths[0].Replace("\\", "/").ToLower(); if (textureIndex < mdl.textures.Length) { textureName = mdl.textures[textureIndex].name.Replace("\\", "/").ToLower(); } //textureName = mdl.textures[textureIndex].name.Replace("\\", "/").ToLower(); if (textureName.IndexOf(texturePath) > -1) { texturePath = ""; } string textureLocation = texturePath + textureName; //if (modelTextures != null && textureIndex < modelTextures.Length) //Should not have this line // textureLocation = modelTextures[textureIndex]?.location; currentFace.faceName = textureLocation; currentFace.material = VMTData.GrabVMT(bspParser, vpkParser, textureLocation); //if (!excludeTextures) // currentFace.texture = SourceTexture.GrabTexture(bspParser, vpkParser, textureLocation); faces.Add(currentFace); textureIndex++; } } } } else { Debug.LogError("SourceModel: MDL and VTX body part count doesn't match (" + modelPath + ")"); } }
/*public static VMTData GrabVMT(byte[] data, string rawPath) * { * VMTData vmtData = null; * * if (!string.IsNullOrEmpty(rawPath)) * { * string vmtFilePath = rawPath.Replace("\\", "/").ToLower(); * * if (vmtCache.ContainsKey(vmtFilePath)) * { * vmtData = vmtCache[vmtFilePath]; * } * else * { * vmtData = new VMTData(vmtFilePath); * vmtData.Parse(data); * } * } * else * Debug.LogError("VMTData: Given path is null or empty"); * * return vmtData; * }*/ public static VMTData GrabVMT(BSPParser bspParser, VPKParser vpkParser, string rawPath, bool grabDependants = true) { VMTData vmtData = null; if (!string.IsNullOrEmpty(rawPath)) { string vmtFilePath = FixLocation(bspParser, vpkParser, rawPath); if (vmtCache.ContainsKey(vmtFilePath)) { vmtData = vmtCache[vmtFilePath]; if (grabDependants) { vmtData.GrabDependants(bspParser, vpkParser); } } else { if (bspParser != null && bspParser.HasPakFile(vmtFilePath)) { vmtData = new VMTData(vmtFilePath); //Debug.Log("Loaded " + vmtFilePath + " from pakfile"); vmtData.Parse(bspParser.GetPakFile(vmtFilePath)); if (grabDependants) { vmtData.GrabDependants(bspParser, vpkParser); } } else if (vpkParser != null && vpkParser.FileExists(vmtFilePath)) { try { byte[] vmtByteData = null; vpkParser.LoadFileAsStream(vmtFilePath, (stream, origOffset, fileLength) => { vmtByteData = new byte[fileLength]; stream.Position = origOffset; stream.Read(vmtByteData, 0, vmtByteData.Length); }); vmtData = new VMTData(vmtFilePath); vmtData.Parse(vmtByteData); if (grabDependants) { vmtData.GrabDependants(bspParser, vpkParser); } } catch (System.Exception e) { Debug.LogError("VMTData: " + e.ToString()); } } else { string vtfFilePath = SourceTexture.FixLocation(bspParser, vpkParser, rawPath); if ((bspParser != null && bspParser.HasPakFile(vtfFilePath)) || (vpkParser != null && vpkParser.FileExists(vtfFilePath))) { vmtData = new VMTData(vmtFilePath); vmtData.baseTexturePath = rawPath; if (grabDependants) { vmtData.GrabDependants(bspParser, vpkParser); } } else { Debug.LogError("VMTData: Could not find VMT file at FixedPath(" + vmtFilePath + ") RawPath(" + rawPath + ")"); } } } } else { Debug.LogError("VMTData: Given path is null or empty"); } return(vmtData); }
public List <string> GetDependencies(CancellationToken cancelToken) { List <string> dependencies = new List <string>(); using (VPKParser vpkParser = new VPKParser(vpkLoc)) using (BSPParser bspParser = new BSPParser(Path.Combine(mapDir, mapName + ".bsp"))) { bool validVPK = vpkParser.IsValid(); if (!validVPK) { return(null); } bspParser.ParseData(cancelToken); if (cancelToken.IsCancellationRequested) { return(null); } //Note: If there are materials that point to textures in separate archives or there are textures used by the models whose vpk archive is not already // added by other dependencies, those archives will not be added. That would require us to read the materials and models to get what textures they use. #region Map face textures dependencies if (FaceLoadPercent > 0) { foreach (dface_t face in bspParser.faces) { if (cancelToken.IsCancellationRequested) { return(null); } texflags currentTexFlags = GetFaceTextureFlags(face, bspParser); string rawTextureLocation = GetFaceTextureLocation(face, bspParser); if (!IsUndesiredTexture(rawTextureLocation, currentTexFlags)) { string fixedLocation = VMTData.FixLocation(bspParser, vpkParser, rawTextureLocation); if (!vpkParser.FileExists(fixedLocation)) { fixedLocation = SourceTexture.FixLocation(bspParser, vpkParser, rawTextureLocation); } string dependency = vpkParser.LocateInArchive(fixedLocation); if (!string.IsNullOrEmpty(dependency) && !dependencies.Contains(dependency)) { dependencies.Add(dependency); } } } } #endregion #region Model dependencies if (ModelLoadPercent > 0) { for (int i = 0; i < bspParser.staticProps.staticPropInfo.Length; i++) { if (cancelToken.IsCancellationRequested) { return(null); } var currentPropInfo = bspParser.staticProps.staticPropInfo[i]; ushort propType = currentPropInfo.PropType; string modelFullPath = bspParser.staticProps.staticPropDict.names[propType]; modelFullPath = modelFullPath.Substring(0, modelFullPath.LastIndexOf(".")); string mdlPath = modelFullPath + ".mdl"; string vvdPath = modelFullPath + ".vvd"; string vtxPath = modelFullPath + ".vtx"; if (!vpkParser.FileExists(vtxPath)) { vtxPath = modelFullPath + ".dx90.vtx"; } string dependency = vpkParser.LocateInArchive(mdlPath); if (!string.IsNullOrEmpty(dependency) && !dependencies.Contains(dependency)) { dependencies.Add(dependency); } dependency = vpkParser.LocateInArchive(vvdPath); if (!string.IsNullOrEmpty(dependency) && !dependencies.Contains(dependency)) { dependencies.Add(dependency); } dependency = vpkParser.LocateInArchive(vtxPath); if (!string.IsNullOrEmpty(dependency) && !dependencies.Contains(dependency)) { dependencies.Add(dependency); } } } #endregion } return(dependencies); }