Пример #1
0
std::set<const Model*> UniformGrid::getModels(const Ray& ray) const {
  std::set<const Model*> models;

  Point3D nextT(0, 0, 0);

  // The point *within* the grid where the ray first intersected it
  Point3D rayStartPoint(0, 0, 0);

  if (!inGrid(ray.start)) {
    const auto& sp = startPoint;
    // Not in the grid: We will use a cube the sz of whole grid to find
    // the point of entry into the grid
    auto gridCubeInverse = (translationMatrix(sp[0], sp[0], sp[0]) *
                           gridSizeScaleMatrix).invert();
    HitRecord hr;
    if (!utilityCube.intersects(ray, &hr, gridCubeInverse)) {
      // Does not intersect the grid even
      return models;
    }
    nextT[0] = hr.t;
    nextT[1] = hr.t;
    nextT[2] = hr.t;
    rayStartPoint = ray.at(hr.t);
  }
  else {
    rayStartPoint = ray.start;
  }

  // Place in the grid we are currently stepping through
  CellCoord gridCoord = coordAt(rayStartPoint);

  Vector3D dir(
      std::abs(ray.dir[0]), std::abs(ray.dir[1]), std::abs(ray.dir[2]));

  // These values are in units of t: how far we must go to travel a whole cell
  Vector3D dt(
    isZero(dir[0]) ? 0 : cellSize / dir[0],
    isZero(dir[1]) ? 0 : cellSize / dir[1],
    isZero(dir[2]) ? 0 : cellSize / dir[2]
  );
  {
    // The bottom left corner of the cell we are starting in
    Point3D gsp = pointAt(gridCoord); // "Grid start point"

    // Determine how far, in units of t, we have to go in any direction
    // to reach the next cell
    // If we are going "forwards" in a coordinate then we need to travel to
    // gsp + cellSize. If we are going "backwards" in a coordinate then we need
    // to travel to only gsp.
    for (int i = 0; i < 3; ++i) {
      if (isZero(dir[i])) {
        nextT[i] = -1;
        continue;
      }
      if (ray.dir[i] < 0) {
        nextT[i] += (rayStartPoint[i] - gsp[i]) / dir[i];
      }
      else {
        nextT[i] += (gsp[i] + cellSize - rayStartPoint[i]) / dir[i];
      }
    }
  }

  // Which direction in the grid to move when we hit a "next" value
  CellCoord incs(
    (ray.dir[0] > 0) ? 1 : -1,
    (ray.dir[1] > 0) ? 1 : -1,
    (ray.dir[2] > 0) ? 1 : -1
  );

  // Check if a coord is still valid
  auto coordOk = [&] (int coord) -> bool {
    return 0 <= coord && coord < sideLength;
  };
  auto smaller = [] (double a, double b) -> bool {
    return (b < 0) || a <= b;
  };

  while (coordOk(gridCoord.x) && coordOk(gridCoord.y) && coordOk(gridCoord.z)) {
    for (const Model* model : cells[indexFor(gridCoord)].models) {
      models.insert(model);
    }

    for (int i = 0; i < 3; ++i) {
      if (nextT[i] < 0) continue;
      const auto a = nextT[(i + 1) % 3];
      const auto b = nextT[(i + 2) % 3];
      if (smaller(nextT[i], a) && smaller(nextT[i], b)) {
        nextT[i] += dt[i];
        gridCoord[i] += incs[i];
        break;
      }
    }
  }

  return models;
}
DCEL DivideAndConquerFor3DCH::BruceForceCH( vector<VERTEX*>* pVertex, const unsigned int offset )
{
    vector<TRIANGLE> triangleSet, finalTriangleSet;

    // Generate all possible triangles
    int pointSetSize = pVertex->size();
    for( int i = 0; i < pointSetSize; i++ )
    {
        for( int j = i + 1; j < pointSetSize; j++ )
        {
            for( int k = j + 1; k < pointSetSize; k++ )
            {
                // Forming face
                TRIANGLE face;
                face.p1.pointOneIndex = i;
                face.p2.pointTwoIndex = j;
                face.p3.pointThreeIndex = k;
                triangleSet.push_back( face );
            }
        }
    }

    // Find the CH for this point set by using RayAndTriangleIntersection method
    for( int i = 0; i < triangleSet.size(); i++ )
    {
        // Create a ray from this surface
        TRIANGLE triangle = triangleSet[ i ];
        // Point2 - point1
        //D3DXVECTOR3 edge1( triangle.pointTwo.x - triangle.pointOne.x, triangle.pointTwo.y - triangle.pointOne.y, triangle.pointTwo.z - triangle.pointOne.z );
        VERTEX* pointOne = (*pVertex)[ triangle.p1.pointOneIndex ];
        VERTEX* pointTwo = (*pVertex)[ triangle.p2.pointTwoIndex ];
        VERTEX* pointThree = (*pVertex)[ triangle.p3.pointThreeIndex ];

        D3DXVECTOR3 edge1( pointTwo->x - pointOne->x, pointTwo->y - pointOne->y, pointTwo->z - pointOne->z );
        D3DXVECTOR3 edge2( pointThree->x - pointOne->x, pointThree->y - pointOne->y, pointThree->z - pointOne->z );
        // point3 - point1
        //D3DXVECTOR3 edge2( triangle.pointThree.x - triangle.pointOne.x, triangle.pointThree.y - triangle.pointOne.y, triangle.pointThree.z - triangle.pointOne.z );

        D3DXVECTOR3 triangleNormal;
        D3DXVec3Cross( &triangleNormal, &edge1, &edge2 );
        D3DXVECTOR3 rayStartPoint( ( pointOne->x + pointTwo->x + pointThree->x ) / 3.0f,
                                   ( pointOne->y + pointTwo->y + pointThree->y ) / 3.0f,
                                   ( pointOne->z + pointTwo->z + pointThree->z ) / 3.0f );

        Ray ray, invRay;
        D3DXVec3Normalize( &ray.direction, &triangleNormal );
        ray.position = rayStartPoint;
        invRay = ray;
        invRay.direction *= -1.0;


        bool rayIntersect = !isNormal(ray, triangleSet[i], pVertex);
        bool invRayIntersect = !isNormal(invRay, triangleSet[i], pVertex);

        // This is the face that contribute to the convex hull and find its vertices order
        if( rayIntersect == false && invRayIntersect == true )
        {
            finalTriangleSet.push_back( triangleSet[ i ] );
        }
        else if( rayIntersect == true && invRayIntersect == false )
        {
            TRIANGLE tmpTri = triangleSet[ i ];
            int tmpVerIndex = tmpTri.p2.pointTwoIndex;
            tmpTri.p2.pointTwoIndex = tmpTri.p3.pointThreeIndex;
            tmpTri.p3.pointThreeIndex = tmpVerIndex;

            finalTriangleSet.push_back( tmpTri );
        }
    }

    DCEL dcel;
    dcel.createDCEL( &finalTriangleSet, pVertex, offset );

    return dcel;
}