#include "gpuCacheIsectUtil.h"
#include <maya/MMatrix.h>
#include <maya/MPointArray.h>
#include <limits>
namespace GPUCache {
double gpuCacheIsectUtil::getClosestPointOnLine(
const MPoint& queryPoint,
const MPoint& pt1,
const MPoint& pt2,
MPoint& closestPoint){
double t = ( (queryPoint - pt1) * edgeVec ) / (edgeVec * edgeVec);
if(t<0) t=0;
if(t>1) t=1;
closestPoint = (1-t) * pt1 + t * pt2;
return t;
}
if(firstRayIntersection(bbox.
min(), bbox.
max(), raySource, rayDirection, NULL, &boxIntersectionPt))
{
snapPoint = boxIntersectionPt;
return 0.0;
}
int edgeIndices[12][2]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{3,7},{2,6}};
double minDistRect = std::numeric_limits<double>::max();
for(int edge=0; edge<12;edge++){
MPoint vertex1Org = verts[edgeIndices[edge][0]];
MPoint vertex2Org = verts[edgeIndices[edge][1]];
double coef_plane = rayDirection * raySource;
double d = coef_plane - rayDirection * vertex1Org;
MPoint vertex1 = vertex1Org + rayDirection * d;
d = coef_plane - rayDirection * vertex2Org;
MPoint vertex2 = vertex2Org + rayDirection * d;
MVector edgeDir = vertex2 - vertex1;
if (edgeDir.
length()<0.0000001){
if (dist < minDistRect) {
minDistRect = dist;
snapPoint = vertex1Org;
}
} else {
double percent = gpuCacheIsectUtil::getClosestPointOnLine(raySource, vertex1, vertex2, edgePt);
if (dist < minDistRect) {
minDistRect = dist;
snapPoint = (vertex1Org + percent * (vertex2Org - vertex1Org));
}
}
}
return minDistRect;
}
double gpuCacheIsectUtil::getEdgeSnapPointOnTriangle(
const MPoint& raySource,
const MVector& rayDirection,
const MPoint& vert1,
const MPoint& vert2,
const MPoint& vert3,
MPoint& snapPoint){
int edgeIndices[3][2]={{0,1},{1,2},{2,0}};
double minDistTri = std::numeric_limits<double>::max();
for(int edge=0; edge<3;edge++){
MPoint vertex1Org = verts[edgeIndices[edge][0]];
MPoint vertex2Org = verts[edgeIndices[edge][1]];
double coef_plane = rayDirection * raySource;
double d = coef_plane - rayDirection * vertex1Org;
MPoint vertex1 = vertex1Org + rayDirection * d;
d = coef_plane - rayDirection * vertex2Org;
MPoint vertex2 = vertex2Org + rayDirection * d;
MVector edgeDir = vertex2 - vertex1;
if (edgeDir.
length()<0.0000001){
if (dist < minDistTri) {
minDistTri = dist;
snapPoint = vertex1Org;
}
} else {
double percent = gpuCacheIsectUtil::getClosestPointOnLine(raySource, vertex1, vertex2, edgePt);
if (dist < minDistTri) {
minDistTri = dist;
snapPoint = (vertex1Org + percent * (vertex2Org - vertex1Org));
}
}
}
return minDistTri;
}
void gpuCacheIsectUtil::getClosestPointToRayOnLine(
const MPoint& vertex1,
const MPoint& vertex2,
const MPoint& raySource,
const MVector& rayDirection,
MPoint& closestPoint,
double& percent){
MVector edgeDir = vertex2 - vertex1;
double len = edgeDir.
length();
if(len < 0.0000001 )
{
percent = 0.0;
closestPoint = vertex1;
return;
}
double dotPrd = fabs(edgeDir * rayDirection);
if(dotPrd > 0.9999){
percent = 0.0;
closestPoint = vertex1;
return;
}
MVector crossProd = edgeDir ^ rayDirection;
MVector planeNormal = rayDirection ^ crossProd;
double t;
if(intersectPlane(raySource, planeNormal, vertex1,edgeDir,t)){
clsPoint = vertex1 + t * edgeDir;
percent = edgeDir * (clsPoint - vertex1) / len;
if (percent < 0)
{
closestPoint = vertex1;
percent = 0.0;
}
else if (percent > 1.0)
{
closestPoint = vertex2;
percent = 1.0;
}
else
{
closestPoint = clsPoint;
}
} else
{
closestPoint = vertex1;
percent = 0.0;
}
}
double sqrDistance = 0.0;
double delta;
for (int i = 0; i < 3; ++i)
{
closest[i] = diff * axis[i];
if (closest[i] < -dimensions[i])
{
delta = closest[i] + dimensions[i];
sqrDistance += delta*delta;
closest[i] = -dimensions[i];
}
else if (closest[i] > dimensions[i])
{
delta = closest[i] - dimensions[i];
sqrDistance += delta*delta;
closest[i] = dimensions[i];
}
}
for (int i = 0; i < 3; ++i)
{
closestPoint += closest[i]*axis[i];
}
return sqrt(sqrDistance);
}
int gpuCacheIsectUtil::intersectRayWithBox(
double isectParams[2]
)
{
const double isectTol = 1.0e-6;
int numFound = 0;
double boundsMin[3]={minPoint[0],minPoint[1],minPoint[2]};
double boundsMax[3]={maxPoint[0],maxPoint[1],maxPoint[2]};
for( int axis = 0; axis < 3; axis++ )
{
if( rayDirection[axis] != 0 )
{
int otherAxis1 = (axis+1)%3;
int otherAxis2 = (axis+2)%3;
double sides[2] = { boundsMin[axis], boundsMax[axis] };
for( int side = 0; side < 2; side++ )
{
double tSide = (sides[side]-rayOrigin[axis])/rayDirection[axis];
if( tSide > 0.0 )
{
double newPointOtherAxis1 = rayOrigin[otherAxis1] +
tSide*rayDirection[otherAxis1];
if( (newPointOtherAxis1 >= (boundsMin[otherAxis1]-isectTol)) && (newPointOtherAxis1 <= (boundsMax[otherAxis1]+isectTol)) )
{
double newPointOtherAxis2 = rayOrigin[otherAxis2] +
tSide*rayDirection[otherAxis2];
if( (newPointOtherAxis2 >= (boundsMin[otherAxis2]-isectTol)) && (newPointOtherAxis2 <= (boundsMax[otherAxis2]+isectTol)) )
{
if( numFound == 0 )
{
isectParams[0] = tSide;
numFound++;
}
else if( numFound == 1 )
{
if( tSide >= (isectParams[0]+1.0e-10) )
{
isectParams[1] = tSide;
numFound++;
}
else if( tSide <= (isectParams[0]-1.0e-10) )
{
isectParams[1] = isectParams[0];
isectParams[0] = tSide;
numFound++;
}
}
}
}
}
}
}
}
return numFound;
}
bool gpuCacheIsectUtil::firstRayIntersection (
double* isectParam,
)
{
double allIsectParams[4] = {0};
if( !intersectRayWithBox( bboxMin, bboxMax, rayOrigin, rayDirection, allIsectParams ) )
{
return false;
}
else
{
if( isectParam != NULL )
{
*isectParam = allIsectParams[0];
}
if( isectPoint != NULL )
{
*isectPoint = rayOrigin + allIsectParams[0]*rayDirection;
}
return true;
}
}
bool gpuCacheIsectUtil::intersectPlane(
const MPoint &planePoint,
const MVector &planeNormal,
const MPoint& rayPoint,
const MVector &rayDirection,
double &t)
{
double denom = planeNormal * rayDirection;
if (denom > 0.0000001) {
MVector p0l0 = planePoint - rayPoint;
t = (p0l0 * planeNormal) / denom;
return (t >= 0);
}
return false;
}
bool gpuCacheIsectUtil::getClosestPointOnTri(
const MPoint &toThisPoint,
const MPoint &pt1,
const MPoint &pt2,
const MPoint &pt3,
MPoint &theClosestPoint,
double &currDist)
{
double sum, a, b, c, len, dist;
mat[2][0] = mat[2][1] = mat[2][2] = 1.;
len = norm * norm;
if (len < 1.175494351e-38F) return false;
len = ( norm * v ) / len;
MPoint pnt = toThisPoint - len * norm;
return false;
int i, j;
if (fabs(norm[0]) > fabs(norm[1]))
{
if (fabs(norm[0]) > fabs(norm[2]))
{
i = 1; j = 2;
}
else
{
i = 0; j = 1;
}
}
else
{
if (fabs(norm[1]) > fabs(norm[2]))
{
i = 0; j = 2;
}
else
{
i = 0; j = 1;
}
}
mat[0][0] = pt1[i]; mat[0][1] = pt2[i]; mat[0][2] = pt3[i];
mat[1][0] = pt1[j]; mat[1][1] = pt2[j]; mat[1][2] = pt3[j];
MPoint abc(pnt[i], pnt[j], 1, 0);
abc = matInv * abc;
if (abc[0]<0) {
if (abc[1]<0) {
a = b = 0;
c = 1;
} else if (abc[2]<0) {
a = c = 0;
b = 1;
} else {
a = 0;
c = ( vp * v23 ) / ( v23[0]*v23[0] + v23[1]*v23[1] + v23[2]*v23[2] );
if (c<0) c = 0; else if (c>1) c = 1;
b = 1 - c;
}
} else if (abc[1]<0) {
if (abc[2]<0) {
b = c = 0;
a = 1;
} else {
b = 0;
a = ( vp * v31 ) / ( v31[0]*v31[0] + v31[1]*v31[1] +v31[2]*v31[2] );
if (a<0) a = 0; else if (a>1) a = 1;
c = 1 - a;
}
} else if (abc[2]<0) {
c = 0;
b = ( vp * v12 ) / ( v12[0]*v12[0] + v12[1]*v12[1] + v12[2]*v12[2] );
if (b<0) b = 0; else if (b>1) b = 1;
a = 1 - b;
} else {
if (abc[0]>0) a = abc[0]; else a = 0;
if (abc[1]>0) b = abc[1]; else b = 0;
if (abc[2]>0) c = abc[2]; else c = 0;
}
sum = a+b+c;
a /= sum ; b /= sum ; c /= sum ;
pnt = a * pt1 + b * pt2 + c * pt3;
if ( dist < currDist)
{
currDist = dist;
theClosestPoint = pnt;
return true;
}
return false;
}
}