示例#1
0
文件: vec3f.cpp 项目: JT-a/USD
/*
 * BuildOrthonormalFrame constructs two unit vectors *v1 and *v2,
 * with *v1 and *v2 perpendicular to each other and (*this).
 * We arbitrarily cross *this with the X axis to form *v1,
 * and if the result is degenerate, we set *v1 = (Y axis) X *this.
 * If L = length(*this) < eps, we shrink v1 and v2 to be of
 * length L/eps.
 */
void
GfBuildOrthonormalFrame(GfVec3f const &v0,
                        GfVec3f* v1,
                        GfVec3f* v2, float eps)
{
    float len = v0.GetLength();

    if (len == 0.) {
	*v1 = *v2 = GfVec3f(0);
    }
    else {
	GfVec3f unitDir = v0 / len;
	*v1 = GfVec3f::XAxis() ^ unitDir;

	if (GfSqr(*v1) < GfSqr(1e-4))
	    *v1 = GfVec3f::YAxis() ^ unitDir;

        GfNormalize(v1);
	*v2 = unitDir ^ *v1;	// this is of unit length

	if (len < eps) {
	    double  desiredLen = len / eps;
	    *v1 *= desiredLen;
	    *v2 *= desiredLen;
	}
    }
}
示例#2
0
文件: ray.cpp 项目: JT-a/USD
bool
GfRay::Intersect(const GfVec3d &origin,
                 const GfVec3d &axis,
                 const double radius, 
                 const double height,
                 double *enterDistance,
                 double *exitDistance) const
{ 
    GfVec3d unitAxis = axis.GetNormalized();
    
    // Apex of cone
    GfVec3d apex = origin + height * unitAxis;
    
    GfVec3d delta = _startPoint - apex;
    GfVec3d u =_direction - GfDot(_direction, unitAxis) * unitAxis;
    GfVec3d v = delta - GfDot(delta, unitAxis) * unitAxis;
    
    double p = GfDot(_direction, unitAxis);
    double q = GfDot(delta, unitAxis);
    
    double cos2 = GfSqr(height) / (GfSqr(height) + GfSqr(radius));
    double sin2 = 1 - cos2;
    
    double a = cos2 * GfDot(u, u) - sin2 * GfSqr(p);
    double b = 2.0 * (cos2 * GfDot(u, v) - sin2 * p * q);
    double c = cos2 * GfDot(v, v) - sin2 * GfSqr(q);
    
    if (!_SolveQuadratic(a, b, c, enterDistance, exitDistance)) {
        return false;
    }
    
    // Eliminate any solutions on the double cone
    bool enterValid = GfDot(unitAxis, GetPoint(*enterDistance) - apex) <= 0.0;
    bool exitValid = GfDot(unitAxis, GetPoint(*exitDistance) - apex) <= 0.0;
    
    if ((!enterValid) && (!exitValid)) {
        
        // Solutions lie only on double cone
        return false;
    }
    
    if (!enterValid) {
        *enterDistance = *exitDistance;
    }
    else if (!exitValid) {
        *exitDistance = *enterDistance;
    }
        
    return true;
}
示例#3
0
double
GfRange3f::GetDistanceSquared(const GfVec3f &p) const
{
    double dist = 0.0;

    if (p[0] < _min[0]) {
	// p is left of box
	dist += GfSqr(_min[0] - p[0]);
    }
    else if (p[0] > _max[0]) {
	// p is right of box
	dist += GfSqr(p[0] - _max[0]);
    }
    if (p[1] < _min[1]) {
	// p is front of box
	dist += GfSqr(_min[1] - p[1]);
    }
    else if (p[1] > _max[1]) {
	// p is back of box
	dist += GfSqr(p[1] - _max[1]);
    }
    if (p[2] < _min[2]) {
	// p is below of box
	dist += GfSqr(_min[2] - p[2]);
    }
    else if (p[2] > _max[2]) {
	// p is above of box
	dist += GfSqr(p[2] - _max[2]);
    }

    return dist;
}
示例#4
0
文件: ray.cpp 项目: JT-a/USD
bool
GfRay::Intersect(const GfVec3d &origin,
                 const GfVec3d &axis,
                 const double radius,
                 double *enterDistance,
                 double *exitDistance) const
{
    GfVec3d unitAxis = axis.GetNormalized();
    
    GfVec3d delta = _startPoint - origin;
    GfVec3d u = _direction - GfDot(_direction, unitAxis) * unitAxis;
    GfVec3d v = delta - GfDot(delta, unitAxis) * unitAxis;
    
    // Quadratic equation for implicit infinite cylinder
    double a = GfDot(u, u);
    double b = 2.0 * GfDot(u, v);
    double c = GfDot(v, v) - GfSqr(radius);
    
    return _SolveQuadratic(a, b, c, enterDistance, exitDistance);
}
示例#5
0
文件: vec3f.cpp 项目: JT-a/USD
/*
 * Given 3 basis vectors *tx, *ty, *tz, orthogonalize and optionally normalize
 * them.
 *
 * This uses an iterative method that is very stable even when the vectors
 * are far from orthogonal (close to colinear).  The number of iterations
 * and thus the computation time does increase as the vectors become
 * close to colinear, however.
 *
 * If the iteration fails to converge, returns false with vectors as close to
 * orthogonal as possible.
 */
