/// <summary> /// Processes a <see cref="DisplacementInfo"/> object into a state where it can be output into a file that Hammer can read. /// For Source engine forks only. /// </summary> /// <param name="displacement">The <see cref="DisplacementInfo"/> object to process.</param> /// <returns>A <see cref="MAPDisplacement"/> object to be added to a <see cref="MAPBrushSide"/>.</returns> private MAPDisplacement ProcessDisplacement(DisplacementInfo displacement) { int power = displacement.power; int first = displacement.dispVertStart; Vector3d start = displacement.startPosition; int numVertsInRow = (int)Math.Pow(2, power) + 1; Vector3d[,] normals = new Vector3d[numVertsInRow, numVertsInRow]; float[,] distances = new float[numVertsInRow, numVertsInRow]; float[,] alphas = new float[numVertsInRow, numVertsInRow]; for (int i = 0; i < numVertsInRow; ++i) { for (int j = 0; j < numVertsInRow; ++j) { normals[i, j] = _bsp.dispVerts[first + (i * numVertsInRow) + j].normal; distances[i, j] = _bsp.dispVerts[first + (i * numVertsInRow) + j].dist; alphas[i, j] = _bsp.dispVerts[first + (i * numVertsInRow) + j].alpha; } } return(new MAPDisplacement() { power = power, start = start, normals = normals, distances = distances, alphas = alphas }); }
/// <summary> /// Converts a hammer displacement to an obj object. /// </summary> /// <param name="displacementPlane">The clipping plane containing the displacement.</param> /// <param name="vertices">The vertices of the brush.</param> /// <returns>A newly created obj object.</returns> public static ObjObject Convert(DisplacementClippingPlane displacementPlane, IEnumerable <Vector> vertices) { Vector[] verticesInPlane = vertices.Where(x => x.OnPlane(displacementPlane)).ToArray(); if (verticesInPlane.Length != 4) { Console.WriteLine("Error - Not enough vertices for displacement."); return(new ObjObject(Array.Empty <Vector>(), Array.Empty <Face>())); } DisplacementInfo dispInfo = displacementPlane.DisplacementInfo; Grid <Vector> grid = CreateGrid(verticesInPlane, dispInfo.Dimensions); grid = ApplyOffsets(grid, dispInfo.Offsets); grid = ApplyDistances(grid, dispInfo.Normals, dispInfo.Elevation, dispInfo.Distances); return(ObjFromGrid(grid, displacementPlane.Texture.Name)); }
#pragma warning restore RECS0018 // Comparison of floating point numbers with equality operator private void Read(DisplacementInfo dispInfo, TextureInfo texInfo) { var vertices = map.Lumps.GetDisplacementVertices(); var triangles = map.Lumps.GetDisplacementTriangles(); var texData = map.Lumps.GetTextureData()[texInfo.TextureData]; var textureOffset = map.Lumps.GetTextureDataStringTable()[texData.NameStringTableId]; var textureName = map.Lumps.GetTextureDataString()[textureOffset]; var vertCount = ((1 << (dispInfo.Power)) + 1) * ((1 << (dispInfo.Power)) + 1); var triCount = (1 << (dispInfo.Power)) * (1 << (dispInfo.Power)) * 2; for (var i = dispInfo.DisplacementVertexStart; i < dispInfo.DisplacementVertexStart + vertCount; i++) { /*this.vertices.Add(new Vertex * { * Position = vertices[i].Vector * });*/ //var indices = GetIndices(textureName); // indices.Add((uint)i); } }
/// <summary> /// Builds a Displacement <see cref="Mesh"/> from the <see cref="DisplacementInfo"/> referenced by /// <paramref name="face"/>, with UVs calculated from <see cref="Face.textureInfo"/> using /// <paramref name="dims"/> as the <see cref="Texture2D"/> width and height. /// </summary> /// <param name="bsp">The <see cref="BSP"/> object which <paramref name="face"/> came from.</param> /// <param name="face">A face referencing a <see cref="DisplacementInfo"/> and a <see cref="TextureInfo"/>.</param> /// <param name="dims">The dimensions of the <see cref="Texture2D"/> to map onto the resulting <see cref="Mesh"/>.</param> /// <returns>The <see cref="Mesh"/> created from the <see cref="DisplacementInfo"/>.</returns> public static Mesh CreateDisplacementMesh(BSP bsp, Face face, Vector2 dims) { Mesh mesh = null; if (face.numEdges > 0) { mesh = LoadVerticesFromEdges(bsp, face); } else { Debug.LogWarning("Cannot create displacement, face contains no edges."); return(null); } Vector3[] faceCorners = mesh.vertices; int[] faceTriangles = mesh.triangles; if (faceCorners.Length != 4 || faceTriangles.Length != 6) { Debug.LogWarning("Cannot create displacement mesh because " + faceCorners.Length + " corners and " + faceTriangles.Length + " triangle indices."); return(null); } DisplacementInfo displacementInfo = bsp.dispInfos[face.displacement]; int numSideTriangles = (int)Mathf.Pow(2, displacementInfo.power); DisplacementVertex[] displacementVertices = bsp.dispVerts.GetVerticesInDisplacement(displacementInfo.dispVertStart, displacementInfo.power); Vector3[] corners = new Vector3[4]; Vector3 start = displacementInfo.startPosition.SwizzleYZ() * inch2MeterScale; if ((faceCorners[faceTriangles[0]] - start).sqrMagnitude < .01f) { corners[0] = faceCorners[faceTriangles[0]]; corners[1] = faceCorners[faceTriangles[1]]; corners[2] = faceCorners[faceTriangles[5]]; corners[3] = faceCorners[faceTriangles[4]]; } else if ((faceCorners[faceTriangles[1]] - start).sqrMagnitude < .01f) { corners[0] = faceCorners[faceTriangles[1]]; corners[1] = faceCorners[faceTriangles[4]]; corners[2] = faceCorners[faceTriangles[0]]; corners[3] = faceCorners[faceTriangles[5]]; } else if ((faceCorners[faceTriangles[5]] - start).sqrMagnitude < .01f) { corners[0] = faceCorners[faceTriangles[5]]; corners[1] = faceCorners[faceTriangles[0]]; corners[2] = faceCorners[faceTriangles[4]]; corners[3] = faceCorners[faceTriangles[1]]; } else if ((faceCorners[faceTriangles[4]] - start).sqrMagnitude < .01f) { corners[0] = faceCorners[faceTriangles[4]]; corners[1] = faceCorners[faceTriangles[5]]; corners[2] = faceCorners[faceTriangles[1]]; corners[3] = faceCorners[faceTriangles[0]]; } else { Debug.LogWarning("Cannot create displacement mesh because start position isn't one of the face corners.\n" + "Start position: " + start + "\n" + "Corners: " + faceCorners[faceTriangles[0]] + " " + faceCorners[faceTriangles[1]] + " " + faceCorners[faceTriangles[5]] + " " + faceCorners[faceTriangles[4]]); return(null); } Vector3[] offsets = new Vector3[displacementVertices.Length]; for (int i = 0; i < displacementVertices.Length; ++i) { offsets[i] = displacementVertices[i].normal.SwizzleYZ() * displacementVertices[i].dist * inch2MeterScale; } Vector2[] uv = new Vector2[4]; Vector2[] uv2 = new Vector2[4]; mesh.vertices = corners; mesh.uv = uv; mesh.uv2 = uv2; mesh.CalculateUVs(bsp.GetTextureInfo(face), dims); mesh.CalculateTerrainVertices(offsets, numSideTriangles); mesh.triangles = BuildDisplacementTriangles(numSideTriangles); mesh.NegateVs(); mesh.RecalculateNormals(); mesh.RecalculateBounds(); return(mesh); }
/// <summary> /// Initializes a new instance of the <see cref="DisplacementClippingPlane" /> class. /// </summary> /// <param name="v1">The first vector.</param> /// <param name="v2">The second vector.</param> /// <param name="v3">The third vector.</param> /// <param name="texture">The texture.</param> /// <param name="displacement">The displacement info.</param> public DisplacementClippingPlane(Vector v1, Vector v2, Vector v3, PlaneTexture texture, DisplacementInfo displacement) : base(v1, v2, v3, texture) => DisplacementInfo = displacement;