예제 #1
0
bool BicubicPatch::intersect_subpatch(const BasicRay &ray, const TripleVector3d& V1, const DBL uu[3], const DBL vv[3], DBL *Depth, Vector3d& P, Vector3d& N, DBL *u, DBL *v) const
{
    DBL squared_b0, squared_b1;
    DBL d, n, a, b, r;
    Vector3d Q;
    Vector3d T1;
    Matrix3x3 B, IB;
    Vector3d NN[3];

    B[0] = V1[1] - V1[0];
    B[1] = V1[2] - V1[0];

    B[2] = cross(B[0], B[1]);

    d = B[2].lengthSqr();

    squared_b0 = B[0].lengthSqr();
    squared_b1 = B[1].lengthSqr();
    if (d <= (BEZIER_EPSILON * squared_b1 * squared_b0))
    {
        return false;
    }

    d = 1.0 / sqrt(d);

    B[2] *= d;

    /* Degenerate triangle. */

    if (!MInvers3(B, IB))
    {
        return false;
    }

    d = dot(ray.Direction, IB[2]);

    if (fabs(d) < BEZIER_EPSILON)
    {
        return false;
    }

    Q = V1[0] - ray.Origin;

    n = dot(Q, IB[2]);

    *Depth = n / d;

    if (*Depth < BEZIER_TOLERANCE)
    {
        return false;
    }

    T1 = ray.Direction * (*Depth);

    P = ray.Origin + T1;

    Q = P - V1[0];

    a = dot(Q, IB[0]);
    b = dot(Q, IB[1]);

    if ((a < 0.0) || (b < 0.0) || (a + b > 1.0))
    {
        return false;
    }

    r = 1.0 - a - b;

    bezier_value(&Control_Points, uu[0], vv[0], T1, NN[0]);
    bezier_value(&Control_Points, uu[1], vv[1], T1, NN[1]);
    bezier_value(&Control_Points, uu[2], vv[2], T1, NN[2]);

    N = NN[0] * r
      + NN[1] * a
      + NN[2] * b;

    *u = r * uu[0] + a * uu[1] + b * uu[2];
    *v = r * vv[0] + a * vv[1] + b * vv[2];

    d = N.lengthSqr();

    if (d > BEZIER_EPSILON)
    {
        d = 1.0 / sqrt(d);

        N *= d;
    }
    else
    {
        N = Vector3d(1.0, 0.0, 0.0);
    }

    return true;
}
예제 #2
0
static int intersect_subpatch(BICUBIC_PATCH *Shape, RAY *ray, VECTOR V1[3], DBL uu[3], DBL  vv[3], DBL  *Depth, VECTOR P, VECTOR  N, DBL *u, DBL  *v)
{
  DBL squared_b0, squared_b1;
  DBL d, n, a, b, r;
  VECTOR Q, T1;
  VECTOR B[3], IB[3], NN[3];

  VSub(B[0], V1[1], V1[0]);
  VSub(B[1], V1[2], V1[0]);

  VCross(B[2], B[0], B[1]);

  VDot(d, B[2], B[2]);

  squared_b0 = VSumSqr(B[0]);
  squared_b1 = VSumSqr(B[1]);
  if (d <= (BEZIER_EPSILON * squared_b1 * squared_b0))
  {
    return (0);
  }

  d = 1.0 / sqrt(d);

  VScaleEq(B[2], d);

  /* Degenerate triangle. */

  if (!MInvers3(B, IB))
  {
    return (0);
  }

  VDot(d, ray->Direction, IB[2]);

  if (fabs(d) < BEZIER_EPSILON)
  {
    return (0);
  }

  VSub(Q, V1[0], ray->Initial);

  VDot(n, Q, IB[2]);

  *Depth = n / d;

  if (*Depth < BEZIER_TOLERANCE)
  {
    return (0);
  }

  VScale(T1, ray->Direction, *Depth);

  VAdd(P, ray->Initial, T1);

  VSub(Q, P, V1[0]);

  VDot(a, Q, IB[0]);
  VDot(b, Q, IB[1]);

  if ((a < 0.0) || (b < 0.0) || (a + b > 1.0))
  {
    return (0);
  }

  r = 1.0 - a - b;

  Make_Vector(N, 0.0, 0.0, 0.0);

  bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[0], vv[0], T1, NN[0]);
  bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[1], vv[1], T1, NN[1]);
  bezier_value((VECTOR(*)[4][4])&Shape->Control_Points, uu[2], vv[2], T1, NN[2]);

  VScale(T1, NN[0], r); VAddEq(N, T1);
  VScale(T1, NN[1], a); VAddEq(N, T1);
  VScale(T1, NN[2], b); VAddEq(N, T1);

  *u = r * uu[0] + a * uu[1] + b * uu[2];
  *v = r * vv[0] + a * vv[1] + b * vv[2];

  VDot(d, N, N);

  if (d > BEZIER_EPSILON)
  {
    d = 1.0 / sqrt(d);

    VScaleEq(N, d);
  }
  else
  {
    Make_Vector(N, 1, 0, 0);
  }

  return (1);
}