From 11c235a29e6b1acdaa3ae444f78db6b5504cffbb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 9 Apr 2014 10:16:56 -0700 Subject: [PATCH] fixes to source files for code remove in regex replace --- libraries/octree/src/CoverageMap.cpp | 37 +++- libraries/shared/src/GeometryUtil.cpp | 293 +++++++++++++++++++++++++- 2 files changed, 328 insertions(+), 2 deletions(-) diff --git a/libraries/octree/src/CoverageMap.cpp b/libraries/octree/src/CoverageMap.cpp index 88d2292812..65d5734b68 100644 --- a/libraries/octree/src/CoverageMap.cpp +++ b/libraries/octree/src/CoverageMap.cpp @@ -9,6 +9,41 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + +#include + +#include + +#include "CoverageMap.h" + +int CoverageMap::_mapCount = 0; +int CoverageMap::_checkMapRootCalls = 0; +int CoverageMap::_notAllInView = 0; +bool CoverageMap::wantDebugging = false; + +const int MAX_POLYGONS_PER_REGION = 50; + +const BoundingBox CoverageMap::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-1.f,-1.f), glm::vec2(2.f,2.f)); + +// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space. +// +// (0,0) (windowWidth, 0) +// -1,1 1,1 +// +-----------------------+ +// | | | +// | | | +// | -1,0 | | +// |-----------+-----------| +// | 0,0 | +// | | | +// | | | +// | | | +// +-----------------------+ +// -1,-1 1,-1 +// (0,windowHeight) (windowWidth,windowHeight) +// + // Choosing a minimum sized polygon. Since we know a typical window is approximately 1500 pixels wide // then a pixel on our screen will be ~ 2.0/1500 or 0.0013 "units" wide, similarly pixels are typically // about that tall as well. If we say that polygons should be at least 10x10 pixels to be considered "big enough" @@ -523,4 +558,4 @@ CoverageMapStorageResult CoverageRegion::checkRegion(OctreeProjectedPolygon* pol } } return result; -} +} \ No newline at end of file diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index d586dad90e..cb2e829811 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -9,6 +9,297 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include + +#include "SharedUtil.h" +#include "GeometryUtil.h" + +glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { + // compute the projection of the point vector onto the segment vector + glm::vec3 segmentVector = end - start; + float lengthSquared = glm::dot(segmentVector, segmentVector); + if (lengthSquared < EPSILON) { + return start - point; // start and end the same + } + float proj = glm::dot(point - start, segmentVector) / lengthSquared; + if (proj <= 0.0f) { // closest to the start + return start - point; + + } else if (proj >= 1.0f) { // closest to the end + return end - point; + + } else { // closest to the middle + return start + segmentVector*proj - point; + } +} + +// Computes the penetration between a point and a sphere (centered at the origin) +// if point is inside sphere: returns true and stores the result in 'penetration' +// (the vector that would move the point outside the sphere) +// otherwise returns false +bool findSpherePenetration(const glm::vec3& point, const glm::vec3& defaultDirection, float sphereRadius, + glm::vec3& penetration) { + float vectorLength = glm::length(point); + if (vectorLength < EPSILON) { + penetration = defaultDirection * sphereRadius; + return true; + } + float distance = vectorLength - sphereRadius; + if (distance < 0.0f) { + penetration = point * (-distance / vectorLength); + return true; + } + return false; +} + +bool findSpherePointPenetration(const glm::vec3& sphereCenter, float sphereRadius, + const glm::vec3& point, glm::vec3& penetration) { + return findSpherePenetration(point - sphereCenter, glm::vec3(0.0f, -1.0f, 0.0f), sphereRadius, penetration); +} + +bool findPointSpherePenetration(const glm::vec3& point, const glm::vec3& sphereCenter, + float sphereRadius, glm::vec3& penetration) { + return findSpherePenetration(sphereCenter - point, glm::vec3(0.0f, -1.0f, 0.0f), sphereRadius, penetration); +} + +bool findSphereSpherePenetration(const glm::vec3& firstCenter, float firstRadius, + const glm::vec3& secondCenter, float secondRadius, glm::vec3& penetration) { + return findSpherePointPenetration(firstCenter, firstRadius + secondRadius, secondCenter, penetration); +} + +bool findSphereSegmentPenetration(const glm::vec3& sphereCenter, float sphereRadius, + const glm::vec3& segmentStart, const glm::vec3& segmentEnd, glm::vec3& penetration) { + return findSpherePenetration(computeVectorFromPointToSegment(sphereCenter, segmentStart, segmentEnd), + glm::vec3(0.0f, -1.0f, 0.0f), sphereRadius, penetration); +} + +bool findSphereCapsulePenetration(const glm::vec3& sphereCenter, float sphereRadius, const glm::vec3& capsuleStart, + const glm::vec3& capsuleEnd, float capsuleRadius, glm::vec3& penetration) { + return findSphereSegmentPenetration(sphereCenter, sphereRadius + capsuleRadius, + capsuleStart, capsuleEnd, penetration); +} + +bool findPointCapsuleConePenetration(const glm::vec3& point, const glm::vec3& capsuleStart, + const glm::vec3& capsuleEnd, float startRadius, float endRadius, glm::vec3& penetration) { + // compute the projection of the point vector onto the segment vector + glm::vec3 segmentVector = capsuleEnd - capsuleStart; + float lengthSquared = glm::dot(segmentVector, segmentVector); + if (lengthSquared < EPSILON) { // start and end the same + return findPointSpherePenetration(point, capsuleStart, + glm::max(startRadius, endRadius), penetration); + } + float proj = glm::dot(point - capsuleStart, segmentVector) / lengthSquared; + if (proj <= 0.0f) { // closest to the start + return findPointSpherePenetration(point, capsuleStart, startRadius, penetration); + + } else if (proj >= 1.0f) { // closest to the end + return findPointSpherePenetration(point, capsuleEnd, endRadius, penetration); + + } else { // closest to the middle + return findPointSpherePenetration(point, capsuleStart + segmentVector * proj, + glm::mix(startRadius, endRadius, proj), penetration); + } +} + +bool findSphereCapsuleConePenetration(const glm::vec3& sphereCenter, + float sphereRadius, const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, + float startRadius, float endRadius, glm::vec3& penetration) { + return findPointCapsuleConePenetration(sphereCenter, capsuleStart, capsuleEnd, + startRadius + sphereRadius, endRadius + sphereRadius, penetration); +} + +bool findSpherePlanePenetration(const glm::vec3& sphereCenter, float sphereRadius, + const glm::vec4& plane, glm::vec3& penetration) { + float distance = glm::dot(plane, glm::vec4(sphereCenter, 1.0f)) - sphereRadius; + if (distance < 0.0f) { + penetration = glm::vec3(plane) * distance; + return true; + } + return false; +} + +bool findSphereDiskPenetration(const glm::vec3& sphereCenter, float sphereRadius, + const glm::vec3& diskCenter, float diskRadius, float diskThickness, const glm::vec3& diskNormal, + glm::vec3& penetration) { + glm::vec3 localCenter = sphereCenter - diskCenter; + float axialDistance = glm::dot(localCenter, diskNormal); + if (std::fabs(axialDistance) < (sphereRadius + 0.5f * diskThickness)) { + // sphere hit the plane, but does it hit the disk? + // Note: this algorithm ignores edge hits. + glm::vec3 axialOffset = axialDistance * diskNormal; + if (glm::length(localCenter - axialOffset) < diskRadius) { + // yes, hit the disk + penetration = (std::fabs(axialDistance) - (sphereRadius + 0.5f * diskThickness) ) * diskNormal; + if (axialDistance < 0.f) { + // hit the backside of the disk, so negate penetration vector + penetration *= -1.f; + } + return true; + } + } + return false; +} + +bool findCapsuleSpherePenetration(const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius, + const glm::vec3& sphereCenter, float sphereRadius, glm::vec3& penetration) { + if (findSphereCapsulePenetration(sphereCenter, sphereRadius, + capsuleStart, capsuleEnd, capsuleRadius, penetration)) { + penetration = -penetration; + return true; + } + return false; +} + +bool findCapsulePlanePenetration(const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius, + const glm::vec4& plane, glm::vec3& penetration) { + float distance = glm::min(glm::dot(plane, glm::vec4(capsuleStart, 1.0f)), + glm::dot(plane, glm::vec4(capsuleEnd, 1.0f))) - capsuleRadius; + if (distance < 0.0f) { + penetration = glm::vec3(plane) * distance; + return true; + } + return false; +} + +glm::vec3 addPenetrations(const glm::vec3& currentPenetration, const glm::vec3& newPenetration) { + // find the component of the new penetration in the direction of the current + float currentLength = glm::length(currentPenetration); + if (currentLength == 0.0f) { + return newPenetration; + } + glm::vec3 currentDirection = currentPenetration / currentLength; + float directionalComponent = glm::dot(newPenetration, currentDirection); + + // if orthogonal or in the opposite direction, we can simply add + if (directionalComponent <= 0.0f) { + return currentPenetration + newPenetration; + } + + // otherwise, we need to take the maximum component of current and new + return currentDirection * glm::max(directionalComponent, currentLength) + + newPenetration - (currentDirection * directionalComponent); +} + +bool findRaySphereIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::vec3& center, float radius, float& distance) { + glm::vec3 relativeOrigin = origin - center; + float c = glm::dot(relativeOrigin, relativeOrigin) - radius * radius; + if (c < 0.0f) { + distance = 0.0f; + return true; // starts inside the sphere + } + float b = glm::dot(direction, relativeOrigin); + float radicand = b * b - c; + if (radicand < 0.0f) { + return false; // doesn't hit the sphere + } + float t = -b - sqrtf(radicand); + if (t < 0.0f) { + return false; // doesn't hit the sphere + } + distance = t; + return true; +} + +bool findRayCapsuleIntersection(const glm::vec3& origin, const glm::vec3& direction, + const glm::vec3& start, const glm::vec3& end, float radius, float& distance) { + if (start == end) { + return findRaySphereIntersection(origin, direction, start, radius, distance); // handle degenerate case + } + glm::vec3 relativeOrigin = origin - start; + glm::vec3 relativeEnd = end - start; + float capsuleLength = glm::length(relativeEnd); + relativeEnd /= capsuleLength; + float originProjection = glm::dot(relativeEnd, relativeOrigin); + glm::vec3 constant = relativeOrigin - relativeEnd * originProjection; + float c = glm::dot(constant, constant) - radius * radius; + if (c < 0.0f) { // starts inside cylinder + if (originProjection < 0.0f) { // below start + return findRaySphereIntersection(origin, direction, start, radius, distance); + + } else if (originProjection > capsuleLength) { // above end + return findRaySphereIntersection(origin, direction, end, radius, distance); + + } else { // between start and end + distance = 0.0f; + return true; + } + } + glm::vec3 coefficient = direction - relativeEnd * glm::dot(relativeEnd, direction); + float a = glm::dot(coefficient, coefficient); + if (a == 0.0f) { + return false; // parallel to enclosing cylinder + } + float b = 2.0f * glm::dot(constant, coefficient); + float radicand = b * b - 4.0f * a * c; + if (radicand < 0.0f) { + return false; // doesn't hit the enclosing cylinder + } + float t = (-b - sqrtf(radicand)) / (2.0f * a); + if (t < 0.0f) { + return false; // doesn't hit the enclosing cylinder + } + glm::vec3 intersection = relativeOrigin + direction * t; + float intersectionProjection = glm::dot(relativeEnd, intersection); + if (intersectionProjection < 0.0f) { // below start + return findRaySphereIntersection(origin, direction, start, radius, distance); + + } else if (intersectionProjection > capsuleLength) { // above end + return findRaySphereIntersection(origin, direction, end, radius, distance); + } + distance = t; // between start and end + return true; +} + +// Do line segments (r1p1.x, r1p1.y)--(r1p2.x, r1p2.y) and (r2p1.x, r2p1.y)--(r2p2.x, r2p2.y) intersect? +// from: http://ptspts.blogspot.com/2010/06/how-to-determine-if-two-line-segments.html +bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2) { + int d1 = computeDirection(r2p1.x, r2p1.y, r2p2.x, r2p2.y, r1p1.x, r1p1.y); + int d2 = computeDirection(r2p1.x, r2p1.y, r2p2.x, r2p2.y, r1p2.x, r1p2.y); + int d3 = computeDirection(r1p1.x, r1p1.y, r1p2.x, r1p2.y, r2p1.x, r2p1.y); + int d4 = computeDirection(r1p1.x, r1p1.y, r1p2.x, r1p2.y, r2p2.x, r2p2.y); + return (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && + ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) || + (d1 == 0 && isOnSegment(r2p1.x, r2p1.y, r2p2.x, r2p2.y, r1p1.x, r1p1.y)) || + (d2 == 0 && isOnSegment(r2p1.x, r2p1.y, r2p2.x, r2p2.y, r1p2.x, r1p2.y)) || + (d3 == 0 && isOnSegment(r1p1.x, r1p1.y, r1p2.x, r1p2.y, r2p1.x, r2p1.y)) || + (d4 == 0 && isOnSegment(r1p1.x, r1p1.y, r1p2.x, r1p2.y, r2p2.x, r2p2.y)); +} + +bool isOnSegment(float xi, float yi, float xj, float yj, float xk, float yk) { + return (xi <= xk || xj <= xk) && (xk <= xi || xk <= xj) && + (yi <= yk || yj <= yk) && (yk <= yi || yk <= yj); +} + +int computeDirection(float xi, float yi, float xj, float yj, float xk, float yk) { + float a = (xk - xi) * (yj - yi); + float b = (xj - xi) * (yk - yi); + return a < b ? -1 : a > b ? 1 : 0; +} + + +// +// Polygon Clipping routines inspired by, pseudo code found here: http://www.cs.rit.edu/~icss571/clipTrans/PolyClipBack.html +// +// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space. +// +// (0,0) (windowWidth, 0) +// -1,1 1,1 +// +-----------------------+ +// | | | +// | | | +// | -1,0 | | +// |-----------+-----------| +// | 0,0 | +// | | | +// | | | +// | | | +// +-----------------------+ +// -1,-1 1,-1 +// (0,windowHeight) (windowWidth,windowHeight) +// + const float PolygonClip::TOP_OF_CLIPPING_WINDOW = 1.0f; const float PolygonClip::BOTTOM_OF_CLIPPING_WINDOW = -1.0f; const float PolygonClip::LEFT_OF_CLIPPING_WINDOW = -1.0f; @@ -175,4 +466,4 @@ void PolygonClip::copyCleanArray(int& lengthA, glm::vec2* vertexArrayA, int& len vertexArrayA[i] = vertexArrayB[i]; } } -} +} \ No newline at end of file