bool CoverageRegion::mergeItemsInArray(VoxelProjectedPolygon* seed, bool seedInArray) { for (int i = 0; i < _polygonCount; i++) { VoxelProjectedPolygon* otherPolygon = _polygons[i]; if (otherPolygon->canMerge(*seed)) { otherPolygon->merge(*seed); if (seedInArray) { int* IGNORED_ADDRESS = NULL; // remove this otherOtherPolygon for our polygon array _polygonCount = removeFromSortedArrays((void*)seed, (void**)_polygons, _polygonDistances, IGNORED_ADDRESS, _polygonCount, _polygonArraySize); _totalPolygons--; } //qDebug("_polygonCount=%d\n",_polygonCount); // clean up if (_managePolygons) { delete seed; } // Now run again using our newly merged polygon as the seed mergeItemsInArray(otherPolygon, true); return true; } } return false; }
CoverageMapStorageResult CoverageRegion::checkRegion(VoxelProjectedPolygon* polygon, const BoundingBox& polygonBox, bool storeIt) { CoverageMapStorageResult result = DOESNT_FIT; if (_isRoot || _myBoundingBox.contains(polygonBox)) { result = NOT_STORED; // if we got here, then we DO fit... // only actually check the polygons if this polygon is in the covered bounds for this region if (!_currentCoveredBounds.contains(polygonBox)) { _regionSkips += _polygonCount; } else { // check to make sure this polygon isn't occluded by something at this level for (int i = 0; i < _polygonCount; i++) { VoxelProjectedPolygon* polygonAtThisLevel = _polygons[i]; // Check to make sure that the polygon in question is "behind" the polygon in the list // otherwise, we don't need to test it's occlusion (although, it means we've potentially // added an item previously that may be occluded??? Is that possible? Maybe not, because two // voxels can't have the exact same outline. So one occludes the other, they can't both occlude // each other. _occlusionTests++; if (polygonAtThisLevel->occludes(*polygon)) { // if the polygonAtThisLevel is actually behind the one we're inserting, then we don't // want to report our inserted one as occluded, but we do want to add our inserted one. if (polygonAtThisLevel->getDistance() >= polygon->getDistance()) { _outOfOrderPolygon++; if (storeIt) { if (polygon->getBoundingBox().area() > CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE) { if (getPolygonCount() < MAX_POLYGONS_PER_REGION) { storeInArray(polygon); return STORED; } else { CoverageRegion::_regionFullSkips++; return NOT_STORED; } } else { _tooSmallSkips++; return NOT_STORED; } } else { return NOT_STORED; } } // this polygon is occluded by a closer polygon, so don't store it, and let the caller know return OCCLUDED; } } } } return result; }
// possible results = STORED/NOT_STORED, OCCLUDED, DOESNT_FIT CoverageMap::StorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, bool storeIt) { if (_isRoot || _myBoundingBox.contains(polygon->getBoundingBox())) { // check to make sure this polygon isn't occluded by something at this level for (int i = 0; i < _polygonCount; i++) { VoxelProjectedPolygon* polygonAtThisLevel = _polygons[i]; // Check to make sure that the polygon in question is "behind" the polygon in the list // otherwise, we don't need to test it's occlusion (although, it means we've potentially // added an item previously that may be occluded??? Is that possible? Maybe not, because two // voxels can't have the exact same outline. So one occludes the other, they can't both occlude // each other. if (polygonAtThisLevel->occludes(*polygon)) { // if the polygonAtThisLevel is actually behind the one we're inserting, then we don't // want to report our inserted one as occluded, but we do want to add our inserted one. if (polygonAtThisLevel->getDistance() >= polygon->getDistance()) { if (storeIt) { storeInArray(polygon); return STORED; } else { return NOT_STORED; } } // this polygon is occluded by a closer polygon, so don't store it, and let the caller know return OCCLUDED; } } // if we made it here, then it means the polygon being stored is not occluded // at this level of the quad tree, so we can continue to insert it into the map. // First we check to see if it fits in any of our sub maps for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { BoundingBox childMapBoundingBox = getChildBoundingBox(i); if (childMapBoundingBox.contains(polygon->getBoundingBox())) { // if no child map exists yet, then create it if (!_childMaps[i]) { _childMaps[i] = new CoverageMap(childMapBoundingBox, NOT_ROOT, _managePolygons); } return _childMaps[i]->checkMap(polygon, storeIt); } } // if we got this far, then the polygon is in our bounding box, but doesn't fit in // any of our child bounding boxes, so we should add it here. if (storeIt) { storeInArray(polygon); return STORED; } else { return NOT_STORED; } } return DOESNT_FIT; }
bool VoxelProjectedPolygon::occludes(const VoxelProjectedPolygon& occludee, bool checkAllInView) const { // if we are completely out of view, then we definitely don't occlude! // if the occludee is completely out of view, then we also don't occlude it // // this is true, but unfortunately, we're not quite handling projects in the // case when SOME points are in view and others are not. So, we will not consider // occlusion for any shadows that are partially in view. if (checkAllInView && (!getAllInView() || !occludee.getAllInView())) { return false; } // first check the bounding boxes, the occludee must be fully within the boounding box of this shadow if ((occludee.getMaxX() > getMaxX()) || (occludee.getMaxY() > getMaxY()) || (occludee.getMinX() < getMinX()) || (occludee.getMinY() < getMinY())) { return false; } // if we got this far, then check each vertex of the occludee, if all those points // are inside our polygon, then the tested occludee is fully occluded for(int i = 0; i < occludee.getVertexCount(); i++) { if (!pointInside(occludee.getVertex(i))) { return false; } } // if we got this far, then indeed the occludee is fully occluded by us return true; }