Beispiel #1
0
void Compute_Matrix_Transform (TRANSFORM *result, const MATRIX matrix)
{
	register int i;

	for (i = 0; i < 4; i++)
	{
		(result->matrix)[i][0] = matrix[i][0];
		(result->matrix)[i][1] = matrix[i][1];
		(result->matrix)[i][2] = matrix[i][2];
		(result->matrix)[i][3] = matrix[i][3];
	}

	MInvers(result->inverse, result->matrix);
}
Beispiel #2
0
void Polygon::Compute_Polygon(int number, Vector3d *points)
{
    int i;
    DBL x, y, z, d;
    Vector3d o, u, v, w, N;
    MATRIX a, b;

    /* Create polygon data. */

    if (Data == NULL)
    {
        Data = reinterpret_cast<POLYGON_DATA *>(POV_MALLOC(sizeof(POLYGON_DATA), "polygon points"));

        Data->References = 1;

        Data->Number = number;

        Data->Points = reinterpret_cast<Vector2d *>(POV_MALLOC(number*sizeof(Vector2d), "polygon points"));
    }
    else
    {
        throw POV_EXCEPTION_STRING("Polygon data already computed.");
    }

    /* Get polygon's coordinate system (one of the many possible) */

    o = points[0];

    /* Find valid, i.e. non-zero u vector. */

    for (i = 1; i < number; i++)
    {
        u = points[i] - o;

        if (u.lengthSqr() > EPSILON)
        {
            break;
        }
    }

    if (i == number)
    {
        Set_Flag(this, DEGENERATE_FLAG);

;// TODO MESSAGE    Warning("Points in polygon are co-linear. Ignoring polygon.");
    }

    /* Find valid, i.e. non-zero v and w vectors. */

    for (i++; i < number; i++)
    {
        v = points[i] - o;

        w = cross(u, v);

        if ((v.lengthSqr() > EPSILON) && (w.lengthSqr() > EPSILON))
        {
            break;
        }
    }

    if (i == number)
    {
        Set_Flag(this, DEGENERATE_FLAG);

;// TODO MESSAGE    Warning("Points in polygon are co-linear. Ignoring polygon.");
    }

    u = cross(v, w);
    v = cross(w, u);

    u.normalize();
    v.normalize();
    w.normalize();

    MIdentity(a);
    MIdentity(b);

    a[3][0] = -o[X];
    a[3][1] = -o[Y];
    a[3][2] = -o[Z];

    b[0][0] =  u[X];
    b[1][0] =  u[Y];
    b[2][0] =  u[Z];

    b[0][1] =  v[X];
    b[1][1] =  v[Y];
    b[2][1] =  v[Z];

    b[0][2] =  w[X];
    b[1][2] =  w[Y];
    b[2][2] =  w[Z];

    MTimesC(Trans->inverse, a, b);

    MInvers(Trans->matrix, Trans->inverse);

    /* Project points onto the u,v-plane (3D --> 2D) */

    for (i = 0; i < number; i++)
    {
        x = points[i][X] - o[X];
        y = points[i][Y] - o[Y];
        z = points[i][Z] - o[Z];

        d = x * w[X] + y * w[Y] + z * w[Z];

        if (fabs(d) > ZERO_TOLERANCE)
        {
            Set_Flag(this, DEGENERATE_FLAG);

;// TODO MESSAGE      Warning("Points in polygon are not co-planar. Ignoring polygons.");
        }

        Data->Points[i][X] = x * u[X] + y * u[Y] + z * u[Z];
        Data->Points[i][Y] = x * v[X] + y * v[Y] + z * v[Z];
    }

    N = Vector3d(0.0, 0.0, 1.0);
    MTransNormal(S_Normal, N, Trans);

    S_Normal.normalize();

    Compute_BBox();
}
Beispiel #3
0
void Sor::Compute_Sor(Vector2d *P, TraceThreadData *Thread)
{
    int i, n;
    DBL *tmp_r1;
    DBL *tmp_r2;
    DBL *tmp_h1;
    DBL *tmp_h2;
    DBL A, B, C, D, w;
    DBL xmax, xmin, ymax, ymin;
    DBL k[4], x[4];
    DBL y[2], r[2];
    DBL c[3];
    MATRIX Mat;

    /* Allocate Number segments. */

    if (Spline == NULL)
    {
        Spline = new SOR_SPLINE;

        Spline->References = 1;

        Spline->Entry = new SOR_SPLINE_ENTRY[Number];
    }
    else
    {
        throw POV_EXCEPTION_STRING("Surface of revolution segments are already defined.");
    }

    /* Allocate temporary lists. */

    tmp_r1 = new DBL[Number];
    tmp_r2 = new DBL[Number];
    tmp_h1 = new DBL[Number];
    tmp_h2 = new DBL[Number];

    /* We want to know the size of the overall bounding cylinder. */

    xmax = ymax = -BOUND_HUGE;
    xmin = ymin =  BOUND_HUGE;

    /* Calculate segments, i.e. cubic patches. */

    for (i = 0; i < Number; i++)
    {
        if ((fabs(P[i+2][Y] - P[i][Y]) < EPSILON) ||
            (fabs(P[i+3][Y] - P[i+1][Y]) < EPSILON))
        {
            throw POV_EXCEPTION_STRING("Incorrect point in surface of revolution.");
        }

        /* Use cubic interpolation. */

        k[0] = P[i+1][X] * P[i+1][X];
        k[1] = P[i+2][X] * P[i+2][X];
        k[2] = (P[i+2][X] - P[i][X]) / (P[i+2][Y] - P[i][Y]);
        k[3] = (P[i+3][X] - P[i+1][X]) / (P[i+3][Y] - P[i+1][Y]);

        k[2] *= 2.0 * P[i+1][X];
        k[3] *= 2.0 * P[i+2][X];

        w = P[i+1][Y];

        Mat[0][0] = w * w * w;
        Mat[0][1] = w * w;
        Mat[0][2] = w;
        Mat[0][3] = 1.0;

        Mat[2][0] = 3.0 * w * w;
        Mat[2][1] = 2.0 * w;
        Mat[2][2] = 1.0;
        Mat[2][3] = 0.0;

        w = P[i+2][Y];

        Mat[1][0] = w * w * w;
        Mat[1][1] = w * w;
        Mat[1][2] = w;
        Mat[1][3] = 1.0;

        Mat[3][0] = 3.0 * w * w;
        Mat[3][1] = 2.0 * w;
        Mat[3][2] = 1.0;
        Mat[3][3] = 0.0;

        MInvers(Mat, Mat);

        /* Calculate coefficients of cubic patch. */

        A = k[0] * Mat[0][0] + k[1] * Mat[0][1] + k[2] * Mat[0][2] + k[3] * Mat[0][3];
        B = k[0] * Mat[1][0] + k[1] * Mat[1][1] + k[2] * Mat[1][2] + k[3] * Mat[1][3];
        C = k[0] * Mat[2][0] + k[1] * Mat[2][1] + k[2] * Mat[2][2] + k[3] * Mat[2][3];
        D = k[0] * Mat[3][0] + k[1] * Mat[3][1] + k[2] * Mat[3][2] + k[3] * Mat[3][3];

        if (fabs(A) < EPSILON) A = 0.0;
        if (fabs(B) < EPSILON) B = 0.0;
        if (fabs(C) < EPSILON) C = 0.0;
        if (fabs(D) < EPSILON) D = 0.0;

        Spline->Entry[i].A = A;
        Spline->Entry[i].B = B;
        Spline->Entry[i].C = C;
        Spline->Entry[i].D = D;

        /* Get minimum and maximum radius**2 in current segment. */

        y[0] = P[i+1][Y];
        y[1] = P[i+2][Y];

        x[0] = x[2] = P[i+1][X];
        x[1] = x[3] = P[i+2][X];

        c[0] = 3.0 * A;
        c[1] = 2.0 * B;
        c[2] = C;

        n = Solve_Polynomial(2, c, r, false, 0.0, Thread);

        while (n--)
        {
            if ((r[n] >= y[0]) && (r[n] <= y[1]))
            {
                x[n] = sqrt(r[n] * (r[n] * (r[n] * A + B) + C) + D);
            }
        }

        /* Set current segment's bounding cylinder. */

        tmp_r1[i] = min(min(x[0], x[1]), min(x[2], x[3]));
        tmp_r2[i] = max(max(x[0], x[1]), max(x[2], x[3]));

        tmp_h1[i] = y[0];
        tmp_h2[i] = y[1];

        /* Keep track of overall bounding cylinder. */

        xmin = min(xmin, tmp_r1[i]);
        xmax = max(xmax, tmp_r2[i]);

        ymin = min(ymin, tmp_h1[i]);
        ymax = max(ymax, tmp_h2[i]);

/*
        fprintf(stderr, "bound spline segment %d: ", i);
        fprintf(stderr, "r = %f - %f, h = %f - %f\n", tmp_r1[i], tmp_r2[i], tmp_h1[i], tmp_h2[i]);
*/
    }

    /* Set overall bounding cylinder. */

    Radius1 = xmin;
    Radius2 = xmax;

    Height1 = ymin;
    Height2 = ymax;

    /* Get cap radius. */

    w = tmp_h2[Number-1];

    A = Spline->Entry[Number-1].A;
    B = Spline->Entry[Number-1].B;
    C = Spline->Entry[Number-1].C;
    D = Spline->Entry[Number-1].D;

    if ((Cap_Radius_Squared = w * (w * (A * w + B) + C) + D) < 0.0)
    {
        Cap_Radius_Squared = 0.0;
    }

    /* Get base radius. */

    w = tmp_h1[0];

    A = Spline->Entry[0].A;
    B = Spline->Entry[0].B;
    C = Spline->Entry[0].C;
    D = Spline->Entry[0].D;

    if ((Base_Radius_Squared = w * (w * (A * w + B) + C) + D) < 0.0)
    {
        Base_Radius_Squared = 0.0;
    }

    /* Get bounding cylinder. */

    Spline->BCyl = Create_BCyl(Number, tmp_r1, tmp_r2, tmp_h1, tmp_h2);

    /* Get rid of temp. memory. */

    delete[] tmp_h2;
    delete[] tmp_h1;
    delete[] tmp_r2;
    delete[] tmp_r1;
}
Beispiel #4
0
void Compute_Polygon(POLYGON *Polyg, int Number, VECTOR *Points)
{
  int i;
  DBL x, y, z, d;
  VECTOR o, u, v, w, N;
  MATRIX a, b;

  /* Create polygon data. */

  if (Polyg->Data == NULL)
  {
    Polyg->Data = (POLYGON_DATA *)POV_MALLOC(sizeof(POLYGON_DATA), "polygon points");

    Polyg->Data->References = 1;

    Polyg->Data->Number = Number;

    Polyg->Data->Points = (UV_VECT *)POV_MALLOC(Number*sizeof(UV_VECT), "polygon points");
  }
  else
  {
    Error("Polygon data already computed.");
  }

  /* Get polygon's coordinate system (one of the many possible) */

  Assign_Vector(o, Points[0]);

  /* Find valid, i.e. non-zero u vector. */
  
  for (i = 1; i < Number; i++)
  {
    VSub(u, Points[i], o);

    if (VSumSqr(u) > EPSILON)
    {
      break;
    }
  }

  if (i == Number)
  {
    Set_Flag(Polyg, DEGENERATE_FLAG);

    Warning(0, "Points in polygon are co-linear. Ignoring polygon.");
  }

  /* Find valid, i.e. non-zero v and w vectors. */
  
  for (i++; i < Number; i++)
  {
    VSub(v, Points[i], o);
    
    VCross(w, u, v);

    if ((VSumSqr(v) > EPSILON) && (VSumSqr(w) > EPSILON))
    {
      break;
    }
  }

  if (i == Number)
  {
    Set_Flag(Polyg, DEGENERATE_FLAG);

    Warning(0, "Points in polygon are co-linear. Ignoring polygon.");
  }

  VCross(u, v, w);
  VCross(v, w, u);

  VNormalize(u, u);
  VNormalize(v, v);
  VNormalize(w, w);

  MIdentity(a);
  MIdentity(b);

  a[3][0] = -o[X];
  a[3][1] = -o[Y];
  a[3][2] = -o[Z];

  b[0][0] =  u[X];
  b[1][0] =  u[Y];
  b[2][0] =  u[Z];

  b[0][1] =  v[X];
  b[1][1] =  v[Y];
  b[2][1] =  v[Z];

  b[0][2] =  w[X];
  b[1][2] =  w[Y];
  b[2][2] =  w[Z];

  MTimesC(Polyg->Trans->inverse, a, b);

  MInvers(Polyg->Trans->matrix, Polyg->Trans->inverse);

  /* Project points onto the u,v-plane (3D --> 2D) */

  for (i = 0; i < Number; i++)
  {
    x = Points[i][X] - o[X];
    y = Points[i][Y] - o[Y];
    z = Points[i][Z] - o[Z];

    d = x * w[X] + y * w[Y] + z * w[Z];

    if (fabs(d) > ZERO_TOLERANCE)
    {
      Set_Flag(Polyg, DEGENERATE_FLAG);

      Warning(0, "Points in polygon are not co-planar. Ignoring polygons.");
    }

    Polyg->Data->Points[i][X] = x * u[X] + y * u[Y] + z * u[Z];
    Polyg->Data->Points[i][Y] = x * v[X] + y * v[Y] + z * v[Z];
  }
  
  Make_Vector(N, 0.0, 0.0, 1.0);
  MTransNormal(Polyg->S_Normal, N, Polyg->Trans);

  VNormalizeEq(Polyg->S_Normal);

  Compute_Polygon_BBox(Polyg);
}