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; }