/// <summary> /// if area is null then area is retained /// </summary> public void MakeHole(List <ShapeDataAbstract> shapes, Area area) { bool appyArea = area != null; byte areaValue = 0; if (appyArea) { areaValue = GetAreaValue(area); } for (int i = 0; i < shapes.Count; i++) { DataCompact[] compactData = TakeCompactData(); var shape = shapes[i]; if (shape is ShapeDataSphere) { ShapeDataSphere castedShape = shape as ShapeDataSphere; AppendSpherePrivate(compactData, castedShape.bounds.center, castedShape.bounds.extents.x, 0f, false, true); } else if (shape is ShapeDataCapsule) { ShapeDataCapsule castedShape = shape as ShapeDataCapsule; AppendCapsulePrivate(compactData, castedShape.sphereA, castedShape.sphereB, castedShape.capsileRadius, true, areaValue); } else if (shape is ShapeDataBox) { ShapeDataBox castedShape = shape as ShapeDataBox; AppendMeshConvexPrivate(compactData, ColliderCollector.cubeVerts, ColliderCollector.cubeTris, castedShape.boxMatrix, areaValue, true); //Debug.LogWarning("dont forget to flip Y in ShapeDataBox"); } else { Debug.LogError("no support for current area modifyer in shape collector"); } Vector3 realChunkPos = template.realOffsetedPosition; Vector3 offset = template.halfVoxelOffset; for (int x = 0; x < sizeX; x++) { for (int z = 0; z < sizeZ; z++) { int index = GetIndex(x, z); DataCompact mask = compactData[index]; if (mask.pass != -1 && arrayData[index].next != -2) { int prevIndex = -1; int curIndex = index; while (true) { if (curIndex < 0) { break; } Data curNode = arrayData[curIndex]; if ((mask.min > curNode.max | mask.max < curNode.min) == false) //if current mask in not higher or lower than current node { if (SomeMath.InRangeExclusive(mask.min, curNode.min, curNode.max)) { arrayData[curIndex].max = mask.min; arrayData[curIndex].pass = mask.pass; if (appyArea) { arrayData[curIndex].area = areaValue; } if (SomeMath.InRangeExclusive(mask.max, curNode.min, curNode.max)) { int freeIndex = GetFreeIndex(); arrayData[freeIndex] = new Data(mask.max, curNode.max, curNode.pass, curNode.next, curNode.area); arrayData[curIndex].next = freeIndex; break; } prevIndex = curIndex; curIndex = arrayData[curIndex].next; } else if (SomeMath.InRangeExclusive(mask.max, curNode.min, curNode.max)) { //top of mask inside current shape arrayData[curIndex].min = mask.max; break;//this nothing can be intersected after that } else { if (curNode.next == -1) //if there no nodes after that { if (prevIndex == -1) //if it first node { arrayData[curIndex].next = -2; //make it invalid } else { arrayData[prevIndex].next = -1; } break; } //if some nodes after that else { //shift next thata to current index //NOTE: curIndex is not changed to check new data at this index ReturnFreeIndex(curNode.next); arrayData[curIndex] = arrayData[curNode.next]; continue; } } } prevIndex = curIndex; curIndex = curNode.next; } } } } GenericPoolArray <DataCompact> .ReturnToPool(ref compactData); } }