/** * Based on the MoveVarShape function in packEvolves * Returns: index of all the shapes that are at bottom of a shape * index == totalShapes represents the bottom of the box * there are suttle idfferences betweeen FindAllBottom and FindNextCon like the use of layerMask */ List <int> FindAllBottom(GameObject shape, int totalShapes) { int layerMask = 1 << 11; layerMask = ~layerMask; packEvol.SetLayerRecursively(shape, 11); Vector3 startPointGridBoxCor = new Vector3(); Vector3 endPointGridBoxCor = new Vector3(); Vector3[] boxesCenterShape = null; Vector3[] boxesHalfExtends = null; packingAgent.FindShapeCorners( shape, ref startPointGridBoxCor, ref endPointGridBoxCor, ref boxesCenterShape, ref boxesHalfExtends); // here start point is the current position // end end point is the lowest possible position Vector3Int startPointGrid = packingAgent.ConToIdxPos(shape.transform.position, isStart0: false); int startPointGridY = startPointGrid.y; int endPointGridY = packingAgent.FloatToInt(startPointGridBoxCor.y); int curPointGridY = startPointGridY; Vector3 curPointContWorld = shape.transform.position; bool isShapeColliding; List <int> shapeCollidingIdx = new List <int>(); while (true) { isShapeColliding = false; for (int i = 0; i < boxesCenterShape.Length; i++) { var colliders = Physics.OverlapBox(boxesCenterShape[i] + curPointContWorld, boxesHalfExtends[i], Quaternion.identity, layerMask); if (colliders.Length > 0) { isShapeColliding = true; foreach (var collider in colliders) { if (collider.gameObject.transform.name.Contains("shape")) { int _shapeCollidingIdx = int.Parse(collider.gameObject.transform.name.Replace("shape", "")); if (!shapeCollidingIdx.Contains(_shapeCollidingIdx)) { shapeCollidingIdx.Add(_shapeCollidingIdx); } } } } } if (isShapeColliding) { break; } // box bottom should only be added is the shape is not colliding with other shapes // at the bottomost position if (curPointGridY == endPointGridY) { shapeCollidingIdx.Add(totalShapes); break; } curPointGridY--; curPointContWorld.y -= GRID_SIZE; } packEvol.SetLayerRecursively(shape, 0); return(shapeCollidingIdx); }
// Tighten and Connect the Pack public int[,] TightConPack(ref Pack pack) { PackEvolver packEvol = GetComponent <PackEvolver>(); GameObject[] shapes = packEvol.VisualizePack(pack, loadFromResources: false, keepRenderer: false); // An Adjagency matrix. The (n+1)th node represents the bottom int[,] shapeCon = new int[shapes.Length + 1, shapes.Length + 1]; for (int i = 0; i < shapes.Length; i++) { List <int> conBotIdx = GetConnectedNodes(shapes.Length, shapeCon); // unConBotIdx: unconnected to bottom index int unConBotIdx = -1; for (int j = 0; j < shapes.Length; j++) { if (!conBotIdx.Contains(j)) { unConBotIdx = j; break; } } Debug.Assert(unConBotIdx != -1, "Error in code as all nodes already connected to bottom"); // List of nodes that are connected to unConBotIdx List <int> unConBotIdxs = GetConnectedNodes(unConBotIdx, SubArray2D(shapeCon, 0, shapes.Length, 0, shapes.Length)); foreach (int idx in unConBotIdxs) { packEvol.SetLayerRecursively(shapes[idx], 11); } int minUnConBotIdx = -1; int minUnConBotVal = 100; int minUnConBotCon = -1; foreach (int idx in unConBotIdxs) { var temp = FindNextCon(shapes[idx], shapes.Length); if (temp.Item2 < minUnConBotVal) { minUnConBotIdx = idx; minUnConBotVal = temp.Item2; minUnConBotCon = temp.Item1; } } shapeCon[minUnConBotIdx, minUnConBotCon] = 1; shapeCon[minUnConBotCon, minUnConBotIdx] = 1; foreach (int idx in unConBotIdxs) { Vector3 temp = shapes[idx].transform.position; temp.y -= ((float)minUnConBotVal) * GRID_SIZE; shapes[idx].transform.position = temp; packEvol.SetLayerRecursively(shapes[idx], 0); } } int shapesLength = shapes.Length; for (int i = 0; i < shapesLength; i++) { pack.positions[i] = shapes[i].transform.position; UnityEngine.Object.DestroyImmediate(shapes[i]); } return(shapeCon); }