public static CubeType[][][] ReadModelVolmetic(string modelFile, double scaleMultiplyier, Transform3D transform, ModelTraceVoxel traceType, Action<double, double> resetProgress, Action incrementProgress) { return ReadModelVolmetic(modelFile, scaleMultiplyier, scaleMultiplyier, scaleMultiplyier, transform, traceType, resetProgress, incrementProgress); }
/// <summary> /// Volumes are calculated across axis where they are whole numbers (rounded to 0 decimal places). /// </summary> /// <param name="modelFile"></param> /// <param name="scaleMultiplyierX"></param> /// <param name="scaleMultiplyierY"></param> /// <param name="scaleMultiplyierZ"></param> /// <param name="transform"></param> /// <param name="traceType"></param> /// <param name="resetProgress"></param> /// <param name="incrementProgress"></param> /// <returns></returns> public static CubeType[][][] ReadModelVolmetic(string modelFile, double scaleMultiplyierX, double scaleMultiplyierY, double scaleMultiplyierZ, Transform3D transform, ModelTraceVoxel traceType, Action<double, double> resetProgress, Action incrementProgress) { var model = MeshHelper.Load(modelFile, ignoreErrors: true); // How far to check in from the proposed Volumetric edge. // This number is just made up, but small enough that it still represents the corner edge of the Volumetric space. // But still large enough that it isn't the exact corner. const double offset = 0.00000456f; if (scaleMultiplyierX > 0 && scaleMultiplyierY > 0 && scaleMultiplyierZ > 0 && scaleMultiplyierX != 1.0f && scaleMultiplyierY != 1.0f && scaleMultiplyierZ != 1.0f) { model.TransformScale(scaleMultiplyierX, scaleMultiplyierY, scaleMultiplyierZ); } var tbounds = model.Bounds; if (transform != null) tbounds = transform.TransformBounds(tbounds); var xMin = (int)Math.Floor(tbounds.X); var yMin = (int)Math.Floor(tbounds.Y); var zMin = (int)Math.Floor(tbounds.Z); var xMax = (int)Math.Ceiling(tbounds.X + tbounds.SizeX); var yMax = (int)Math.Ceiling(tbounds.Y + tbounds.SizeY); var zMax = (int)Math.Ceiling(tbounds.Z + tbounds.SizeZ); var xCount = xMax - xMin; var yCount = yMax - yMin; var zCount = zMax - zMin; var ccubic = ArrayHelper.Create<CubeType>(xCount, yCount, zCount); if (resetProgress != null) { double count = (from GeometryModel3D gm in model.Children select gm.Geometry as MeshGeometry3D).Aggregate<MeshGeometry3D, double>(0, (current, g) => current + (g.TriangleIndices.Count / 3)); if (traceType == ModelTraceVoxel.ThinSmoothed || traceType == ModelTraceVoxel.ThickSmoothedUp) { count += (xCount * yCount * zCount * 3); } resetProgress.Invoke(0, count); } #region basic ray trace of every individual triangle. foreach (var model3D in model.Children) { var gm = (GeometryModel3D)model3D; var g = gm.Geometry as MeshGeometry3D; var materials = gm.Material as MaterialGroup; System.Windows.Media.Color color = Colors.Transparent; if (materials != null) { var material = materials.Children.OfType<DiffuseMaterial>().FirstOrDefault(); if (material != null && material != null && material.Brush is SolidColorBrush) { color = ((SolidColorBrush)material.Brush).Color; } } for (var t = 0; t < g.TriangleIndices.Count; t += 3) { if (incrementProgress != null) { incrementProgress.Invoke(); } var p1 = g.Positions[g.TriangleIndices[t]]; var p2 = g.Positions[g.TriangleIndices[t + 1]]; var p3 = g.Positions[g.TriangleIndices[t + 2]]; if (transform != null) { p1 = transform.Transform(p1); p2 = transform.Transform(p2); p3 = transform.Transform(p3); } var minBound = MeshHelper.Min(p1, p2, p3).Floor(); var maxBound = MeshHelper.Max(p1, p2, p3).Ceiling(); Point3D[] rays; for (var y = minBound.Y; y < maxBound.Y; y++) { for (var z = minBound.Z; z < maxBound.Z; z++) { if (traceType == ModelTraceVoxel.Thin || traceType == ModelTraceVoxel.ThinSmoothed) { rays = new Point3D[] // 1 point ray trace in the center. { new Point3D(xMin, y + 0.5 + offset, z + 0.5 + offset), new Point3D(xMax, y + 0.5 + offset, z + 0.5 + offset) }; } else { rays = new Point3D[] // 4 point ray trace within each corner of the expected Volumetric cube. { new Point3D(xMin, y + offset, z + offset), new Point3D(xMax, y + offset, z + offset), new Point3D(xMin, y + 1 - offset, z + offset), new Point3D(xMax, y + 1 - offset, z + offset), new Point3D(xMin, y + offset, z + 1 - offset), new Point3D(xMax, y + offset, z + 1 - offset), new Point3D(xMin, y + 1 - offset, z + 1 - offset), new Point3D(xMax, y + 1 - offset, z + 1 - offset) }; } Point3D intersect; int normal; if (MeshHelper.RayIntersetTriangleRound(p1, p2, p3, rays, out intersect, out normal)) { ccubic[(int)Math.Floor(intersect.X) - xMin][(int)Math.Floor(intersect.Y) - yMin][(int)Math.Floor(intersect.Z) - zMin] = CubeType.Cube; } } } for (var x = minBound.X; x < maxBound.X; x++) { for (var z = minBound.Z; z < maxBound.Z; z++) { if (traceType == ModelTraceVoxel.Thin || traceType == ModelTraceVoxel.ThinSmoothed) { rays = new Point3D[] // 1 point ray trace in the center. { new Point3D(x + 0.5 + offset, yMin, z + 0.5 + offset), new Point3D(x + 0.5 + offset, yMax, z + 0.5 + offset) }; } else { rays = new Point3D[] // 4 point ray trace within each corner of the expected Volumetric cube. { new Point3D(x + offset, yMin, z + offset), new Point3D(x + offset, yMax, z + offset), new Point3D(x + 1 - offset, yMin, z + offset), new Point3D(x + 1 - offset, yMax, z + offset), new Point3D(x + offset, yMin, z + 1 - offset), new Point3D(x + offset, yMax, z + 1 - offset), new Point3D(x + 1 - offset, yMin, z + 1 - offset), new Point3D(x + 1 - offset, yMax, z + 1 - offset) }; } Point3D intersect; int normal; if (MeshHelper.RayIntersetTriangleRound(p1, p2, p3, rays, out intersect, out normal)) { ccubic[(int)Math.Floor(intersect.X) - xMin][(int)Math.Floor(intersect.Y) - yMin][(int)Math.Floor(intersect.Z) - zMin] = CubeType.Cube; } } } for (var x = minBound.X; x < maxBound.X; x++) { for (var y = minBound.Y; y < maxBound.Y; y++) { if (traceType == ModelTraceVoxel.Thin || traceType == ModelTraceVoxel.ThinSmoothed) { rays = new Point3D[] // 1 point ray trace in the center. { new Point3D(x + 0.5 + offset, y + 0.5 + offset, zMin), new Point3D(x + 0.5 + offset, y + 0.5 + offset, zMax), }; } else { rays = new Point3D[] // 4 point ray trace within each corner of the expected Volumetric cube. { new Point3D(x + offset, y + offset, zMin), new Point3D(x + offset, y + offset, zMax), new Point3D(x + 1 - offset, y + offset, zMin), new Point3D(x + 1 - offset, y + offset, zMax), new Point3D(x + offset, y + 1 - offset, zMin), new Point3D(x + offset, y + 1 - offset, zMax), new Point3D(x + 1 - offset, y + 1 - offset, zMin), new Point3D(x + 1 - offset, y + 1 - offset, zMax) }; } Point3D intersect; int normal; if (MeshHelper.RayIntersetTriangleRound(p1, p2, p3, rays, out intersect, out normal)) { ccubic[(int)Math.Floor(intersect.X) - xMin][(int)Math.Floor(intersect.Y) - yMin][(int)Math.Floor(intersect.Z) - zMin] = CubeType.Cube; } } } } } #endregion CrawlExterior(ccubic); if (traceType == ModelTraceVoxel.ThinSmoothed || traceType == ModelTraceVoxel.ThickSmoothedUp) { CalculateAddedInverseCorners(ccubic, incrementProgress); CalculateAddedSlopes(ccubic, incrementProgress); CalculateAddedCorners(ccubic, incrementProgress); } //if (traceType == ModelTraceVoxel.ThickSmoothedDown) //{ // CalculateSubtractedCorners(ccubic); // CalculateSubtractedSlopes(ccubic); // CalculateSubtractedInverseCorners(ccubic); //} return ccubic; }
public static CubeType[][][] ReadModelVolmetic(string modelFile, double scaleMultiplyier, Transform3D transform, ModelTraceVoxel traceType) { return ReadModelVolmetic(modelFile, scaleMultiplyier, scaleMultiplyier, scaleMultiplyier, transform, traceType, null, null); }
public static MyVoxelMap BuildAsteroidFromModel(bool multiThread, string sourceVolumetricFile, string material, string faceMaterial, bool fillObject, string interiorMaterial, ModelTraceVoxel traceType, double scale, Transform3D transform, Action <double, double> resetProgress, Action incrementProgress) { var volmeticMap = Modelling.ReadModelVolmetic(sourceVolumetricFile, scale, transform, traceType, resetProgress, incrementProgress); var size = new Vector3I(volmeticMap.Length + 12, volmeticMap[0].Length + 12, volmeticMap[0][0].Length + 12); var action = (Action <MyVoxelBuilderArgs>) delegate(MyVoxelBuilderArgs e) { if (e.CoordinatePoint.X > 5 && e.CoordinatePoint.Y > 5 && e.CoordinatePoint.Z > 5 && (e.CoordinatePoint.X <= volmeticMap.Length + 5) && (e.CoordinatePoint.Y <= volmeticMap[0].Length + 5) && (e.CoordinatePoint.Z <= volmeticMap[0][0].Length + 5)) { var cube = volmeticMap[e.CoordinatePoint.X - 6][e.CoordinatePoint.Y - 6][e.CoordinatePoint.Z - 6]; if (cube == CubeType.Interior && fillObject) { e.Volume = 0xff; // 100% if (interiorMaterial != null) { e.Material = interiorMaterial; } } else if (cube == CubeType.Cube) { e.Volume = 0xff; // 100% "11111111" } else if (cube.ToString().StartsWith("InverseCorner")) { e.Volume = 0xD4; // 83% "11010100" } else if (cube.ToString().StartsWith("Slope")) { e.Volume = 0x7F; // 50% "01111111" } else if (cube.ToString().StartsWith("NormalCorner")) { e.Volume = 0x2B; // 16% "00101011" } else { e.Volume = 0x00; // 0% "00000000" } } else { e.Volume = 0x00; } }; return(BuildAsteroid(multiThread, size, material, faceMaterial, action)); }
public static MyVoxelMap BuildAsteroidFromModel(bool multiThread, string sourceVolumetricFile, string material, string faceMaterial, bool fillObject, string interiorMaterial, ModelTraceVoxel traceType, double scale, Transform3D transform) { return(BuildAsteroidFromModel(multiThread, sourceVolumetricFile, material, faceMaterial, fillObject, interiorMaterial, traceType, scale, transform, null, null)); }
public static MyVoxelMap BuildAsteroidFromModel(bool multiThread, string sourceVolumetricFile, string material, string faceMaterial, bool fillObject, string interiorMaterial, ModelTraceVoxel traceType, double scale, Transform3D transform, Action<double, double> resetProgress, Action incrementProgress) { var volmeticMap = Modelling.ReadModelVolmetic(sourceVolumetricFile, scale, transform, traceType, resetProgress, incrementProgress); var size = new Vector3I(volmeticMap.Length + 12, volmeticMap[0].Length + 12, volmeticMap[0][0].Length + 12); var action = (Action<MyVoxelBuilderArgs>)delegate(MyVoxelBuilderArgs e) { if (e.CoordinatePoint.X > 5 && e.CoordinatePoint.Y > 5 && e.CoordinatePoint.Z > 5 && (e.CoordinatePoint.X <= volmeticMap.Length + 5) && (e.CoordinatePoint.Y <= volmeticMap[0].Length + 5) && (e.CoordinatePoint.Z <= volmeticMap[0][0].Length + 5)) { var cube = volmeticMap[e.CoordinatePoint.X - 6][e.CoordinatePoint.Y - 6][e.CoordinatePoint.Z - 6]; if (cube == CubeType.Interior && fillObject) { e.Volume = 0xff; // 100% if (interiorMaterial != null) { e.Material = interiorMaterial; } } else if (cube == CubeType.Cube) e.Volume = 0xff; // 100% "11111111" else if (cube.ToString().StartsWith("InverseCorner")) e.Volume = 0xD4; // 83% "11010100" else if (cube.ToString().StartsWith("Slope")) e.Volume = 0x7F; // 50% "01111111" else if (cube.ToString().StartsWith("NormalCorner")) e.Volume = 0x2B; // 16% "00101011" else e.Volume = 0x00; // 0% "00000000" } else { e.Volume = 0x00; } }; return BuildAsteroid(multiThread, size, material, faceMaterial, action); }
public static MyVoxelMap BuildAsteroidFromModel(bool multiThread, string sourceVolumetricFile, string material, string faceMaterial, bool fillObject, string interiorMaterial, ModelTraceVoxel traceType, double scale, Transform3D transform) { return BuildAsteroidFromModel(multiThread, sourceVolumetricFile, material, faceMaterial, fillObject, interiorMaterial, traceType, scale, transform, null, null); }