Fix T49479: Freestyle inconsistent line drawing with large geometry dimension.

Ray-plane intersection routine GeomUtils::intersectRayPlane() was used with an
unnormalized direction vector as input.
This commit is contained in:
Tamito Kajiyama 2016-12-28 18:05:28 +09:00
parent 6559ab2d51
commit 7f262acb92
Notes: blender-bot 2023-02-14 07:33:55 +01:00
Referenced by issue #49479, Freestyle inconsistent line drawing with large geometry dimension
3 changed files with 25 additions and 19 deletions

View File

@ -470,6 +470,8 @@ bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir, const Vec3r& v0,
}
// Intersection between plane and ray, adapted from Graphics Gems, Didier Badouel
// The plane is represented by a set of points P implicitly defined as dot(norm, P) + d = 0.
// The ray is represented as r(t) = orig + dir * t.
intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, const Vec3r& norm, const real d,
real& t, const real epsilon)
{

View File

@ -57,7 +57,7 @@ using namespace std;
template <typename G, typename I>
static void findOccludee(FEdge *fe, G& /*grid*/, I& occluders, real epsilon, WFace **oaWFace,
Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices)
Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edgeDir, vector<WVertex*>& faceVertices)
{
WFace *face = NULL;
if (fe->isSmooth()) {
@ -125,7 +125,7 @@ static void findOccludee(FEdge *fe, G& /*grid*/, I& occluders, real epsilon, WFa
// check whether the edge and the polygon plane are coincident:
//-------------------------------------------------------------
//first let us compute the plane equation.
if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, p->getNormal(), d, t, epsilon))
if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edgeDir, p->getNormal(), d, t, epsilon))
{
#if LOGGING
if (_global.debug & G_DEBUG_FREESTYLE) {
@ -172,10 +172,11 @@ template <typename G, typename I>
static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge * /*ve*/, WFace **oaFace)
{
Vec3r A;
Vec3r edge;
Vec3r edgeDir;
Vec3r origin;
A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0);
edge = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D());
edgeDir = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D());
edgeDir.normalize();
origin = Vec3r((fe)->vertexA()->point3D());
Vec3r u;
if (grid.orthographicProjection()) {
@ -199,7 +200,7 @@ static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge * /*ve*/, WF
}
I occluders(grid, A, epsilon);
findOccludee<G, I>(fe, grid, occluders, epsilon, oaFace, u, A, origin, edge, faceVertices);
findOccludee<G, I>(fe, grid, occluders, epsilon, oaFace, u, A, origin, edgeDir, faceVertices);
}
// computeVisibility takes a pointer to foundOccluders, instead of using a reference,
@ -211,11 +212,12 @@ static int computeVisibility(ViewMap *viewMap, FEdge *fe, G& grid, real epsilon,
int qi = 0;
Vec3r center;
Vec3r edge;
Vec3r edgeDir;
Vec3r origin;
center = fe->center3d();
edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D());
edgeDir = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D());
edgeDir.normalize();
origin = Vec3r(fe->vertexA()->point3D());
Vec3r vp;
@ -337,7 +339,7 @@ static int computeVisibility(ViewMap *viewMap, FEdge *fe, G& grid, real epsilon,
// check whether the edge and the polygon plane are coincident:
//-------------------------------------------------------------
//first let us compute the plane equation.
if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, p->getNormal(), d, t, epsilon)) {
if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edgeDir, p->getNormal(), d, t, epsilon)) {
#if LOGGING
if (_global.debug & G_DEBUG_FREESTYLE) {
cout << "\t\tRejecting occluder for target coincidence." << endl;
@ -391,7 +393,7 @@ static int computeVisibility(ViewMap *viewMap, FEdge *fe, G& grid, real epsilon,
}
// Find occludee
findOccludee<G, I>(fe, grid, occluders, epsilon, oaWFace, u, center, origin, edge, faceVertices);
findOccludee<G, I>(fe, grid, occluders, epsilon, oaWFace, u, center, origin, edgeDir, faceVertices);
return qi;
}
@ -1788,7 +1790,7 @@ void ViewMapBuilder::ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, rea
}
void ViewMapBuilder::FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp,
Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices)
Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edgeDir, vector<WVertex*>& faceVertices)
{
WFace *face = NULL;
if (fe->isSmooth()) {
@ -1856,7 +1858,7 @@ void ViewMapBuilder::FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3
continue;
}
else {
if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon))
if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edgeDir, normal, d, t, epsilon))
continue;
}
if ((*p)->rayIntersect(A, v, t, t_u, t_v)) {
@ -1883,10 +1885,11 @@ void ViewMapBuilder::FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3
OccludersSet occluders;
Vec3r A;
Vec3r edge;
Vec3r edgeDir;
Vec3r origin;
A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0);
edge = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D());
edgeDir = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D());
edgeDir.normalize();
origin = Vec3r((fe)->vertexA()->point3D());
Vec3r u;
if (_orthographicProjection) {
@ -1910,7 +1913,7 @@ void ViewMapBuilder::FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3
if (face)
face->RetrieveVertexList(faceVertices);
return FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, A, origin, edge, faceVertices);
return FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, A, origin, edgeDir, faceVertices);
}
int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real epsilon, set<ViewShape*>& oOccluders,
@ -1920,11 +1923,12 @@ int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real eps
int qi = 0;
Vec3r center;
Vec3r edge;
Vec3r edgeDir;
Vec3r origin;
center = fe->center3d();
edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D());
edgeDir = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D());
edgeDir.normalize();
origin = Vec3r(fe->vertexA()->point3D());
// Is the edge outside the view frustum ?
Vec3r gridOrigin(iGrid->getOrigin());
@ -2062,7 +2066,7 @@ int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real eps
//-------------------------------------------------------------
//first let us compute the plane equation.
if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon)) {
if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edgeDir, normal, d, t, epsilon)) {
#if LOGGING
if (_global.debug & G_DEBUG_FREESTYLE) {
cout << "\t\tRejecting occluder for target coincidence." << endl;
@ -2099,7 +2103,7 @@ int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real eps
}
// Find occludee
FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, center, origin, edge, faceVertices);
FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, center, origin, edgeDir, faceVertices);
return qi;
}

View File

@ -250,7 +250,7 @@ protected:
// FIXME
void FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp);
void FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp,
Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices);
Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edgeDir, vector<WVertex*>& faceVertices);
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMapBuilder")