コード例 #1
0
static void
computeBestFitOBB(TheaArray<Vector3> const & points, Box3 & result, bool has_up, Vector3 const & up)
{
  if (points.empty())
  {
    result = Box3();
    return;
  }
  else if (points.size() == 1)
  {
    result = Box3(AxisAlignedBox3(points[0]));
    return;
  }

  Vector3 centroid;
  CoordinateFrame3 cframe;

  if (has_up)
  {
    centroid = CentroidN<Vector3, 3>::compute(points.begin(), points.end());
    Vector3 u, v;
    up.createOrthonormalBasis(u, v);
    cframe = CoordinateFrame3::_fromAffine(AffineTransform3(basisMatrix(u, v, up), centroid));
  }
  else
  {
    Plane3 plane;
    LinearLeastSquares3<Vector3>::fitPlane(points.begin(), points.end(), plane, &centroid);
    planeToCFrame(plane, centroid, cframe);
  }

  OBB best_obb;
  computeOBB(points, cframe, best_obb, true);

  Matrix3 rot = Matrix3::rotationAxisAngle((has_up ? up : Vector3::unitY()), Math::degreesToRadians(10));
  for (int a = 10;  a < 180; a += 10)
  {
    cframe._setRotation(cframe.getRotation() * rot);
    computeOBB(points, cframe, best_obb, false);
  }

  result = Box3(AxisAlignedBox3(best_obb.lo, best_obb.hi), best_obb.cframe);
}
コード例 #2
0
ファイル: bestfitobb.cpp プロジェクト: CZdravko/Horde
void computeBestFitOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *matrix)
{

  float bmin[3];
  float bmax[3];

  fm_getAABB(vcount,points,pstride,bmin,bmax);

  float center[3];

  center[0] = (bmax[0]-bmin[0])*0.5f + bmin[0];
  center[1] = (bmax[1]-bmin[1])*0.5f + bmin[1];
  center[2] = (bmax[2]-bmin[2])*0.5f + bmin[2];

  float ax = 0;
  float ay = 0;
  float az = 0;

  float sweep =  45.0f; // 180 degree sweep on all three axes.
  float steps =   8.0f; // 16 steps on each axis.

  float bestVolume = 1e9;
  float angle[3];

  while ( sweep >= 1 )
  {

    bool found = false;

    float stepsize = sweep / steps;

    for (float x=ax-sweep; x<=ax+sweep; x+=stepsize)
    {
      for (float y=ay-sweep; y<=ay+sweep; y+=stepsize)
      {
        for (float z=az-sweep; z<=az+sweep; z+=stepsize)
        {
          float pmatrix[16];

          fm_eulerMatrix( x*FM_DEG_TO_RAD, y*FM_DEG_TO_RAD, z*FM_DEG_TO_RAD, pmatrix );

          pmatrix[3*4+0] = center[0];
          pmatrix[3*4+1] = center[1];
          pmatrix[3*4+2] = center[2];

          float psides[3];

          computeOBB( vcount, points, pstride, psides, pmatrix );

          float volume = psides[0]*psides[1]*psides[2]; // the volume of the cube

          if ( volume <= bestVolume )
          {
            bestVolume = volume;

            sides[0] = psides[0];
            sides[1] = psides[1];
            sides[2] = psides[2];

            angle[0] = ax;
            angle[1] = ay;
            angle[2] = az;

            memcpy(matrix,pmatrix,sizeof(float)*16);
            found = true; // yes, we found an improvement.
          }
        }
      }
    }

    if ( found )
    {

      ax = angle[0];
      ay = angle[1];
      az = angle[2];

      sweep*=0.5f; // sweep 1/2 the distance as the last time.
    }
    else
    {
      break; // no improvement, so just
    }

  }

}