namespace Pathfinding.Voxels { /// Utility for clipping polygons internal struct VoxelPolygonClipper { public float[] x; public float[] y; public float[] z; public int n; public VoxelPolygonClipper (int capacity) { x = new float[capacity]; y = new float[capacity]; z = new float[capacity]; n = 0; } public UnityEngine.Vector3 this[int i] { set { x[i] = value.x; y[i] = value.y; z[i] = value.z; } } /// /// Clips a polygon against an axis aligned half plane. /// The polygons stored in this object are clipped against the half plane at x = -offset. /// /// Ouput vertices /// Scale factor for the input vertices. Should be +1 or -1. If -1 the negative half plane is kept. /// Offset to move the input vertices with before cutting public void ClipPolygonAlongX (ref VoxelPolygonClipper result, float multi, float offset) { // Number of resulting vertices int m = 0; bool prev, curr; float dj = multi*x[(n-1)]+offset; for (int i = 0, j = n-1; i < n; j = i, i++) { float di = multi*x[i]+offset; prev = dj >= 0; curr = di >= 0; if (prev != curr) { float s = dj / (dj - di); result.x[m] = x[j] + (x[i]-x[j])*s; result.y[m] = y[j] + (y[i]-y[j])*s; result.z[m] = z[j] + (z[i]-z[j])*s; m++; } if (curr) { result.x[m] = x[i]; result.y[m] = y[i]; result.z[m] = z[i]; m++; } dj = di; } result.n = m; } /// /// Clips a polygon against an axis aligned half plane. /// The polygons stored in this object are clipped against the half plane at z = -offset. /// /// Ouput vertices. Only the Y and Z coordinates are calculated. The X coordinates are undefined. /// Scale factor for the input vertices. Should be +1 or -1. If -1 the negative half plane is kept. /// Offset to move the input vertices with before cutting public void ClipPolygonAlongZWithYZ (ref VoxelPolygonClipper result, float multi, float offset) { // Number of resulting vertices int m = 0; bool prev, curr; float dj = multi*z[(n-1)]+offset; for (int i = 0, j = n-1; i < n; j = i, i++) { float di = multi*z[i]+offset; prev = dj >= 0; curr = di >= 0; if (prev != curr) { float s = dj / (dj - di); result.y[m] = y[j] + (y[i]-y[j])*s; result.z[m] = z[j] + (z[i]-z[j])*s; m++; } if (curr) { result.y[m] = y[i]; result.z[m] = z[i]; m++; } dj = di; } result.n = m; } /// /// Clips a polygon against an axis aligned half plane. /// The polygons stored in this object are clipped against the half plane at z = -offset. /// /// Ouput vertices. Only the Y coordinates are calculated. The X and Z coordinates are undefined. /// Scale factor for the input vertices. Should be +1 or -1. If -1 the negative half plane is kept. /// Offset to move the input vertices with before cutting public void ClipPolygonAlongZWithY (ref VoxelPolygonClipper result, float multi, float offset) { // Number of resulting vertices int m = 0; bool prev, curr; float dj = multi*z[(n-1)]+offset; for (int i = 0, j = n-1; i < n; j = i, i++) { float di = multi*z[i]+offset; prev = dj >= 0; curr = di >= 0; if (prev != curr) { float s = dj / (dj - di); result.y[m] = y[j] + (y[i]-y[j])*s; m++; } if (curr) { result.y[m] = y[i]; m++; } dj = di; } result.n = m; } } /// Utility for clipping polygons internal struct Int3PolygonClipper { /// Cache this buffer to avoid unnecessary allocations float[] clipPolygonCache; /// Cache this buffer to avoid unnecessary allocations int[] clipPolygonIntCache; /// Initialize buffers if they are null public void Init () { if (clipPolygonCache == null) { clipPolygonCache = new float[7*3]; clipPolygonIntCache = new int[7*3]; } } /// /// Clips a polygon against an axis aligned half plane. /// /// Returns: Number of output vertices /// /// The vertices will be scaled and then offset, after that they will be cut using either the /// x axis, y axis or the z axis as the cutting line. The resulting vertices will be added to the /// vOut array in their original space (i.e before scaling and offsetting). /// /// Input vertices /// Number of input vertices (may be less than the length of the vIn array) /// Output vertices, needs to be large enough /// Scale factor for the input vertices /// Offset to move the input vertices with before cutting /// Axis to cut along, either x=0, y=1, z=2 public int ClipPolygon (Int3[] vIn, int n, Int3[] vOut, int multi, int offset, int axis) { Init(); int[] d = clipPolygonIntCache; for (int i = 0; i < n; i++) { d[i] = multi*vIn[i][axis]+offset; } // Number of resulting vertices int m = 0; for (int i = 0, j = n-1; i < n; j = i, i++) { bool prev = d[j] >= 0; bool curr = d[i] >= 0; if (prev != curr) { double s = (double)d[j] / (d[j] - d[i]); vOut[m] = vIn[j] + (vIn[i]-vIn[j])*s; m++; } if (curr) { vOut[m] = vIn[i]; m++; } } return m; } } }