bool
GfOrthogonalizeBasis(GfVec3f *tx, GfVec3f *ty, GfVec3f *tz,
                     bool normalize, double eps)
{
    GfVec3f ax,bx,cx,ay,by,cy,az,bz,cz;

    if (normalize) {
	GfNormalize(tx);
	GfNormalize(ty);
	GfNormalize(tz);
	ax = *tx;
	ay = *ty;
	az = *tz;
    } else {
	ax = *tx;
	ay = *ty;
	az = *tz;
	ax.Normalize();
	ay.Normalize();
	az.Normalize();
    }

    /* Check for colinear vectors. This is not only a quick-out: the
     * error computation below will evaluate to zero if there's no change
     * after an iteration, which can happen either because we have a good
     * solution or because the vectors are colinear.   So we have to check
     * the colinear case beforehand, or we'll get fooled in the error
     * computation.
     */
    if (GfIsClose(ax,ay,eps) || GfIsClose(ax,az,eps) || GfIsClose(ay,az,eps)) {
	return false;
    }

    const int MAX_ITERS = 20;
    int iter;
    for (iter = 0; iter < MAX_ITERS; ++iter) {
	bx = *tx;
	by = *ty;
	bz = *tz;

	bx -= GfDot(ay,bx) * ay;
	bx -= GfDot(az,bx) * az;

	by -= GfDot(ax,by) * ax;
	by -= GfDot(az,by) * az;

	bz -= GfDot(ax,bz) * ax;
	bz -= GfDot(ay,bz) * ay;

	cx = 0.5*(*tx + bx);
	cy = 0.5*(*ty + by);
	cz = 0.5*(*tz + bz);

	if (normalize) {
            cx.Normalize();
            cy.Normalize();
            cz.Normalize();
	}

	GfVec3f xDiff = *tx - cx;
	GfVec3f yDiff = *ty - cy;
	GfVec3f zDiff = *tz - cz;

	double error =
            GfDot(xDiff,xDiff) + GfDot(yDiff,yDiff) + GfDot(zDiff,zDiff);

	// error is squared, so compare to squared tolerance
	if (error < GfSqr(eps))
	    break;

	*tx = cx;
	*ty = cy;
	*tz = cz;

	ax = *tx;
	ay = *ty;
	az = *tz;

	if (!normalize) {
            ax.Normalize();
            ay.Normalize();
            az.Normalize();
	}
    }

    return iter < MAX_ITERS;
}
示例#6
0
文件: ray.cpp 项目: JT-a/USD
bool
GfRay::_SolveQuadratic(const double a, 
                       const double b,
                       const double c,
                       double *enterDistance, 
                       double *exitDistance) const
{
    if (GfIsClose(a, 0.0, tolerance)) {
        if (GfIsClose(b, 0.0, tolerance)) {
            
            // Degenerate solution
            return false;
        }
        
        double t = -c / b;
        
        if (t < 0.0) {
            return false;
        }
        
        if (enterDistance) {
            *enterDistance = t;
        }
        
        if (exitDistance) {
            *exitDistance = t;
        }
        
        return true;
    }
    
    // Discriminant
    double disc = GfSqr(b) - 4.0 * a * c;
    
    if (GfIsClose(disc, 0.0, tolerance)) {
        
        // Tangent
        double t = -b / (2.0 * a);
        
        if (t < 0.0) {
            return false;
        }
        
        if (enterDistance) {
            *enterDistance = t;
        }
        
        if (exitDistance) {
            *exitDistance = t;
        }
        
        return true;
    }
    
    if (disc < 0.0) {

        // No intersection
        return false;
    }

    // Two intersection points
    double q = -0.5 * (b + copysign(1.0, b) * GfSqrt(disc));
    double t0 = q / a;
    double t1 = c / q;

    if (t0 > t1) {
        std::swap(t0, t1);
    }
    
    if (t1 >= 0) {

        if (enterDistance) {
            *enterDistance = t0;
        }
            
        if (exitDistance) {
            *exitDistance  = t1;
        }

        return true;
    }
    
    return false;
}