Beispiel #1
0
// This routine computes the spread of a closed convex polyhedron.
// The vertices, faces, and center of mass (centroids weighted by area)
// are given.  Resulting from eigen-vectors are returned.
// This algorithm was derived from the SIGGRAPH 96 paper on OBB's.
void Compute_Spread( SWIFT_Array<SWIFT_Tri_Vertex>& vs, int* fs, int fn,
                     bool have_com,
                     SWIFT_Triple& com, SWIFT_Triple& min_dir,
                     SWIFT_Triple& mid_dir, SWIFT_Triple& max_dir )
{
    int i;
    int mine, mide, maxe;
    SWIFT_Real area_x2;
    SWIFT_Real total_area;
    SWIFT_Real s[3];
    SWIFT_Real C[3][3];
    SWIFT_Real E[3][3];
    SWIFT_Triple centroid;
    SWIFT_Triple areav;

    // Create the covariance matrix
    C[0][0] = C[0][1] = C[0][2] = C[1][1] = C[1][2] = C[2][2] = 0.0;

    total_area = 0.0;
    if( have_com ) {
        for( i = 0; i < fn*3; ) {
            const SWIFT_Triple& vx = vs[fs[i++]].Coords();
            const SWIFT_Triple& vy = vs[fs[i++]].Coords();
            const SWIFT_Triple& vz = vs[fs[i++]].Coords();
            areav = (vx - vy) % (vx - vz);
            area_x2 = areav.Length();
            total_area += area_x2;
            centroid = vx + vy + vz;

            C[0][0] += area_x2 * (centroid.X() * centroid.X() +
                        vx.X() * vx.X() + vy.X() * vy.X() + vz.X() * vz.X());
            C[0][1] += area_x2 * (centroid.X() * centroid.Y() +
                        vx.X() * vx.Y() + vy.X() * vy.Y() + vz.X() * vz.Y());
            C[0][2] += area_x2 * (centroid.X() * centroid.Z() +
                        vx.X() * vx.Z() + vy.X() * vy.Z() + vz.X() * vz.Z());
            C[1][1] += area_x2 * (centroid.Y() * centroid.Y() +
                        vx.Y() * vx.Y() + vy.Y() * vy.Y() + vz.Y() * vz.Y());
            C[1][2] += area_x2 * (centroid.Y() * centroid.Z() +
                        vx.Y() * vx.Z() + vy.Y() * vy.Z() + vz.Y() * vz.Z());
            C[2][2] += area_x2 * (centroid.Z() * centroid.Z() +
                        vx.Z() * vx.Z() + vy.Z() * vy.Z() + vz.Z() * vz.Z());
        }
    } else {
        com.Set_Value( 0.0, 0.0, 0.0 );
        for( i = 0; i < fn*3; ) {
            const SWIFT_Triple& vx = vs[fs[i++]].Coords();
            const SWIFT_Triple& vy = vs[fs[i++]].Coords();
            const SWIFT_Triple& vz = vs[fs[i++]].Coords();
            areav = (vx - vy) % (vx - vz);
            area_x2 = areav.Length();
            total_area += area_x2;
            centroid = vx + vy + vz;

            com += area_x2 * (vx + vy + vz);
            C[0][0] += area_x2 * (centroid.X() * centroid.X() +
                        vx.X() * vx.X() + vy.X() * vy.X() + vz.X() * vz.X());
            C[0][1] += area_x2 * (centroid.X() * centroid.Y() +
                        vx.X() * vx.Y() + vy.X() * vy.Y() + vz.X() * vz.Y());
            C[0][2] += area_x2 * (centroid.X() * centroid.Z() +
                        vx.X() * vx.Z() + vy.X() * vy.Z() + vz.X() * vz.Z());
            C[1][1] += area_x2 * (centroid.Y() * centroid.Y() +
                        vx.Y() * vx.Y() + vy.Y() * vy.Y() + vz.Y() * vz.Y());
            C[1][2] += area_x2 * (centroid.Y() * centroid.Z() +
                        vx.Y() * vx.Z() + vy.Y() * vy.Z() + vz.Y() * vz.Z());
            C[2][2] += area_x2 * (centroid.Z() * centroid.Z() +
                        vx.Z() * vx.Z() + vy.Z() * vy.Z() + vz.Z() * vz.Z());
        }
        com /= 3.0 * total_area;
    }

    total_area *= 0.5;
    C[0][0] = C[0][0] / 24.0 - com.X() * com.X() * total_area;
    C[0][1] = C[0][1] / 24.0 - com.X() * com.Y() * total_area;
    C[1][0] = C[0][1];
    C[0][2] = C[0][2] / 24.0 - com.X() * com.Z() * total_area;
    C[2][0] = C[0][2];
    C[1][1] = C[1][1] / 24.0 - com.Y() * com.Y() * total_area;
    C[1][2] = C[1][2] / 24.0 - com.Y() * com.Z() * total_area;
    C[2][1] = C[1][2];
    C[2][2] = C[2][2] / 24.0 - com.Z() * com.Z() * total_area;

    // Do eigen-analysis to find the major/minor axes of the object
    Meigen( E, s, C );

    // Compare the eigen values and sort them
    if (s[0] > s[1]) { maxe = 0; mine = 1; }
    else { mine = 0; maxe = 1; }
    if (s[2] < s[mine]) { mide = mine; mine = 2; }
    else if (s[2] > s[maxe]) { mide = maxe; maxe = 2; }
    else { mide = 2; }

    min_dir = SWIFT_Triple( E[0][mine], E[1][mine], E[2][mine] );
    mid_dir = SWIFT_Triple( E[0][mide], E[1][mide], E[2][mide] );
    max_dir = SWIFT_Triple( E[0][maxe], E[1][maxe], E[2][maxe] );
    // Ensure a rotation matrix
    if( (max_dir % mid_dir) * min_dir < 0.0 ) {
        max_dir.Negate();
    }
}
Beispiel #2
0
// not a full sort -- just makes column 1 the largest
int
eigen_and_sort1(double evecs[3][3], double cov[3][3])
{
  double t;
  double evals[3];
  int n;

  n = Meigen(evecs, evals, cov);

  if (evals[2] > evals[0])
    {
      if (evals[2] > evals[1])
	{
	  // 2 is largest, swap with column 0
	  t = evecs[0][2]; 
	  evecs[0][2] = evecs[0][0]; 
	  evecs[0][0] = t;
	  t = evecs[1][2]; 
	  evecs[1][2] = evecs[1][0]; 
	  evecs[1][0] = t;
	  t = evecs[2][2]; 
	  evecs[2][2] = evecs[2][0]; 
	  evecs[2][0] = t;
	}
      else
	{
	  // 1 is largest, swap with column 0
	  t = evecs[0][1]; 
	  evecs[0][1] = evecs[0][0]; 
	  evecs[0][0] = t;
	  t = evecs[1][1]; 
	  evecs[1][1] = evecs[1][0]; 
	  evecs[1][0] = t;
	  t = evecs[2][1]; 
	  evecs[2][1] = evecs[2][0]; 
	  evecs[2][0] = t;
	}
    }
  else
    {
      if (evals[0] > evals[1])
	{
	  // 0 is largest, do nothing
	}
      else
	{
  	  // 1 is largest
	  t = evecs[0][1]; 
	  evecs[0][1] = evecs[0][0]; 
	  evecs[0][0] = t;
	  t = evecs[1][1]; 
	  evecs[1][1] = evecs[1][0]; 
	  evecs[1][0] = t;
	  t = evecs[2][1]; 
	  evecs[2][1] = evecs[2][0]; 
	  evecs[2][0] = t;
	}
    }

  // we are returning the number of iterations Meigen took.
  // too many iterations means our chosen orientation is bad.
  return n; 
}
Beispiel #3
0
void Compute_Spread( SWIFT_Array<SWIFT_Tri_Vertex>& vs, int* fs, int fn,   
                     const SWIFT_Triple& com,
                     SWIFT_Triple& min_dir, SWIFT_Real& min_spread,
                     SWIFT_Triple& max_dir, SWIFT_Real& max_spread )
{
    int i;
    int mine, mide, maxe;
    SWIFT_Real area;
    SWIFT_Real total_area;
    SWIFT_Real s[3];
    SWIFT_Real C[3][3];
    SWIFT_Real E[3][3];
    SWIFT_Triple centroid;
    SWIFT_Triple areav;

    // Create the covariance matrix
    C[0][0] = 0.0; C[0][1] = 0.0; C[0][2] = 0.0;
    C[1][0] = 0.0; C[1][1] = 0.0; C[1][2] = 0.0;
    C[2][0] = 0.0; C[2][1] = 0.0; C[2][2] = 0.0;

    total_area = 0.0;
    for( i = 0; i < fn*3; ) {
        const SWIFT_Triple& vx = vs[fs[i++]].Coords();
        const SWIFT_Triple& vy = vs[fs[i++]].Coords();
        const SWIFT_Triple& vz = vs[fs[i++]].Coords();
        areav = (vx - vy) % (vx - vz);
        area = 0.5 * areav.Length();
        total_area += area;
        centroid = vx + vy + vz;

        C[0][0] += area * (centroid.X() * centroid.X()+
                        vx.X() * vx.X()+ vy.X() * vy.X()+ vz.X() * vz.X());
        C[0][1] += area * (centroid.X() * centroid.Y()+
                        vx.X() * vx.Y()+ vy.X() * vy.Y()+ vz.X() * vz.Y());
        C[0][2] += area * (centroid.X() * centroid.Z()+
                        vx.X() * vx.Z()+ vy.X() * vy.Z()+ vz.X() * vz.Z());
        C[1][1] += area * (centroid.Y() * centroid.Y()+
                        vx.Y() * vx.Y()+ vy.Y() * vy.Y()+ vz.Y() * vz.Y());
        C[1][2] += area * (centroid.Y() * centroid.Z()+
                        vx.Y() * vx.Z()+ vy.Y() * vy.Z()+ vz.Y() * vz.Z());
        C[2][2] += area * (centroid.Z() * centroid.Z()+
                        vx.Z() * vx.Z()+ vy.Z() * vy.Z()+ vz.Z() * vz.Z());
    }

    C[0][0] = C[0][0] / 12.0 - com.X() * com.X() * total_area;
    C[0][1] = C[0][1] / 12.0 - com.X() * com.Y() * total_area;
    C[0][2] = C[0][2] / 12.0 - com.X() * com.Z() * total_area;
    C[1][1] = C[1][1] / 12.0 - com.Y() * com.Y() * total_area;
    C[1][2] = C[1][2] / 12.0 - com.Y() * com.Z() * total_area;
    C[2][2] = C[2][2] / 12.0 - com.Z() * com.Z() * total_area;

    C[1][0] = C[0][1];
    C[2][0] = C[0][2];
    C[2][1] = C[1][2];

    // Do eigen-analysis to find the major/minor axes of the object
    Meigen( E, s, C );

    // Compare the eigen values and sort them
    if (s[0] > s[1]) { maxe = 0; mine = 1; }
    else { mine = 0; maxe = 1; }
    if (s[2] < s[mine]) { mide = mine; mine = 2; }
    else if (s[2] > s[maxe]) { mide = maxe; maxe = 2; }
    else { mide = 2; }

    min_dir =  SWIFT_Triple( E[0][mine], E[1][mine], E[2][mine] );
    min_spread = s[mine];
    max_dir =  SWIFT_Triple( E[0][maxe], E[1][maxe], E[2][maxe] );
    max_spread = s[maxe];
}
Beispiel #4
0
int
build_recurse(PQP_Model *m, int bn, int first_tri, int num_tris)
{
  BV *b = m->child(bn);

  // compute a rotation matrix

  PQP_REAL C[3][3], E[3][3], R[3][3], s[3], axis[3], mean[3], coord;

#if RAPID2_FIT
  moment *tri_moment = new moment[num_tris];
  compute_moments(tri_moment, &(m->tris[first_tri]), num_tris);  
  accum acc;
  clear_accum(acc);
  for(int i = 0; i < num_tris; i++) accum_moment(acc, tri_moment[i]);
  delete [] tri_moment;
  covariance_from_accum(C,acc);
#else
  get_covariance_triverts(C,&m->tris[first_tri],num_tris);
#endif

  Meigen(E, s, C);

  // place axes of E in order of increasing s

  int min, mid, max;
  if (s[0] > s[1]) { max = 0; min = 1; }
  else { min = 0; max = 1; }
  if (s[2] < s[min]) { mid = min; min = 2; }
  else if (s[2] > s[max]) { mid = max; max = 2; }
  else { mid = 2; }
  McolcMcol(R,0,E,max);
  McolcMcol(R,1,E,mid);
  R[0][2] = E[1][max]*E[2][mid] - E[1][mid]*E[2][max];
  R[1][2] = E[0][mid]*E[2][max] - E[0][max]*E[2][mid];
  R[2][2] = E[0][max]*E[1][mid] - E[0][mid]*E[1][max];

  // fit the BV

  b->FitToTris(R, &m->tris[first_tri], num_tris);

  if (num_tris == 1)
  {
    // BV is a leaf BV - first_child will index a triangle

    b->first_child = -(first_tri + 1);
  }
  else if (num_tris > 1)
  {
    // BV not a leaf - first_child will index a BV

    b->first_child = m->num_bvs;
    m->num_bvs+=2;

    // choose splitting axis and splitting coord

    McolcV(axis,R,0);

#if RAPID2_FIT
    mean_from_accum(mean,acc);
#else
    get_centroid_triverts(mean,&m->tris[first_tri],num_tris);
#endif
    coord = VdotV(axis, mean);

    // now split

    int num_first_half = split_tris(&m->tris[first_tri], num_tris, 
                                    axis, coord);

    // recursively build the children

    build_recurse(m, m->child(bn)->first_child, first_tri, num_first_half); 
    build_recurse(m, m->child(bn)->first_child + 1,
                  first_tri + num_first_half, num_tris - num_first_half); 
  }
  return PQP_OK;
}