/// <inheritdoc/> public PlaneExtractionVoxelGrid( VoxelGridOrientation orientation, Bounds containedBounds, float voxelSize, VoxelPlaneFindingParams planeFindingParams) : base(orientation, containedBounds, voxelSize, planeFindingParams) { }
static void GenerateVoxelGrids(GameObject prefabRoot, PlaneVoxelGenerationParams voxelGenerationParams, VoxelPlaneFindingParams planeFindingParams) { // Rather than modifying collider properties and risking corrupting the scene, for each object with a mesh // we create a game object with a collider that uses that mesh and add that object to a preview scene. var tempPreviewScene = EditorSceneManager.NewPreviewScene(); var tempPhysicsScene = tempPreviewScene.GetPhysicsScene(); // k_MeshFilters is cleared by GetComponentsInChildren prefabRoot.GetComponentsInChildren(k_MeshFilters); var meshesRoot = new GameObject("Meshes").transform; k_MeshColliders.Clear(); foreach (var meshFilter in k_MeshFilters) { // Ignore synth planes if (meshFilter.GetComponent <SynthesizedPlane>()) { continue; } var meshCopyTrans = new GameObject(string.Format("{0} (Mesh)", meshFilter.gameObject.name)).transform; var meshCopyCollider = meshCopyTrans.gameObject.AddComponent <MeshCollider>(); k_MeshColliders.Add(meshCopyCollider); meshCopyCollider.sharedMesh = meshFilter.sharedMesh; meshCopyTrans.SetParent(meshesRoot); var meshFilterTrans = meshFilter.transform; meshCopyTrans.position = meshFilterTrans.position; meshCopyTrans.rotation = meshFilterTrans.rotation; meshCopyTrans.localScale = meshFilterTrans.lossyScale; } SceneManager.MoveGameObjectToScene(meshesRoot.gameObject, tempPreviewScene); var sceneBounds = BoundsUtils.GetBounds(k_MeshColliders); var sceneBoundsMin = sceneBounds.min; var sceneBoundsMax = sceneBounds.max; // Make mesh colliders convex so that we can use CheckSphere to make sure our // raycasts don't originate within meshes. foreach (var meshCollider in k_MeshColliders) { meshCollider.convex = true; } // Seed the random number generator so that results are deterministic Random.InitState(voxelGenerationParams.raycastSeed); // Setup all ray origins before raycasting since we need mesh colliders to be convex for this step // but concave for the raycasting. var raycastCount = voxelGenerationParams.raycastCount; k_RayOrigins.Clear(); k_RayOrigins.Capacity = raycastCount; for (var i = 0; i < raycastCount; i++) { var rayGenerationAttempts = 0; Vector3 origin; while (true) { origin = new Vector3( Random.Range(sceneBoundsMin.x, sceneBoundsMax.x), Random.Range(sceneBoundsMin.y, sceneBoundsMax.y), Random.Range(sceneBoundsMin.z, sceneBoundsMax.z)); // If the randomly generated ray origin lies inside a mesh, try again if (tempPhysicsScene.OverlapSphere(origin, k_CheckSphereRadius, k_Colliders, Physics.DefaultRaycastLayers, QueryTriggerInteraction.Collide) == 0) { break; } rayGenerationAttempts++; if (rayGenerationAttempts >= k_MaxRayGenerationRetries) { break; } } k_RayOrigins.Add(origin); } foreach (var meshCollider in k_MeshColliders) { // Make mesh colliders concave for more useful raycast results meshCollider.convex = false; } k_UpGridPoints.Clear(); k_DownGridPoints.Clear(); k_ForwardGridPoints.Clear(); k_BackGridPoints.Clear(); k_RightGridPoints.Clear(); k_LeftGridPoints.Clear(); var outerPointsThreshold = voxelGenerationParams.outerPointsThreshold; var upGridBounds = sceneBounds; var upGridMax = upGridBounds.max; upGridMax.y -= Mathf.Min(outerPointsThreshold, upGridBounds.size.y); upGridBounds.max = upGridMax; var downGridBounds = sceneBounds; var downGridMin = downGridBounds.min; downGridMin.y += Mathf.Min(outerPointsThreshold, downGridBounds.size.y); downGridBounds.min = downGridMin; var forwardGridBounds = sceneBounds; var forwardGridMax = forwardGridBounds.max; forwardGridMax.z -= Mathf.Min(outerPointsThreshold, forwardGridBounds.size.z); forwardGridBounds.max = forwardGridMax; var backGridBounds = sceneBounds; var backGridMin = backGridBounds.min; backGridMin.z += Mathf.Min(outerPointsThreshold, backGridBounds.size.z); backGridBounds.min = backGridMin; var rightGridBounds = sceneBounds; var rightGridMax = rightGridBounds.max; rightGridMax.x -= Mathf.Min(outerPointsThreshold, rightGridBounds.size.x); rightGridBounds.max = rightGridMax; var leftGridBounds = sceneBounds; var leftGridMin = leftGridBounds.min; leftGridMin.x += Mathf.Min(outerPointsThreshold, leftGridBounds.size.x); leftGridBounds.min = leftGridMin; // Start raycasting. We run raycasts synchronously so the user can't switch scenes or make scene changes while they are running. var maxHitDistance = voxelGenerationParams.maxHitDistance; var normalToleranceAngle = voxelGenerationParams.normalToleranceAngle; var rayIndex = 0; var up = Vector3.up; var down = Vector3.down; var back = Vector3.back; var right = Vector3.right; var left = Vector3.left; while (rayIndex < raycastCount) { if (EditorUtility.DisplayCancelableProgressBar( "Generating Point Cloud", string.Format("{0}/{1} raycasts completed", rayIndex, raycastCount), (float)rayIndex / raycastCount)) { EditorUtility.ClearProgressBar(); GUIUtility.ExitGUI(); break; } for (var i = 0; i < k_RaycastProgressBatchSize && rayIndex < raycastCount; i++, rayIndex++) { var origin = k_RayOrigins[rayIndex]; var direction = RandomRayDirection(); RaycastHit raycastHit; if (!tempPhysicsScene.Raycast(origin, direction, out raycastHit, maxHitDistance)) { continue; } var point = raycastHit.point; var normal = raycastHit.normal; if (Vector3.Angle(normal, up) <= normalToleranceAngle && upGridBounds.Contains(point)) { k_UpGridPoints.Add(point); } if (Vector3.Angle(normal, down) <= normalToleranceAngle && downGridBounds.Contains(point)) { k_DownGridPoints.Add(point); } if (Vector3.Angle(normal, k_Forward) <= normalToleranceAngle && forwardGridBounds.Contains(point)) { k_ForwardGridPoints.Add(point); } if (Vector3.Angle(normal, back) <= normalToleranceAngle && backGridBounds.Contains(point)) { k_BackGridPoints.Add(point); } if (Vector3.Angle(normal, right) <= normalToleranceAngle && rightGridBounds.Contains(point)) { k_RightGridPoints.Add(point); } if (Vector3.Angle(normal, left) <= normalToleranceAngle && leftGridBounds.Contains(point)) { k_LeftGridPoints.Add(point); } } } EditorUtility.ClearProgressBar(); EditorSceneManager.ClosePreviewScene(tempPreviewScene); // Reset the seed so other uses of Random are not deterministic Random.InitState((int)DateTime.Now.Ticks); // Generate voxel grids from point cloud var voxelSize = voxelGenerationParams.voxelSize; s_UpVoxelGrid = new PlaneExtractionVoxelGrid(VoxelGridOrientation.Up, upGridBounds, voxelSize, planeFindingParams); s_DownVoxelGrid = new PlaneExtractionVoxelGrid(VoxelGridOrientation.Down, downGridBounds, voxelSize, planeFindingParams); s_ForwardVoxelGrid = new PlaneExtractionVoxelGrid(VoxelGridOrientation.Forward, forwardGridBounds, voxelSize, planeFindingParams); s_BackVoxelGrid = new PlaneExtractionVoxelGrid(VoxelGridOrientation.Back, backGridBounds, voxelSize, planeFindingParams); s_RightVoxelGrid = new PlaneExtractionVoxelGrid(VoxelGridOrientation.Right, rightGridBounds, voxelSize, planeFindingParams); s_LeftVoxelGrid = new PlaneExtractionVoxelGrid(VoxelGridOrientation.Left, leftGridBounds, voxelSize, planeFindingParams); s_UpVoxelGrid.AddPoints(k_UpGridPoints); s_DownVoxelGrid.AddPoints(k_DownGridPoints); s_ForwardVoxelGrid.AddPoints(k_ForwardGridPoints); s_BackVoxelGrid.AddPoints(k_BackGridPoints); s_RightVoxelGrid.AddPoints(k_RightGridPoints); s_LeftVoxelGrid.AddPoints(k_LeftGridPoints); }