public static void ChangeMaterialInBoxRelative(MyVoxelMap voxelMap, Vector3 relativeMin, Vector3 relativeMax, MyMwcVoxelMaterialsEnum material) { BoundingBox boundingBox = voxelMap.WorldAABB; // Get min and max cell coordinate where camera bounding box can fit MyMwcVector3Int cellCoordMin = voxelMap.GetVoxelCoordinateFromMeters(boundingBox.Min); MyMwcVector3Int cellCoordMax = voxelMap.GetVoxelCoordinateFromMeters(boundingBox.Max); // Fix min and max cell coordinates so they don't overlap the voxelmap voxelMap.FixVoxelCoord(ref cellCoordMin); voxelMap.FixVoxelCoord(ref cellCoordMax); cellCoordMin.X = (int)(cellCoordMax.X * relativeMin.X); cellCoordMin.Y = (int)(cellCoordMax.Y * relativeMin.Y); cellCoordMin.Z = (int)(cellCoordMax.Z * relativeMin.Z); cellCoordMax.X = (int)(cellCoordMax.X * relativeMax.X); cellCoordMax.Y = (int)(cellCoordMax.Y * relativeMax.Y); cellCoordMax.Z = (int)(cellCoordMax.Z * relativeMax.Z); MyMwcVector3Int cellCoord; for (cellCoord.X = cellCoordMin.X; cellCoord.X <= cellCoordMax.X; cellCoord.X++) { for (cellCoord.Y = cellCoordMin.Y; cellCoord.Y <= cellCoordMax.Y; cellCoord.Y++) { for (cellCoord.Z = cellCoordMin.Z; cellCoord.Z <= cellCoordMax.Z; cellCoord.Z++) { voxelMap.SetVoxelMaterialAndIndestructibleContent(material, 0, ref cellCoord); } } } voxelMap.InvalidateCache(cellCoordMin, cellCoordMax); voxelMap.CalcAverageDataCellMaterials(); //MyVoxelMaps.RecalcVoxelMaps(); }
} //CreateCylinder public static void CutOutCylinder(MyVoxelMap voxelMap, float radius1, float radius2, MyOrientedBoundingBox box, MyMwcVoxelMaterialsEnum? material, ref bool changed) { //box.HalfExtent x = radius1 //box.HalfExtent y = length/2 //box.HalfExtent z = radius2 BoundingBox aabb = box.GetAABB(); MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Min - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Max + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); MyMwcVector3Int tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { Vector3 position = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord); //BoundingBox voxelAABB = new BoundingBox(position - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF), position + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)); byte newContent = 0; // Transform the point into box-local space and check against // our extents. Quaternion qinv = Quaternion.Conjugate(box.Orientation); Vector3 plocal = Vector3.Transform(position - box.Center, qinv); //MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF float distY = 0; int sY = System.Math.Sign(plocal.Y); if (sY > 0) { distY = plocal.Y - box.HalfExtent.Y; } else { distY = plocal.Y + box.HalfExtent.Y; } float distRatio = 1; distRatio = MathHelper.Clamp((plocal.Y + box.HalfExtent.Y) / (2 * box.HalfExtent.Y), 0, 1); int contentY = -1; if (sY > 0) { if (distY > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_FULL; } else if (distY < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else { // This formula will work even if diff is positive or negative //contentY = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); contentY = MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } else { if (distY < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_FULL; } else if (distY > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else { // This formula will work even if diff is positive or negative //contentY = MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); contentY = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } Matrix boxMatrix = Matrix.CreateFromQuaternion(box.Orientation); Vector3 hY1 = box.Center + boxMatrix.Up * box.HalfExtent.Y; Vector3 hY2 = box.Center + boxMatrix.Down * box.HalfExtent.Y; float dist = MyUtils.GetPointLineDistance(ref hY1, ref hY2, ref position); float diff = dist - MathHelper.Lerp(radius2, radius1, distRatio); //float diff = dist - box.HalfExtent.Z; byte newContent2; if (diff > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent2 = MyVoxelConstants.VOXEL_CONTENT_FULL; } else if (diff < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent2 = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else { // This formula will work even if diff is positive or negative //newContent2 = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - diff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); newContent2 = (byte)(MyVoxelConstants.VOXEL_CONTENT_FULL - (int)(MyVoxelConstants.VOXEL_ISO_LEVEL - diff / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL)); } newContent = (byte)System.Math.Max(contentY, newContent2); //newContent = (byte)contentY; byte originalContent = voxelMap.GetVoxelContent(ref tempVoxelCoord); if (newContent < originalContent) { voxelMap.SetVoxelContent(newContent, ref tempVoxelCoord); if (material.HasValue) voxelMap.SetVoxelMaterialAndIndestructibleContent(material.Value, 0, ref tempVoxelCoord); } } } } voxelMap.InvalidateCache(minCorner, maxCorner); voxelMap.CalcAverageDataCellMaterials(); } //CutoutCylinder
} //Create Cuboid public static void CutOutCuboid(MyVoxelMap voxelMap, MyCuboid cuboid, MyMwcVoxelMaterialsEnum? material) { BoundingBox aabb = cuboid.GetAABB(); MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Min - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Max + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); MyMwcVector3Int tempVoxelCoord; for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { Vector3 position = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord); BoundingBox voxelAABB = new BoundingBox(position - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF), position + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)); bool isInside = true; for (int i = 0; i < cuboid.Sides.Length; i++) { MyPlane side = cuboid.Sides[i].Plane; float distance = MyUtils.GetDistanceFromPointToPlane(ref position, ref side); if (distance > 0) { isInside = false; break; } } float minDistance = float.MaxValue; for (int i = 0; i < cuboid.Sides.Length; i++) { MyQuad quad = new MyQuad(); quad.Point0 = cuboid.Sides[i].Lines[0].From; quad.Point1 = cuboid.Sides[i].Lines[1].From; quad.Point2 = cuboid.Sides[i].Lines[3].From; quad.Point3 = cuboid.Sides[i].Lines[2].From; float distance = MyUtils.GetDistancePointToQuad(ref position, ref quad); if (distance < minDistance) { minDistance = distance; } } byte newContent = 0; if (isInside) { if (minDistance > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else { // This formula will work even if diff is positive or negative //newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - minDistance / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); //newContent = (byte)(MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - minDistance / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL)); } } else { if (minDistance > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { //newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; // This formula will work even if diff is positive or negative //newContent = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - minDistance / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); newContent = (byte)(MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - minDistance / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL)); } } byte originalContent = voxelMap.GetVoxelContent(ref tempVoxelCoord); if (newContent < originalContent) { voxelMap.SetVoxelContent(newContent, ref tempVoxelCoord); if (material.HasValue) voxelMap.SetVoxelMaterialAndIndestructibleContent(material.Value, 0, ref tempVoxelCoord); } } } } voxelMap.InvalidateCache(minCorner, maxCorner); voxelMap.CalcAverageDataCellMaterials(); } //CutOut Cuboid
public static void CutOutOrientedBox(MyVoxelMap voxelMap, MyOrientedBoundingBox box, ref bool changed) { BoundingBox aabb = box.GetAABB(); MyMwcVector3Int minCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Min - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); MyMwcVector3Int maxCorner = voxelMap.GetVoxelCoordinateFromMeters(aabb.Max + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES)); voxelMap.FixVoxelCoord(ref minCorner); voxelMap.FixVoxelCoord(ref maxCorner); System.Threading.Tasks.Parallel.For(minCorner.X, maxCorner.X, i => { System.Threading.Tasks.Parallel.For(minCorner.Y, maxCorner.Y, j => { System.Threading.Tasks.Parallel.For(minCorner.Z, maxCorner.Z, k => { MyMwcVector3Int tempVoxelCoord = new MyMwcVector3Int(i, j, k); Vector3 position = voxelMap.GetVoxelCenterPositionAbsolute(ref tempVoxelCoord); BoundingBox voxelAABB = new BoundingBox(position - new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF), position + new Vector3(MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF)); byte newContent = 0; ContainmentType ct = box.Contains(ref voxelAABB); if (ct == ContainmentType.Contains) { newContent = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (ct == ContainmentType.Disjoint) { newContent = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // Transform the point into box-local space and check against // our extents. Quaternion qinv = Quaternion.Conjugate(box.Orientation); Vector3 plocal = Vector3.Transform(position - box.Center, qinv); //MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF float distX = 0; float distY = 0; float distZ = 0; int sX = System.Math.Sign(plocal.X); int sY = System.Math.Sign(plocal.Y); int sZ = System.Math.Sign(plocal.Z); if (sX > 0) { distX = plocal.X - box.HalfExtent.X; } else { distX = plocal.X + box.HalfExtent.X; } if (sY > 0) { distY = plocal.Y - box.HalfExtent.Y; } else { distY = plocal.Y + box.HalfExtent.Y; } if (sZ > 0) { distZ = plocal.Z - box.HalfExtent.Z; } else { distZ = plocal.Z + box.HalfExtent.Z; } //float diff = (distX + distY + distZ) / 3; //float diff = (sX*sY*sZ) * System.Math.Min(System.Math.Min(distX,distY), distZ); int contentX; int contentY; int contentZ; if (sX < 0) { if (distX > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentX = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distX < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentX = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentX = MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distX / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } else { if (distX < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentX = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distX > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentX = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentX = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distX / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } if (sY < 0) { if (distY > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distY < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentY = MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } else { if (distY < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distY > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentY = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentY = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distY / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } if (sZ < 0) { if (distZ > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentZ = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distZ < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentZ = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentZ = MyVoxelConstants.VOXEL_CONTENT_FULL - (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distZ / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } else { if (distZ < -MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentZ = MyVoxelConstants.VOXEL_CONTENT_EMPTY; } else if (distZ > MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF) { contentZ = MyVoxelConstants.VOXEL_CONTENT_FULL; } else { // This formula will work even if diff is positive or negative contentZ = (byte)(MyVoxelConstants.VOXEL_ISO_LEVEL - distZ / MyVoxelConstants.VOXEL_SIZE_IN_METRES_HALF * MyVoxelConstants.VOXEL_ISO_LEVEL); } } //voxelMap.SetVoxelContent( (byte)((contentX + contentY + contentZ)/3.0f), ref tempVoxelCoord); newContent = (byte)(System.Math.Min(System.Math.Min(contentX, contentY), contentZ)); } byte originalContent = voxelMap.GetVoxelContent(ref tempVoxelCoord); if (newContent < originalContent) { voxelMap.SetVoxelContent(newContent, ref tempVoxelCoord, true); //changed = true; } }); }); }); /* for (tempVoxelCoord.X = minCorner.X; tempVoxelCoord.X <= maxCorner.X; tempVoxelCoord.X++) { for (tempVoxelCoord.Y = minCorner.Y; tempVoxelCoord.Y <= maxCorner.Y; tempVoxelCoord.Y++) { for (tempVoxelCoord.Z = minCorner.Z; tempVoxelCoord.Z <= maxCorner.Z; tempVoxelCoord.Z++) { } } }*/ changed = true; voxelMap.InvalidateCache(minCorner, maxCorner); voxelMap.CalcAverageDataCellMaterials(); }