diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d5ed296804..4b5faaf4ed 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2475,6 +2475,30 @@ void Application::renderCoverageMapsRecursively(CoverageMap* map) { for (int i = 0; i < map->getPolygonCount(); i++) { VoxelProjectedPolygon* polygon = map->getPolygon(i); + + if (polygon->getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_BOTTOM)) { + glColor3f(.5,0,0); // dark red + } else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_RIGHT | PROJECTION_TOP)) { + glColor3f(0,.5,0); // dark green + } else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_RIGHT)) { + glColor3f(.5,.5,0); // dark yellow + } else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT)) { + glColor3f(.5,.5,.5); // gray + } else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT | PROJECTION_TOP)) { + glColor3f(0,0,1); // Blue + } else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT | PROJECTION_BOTTOM)) { + glColor3f(.5,0,.5); // dark magenta + } else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_BOTTOM)) { + glColor3f(1,0,0); // red + } else if (polygon->getProjectionType() == (PROJECTION_NEAR | PROJECTION_TOP)) { + glColor3f(1,0,1); // magenta + } else if (polygon->getProjectionType() == (PROJECTION_NEAR)) { + glColor3f(1,1,0); // yellow + } else if (polygon->getProjectionType() == (PROJECTION_FAR | PROJECTION_RIGHT | PROJECTION_BOTTOM)) { + glColor3f(0,.5,.5); // dark cyan + } else { + glColor3f(0,0,1); + } glm::vec2 firstPoint = getScaledScreenPoint(polygon->getVertex(0)); glm::vec2 lastPoint(firstPoint); diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index bdc35ff3f5..aaa21a5a7b 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -440,3 +440,25 @@ int insertIntoSortedArrays(void* value, float key, int originalIndex, return -1; // error case } +int removeFromSortedArrays(void* value, void** valueArray, float* keyArray, int* originalIndexArray, + int currentCount, int maxCount) { + + int i = 0; + if (currentCount > 0) { + while (i < currentCount && value != valueArray[i]) { + i++; + } + + if (value == valueArray[i] && i < currentCount) { + // i is the location of the item we were looking for + // shift array elements to the left + memmove(&valueArray[i], &valueArray[i + 1], sizeof(void*) * ((currentCount-1) - i)); + memmove(&keyArray[i], &keyArray[i + 1], sizeof(float) * ((currentCount-1) - i)); + if (originalIndexArray) { + memmove(&originalIndexArray[i], &originalIndexArray[i + 1], sizeof(int) * ((currentCount-1) - i)); + } + return currentCount-1; + } + } + return -1; // error case +} diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 2c9e1e6317..f134828945 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -88,6 +88,11 @@ int insertIntoSortedArrays(void* value, float key, int originalIndex, void** valueArray, float* keyArray, int* originalIndexArray, int currentCount, int maxCount); +int removeFromSortedArrays(void* value, void** valueArray, float* keyArray, int* originalIndexArray, + int currentCount, int maxCount); + + + // Helper Class for debugging class debug { public: diff --git a/libraries/voxels/src/CoverageMap.cpp b/libraries/voxels/src/CoverageMap.cpp index 92533786b8..82c529ded6 100644 --- a/libraries/voxels/src/CoverageMap.cpp +++ b/libraries/voxels/src/CoverageMap.cpp @@ -196,6 +196,7 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b bool fitsInAHalf = false; // Check each half of the box independently +/** if (_topHalf.contains(polygonBox)) { result = _topHalf.checkRegion(polygon, polygonBox, storeIt); storeIn = &_topHalf; @@ -213,6 +214,7 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b storeIn = &_rightHalf; fitsInAHalf = true; } +**/ // if we got this far, there are one of two possibilities, either a polygon doesn't fit // in one of the halves, or it did fit, but it wasn't occluded by anything only in that @@ -239,6 +241,7 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b // 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 +if (false) { for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { BoundingBox childMapBoundingBox = getChildBoundingBox(i); if (childMapBoundingBox.contains(polygon->getBoundingBox())) { @@ -268,6 +271,7 @@ CoverageMapStorageResult CoverageMap::checkMap(VoxelProjectedPolygon* polygon, b return result; } } +} // 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) { @@ -397,13 +401,53 @@ int CoverageRegion::_tooSmallSkips = 0; int CoverageRegion::_outOfOrderPolygon = 0; int CoverageRegion::_clippedPolygons = 0; + +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) { + const int IGNORED = NULL; + // remove this otherOtherPolygon for our polygon array + _polygonCount = removeFromSortedArrays((void*)seed, + (void**)_polygons, _polygonDistances, IGNORED, + _polygonCount, _polygonArraySize); + _totalPolygons--; + } + + //printLog("_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; +} + // just handles storage in the array, doesn't test for occlusion or // determining if this is the correct map to store in! void CoverageRegion::storeInArray(VoxelProjectedPolygon* polygon) { - _totalPolygons++; - _currentCoveredBounds.explandToInclude(polygon->getBoundingBox()); + + + // Before we actually store this polygon in the array, check to see if this polygon can be merged to any of the existing + // polygons already in our array. + if (mergeItemsInArray(polygon, false)) { + return; // exit early + } + + // only after we attempt to merge! + _totalPolygons++; if (_polygonArraySize < _polygonCount + 1) { growPolygonArray(); @@ -414,11 +458,11 @@ void CoverageRegion::storeInArray(VoxelProjectedPolygon* polygon) { // in the list. We still check to see if the polygon is "in front" of the target polygon before we test occlusion. Since // sometimes things come out of order. const bool SORT_BY_SIZE = false; + const int IGNORED = NULL; if (SORT_BY_SIZE) { // This old code assumes that polygons will always be added in z-buffer order, but that doesn't seem to // be a good assumption. So instead, we will need to sort this by distance. Use a binary search to find the // insertion point in this array, and shift the array accordingly - const int IGNORED = NULL; float area = polygon->getBoundingBox().area(); float reverseArea = 4.0f - area; //printLog("store by size area=%f reverse area=%f\n", area, reverseArea); @@ -458,13 +502,13 @@ CoverageMapStorageResult CoverageRegion::checkRegion(VoxelProjectedPolygon* poly // 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 diff --git a/libraries/voxels/src/CoverageMap.h b/libraries/voxels/src/CoverageMap.h index 7fee7cb6a5..6c0a1f86cb 100644 --- a/libraries/voxels/src/CoverageMap.h +++ b/libraries/voxels/src/CoverageMap.h @@ -59,6 +59,9 @@ private: float* _polygonSizes; void growPolygonArray(); static const int DEFAULT_GROW_SIZE = 100; + + bool mergeItemsInArray(VoxelProjectedPolygon* seed, bool seedInArray); + }; class CoverageMap { diff --git a/libraries/voxels/src/ViewFrustum.cpp b/libraries/voxels/src/ViewFrustum.cpp index cb6c0b219d..b2976c8907 100644 --- a/libraries/voxels/src/ViewFrustum.cpp +++ b/libraries/voxels/src/ViewFrustum.cpp @@ -461,7 +461,7 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERT //0 {0}, // inside {4, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR}, // right - {4, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR }, // left + {4, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR }, // left {0}, // n/a //4 @@ -480,20 +480,25 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERT {0}, // n/a {0}, // n/a //16 - {4, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR}, // front or near - {6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR}, // front, right - {6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR}, // front, left + {4, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front or near + + {6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front, right + {6, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, }, // front, left {0}, // n/a //20 - {6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR }, // front,bottom + {6, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, // front,bottom + //21 {6, BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR }, //front,bottom,right //22 - {6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR }, //front,bottom,left + {6, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR }, //front,bottom,left {0}, // n/a - {6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR}, // front, top - {6, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR}, // front, top, right - {6, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR}, // front, top, left + + {6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR}, // front, top + + {6, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR, TOP_LEFT_FAR, TOP_LEFT_NEAR }, // front, top, right + + {6, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR }, // front, top, left {0}, // n/a {0}, // n/a {0}, // n/a @@ -553,7 +558,7 @@ VoxelProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const { projectedPolygon.setVertex(i, projectedPoint); } - /***/ + /*** // Now that we've got the polygon, if it extends beyond the clipping window, then let's clip it // NOTE: This clipping does not improve our overall performance. It basically causes more polygons to // end up in the same quad/half and so the polygon lists get longer, and that's more calls to polygon.occludes() @@ -574,6 +579,8 @@ VoxelProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const { projectedPolygon.setVertex(i, clippedVertices[i]); } delete[] clippedVertices; + + lookUp += PROJECTION_CLIPPED; } /***/ } @@ -582,5 +589,6 @@ VoxelProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const { projectedPolygon.setDistance(distance); projectedPolygon.setAnyInView(anyPointsInView); projectedPolygon.setAllInView(allPointsInView); + projectedPolygon.setProjectionType(lookUp); // remember the projection type return projectedPolygon; } diff --git a/libraries/voxels/src/VoxelProjectedPolygon.cpp b/libraries/voxels/src/VoxelProjectedPolygon.cpp index 778ee8e525..07a4d04c48 100644 --- a/libraries/voxels/src/VoxelProjectedPolygon.cpp +++ b/libraries/voxels/src/VoxelProjectedPolygon.cpp @@ -369,4 +369,751 @@ bool VoxelProjectedPolygon::intersectsOnAxes(const VoxelProjectedPolygon& testee return true; } +bool VoxelProjectedPolygon::canMerge(const VoxelProjectedPolygon& that) const { + // RIGHT/NEAR + // LEFT/NEAR + if ( + (getProjectionType() == that.getProjectionType()) && + ( + getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR) || + getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR) + ) + ) { + if (getVertex(1) == that.getVertex(0) && getVertex(4) == that.getVertex(5)) { + return true; + } + if (getVertex(0) == that.getVertex(1) && getVertex(5) == that.getVertex(4)) { + return true; + } + if (getVertex(2) == that.getVertex(1) && getVertex(3) == that.getVertex(4)) { + return true; + } + if (getVertex(1) == that.getVertex(2) && getVertex(4) == that.getVertex(3)) { + return true; + } + } + // NEAR/BOTTOM + if ( + (getProjectionType() == that.getProjectionType()) && + ( + getProjectionType() == (PROJECTION_NEAR | PROJECTION_BOTTOM) + ) + ) { + if (getVertex(0) == that.getVertex(5) && getVertex(3) == that.getVertex(4)) { + return true; + } + if (getVertex(5) == that.getVertex(0) && getVertex(4) == that.getVertex(3)) { + return true; + } + if (getVertex(1) == that.getVertex(0) && getVertex(2) == that.getVertex(3)) { + return true; + } + if (getVertex(0) == that.getVertex(1) && getVertex(3) == that.getVertex(2)) { + return true; + } + } + + // NEAR/TOP + if ( + (getProjectionType() == that.getProjectionType()) && + ( + getProjectionType() == (PROJECTION_NEAR | PROJECTION_TOP) + ) + ) { + if (getVertex(0) == that.getVertex(5) && getVertex(1) == that.getVertex(2)) { + return true; + } + if (getVertex(5) == that.getVertex(0) && getVertex(2) == that.getVertex(1)) { + return true; + } + if (getVertex(4) == that.getVertex(5) && getVertex(3) == that.getVertex(2)) { + return true; + } + if (getVertex(5) == that.getVertex(4) && getVertex(2) == that.getVertex(3)) { + return true; + } + } + + // RIGHT/NEAR & NEAR/RIGHT/TOP + // LEFT/NEAR & NEAR/LEFT/TOP + if ( + ((getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_TOP)) && + (that.getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR))) + || + ((getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_TOP)) && + (that.getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR))) + ) + { + if (getVertex(5) == that.getVertex(0) && getVertex(3) == that.getVertex(2)) { + return true; + } + } + // RIGHT/NEAR & NEAR/RIGHT/TOP + // LEFT/NEAR & NEAR/LEFT/TOP + if ( + ((that.getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_TOP)) && + (getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR))) + || + ((that.getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_TOP)) && + (getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR))) + + ) + { + if (getVertex(0) == that.getVertex(5) && getVertex(2) == that.getVertex(3)) { + return true; + } + } + + // RIGHT/NEAR & NEAR/RIGHT/BOTTOM + // NEAR/LEFT & NEAR/LEFT/BOTTOM + if ( + ((that.getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_BOTTOM)) && + (getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR))) + || + ((that.getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_BOTTOM)) && + (getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR))) + + ) + { + if (getVertex(5) == that.getVertex(0) && getVertex(3) == that.getVertex(2)) { + return true; + } + } + // RIGHT/NEAR & NEAR/RIGHT/BOTTOM + // NEAR/LEFT & NEAR/LEFT/BOTTOM + if ( + ((getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_BOTTOM)) && + (that.getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR))) + || + ((getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_BOTTOM)) && + (that.getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR))) + ) + { + if (getVertex(0) == that.getVertex(5) && getVertex(2) == that.getVertex(3)) { + return true; + } + } + + // NEAR/TOP & NEAR + if ( + (getProjectionType() == (PROJECTION_NEAR )) && + (that.getProjectionType() == (PROJECTION_NEAR | PROJECTION_TOP )) + ) + { + if (getVertex(0) == that.getVertex(5) && getVertex(1) == that.getVertex(2)) { + return true; + } + } + + // NEAR/TOP & NEAR + if ( + (that.getProjectionType() == (PROJECTION_NEAR )) && + (getProjectionType() == (PROJECTION_NEAR | PROJECTION_TOP )) + ) + { + if (getVertex(5) == that.getVertex(0) && getVertex(2) == that.getVertex(1)) { + return true; + } + } + + // NEAR/BOTTOM & NEAR + if ( + (getProjectionType() == (PROJECTION_NEAR )) && + (that.getProjectionType() == (PROJECTION_NEAR | PROJECTION_BOTTOM )) + ) + { + if (getVertex(2) == that.getVertex(3) && getVertex(3) == that.getVertex(0)) { + return true; + } + } + + // NEAR/BOTTOM & NEAR + if ( + (that.getProjectionType() == (PROJECTION_NEAR )) && + (getProjectionType() == (PROJECTION_NEAR | PROJECTION_BOTTOM )) + ) + { + if (getVertex(3) == that.getVertex(2) && getVertex(0) == that.getVertex(3)) { + return true; + } + } + + // NEAR/RIGHT & NEAR + if ( + (getProjectionType() == (PROJECTION_NEAR )) && + (that.getProjectionType() == (PROJECTION_NEAR | PROJECTION_RIGHT )) + ) + { + if (getVertex(0) == that.getVertex(1) && getVertex(3) == that.getVertex(4)) { + return true; + } + } + + // NEAR/RIGHT & NEAR + if ( + (that.getProjectionType() == (PROJECTION_NEAR )) && + (getProjectionType() == (PROJECTION_NEAR | PROJECTION_RIGHT )) + ) + { + if (getVertex(1) == that.getVertex(0) && getVertex(4) == that.getVertex(3)) { + return true; + } + } + + // NEAR/LEFT & NEAR + if ( + (getProjectionType() == (PROJECTION_NEAR )) && + (that.getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT )) + ) + { + if (getVertex(1) == that.getVertex(1) && getVertex(2) == that.getVertex(4)) { + return true; + } + } + + // NEAR/LEFT & NEAR + if ( + (that.getProjectionType() == (PROJECTION_NEAR )) && + (getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT )) + ) + { + if (getVertex(1) == that.getVertex(0) && getVertex(4) == that.getVertex(3)) { + return true; + } + } + + + // NEAR/RIGHT/BOTTOM & NEAR/BOTTOM + if ( + (getProjectionType() == (PROJECTION_BOTTOM | PROJECTION_NEAR )) && + (that.getProjectionType() == (PROJECTION_BOTTOM | PROJECTION_NEAR | PROJECTION_RIGHT )) + ) + { + if (getVertex(1) == that.getVertex(2) && getVertex(5) == that.getVertex(4)) { + return true; + } + } + + // NEAR/RIGHT/BOTTOM & NEAR/BOTTOM + if ( + (that.getProjectionType() == (PROJECTION_BOTTOM | PROJECTION_NEAR )) && + (getProjectionType() == (PROJECTION_BOTTOM | PROJECTION_NEAR | PROJECTION_RIGHT )) + ) + { + if (getVertex(2) == that.getVertex(1) && getVertex(4) == that.getVertex(5)) { + return true; + } + } + + + // RIGHT/NEAR/BOTTOM + // RIGHT/NEAR/TOP + // LEFT/NEAR/BOTTOM + // LEFT/NEAR/TOP + if ( + (getProjectionType() == that.getProjectionType()) && + ( + getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_BOTTOM ) || + getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_TOP ) || + getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_BOTTOM ) || + getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_TOP ) + ) + ) { + if (getVertex(0) == that.getVertex(5) && getVertex(2) == that.getVertex(3)) { + return true; + } + if (getVertex(5) == that.getVertex(0) && getVertex(3) == that.getVertex(2)) { + return true; + } + if (getVertex(2) == that.getVertex(1) && getVertex(4) == that.getVertex(5)) { + return true; + } + if (getVertex(1) == that.getVertex(2) && getVertex(5) == that.getVertex(4)) { + return true; + } + if (getVertex(1) == that.getVertex(0) && getVertex(3) == that.getVertex(4)) { + return true; + } + if (getVertex(0) == that.getVertex(1) && getVertex(4) == that.getVertex(3)) { + return true; + } + } + + return false; +} + + +void VoxelProjectedPolygon::merge(const VoxelProjectedPolygon& that) { + + // RIGHT/NEAR + // LEFT/NEAR + if ( + (getProjectionType() == that.getProjectionType()) && + ( + getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR) || + getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR) + ) + ) { + if (getVertex(1) == that.getVertex(0) && getVertex(4) == that.getVertex(5)) { + //setVertex(0, this.getVertex(0)); // no change + setVertex(1, that.getVertex(1)); + setVertex(2, that.getVertex(2)); + setVertex(3, that.getVertex(3)); + setVertex(4, that.getVertex(4)); + //setVertex(5, this.getVertex(5)); // no change + return; // done + } + if (getVertex(0) == that.getVertex(1) && getVertex(5) == that.getVertex(4)) { + setVertex(0, that.getVertex(0)); + //setVertex(1, this.getVertex(1)); // no change + //setVertex(2, this.getVertex(2)); // no change + //setVertex(3, this.getVertex(3)); // no change + //setVertex(4, that.getVertex(4)); // no change + setVertex(5, that.getVertex(5)); + return; // done + } + if (getVertex(2) == that.getVertex(1) && getVertex(3) == that.getVertex(4)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, this.getVertex(1)); // no change + setVertex(2, that.getVertex(2)); + setVertex(3, that.getVertex(3)); + //setVertex(4, this.getVertex(4)); // no change + //setVertex(5, that.getVertex(5)); // no change + return; // done + } + if (getVertex(1) == that.getVertex(2) && getVertex(4) == that.getVertex(3)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + //setVertex(2, this.getVertex(2)); // no change + //setVertex(3, that.getVertex(3)); // no change + setVertex(4, that.getVertex(4)); + setVertex(5, that.getVertex(5)); + return; // done + } + } + + // NEAR/BOTTOM + if ( + (getProjectionType() == that.getProjectionType()) && + ( + getProjectionType() == (PROJECTION_NEAR | PROJECTION_BOTTOM) + ) + ) { + if (getVertex(0) == that.getVertex(5) && getVertex(3) == that.getVertex(4)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + setVertex(2, that.getVertex(2)); + setVertex(3, that.getVertex(3)); + //setVertex(4, this.getVertex(4)); // no change + //setVertex(5, that.getVertex(5)); // no change + return; // done + } + if (getVertex(5) == that.getVertex(0) && getVertex(4) == that.getVertex(3)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, that.getVertex(1)); // no change + //setVertex(2, this.getVertex(2)); // no change + //setVertex(3, that.getVertex(3)); // no change + setVertex(4, that.getVertex(4)); + setVertex(5, that.getVertex(5)); + return; // done + } + if (getVertex(1) == that.getVertex(0) && getVertex(2) == that.getVertex(3)) { + //setVertex(0, this.getVertex(0)); // no change + setVertex(1, that.getVertex(1)); + setVertex(2, that.getVertex(2)); + //setVertex(3, that.getVertex(3)); // no change + //setVertex(4, this.getVertex(4)); // no change + //setVertex(5, that.getVertex(5)); // no change + return; // done + } + if (getVertex(0) == that.getVertex(1) && getVertex(3) == that.getVertex(2)) { + setVertex(0, that.getVertex(0)); + //setVertex(1, this.getVertex(1)); // no change + //setVertex(2, that.getVertex(2)); // no change + setVertex(3, that.getVertex(3)); + setVertex(4, that.getVertex(4)); + setVertex(5, that.getVertex(5)); + return; // done + } + } + + // NEAR/TOP + if ( + (getProjectionType() == that.getProjectionType()) && + ( + getProjectionType() == (PROJECTION_NEAR | PROJECTION_TOP) + ) + ) { + if (getVertex(0) == that.getVertex(5) && getVertex(1) == that.getVertex(2)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + //setVertex(2, this.getVertex(2)); // no change + //setVertex(3, that.getVertex(3)); // no change + //setVertex(4, this.getVertex(4)); // no change + //setVertex(5, that.getVertex(5)); // no change + return; // done + } + if (getVertex(5) == that.getVertex(0) && getVertex(2) == that.getVertex(1)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, that.getVertex(1)); // no change + setVertex(2, that.getVertex(2)); + setVertex(3, that.getVertex(3)); + setVertex(4, that.getVertex(4)); + setVertex(5, that.getVertex(5)); + return; // done + } + if (getVertex(4) == that.getVertex(5) && getVertex(3) == that.getVertex(2)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, that.getVertex(1)); // no change + //setVertex(2, that.getVertex(2)); // no change + setVertex(3, that.getVertex(3)); + setVertex(4, that.getVertex(4)); + //setVertex(5, that.getVertex(5)); // no change + return; // done + } + if (getVertex(5) == that.getVertex(4) && getVertex(2) == that.getVertex(3)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + setVertex(2, that.getVertex(2)); + //setVertex(3, this.getVertex(3)); // no change + //setVertex(4, that.getVertex(3)); // no change + setVertex(5, that.getVertex(5)); + return; // done + } + } + + + // RIGHT/NEAR & NEAR/RIGHT/TOP + // LEFT/NEAR & NEAR/LEFT/TOP + if ( + ((getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_TOP)) && + (that.getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR))) + || + ((getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_TOP)) && + (that.getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR))) + ) + { + if (getVertex(5) == that.getVertex(0) && getVertex(3) == that.getVertex(2)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, this.getVertex(1)); // no change + //setVertex(2, this.getVertex(2)); // no change + setVertex(3, that.getVertex(3)); + setVertex(4, that.getVertex(4)); + setVertex(5, that.getVertex(5)); + setProjectionType((PROJECTION_RIGHT | PROJECTION_NEAR)); + return; // done + } + } + + // RIGHT/NEAR & NEAR/RIGHT/TOP + // LEFT/NEAR & NEAR/LEFT/TOP + if ( + ((that.getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_TOP)) && + (getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR))) + || + ((that.getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_TOP)) && + (getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR))) + + ) + { + if (getVertex(0) == that.getVertex(5) && getVertex(2) == that.getVertex(3)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + setVertex(2, that.getVertex(2)); + //setVertex(3, this.getVertex(3)); // no change + //setVertex(4, this.getVertex(4)); // no change + //setVertex(5, this.getVertex(5)); // no change + //setProjectionType((PROJECTION_RIGHT | PROJECTION_NEAR)); // no change + return; // done + } + } + + // RIGHT/NEAR & NEAR/RIGHT/BOTTOM + // NEAR/LEFT & NEAR/LEFT/BOTTOM + if ( + ((that.getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_BOTTOM)) && + (getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR))) + || + ((that.getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_BOTTOM)) && + (getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR))) + + ) + { + if (getVertex(5) == that.getVertex(0) && getVertex(3) == that.getVertex(2)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, this.getVertex(1)); // no change + //setVertex(2, this.getVertex(2)); // no change + setVertex(3, that.getVertex(3)); + setVertex(4, that.getVertex(4)); + setVertex(5, that.getVertex(5)); + //setProjectionType((PROJECTION_RIGHT | PROJECTION_NEAR)); // no change + return; // done + } + } + // RIGHT/NEAR & NEAR/RIGHT/BOTTOM + // NEAR/LEFT & NEAR/LEFT/BOTTOM + if ( + ((getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_BOTTOM)) && + (that.getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR))) + || + ((getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_BOTTOM)) && + (that.getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR))) + ) + { + if (getVertex(0) == that.getVertex(5) && getVertex(2) == that.getVertex(3)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + setVertex(2, that.getVertex(2)); + //setVertex(3, this.getVertex(3)); // no change + //setVertex(4, this.getVertex(4)); // no change + //setVertex(5, this.getVertex(5)); // no change + setProjectionType((PROJECTION_RIGHT | PROJECTION_NEAR)); + return; // done + } + } + + + // NEAR/TOP & NEAR + if ( + (getProjectionType() == (PROJECTION_NEAR )) && + (that.getProjectionType() == (PROJECTION_NEAR | PROJECTION_TOP )) + ) + { + if (getVertex(0) == that.getVertex(5) && getVertex(1) == that.getVertex(2)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + //setVertex(2, this.getVertex(2)); // no change + //setVertex(3, this.getVertex(3)); // no change + //setVertexCount(4); // no change + //setProjectionType((PROJECTION_NEAR)); // no change + return; // done + } + } + + // NEAR/TOP & NEAR + if ( + (that.getProjectionType() == (PROJECTION_NEAR )) && + (getProjectionType() == (PROJECTION_NEAR | PROJECTION_TOP )) + ) + { + if (getVertex(5) == that.getVertex(0) && getVertex(2) == that.getVertex(1)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, this.getVertex(1)); // no change + setVertex(2, that.getVertex(2)); + setVertex(3, that.getVertex(3)); + setVertexCount(4); + setProjectionType((PROJECTION_NEAR)); + return; // done + } + } + + // NEAR/BOTTOM & NEAR + if ( + (getProjectionType() == (PROJECTION_NEAR )) && + (that.getProjectionType() == (PROJECTION_NEAR | PROJECTION_BOTTOM )) + ) + { + if (getVertex(2) == that.getVertex(3) && getVertex(3) == that.getVertex(0)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, this.getVertex(1)); // no change + setVertex(2, that.getVertex(4)); + setVertex(3, that.getVertex(5)); + //setVertexCount(4); // no change + //setProjectionType((PROJECTION_NEAR)); // no change + } + } + + // NEAR/BOTTOM & NEAR + if ( + (that.getProjectionType() == (PROJECTION_NEAR )) && + (getProjectionType() == (PROJECTION_NEAR | PROJECTION_BOTTOM )) + ) + { + if (getVertex(3) == that.getVertex(2) && getVertex(0) == that.getVertex(3)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + setVertex(2, getVertex(4)); + setVertex(3, getVertex(5)); + setVertexCount(4); + setProjectionType((PROJECTION_NEAR)); + return; // done + } + } + + // NEAR/RIGHT & NEAR + if ( + (getProjectionType() == (PROJECTION_NEAR )) && + (that.getProjectionType() == (PROJECTION_NEAR | PROJECTION_RIGHT )) + ) + { + if (getVertex(0) == that.getVertex(1) && getVertex(3) == that.getVertex(4)) { + setVertex(0, that.getVertex(0)); + //setVertex(1, this.getVertex(1)); // no change + //setVertex(2, this.getVertex(2)); // no change + setVertex(3, that.getVertex(5)); + //setVertexCount(4); // no change + //setProjectionType((PROJECTION_NEAR)); // no change + } + } + + // NEAR/RIGHT & NEAR + if ( + (that.getProjectionType() == (PROJECTION_NEAR )) && + (getProjectionType() == (PROJECTION_NEAR | PROJECTION_RIGHT )) + ) + { + if (getVertex(1) == that.getVertex(0) && getVertex(4) == that.getVertex(3)) { + //setVertex(0, this.getVertex(0)); // no change + setVertex(1, that.getVertex(1)); + setVertex(2, that.getVertex(2)); + setVertex(3, getVertex(5)); + setVertexCount(4); + setProjectionType((PROJECTION_NEAR)); + return; // done + } + } + + // NEAR/LEFT & NEAR + if ( + (getProjectionType() == (PROJECTION_NEAR )) && + (that.getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT )) + ) + { + if (getVertex(1) == that.getVertex(1) && getVertex(2) == that.getVertex(4)) { + //setVertex(0, this.getVertex()); // no change + setVertex(1, that.getVertex(2)); + setVertex(2, that.getVertex(3)); + //setVertex(3, this.getVertex(3)); // no change + //setVertexCount(4); // no change + //setProjectionType((PROJECTION_NEAR)); // no change + return; // done + } + } + + // NEAR/LEFT & NEAR + if ( + (that.getProjectionType() == (PROJECTION_NEAR )) && + (getProjectionType() == (PROJECTION_NEAR | PROJECTION_LEFT )) + ) + { + if (getVertex(1) == that.getVertex(0) && getVertex(4) == that.getVertex(3)) { + setVertex(0, that.getVertex(0)); + setVertex(1, getVertex(2)); + setVertex(2, getVertex(3)); + setVertex(3, that.getVertex(3)); + setVertexCount(4); + setProjectionType((PROJECTION_NEAR)); + return; // done + } + } + + + // NEAR/RIGHT/BOTTOM & NEAR/BOTTOM + if ( + (getProjectionType() == (PROJECTION_BOTTOM | PROJECTION_NEAR )) && + (that.getProjectionType() == (PROJECTION_BOTTOM | PROJECTION_NEAR | PROJECTION_RIGHT )) + ) + { + if (getVertex(1) == that.getVertex(2) && getVertex(5) == that.getVertex(4)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + //setVertex(2, this.getVertex(2)); // no change + //setVertex(3, this.getVertex(3)); // no change + //setVertex(4, this.getVertex(4)); // no change + setVertex(5, that.getVertex(5)); + return; // done + } + } + + // NEAR/RIGHT/BOTTOM & NEAR/BOTTOM + if ( + (that.getProjectionType() == (PROJECTION_BOTTOM | PROJECTION_NEAR )) && + (getProjectionType() == (PROJECTION_BOTTOM | PROJECTION_NEAR | PROJECTION_RIGHT )) + ) + { + if (getVertex(2) == that.getVertex(1) && getVertex(4) == that.getVertex(5)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, this.getVertex(1)); // no change + setVertex(2, that.getVertex(2)); + setVertex(3, that.getVertex(3)); + setVertex(4, that.getVertex(4)); + //setVertex(5, this.getVertex(5)); // no change + setProjectionType((PROJECTION_BOTTOM | PROJECTION_NEAR)); + return; // done + } + } + + + // RIGHT/NEAR/BOTTOM + // RIGHT/NEAR/TOP + // LEFT/NEAR/BOTTOM + // LEFT/NEAR/TOP + if ( + (getProjectionType() == that.getProjectionType()) && + ( + getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_BOTTOM ) || + getProjectionType() == (PROJECTION_RIGHT | PROJECTION_NEAR | PROJECTION_TOP ) || + getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_BOTTOM ) || + getProjectionType() == (PROJECTION_LEFT | PROJECTION_NEAR | PROJECTION_TOP ) + ) + ) { + if (getVertex(0) == that.getVertex(5) && getVertex(2) == that.getVertex(3)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + setVertex(2, that.getVertex(2)); + //setVertex(3, this.getVertex(3)); // no change + //setVertex(4, this.getVertex(4)); // no change + //setVertex(5, this.getVertex(5)); // no change + return; // done + } + if (getVertex(5) == that.getVertex(0) && getVertex(3) == that.getVertex(2)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, this.getVertex(1)); // no change + //setVertex(2, this.getVertex(2)); // no change + setVertex(3, that.getVertex(3)); + setVertex(4, that.getVertex(4)); + setVertex(5, that.getVertex(5)); + return; // done + } + if (getVertex(2) == that.getVertex(1) && getVertex(4) == that.getVertex(5)) { + //setVertex(0, this.getVertex(0)); // no change + //setVertex(1, this.getVertex(1)); // no change + setVertex(2, that.getVertex(2)); + setVertex(3, that.getVertex(3)); + setVertex(4, that.getVertex(4)); + //setVertex(5, this.getVertex(5)); // no change + return; // done + } + if (getVertex(1) == that.getVertex(2) && getVertex(5) == that.getVertex(4)) { + setVertex(0, that.getVertex(0)); + setVertex(1, that.getVertex(1)); + //setVertex(2, this.getVertex(2)); // no change + //setVertex(3, this.getVertex(3)); // no change + //setVertex(4, this.getVertex(4)); // no change + setVertex(5, that.getVertex(5)); + return; // done + } + // if this.([1],[3]) == that.([0],[4]) then create polygon: this.[0], that.[1], that.[2], that.[3], this.[4], this.[5] + if (getVertex(1) == that.getVertex(0) && getVertex(3) == that.getVertex(4)) { + //setVertex(0, this.getVertex(0)); // no change + setVertex(1, that.getVertex(1)); + setVertex(2, that.getVertex(2)); + setVertex(3, that.getVertex(3)); + //setVertex(4, this.getVertex(4)); // no change + //setVertex(5, this.getVertex(5)); // no change + return; // done + } + // if this.([0],[4]) == that.([1],[3]) then create polygon: that.[0], this.[1], this.[2], this.[3], that.[4], that.[5] + if (getVertex(0) == that.getVertex(1) && getVertex(4) == that.getVertex(3)) { + setVertex(0, that.getVertex(0)); + //setVertex(1, this.getVertex(1)); // no change + //setVertex(2, this.getVertex(2)); // no change + //setVertex(3, this.getVertex(3)); // no change + setVertex(4, that.getVertex(4)); + setVertex(5, that.getVertex(5)); + return; // done + } + } + +} diff --git a/libraries/voxels/src/VoxelProjectedPolygon.h b/libraries/voxels/src/VoxelProjectedPolygon.h index 0681ce4fc1..47d661a39d 100644 --- a/libraries/voxels/src/VoxelProjectedPolygon.h +++ b/libraries/voxels/src/VoxelProjectedPolygon.h @@ -49,6 +49,14 @@ private: bool _set; }; +const int PROJECTION_RIGHT = 1; +const int PROJECTION_LEFT = 2; +const int PROJECTION_BOTTOM = 4; +const int PROJECTION_TOP = 8; +const int PROJECTION_NEAR = 16; +const int PROJECTION_FAR = 32; +const int PROJECTION_CLIPPED = 64; + class VoxelProjectedPolygon { public: @@ -64,16 +72,18 @@ public: const ProjectedVertices& getVertices() const { return _vertices; }; const glm::vec2& getVertex(int i) const { return _vertices[i]; }; void setVertex(int vertex, const glm::vec2& point); - int getVertexCount() const { return _vertexCount; }; - void setVertexCount(int vertexCount) { _vertexCount = vertexCount; }; - float getDistance() const { return _distance; } - void setDistance(float distance) { _distance = distance; } + int getVertexCount() const { return _vertexCount; }; + void setVertexCount(int vertexCount) { _vertexCount = vertexCount; }; + float getDistance() const { return _distance; } + void setDistance(float distance) { _distance = distance; } + bool getAnyInView() const { return _anyInView; }; + void setAnyInView(bool anyInView) { _anyInView = anyInView; }; + bool getAllInView() const { return _allInView; }; + void setAllInView(bool allInView) { _allInView = allInView; }; + void setProjectionType(unsigned char type) { _projectionType = type; }; + unsigned char getProjectionType() const { return _projectionType; }; - bool getAnyInView() const { return _anyInView; }; - void setAnyInView(bool anyInView) { _anyInView = anyInView; }; - bool getAllInView() const { return _allInView; }; - void setAllInView(bool allInView) { _allInView = allInView; }; bool pointInside(const glm::vec2& point, bool* matchesVertex = NULL) const; bool occludes(const VoxelProjectedPolygon& occludee, bool checkAllInView = false) const; @@ -82,8 +92,10 @@ public: bool intersects(const BoundingBox& box) const; bool matches(const VoxelProjectedPolygon& testee) const; bool matches(const BoundingBox& testee) const; - bool intersectsOnAxes(const VoxelProjectedPolygon& testee) const; + + bool canMerge(const VoxelProjectedPolygon& that) const; + void merge(const VoxelProjectedPolygon& that); // replaces vertices of this with new merged version float getMaxX() const { return _maxX; } float getMaxY() const { return _maxY; } @@ -109,6 +121,7 @@ private: float _distance; bool _anyInView; // if any points are in view bool _allInView; // if all points are in view + unsigned char _projectionType; };