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 string GetFaceTextureLocation(dface_t face, BSPParser bspParser) { int faceTexInfoIndex = face.texinfo; int texDataIndex = bspParser.texInfo[faceTexInfoIndex].texdata; int nameStringTableIndex = bspParser.texData[texDataIndex].nameStringTableID; return(bspParser.textureStringData[nameStringTableIndex]); }
private texflags GetFaceTextureFlags(dface_t face, BSPParser bspParser) { texflags currentTexFlag = texflags.SURF_SKIP; if (bspParser.texInfo != null && face.texinfo < bspParser.texInfo.Length) { currentTexFlag = (texflags)bspParser.texInfo[face.texinfo].flags; } return(currentTexFlag); }
public MeshHelpers.MeshData MakeFace(BSPParser bspParser, dface_t face) { #region Get all vertices of face List <Vector3> surfaceVertices = new List <Vector3>(); List <Vector3> originalVertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); for (int i = 0; i < face.numedges; i++) { ushort[] currentEdge = bspParser.edges[Mathf.Abs(bspParser.surfedges[face.firstedge + i])].v; Vector3 point1 = bspParser.vertices[currentEdge[0]], point2 = bspParser.vertices[currentEdge[1]]; Vector3 planeNormal = bspParser.planes[face.planenum].normal; point1 = new Vector3(point1.x, point1.y, point1.z); point2 = new Vector3(point2.x, point2.y, point2.z); if (bspParser.surfedges[face.firstedge + i] >= 0) { if (surfaceVertices.IndexOf(point1) < 0) { surfaceVertices.Add(point1); normals.Add(planeNormal); } originalVertices.Add(point1); if (surfaceVertices.IndexOf(point2) < 0) { surfaceVertices.Add(point2); normals.Add(planeNormal); } originalVertices.Add(point2); } else { if (surfaceVertices.IndexOf(point2) < 0) { surfaceVertices.Add(point2); normals.Add(planeNormal); } originalVertices.Add(point2); if (surfaceVertices.IndexOf(point1) < 0) { surfaceVertices.Add(point1); normals.Add(planeNormal); } originalVertices.Add(point1); } } #endregion #region Apply Displacement if (face.dispinfo > -1) { ddispinfo_t disp = bspParser.dispInfo[face.dispinfo]; int power = Mathf.RoundToInt(Mathf.Pow(2, disp.power)); List <Vector3> dispVertices = new List <Vector3>(); Vector3 startingPosition = surfaceVertices[0]; Vector3 topCorner = surfaceVertices[1], topRightCorner = surfaceVertices[2], rightCorner = surfaceVertices[3]; #region Setting Orientation Vector3 dispStartingVertex = disp.startPosition; if (Vector3.Distance(dispStartingVertex, topCorner) < 0.01f) { Vector3 tempCorner = startingPosition; startingPosition = topCorner; topCorner = topRightCorner; topRightCorner = rightCorner; rightCorner = tempCorner; } else if (Vector3.Distance(dispStartingVertex, rightCorner) < 0.01f) { Vector3 tempCorner = startingPosition; startingPosition = rightCorner; rightCorner = topRightCorner; topRightCorner = topCorner; topCorner = tempCorner; } else if (Vector3.Distance(dispStartingVertex, topRightCorner) < 0.01f) { Vector3 tempCorner = startingPosition; startingPosition = topRightCorner; topRightCorner = tempCorner; tempCorner = rightCorner; rightCorner = topCorner; topCorner = tempCorner; } #endregion int orderNum = 0; #region Method 13 (The one and only two) Vector3 leftSide = (topCorner - startingPosition), rightSide = (topRightCorner - rightCorner); float leftSideLineSegmentationDistance = leftSide.magnitude / power, rightSideLineSegmentationDistance = rightSide.magnitude / power; for (int line = 0; line < (power + 1); line++) { for (int point = 0; point < (power + 1); point++) { Vector3 leftPoint = (leftSide.normalized * line * leftSideLineSegmentationDistance) + startingPosition; Vector3 rightPoint = (rightSide.normalized * line * rightSideLineSegmentationDistance) + rightCorner; Vector3 currentLine = rightPoint - leftPoint; Vector3 pointDirection = currentLine.normalized; float pointSideSegmentationDistance = currentLine.magnitude / power; Vector3 pointA = leftPoint + (pointDirection * pointSideSegmentationDistance * point); Vector3 dispDirectionA = bspParser.dispVerts[disp.DispVertStart + orderNum].vec; dispVertices.Add(pointA + (dispDirectionA * bspParser.dispVerts[disp.DispVertStart + orderNum].dist)); orderNum++; } } #endregion surfaceVertices = dispVertices; } #endregion #region Triangulate List <int> triangleIndices = new List <int>(); if (face.dispinfo > -1) { ddispinfo_t disp = bspParser.dispInfo[face.dispinfo]; int power = Mathf.RoundToInt(Mathf.Pow(2, disp.power)); #region Method 12 Triangulation for (int row = 0; row < power; row++) { for (int col = 0; col < power; col++) { int currentLine = row * (power + 1); int nextLineStart = (row + 1) * (power + 1); triangleIndices.Add(currentLine + col); triangleIndices.Add(currentLine + col + 1); triangleIndices.Add(nextLineStart + col); triangleIndices.Add(currentLine + col + 1); triangleIndices.Add(nextLineStart + col + 1); triangleIndices.Add(nextLineStart + col); } } #endregion } else { for (int i = 0; i < (originalVertices.Count / 2) - 0; i++) { int firstOrigIndex = i * 2, secondOrigIndex = (i * 2) + 1, thirdOrigIndex = 0; int firstIndex = surfaceVertices.IndexOf(originalVertices[firstOrigIndex]); int secondIndex = surfaceVertices.IndexOf(originalVertices[secondOrigIndex]); int thirdIndex = surfaceVertices.IndexOf(originalVertices[thirdOrigIndex]); triangleIndices.Add(thirdIndex); triangleIndices.Add(secondIndex); triangleIndices.Add(firstIndex); } } #endregion #region Map UV Points Vector3 s = Vector3.zero, t = Vector3.zero; float xOffset = 0, yOffset = 0; try { s = new Vector3(bspParser.texInfo[face.texinfo].textureVecs[0][0], bspParser.texInfo[face.texinfo].textureVecs[0][1], bspParser.texInfo[face.texinfo].textureVecs[0][2]); t = new Vector3(bspParser.texInfo[face.texinfo].textureVecs[1][0], bspParser.texInfo[face.texinfo].textureVecs[1][1], bspParser.texInfo[face.texinfo].textureVecs[1][2]); xOffset = bspParser.texInfo[face.texinfo].textureVecs[0][3]; yOffset = bspParser.texInfo[face.texinfo].textureVecs[1][3]; } catch (Exception e) { Debug.LogError(e); } Vector2[] uvPoints = new Vector2[surfaceVertices.Count]; int textureWidth = 0, textureHeight = 0; try { textureWidth = bspParser.texData[bspParser.texInfo[face.texinfo].texdata].width; textureHeight = bspParser.texData[bspParser.texInfo[face.texinfo].texdata].height; } catch (Exception e) { Debug.LogError(e); } for (int i = 0; i < uvPoints.Length; i++) { uvPoints[i] = new Vector2((Vector3.Dot(surfaceVertices[i], s) + xOffset) / textureWidth, (textureHeight - (Vector3.Dot(surfaceVertices[i], t) + yOffset)) / textureHeight); } #endregion #region Organize Mesh Data MeshHelpers.MeshData meshData = new MeshHelpers.MeshData(); meshData.vertices = surfaceVertices.ToArray(); meshData.triangles = triangleIndices.ToArray(); meshData.normals = normals.ToArray(); meshData.uv = uvPoints; #endregion #region Clear References surfaceVertices.Clear(); surfaceVertices = null; originalVertices.Clear(); originalVertices = null; normals.Clear(); normals = null; triangleIndices.Clear(); triangleIndices = null; uvPoints = null; #endregion return(meshData); }