private bool CheckIntersection(Vec3 p, Vec3 direction, Vec3 edge1, Vec3 edge2, Vec3 v0, Vec3 h, float f, ref float t, ref float u, ref float v) { Vec3 s = p - v0; u = f * s.dot(h); if (u < 0f || u > 1f) { return(false); } Vec3 q = s.Cross(edge1); v = f * direction.dot(q); if (v < 0f || v > 1f) { return(false); } if (u + v > 1f) { return(false); } t = f * edge2.dot(q); return(true); }
public List <Vec3> GetAllVoxelOnPlane(Vec3 p1, Vec3 p2, Vec3 p3, bool getAll) { List <Vec3> result = new List <Vec3>(); Vec3 normal = (p2 - p1).Cross((p3 - p1)); float d = -p1.dot(normal); uint resolution = xResolution; Vec3 mainDirection = new Vec3(1, 0, 0); if (Math.Abs(normal.x) < Math.Abs(normal.y)) { if (Math.Abs(normal.z) < Math.Abs(normal.y)) { resolution = yResolution; mainDirection = new Vec3(0, 1, 0); } else { resolution = zResolution; mainDirection = new Vec3(0, 0, 1); } } else if (Math.Abs(normal.x) < Math.Abs(normal.z)) { resolution = zResolution; mainDirection = new Vec3(0, 0, 1); } Vec3 planeCoord1 = new Vec3(mainDirection.z, mainDirection.x, mainDirection.y); Vec3 planeCoord2 = new Vec3(mainDirection.y, mainDirection.z, mainDirection.x); float min = -d / mainDirection.dot(normal); float max = min; float tmp = -(d + (planeCoord1 * resolution).dot(normal)) / mainDirection.dot(normal); min = tmp < min ? tmp : min; max = tmp > max ? tmp : max; tmp = -(d + (planeCoord2 * resolution).dot(normal)) / mainDirection.dot(normal); min = tmp < min ? tmp : min; max = tmp > max ? tmp : max; tmp = -(d + (planeCoord1 * resolution + planeCoord2 * resolution).dot(normal)) / mainDirection.dot(normal); min = tmp < min ? tmp : min; max = tmp > max ? tmp : max; min = (float)Math.Floor(min); max = (float)Math.Ceiling(max); min = min < 0 ? 0 : min; max = max > resolution ? resolution : max; Vec3 maxHeightVector = mainDirection * max; if (max - min > 1) { Vec3 point1 = new Vec3(); Vec3 point2 = new Vec3(); Vec3 maxVector1 = planeCoord1 * resolution; Vec3 minVector1 = new Vec3(0, 0, 0); Vec3 minVector2 = new Vec3(); Vec3 maxVector2 = new Vec3(); Vec3 lineNormal = normal.Cross(mainDirection); lineNormal.Normalize(); float t; float dotTmp; Vec3 tmpVec; Vec3 tmpResult = new Vec3(); if (lineNormal.dot(planeCoord1) == 0) { tmpVec = planeCoord1; planeCoord1 = planeCoord2; planeCoord2 = tmpVec; maxVector1 = planeCoord1 * resolution; minVector1 = new Vec3(0, 0, 0); } for (Vec3 mainVec = mainDirection * min; mainVec != maxHeightVector; mainVec = mainVec + mainDirection) { if (normal.dot(planeCoord1) != 0) { point1 = planeCoord1 * -(mainVec.dot(normal) + d) / (normal.dot(planeCoord1)) + mainVec; point2 = planeCoord1 * -((mainVec + mainDirection).dot(normal) + d) / (normal.dot(planeCoord1)) + (mainVec + mainDirection); } else { point1 = planeCoord2 * -(mainVec.dot(normal) + d) / (normal.dot(planeCoord2)) + mainVec; point2 = planeCoord2 * -((mainVec + mainDirection).dot(normal) + d) / (normal.dot(planeCoord2)) + (mainVec + mainDirection); } for (Vec3 direction1 = minVector1; direction1 != maxVector1; direction1 += planeCoord1) { dotTmp = lineNormal.dot(planeCoord1); t = (direction1 + mainVec - point1).dot(planeCoord1) / dotTmp; minVector2 = point1 + lineNormal * t; t = (direction1 + mainVec + mainDirection - point2).dot(planeCoord1) / dotTmp; maxVector2 = point2 + lineNormal * t; dotTmp = maxVector2.dot(planeCoord2); if (dotTmp < minVector2.dot(planeCoord2)) { tmpVec = minVector2; minVector2 = maxVector2; maxVector2 = tmpVec; dotTmp = maxVector2.dot(planeCoord2); } if (dotTmp < 0) { continue; } if ((dotTmp + 1) > resolution) { maxVector2 = planeCoord1 * maxVector2.dot(planeCoord1) + planeCoord2 * resolution + mainVec; } else { maxVector2 = planeCoord1 * maxVector2.dot(planeCoord1) + planeCoord2 * (dotTmp + 1) + mainVec; } dotTmp = minVector2.dot(planeCoord2); if (dotTmp > resolution) { continue; } if (dotTmp < 0) { minVector2 = planeCoord1 * (minVector2.dot(planeCoord1)) + mainVec; } minVector2 = direction1 + mainVec + planeCoord2 * (float)Math.Floor(planeCoord2.dot(minVector2)); maxVector2 = direction1 + mainVec + planeCoord2 * (float)Math.Ceiling(planeCoord2.dot(maxVector2)); for (Vec3 direction2 = minVector2; direction2 != maxVector2; direction2 += planeCoord2) { tmpResult.x = (float)Math.Floor(direction2.x); tmpResult.y = (float)Math.Floor(direction2.y); tmpResult.z = (float)Math.Floor(direction2.z); if (grid[(int)tmpResult.x, (int)tmpResult.y, (int)tmpResult.z].set || getAll) { result.Add(tmpResult); } } } } } else { Vec3 pos; for (int i = 0; i < resolution; ++i) { for (int j = 0; j < resolution; ++j) { pos = planeCoord1 * i + planeCoord2 * j + maxHeightVector; if (grid[(int)pos.x, (int)pos.y, (int)pos.z].set || getAll) { result.Add(pos); } } } } return(result); }
private void FindOverlappedIndices(Vec3[] face, Vec3 normal) { Vec3[] newCoord = new Vec3[3]; uint i; Vec3[] projectedCoord = new Vec3[3]; for (i = 0; i < 3; ++i) { newCoord[i] = new Vec3(); newCoord[i].x = (face[i].x - minOffset.x) / sizeVoxel; newCoord[i].y = (face[i].y - minOffset.y) / sizeVoxel; newCoord[i].z = (face[i].z - minOffset.z) / sizeVoxel; projectedCoord[i] = newCoord[i].outer(planeCoord1) + newCoord[i].outer(planeCoord2); } float normalSign = normal.dot(direction); Vec3 min = new Vec3(), max = new Vec3(); Utility.CalcBoundingBox(projectedCoord, ref min, ref max); Vec3 edge1 = newCoord[1] - newCoord[0]; Vec3 edge2 = newCoord[2] - newCoord[0]; Vec3 h = direction.Cross(edge2); float f = 1f / edge1.dot(h); Vec3[] normals = new Vec3[3]; Vec3[] normals3d = new Vec3[3]; float t = 0; float u = 0; float v = 0; for (i = 0; i < 3; ++i) { if (normalSign >= 0) { normals[i] = planeCoord1 * (projectedCoord[i].dot(planeCoord2) - projectedCoord[(i + 1) % 3].dot(planeCoord2)) + planeCoord2 * (projectedCoord[(i + 1) % 3].dot(planeCoord1) - projectedCoord[i].dot(planeCoord1)); } else { normals[i] = planeCoord1 * (projectedCoord[(i + 1) % 3].dot(planeCoord2) - projectedCoord[i].dot(planeCoord2)) + planeCoord2 * (projectedCoord[i].dot(planeCoord1) - projectedCoord[(i + 1) % 3].dot(planeCoord1)); } normals[i].Normalize(); } min.x = (float)Math.Floor(min.x); min.y = (float)Math.Floor(min.y); min.z = (float)Math.Floor(min.z); max.x = (float)Math.Ceiling(max.x); max.y = (float)Math.Ceiling(max.y); max.z = (float)Math.Ceiling(max.z); Vec3 min1 = new Vec3(); Vec3 min2 = new Vec3(); Vec3 max1 = new Vec3(); Vec3 max2 = new Vec3(); min1.x = min.x * planeCoord1.x; min1.y = min.y * planeCoord1.y; min1.z = min.z * planeCoord1.z; min2.x = min.x * planeCoord2.x; min2.y = min.y * planeCoord2.y; min2.z = min.z * planeCoord2.z; max1.x = max.x * planeCoord1.x; max1.y = max.y * planeCoord1.y; max1.z = max.z * planeCoord1.z; max2.x = max.x * planeCoord2.x; max2.y = max.y * planeCoord2.y; max2.z = max.z * planeCoord2.z; Vec3 tmp; Vec3 pos; bool[] leftEdge = new bool[3]; for (i = 0; i < 3; ++i) { leftEdge[i] = normals[i].compareGreater(0, planeCoord1); leftEdge[i] |= normals[i].compareEqual(0, planeCoord1) && normals[i].compareSmaller(0, planeCoord2); } float epsilon = 0.00000001f; bool edge = true; for (Vec3 dir1 = min1; dir1 != max1; dir1 += planeCoord1) { for (Vec3 dir2 = min2; dir2 != max2; dir2 += planeCoord2) { edge = true; tmp = dir1 + dir2 + planeCoord1 * 0.5f + planeCoord2 * 0.5f; if (CheckIntersection(tmp, direction, edge1, edge2, newCoord[0], h, f, ref t, ref u, ref v)) { if (u < (0f + epsilon)) { edge = edge && leftEdge[2]; } if (v < (0f + epsilon)) { edge = edge && leftEdge[0]; } if ((u + v - 1f) < (0f + epsilon) && (u + v - 1f) > (0f - epsilon)) { edge = edge && leftEdge[1]; } if (edge) { pos = tmp + direction * t; grid[(int)Math.Floor(pos.x), (int)Math.Floor(pos.y), (int)Math.Floor(pos.z)].set ^= true; } } } } }
private void CreateStart() { float lowestX = points[0].x, highestX = points[0].x; float lowestY = points[0].y, highestY = points[0].y; float lowestZ = points[0].z, highestZ = points[0].z; int[] lowest = new int[3]; int[] highest = new int[3]; int listSize = points.Count; Vec3 point; for (int i = 0; i < listSize; ++i) { point = points[i]; if (point.x < lowestX) { lowestX = point.x; lowest[0] = i; } if (point.x > highestX) { highestX = point.x; highest[0] = i; } if (point.y < lowestY) { lowestY = point.y; lowest[1] = i; } if (point.y > highestY) { highestY = point.y; highest[1] = i; } if (point.z < lowestZ) { lowestZ = point.z; lowest[2] = i; } if (point.z > highestZ) { highestZ = point.z; highest[2] = i; } } int greatestDistanceUp = lowest[0]; int greatestDistanceDown = highest[0]; Vec3 distanceVec = points[greatestDistanceDown] - points[greatestDistanceUp]; float maxDistance = distanceVec.dot(distanceVec); float tmpDistance = 0; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { distanceVec = points[lowest[i]] - points[highest[j]]; tmpDistance = distanceVec.dot(distanceVec); if (tmpDistance > maxDistance) { greatestDistanceUp = lowest[i]; greatestDistanceDown = highest[j]; maxDistance = tmpDistance; } } } distanceVec = points[greatestDistanceDown] - points[greatestDistanceUp]; int distanceIdx = 0; Vec3 tmpVec; float newMaxDistance = 0; for (int i = 0; i < 3; ++i) { tmpVec = distanceVec.Cross(points[greatestDistanceUp] - points[lowest[i]]); tmpDistance = (tmpVec).dot(tmpVec) / maxDistance; if (tmpDistance > newMaxDistance) { distanceIdx = lowest[i]; newMaxDistance = tmpDistance; } } for (int i = 0; i < 3; ++i) { tmpVec = distanceVec.Cross(points[greatestDistanceUp] - points[highest[i]]); tmpDistance = (tmpVec).dot(tmpVec) / maxDistance; if (tmpDistance > newMaxDistance) { distanceIdx = highest[i]; newMaxDistance = tmpDistance; } } Vec3 normal = (distanceVec.Cross(points[greatestDistanceDown] - points[distanceIdx])); normal.Normalize(); newMaxDistance = 0; int distanceIdx2 = 0; for (int i = 0; i < 3; ++i) { tmpDistance = Math.Abs(normal.dot(points[distanceIdx] - points[lowest[i]])); if (tmpDistance > newMaxDistance) { distanceIdx2 = lowest[i]; newMaxDistance = tmpDistance; } } for (int i = 0; i < 3; ++i) { tmpDistance = Math.Abs(normal.dot(points[distanceIdx] - points[highest[i]])); if (tmpDistance > newMaxDistance) { distanceIdx2 = highest[i]; newMaxDistance = tmpDistance; } } if (normal.dot(points[distanceIdx2] - points[distanceIdx]) > 0) { //Face 0 HalfEdge newHalfEdge = new HalfEdge(); newHalfEdge.vertex = greatestDistanceUp; newHalfEdge.face = 0; newHalfEdge.opposite = 3; edges.Add(newHalfEdge); newHalfEdge.vertex = distanceIdx; newHalfEdge.face = 0; newHalfEdge.opposite = 6; edges.Add(newHalfEdge); newHalfEdge.vertex = greatestDistanceDown; newHalfEdge.face = 0; newHalfEdge.opposite = 9; edges.Add(newHalfEdge); //Face 1 newHalfEdge.vertex = greatestDistanceDown; newHalfEdge.face = 1; newHalfEdge.opposite = 0; edges.Add(newHalfEdge); newHalfEdge.vertex = distanceIdx2; newHalfEdge.face = 1; newHalfEdge.opposite = 11; edges.Add(newHalfEdge); newHalfEdge.vertex = greatestDistanceUp; newHalfEdge.face = 1; newHalfEdge.opposite = 7; edges.Add(newHalfEdge); //Face2 newHalfEdge.vertex = greatestDistanceUp; newHalfEdge.face = 2; newHalfEdge.opposite = 1; edges.Add(newHalfEdge); newHalfEdge.vertex = distanceIdx2; newHalfEdge.face = 2; newHalfEdge.opposite = 5; edges.Add(newHalfEdge); newHalfEdge.vertex = distanceIdx; newHalfEdge.face = 2; newHalfEdge.opposite = 10; edges.Add(newHalfEdge); //Face3 newHalfEdge.vertex = distanceIdx; newHalfEdge.face = 3; newHalfEdge.opposite = 2; edges.Add(newHalfEdge); newHalfEdge.vertex = distanceIdx2; newHalfEdge.face = 3; newHalfEdge.opposite = 8; edges.Add(newHalfEdge); newHalfEdge.vertex = greatestDistanceDown; newHalfEdge.face = 3; newHalfEdge.opposite = 4; edges.Add(newHalfEdge); } else { //Face 0 HalfEdge newHalfEdge = new HalfEdge(); newHalfEdge.vertex = distanceIdx; newHalfEdge.face = 0; newHalfEdge.opposite = 11; edges.Add(newHalfEdge); newHalfEdge.vertex = greatestDistanceUp; newHalfEdge.face = 0; newHalfEdge.opposite = 8; edges.Add(newHalfEdge); newHalfEdge.vertex = greatestDistanceDown; newHalfEdge.face = 0; newHalfEdge.opposite = 5; edges.Add(newHalfEdge); //Face 1 newHalfEdge.vertex = distanceIdx2; newHalfEdge.face = 1; newHalfEdge.opposite = 7; edges.Add(newHalfEdge); newHalfEdge.vertex = greatestDistanceDown; newHalfEdge.face = 1; newHalfEdge.opposite = 9; edges.Add(newHalfEdge); newHalfEdge.vertex = greatestDistanceUp; newHalfEdge.face = 1; newHalfEdge.opposite = 2; edges.Add(newHalfEdge); //Face2 newHalfEdge.vertex = distanceIdx2; newHalfEdge.face = 2; newHalfEdge.opposite = 10; edges.Add(newHalfEdge); newHalfEdge.vertex = greatestDistanceUp; newHalfEdge.face = 2; newHalfEdge.opposite = 3; edges.Add(newHalfEdge); newHalfEdge.vertex = distanceIdx; newHalfEdge.face = 2; newHalfEdge.opposite = 1; edges.Add(newHalfEdge); //Face3 newHalfEdge.vertex = distanceIdx2; newHalfEdge.face = 3; newHalfEdge.opposite = 4; edges.Add(newHalfEdge); newHalfEdge.vertex = distanceIdx; newHalfEdge.face = 3; newHalfEdge.opposite = 6; edges.Add(newHalfEdge); newHalfEdge.vertex = greatestDistanceDown; newHalfEdge.face = 3; newHalfEdge.opposite = 0; edges.Add(newHalfEdge); } Face newFace = new Face(); for (int i = 0; i < 4; ++i) { newFace.halfEdge = i * 3; newFace.normal = ((points[edges[i * 3 + 2].vertex] - points[edges[i * 3].vertex]).Cross(points[edges[i * 3 + 1].vertex] - points[edges[i * 3].vertex])); newFace.normal.Normalize(); newFace.pointList = -1; faces.Add(newFace); } }