This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/freestyle/intern/geometry/GeomUtils.cpp
Tamito Kajiyama 4569f9ae4e Optimized view map calculation by Alexander Beels.
* View map calculation has been intensively optimized for speed by
means of:

1) new spatial grid data structures (SphericalGrid for perspective
cameras and BoxGrid for orthographic cameras; automatically switched
based on the camera type);

2) a heuristic grid density calculation algorithm; and

3) new line visibility computation algorithms: A "traditional"
algorithm for emulating old visibility algorithms, and a "cumulative"
algorithm for improved, more consistent line visibility, both exploiting
the new spatial grid data structures for fast ray casting.

A new option "Raycasting Algorithm" was added to allow users to choose
a ray casting (line visibility) algorithm.  Available choices are:

- Normal Ray Casting
- Fast Ray Casting
- Very Fast Ray Casting
- Culled Traditional Visibility Detection
- Unculled Traditional Visibility Detection
- Culled Cumulative Visibility Detection
- Unculled Cumulative Visibility Detection

The first three algorithms are those available in the original
Freestyle (the "normal" ray casting was used unconditionally, though).
The "fast" and "very fast" ray casting algorithms achieve a faster
calculation at the cost of less visibility accuracy.

The last four are newly introduced optimized options.  The culled
versions of the new algorithms will exclude from visibility
calculation those faces that lay outside the camera, which leads to a
faster view map construction.  The unculled counterparts will take all
faces into account.  The unculled visibility algorithms are useful
when culling affects stroke chaining.

The recommended options for users are the culled/unculled cumulative
visibility algorithms.  These options are meant to replace the old
algorithms in the future.

Performance improvements over the old algorithms depend on the scenes
to be rendered.

* Silhouette detection has also been considerably optimized for speed.

Performance gains by this optimization do not depend on scenes.

* Improper handling of error conditions in the view map construction
was fixed.
2011-03-14 00:36:27 +00:00

754 lines
22 KiB
C++
Executable File

//
// Copyright (C) : Please refer to the COPYRIGHT file distributed
// with this source distribution.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
///////////////////////////////////////////////////////////////////////////////
#include "GeomUtils.h"
namespace GeomUtils {
// This internal procedure is defined below.
bool intersect2dSegPoly(Vec2r* seg,
Vec2r* poly,
unsigned n);
bool intersect2dSeg2dArea(const Vec2r& min,
const Vec2r& max,
const Vec2r& A,
const Vec2r& B) {
Vec2r seg[2];
seg[0] = A;
seg[1] = B;
Vec2r poly[5];
poly[0][0] = min[0];
poly[0][1] = min[1];
poly[1][0] = max[0];
poly[1][1] = min[1];
poly[2][0] = max[0];
poly[2][1] = max[1];
poly[3][0] = min[0];
poly[3][1] = max[1];
poly[4][0] = min[0];
poly[4][1] = min[1];
return intersect2dSegPoly(seg, poly, 4);
}
bool include2dSeg2dArea(const Vec2r& min,
const Vec2r& max,
const Vec2r& A,
const Vec2r& B) {
if((((max[0] > A[0])&&(A[0] > min[0]))&&((max[0] > B[0])&&(B[0] > min[0])))
&& (((max[1] > A[1])&&(A[1] > min[1]))&&((max[1] > B[1])&&(B[1] > min[1]))))
return true;
return false;
}
intersection_test intersect2dSeg2dSeg(const Vec2r& p1,
const Vec2r& p2,
const Vec2r& p3,
const Vec2r& p4,
Vec2r& res) {
real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
real r1, r2, r3, r4; // 'Sign' values
real denom, num; // Intermediate values
// Compute a1, b1, c1, where line joining points p1 and p2
// is "a1 x + b1 y + c1 = 0".
a1 = p2[1] - p1[1];
b1 = p1[0] - p2[0];
c1 = p2[0] * p1[1] - p1[0] * p2[1];
// Compute r3 and r4.
r3 = a1 * p3[0] + b1 * p3[1] + c1;
r4 = a1 * p4[0] + b1 * p4[1] + c1;
// Check signs of r3 and r4. If both point 3 and point 4 lie on
// same side of line 1, the line segments do not intersect.
if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
return (DONT_INTERSECT);
// Compute a2, b2, c2
a2 = p4[1] - p3[1];
b2 = p3[0] - p4[0];
c2 = p4[0] * p3[1] - p3[0] * p4[1];
// Compute r1 and r2
r1 = a2 * p1[0] + b2 * p1[1] + c2;
r2 = a2 * p2[0] + b2 * p2[1] + c2;
// Check signs of r1 and r2. If both point 1 and point 2 lie
// on same side of second line segment, the line segments do
// not intersect.
if ( r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
return (DONT_INTERSECT);
// Line segments intersect: compute intersection point.
denom = a1 * b2 - a2 * b1;
if (fabs(denom) < M_EPSILON)
return (COLINEAR);
num = b1 * c2 - b2 * c1;
res[0] = num / denom;
num = a2 * c1 - a1 * c2;
res[1] = num / denom;
return (DO_INTERSECT);
}
intersection_test intersect2dLine2dLine(const Vec2r& p1,
const Vec2r& p2,
const Vec2r& p3,
const Vec2r& p4,
Vec2r& res) {
real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
real denom, num; // Intermediate values
// Compute a1, b1, c1, where line joining points p1 and p2
// is "a1 x + b1 y + c1 = 0".
a1 = p2[1] - p1[1];
b1 = p1[0] - p2[0];
c1 = p2[0] * p1[1] - p1[0] * p2[1];
// Compute a2, b2, c2
a2 = p4[1] - p3[1];
b2 = p3[0] - p4[0];
c2 = p4[0] * p3[1] - p3[0] * p4[1];
// Line segments intersect: compute intersection point.
denom = a1 * b2 - a2 * b1;
if (fabs(denom) < M_EPSILON)
return (COLINEAR);
num = b1 * c2 - b2 * c1;
res[0] = num / denom;
num = a2 * c1 - a1 * c2;
res[1] = num / denom;
return (DO_INTERSECT);
}
intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1,
const Vec2r& p2,
const Vec2r& p3,
const Vec2r& p4,
real& t,
real& u,
real epsilon) {
real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
real r1, r2, r3, r4; // 'Sign' values
real denom, num; // Intermediate values
// Compute a1, b1, c1, where line joining points p1 and p2
// is "a1 x + b1 y + c1 = 0".
a1 = p2[1] - p1[1];
b1 = p1[0] - p2[0];
c1 = p2[0] * p1[1] - p1[0] * p2[1];
// Compute r3 and r4.
r3 = a1 * p3[0] + b1 * p3[1] + c1;
r4 = a1 * p4[0] + b1 * p4[1] + c1;
// Check signs of r3 and r4. If both point 3 and point 4 lie on
// same side of line 1, the line segments do not intersect.
if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
return (DONT_INTERSECT);
// Compute a2, b2, c2
a2 = p4[1] - p3[1];
b2 = p3[0] - p4[0];
c2 = p4[0] * p3[1] - p3[0] * p4[1];
// Compute r1 and r2
r1 = a2 * p1[0] + b2 * p1[1] + c2;
r2 = a2 * p2[0] + b2 * p2[1] + c2;
// Check signs of r1 and r2. If both point 1 and point 2 lie
// on same side of second line segment, the line segments do
// not intersect.
if ( r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
return (DONT_INTERSECT);
// Line segments intersect: compute intersection point.
denom = a1 * b2 - a2 * b1;
if (fabs(denom) < epsilon)
return (COLINEAR);
real d1, d2, e1;
d1 = p1[1] - p3[1];
d2 = p2[1] - p1[1];
e1 = p1[0] - p3[0];
num = -b2 * d1 - a2 * e1;
t = num / denom;
num = -b1 * d1 - a1 * e1;
u = num / denom;
return (DO_INTERSECT);
}
// AABB-triangle overlap test code
// by Tomas Akenine-Möller
// Function: int triBoxOverlap(real boxcenter[3],
// real boxhalfsize[3],real triverts[3][3]);
// History:
// 2001-03-05: released the code in its first version
// 2001-06-18: changed the order of the tests, faster
//
// Acknowledgement: Many thanks to Pierre Terdiman for
// suggestions and discussions on how to optimize code.
// Thanks to David Hunt for finding a ">="-bug!
#define X 0
#define Y 1
#define Z 2
#define FINDMINMAX(x0, x1, x2, min, max) \
min = max = x0; \
if(x1<min) min=x1; \
if(x1>max) max=x1; \
if(x2<min) min=x2; \
if(x2>max) max=x2;
//======================== X-tests ========================//
#define AXISTEST_X01(a, b, fa, fb) \
p0 = a*v0[Y] - b*v0[Z]; \
p2 = a*v2[Y] - b*v2[Z]; \
if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
if(min>rad || max<-rad) return 0;
#define AXISTEST_X2(a, b, fa, fb) \
p0 = a*v0[Y] - b*v0[Z]; \
p1 = a*v1[Y] - b*v1[Z]; \
if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
if(min>rad || max<-rad) return 0;
//======================== Y-tests ========================//
#define AXISTEST_Y02(a, b, fa, fb) \
p0 = -a*v0[X] + b*v0[Z]; \
p2 = -a*v2[X] + b*v2[Z]; \
if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
if(min>rad || max<-rad) return 0;
#define AXISTEST_Y1(a, b, fa, fb) \
p0 = -a*v0[X] + b*v0[Z]; \
p1 = -a*v1[X] + b*v1[Z]; \
if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
if(min>rad || max<-rad) return 0;
//======================== Z-tests ========================//
#define AXISTEST_Z12(a, b, fa, fb) \
p1 = a*v1[X] - b*v1[Y]; \
p2 = a*v2[X] - b*v2[Y]; \
if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \
rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
if(min>rad || max<-rad) return 0;
#define AXISTEST_Z0(a, b, fa, fb) \
p0 = a*v0[X] - b*v0[Y]; \
p1 = a*v1[X] - b*v1[Y]; \
if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
if(min>rad || max<-rad) return 0;
// This internal procedure is defined below.
bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox);
// Use separating axis theorem to test overlap between triangle and box
// need to test for overlap in these directions:
// 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
// we do not even need to test these)
// 2) normal of the triangle
// 3) crossproduct(edge from tri, {x,y,z}-directin)
// this gives 3x3=9 more tests
bool overlapTriangleBox(Vec3r& boxcenter,
Vec3r& boxhalfsize,
Vec3r triverts[3]) {
Vec3r v0, v1, v2, normal, e0, e1, e2;
real min, max, d, p0, p1, p2, rad, fex, fey, fez;
// This is the fastest branch on Sun
// move everything so that the boxcenter is in (0, 0, 0)
v0 = triverts[0] - boxcenter;
v1 = triverts[1] - boxcenter;
v2 = triverts[2] - boxcenter;
// compute triangle edges
e0 = v1 - v0;
e1 = v2 - v1;
e2 = v0 - v2;
// Bullet 3:
// Do the 9 tests first (this was faster)
fex = fabs(e0[X]);
fey = fabs(e0[Y]);
fez = fabs(e0[Z]);
AXISTEST_X01(e0[Z], e0[Y], fez, fey);
AXISTEST_Y02(e0[Z], e0[X], fez, fex);
AXISTEST_Z12(e0[Y], e0[X], fey, fex);
fex = fabs(e1[X]);
fey = fabs(e1[Y]);
fez = fabs(e1[Z]);
AXISTEST_X01(e1[Z], e1[Y], fez, fey);
AXISTEST_Y02(e1[Z], e1[X], fez, fex);
AXISTEST_Z0(e1[Y], e1[X], fey, fex);
fex = fabs(e2[X]);
fey = fabs(e2[Y]);
fez = fabs(e2[Z]);
AXISTEST_X2(e2[Z], e2[Y], fez, fey);
AXISTEST_Y1(e2[Z], e2[X], fez, fex);
AXISTEST_Z12(e2[Y], e2[X], fey, fex);
// Bullet 1:
// first test overlap in the {x,y,z}-directions
// find min, max of the triangle each direction, and test for overlap in
// that direction -- this is equivalent to testing a minimal AABB around
// the triangle against the AABB
// test in X-direction
FINDMINMAX(v0[X], v1[X], v2[X], min, max);
if (min > boxhalfsize[X] || max < -boxhalfsize[X])
return false;
// test in Y-direction
FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
if (min > boxhalfsize[Y] || max < -boxhalfsize[Y])
return false;
// test in Z-direction
FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
if(min > boxhalfsize[Z] || max < -boxhalfsize[Z])
return false;
// Bullet 2:
// test if the box intersects the plane of the triangle
// compute plane equation of triangle: normal * x + d = 0
normal = e0 ^ e1;
d = -(normal * v0); // plane eq: normal.x + d = 0
if (!overlapPlaneBox(normal, d, boxhalfsize))
return false;
return true; // box and triangle overlaps
}
// Fast, Minimum Storage Ray-Triangle Intersection
//
// Tomas Möller
// Prosolvia Clarus AB
// Sweden
// tompa@clarus.se
//
// Ben Trumbore
// Cornell University
// Ithaca, New York
// wbt@graphics.cornell.edu
bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir,
const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
real& t, real& u, real& v, const real epsilon) {
Vec3r edge1, edge2, tvec, pvec, qvec;
real det, inv_det;
// find vectors for two edges sharing v0
edge1 = v1 - v0;
edge2 = v2 - v0;
// begin calculating determinant - also used to calculate U parameter
pvec = dir ^ edge2;
// if determinant is near zero, ray lies in plane of triangle
det = edge1 * pvec;
// calculate distance from v0 to ray origin
tvec = orig - v0;
inv_det = 1.0 / det;
qvec = tvec ^ edge1;
if (det > epsilon) {
u = tvec * pvec;
if (u < 0.0 || u > det)
return false;
// calculate V parameter and test bounds
v = dir * qvec;
if (v < 0.0 || u + v > det)
return false;
}
else if(det < -epsilon) {
// calculate U parameter and test bounds
u = tvec * pvec;
if (u > 0.0 || u < det)
return false;
// calculate V parameter and test bounds
v = dir * qvec;
if (v > 0.0 || u + v < det)
return false;
}
else
return false; // ray is parallell to the plane of the triangle
u *= inv_det;
v *= inv_det;
t = (edge2 * qvec) * inv_det;
return true;
}
// Intersection between plane and ray, adapted from Graphics Gems, Didier Badouel
intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir,
const Vec3r& norm, const real d,
real& t,
const real epsilon) {
real denom = norm * dir;
if(fabs(denom) <= epsilon) { // plane and ray are parallel
if(fabs((norm * orig) + d) <= epsilon)
return COINCIDENT; // plane and ray are coincident
else
return COLINEAR;
}
t = -(d + (norm * orig)) / denom;
if (t < 0.0f)
return DONT_INTERSECT;
return DO_INTERSECT;
}
bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
real t0, real t1,
real& tmin, real& tmax, // I0=orig+tmin*dir is the first intersection, I1=orig+tmax*dir is the second intersection
real epsilon){
float tymin, tymax, tzmin, tzmax;
Vec3r inv_direction(1.0/dir[0], 1.0/dir[1], 1.0/dir[2]);
int sign[3];
sign[0] = (inv_direction.x() < 0);
sign[1] = (inv_direction.y() < 0);
sign[2] = (inv_direction.z() < 0);
Vec3r bounds[2];
bounds[0] = boxMin;
bounds[1] = boxMax;
tmin = (bounds[sign[0]].x() - orig.x()) * inv_direction.x();
tmax = (bounds[1-sign[0]].x() - orig.x()) * inv_direction.x();
tymin = (bounds[sign[1]].y() - orig.y()) * inv_direction.y();
tymax = (bounds[1-sign[1]].y() - orig.y()) * inv_direction.y();
if ( (tmin > tymax) || (tymin > tmax) )
return false;
if (tymin > tmin)
tmin = tymin;
if (tymax < tmax)
tmax = tymax;
tzmin = (bounds[sign[2]].z() - orig.z()) * inv_direction.z();
tzmax = (bounds[1-sign[2]].z() - orig.z()) * inv_direction.z();
if ( (tmin > tzmax) || (tzmin > tmax) )
return false;
if (tzmin > tmin)
tmin = tzmin;
if (tzmax < tmax)
tmax = tzmax;
return ( (tmin < t1) && (tmax > t0) );
}
// Checks whether 3D points p lies inside or outside of the triangle ABC
bool includePointTriangle(const Vec3r& P,
const Vec3r& A,
const Vec3r& B,
const Vec3r& C) {
Vec3r AB(B - A);
Vec3r BC(C - B);
Vec3r CA(A - C);
Vec3r AP(P - A);
Vec3r BP(P - B);
Vec3r CP(P - C);
Vec3r N(AB ^ BC); // triangle's normal
N.normalize();
Vec3r J(AB ^ AP), K(BC ^ BP), L(CA ^ CP);
J.normalize();
K.normalize();
L.normalize();
if(J * N < 0)
return false; // on the right of AB
if(K * N < 0)
return false; // on the right of BC
if(L * N < 0)
return false; // on the right of CA
return true;
}
void transformVertex(const Vec3r& vert,
const Matrix44r& matrix,
Vec3r& res) {
HVec3r hvert(vert), res_tmp;
real scale;
for (unsigned j = 0; j < 4; j++) {
scale = hvert[j];
for (unsigned i = 0; i < 4; i++)
res_tmp[i] += matrix(i, j) * scale;
}
res[0] = res_tmp.x();
res[1] = res_tmp.y();
res[2] = res_tmp.z();
}
void transformVertices(const vector<Vec3r>& vertices,
const Matrix44r& trans,
vector<Vec3r>& res) {
for (vector<Vec3r>::const_iterator v = vertices.begin();
v != vertices.end();
v++) {
Vec3r *res_tmp = new Vec3r;
transformVertex(*v, trans, *res_tmp);
res.push_back(*res_tmp);
}
}
Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v) {
Vec3r res;
for (unsigned i = 0; i < 3; i++) {
res[i] = 0;
for (unsigned j = 0; j < 3; j++)
res[i] += mat(i, j) * v[j];
}
res.normalize();
return res;
}
// This internal procedure is defined below.
void fromCoordAToCoordB(const Vec3r& p,
Vec3r& q,
const real transform[4][4]);
void fromWorldToCamera(const Vec3r& p,
Vec3r& q,
const real model_view_matrix[4][4]) {
fromCoordAToCoordB(p, q, model_view_matrix);
}
void fromCameraToRetina(const Vec3r& p,
Vec3r& q,
const real projection_matrix[4][4]) {
fromCoordAToCoordB(p, q, projection_matrix);
}
void fromRetinaToImage(const Vec3r& p,
Vec3r& q,
const int viewport[4]) {
// winX:
q[0] = viewport[0] + viewport[2] * (p[0] + 1.0) / 2.0;
// winY:
q[1] = viewport[1] + viewport[3] * (p[1] + 1.0) / 2.0;
// winZ:
q[2] = (p[2] + 1.0) / 2.0;
}
void fromWorldToImage(const Vec3r& p,
Vec3r& q,
const real model_view_matrix[4][4],
const real projection_matrix[4][4],
const int viewport[4]) {
Vec3r p1, p2;
fromWorldToCamera(p, p1, model_view_matrix);
fromCameraToRetina(p1, p2, projection_matrix);
fromRetinaToImage(p2, q, viewport);
q[2] = p1[2];
}
void fromWorldToImage(const Vec3r& p,
Vec3r& q,
const real transform[4][4],
const int viewport[4]) {
fromCoordAToCoordB(p, q, transform);
// winX:
q[0] = viewport[0] + viewport[2] * (q[0] + 1.0) / 2.0;
//winY:
q[1] = viewport[1] + viewport[3] * (q[1] + 1.0) / 2.0;
}
void fromImageToRetina(const Vec3r& p,
Vec3r& q,
const int viewport[4]) {
q = p;
q[0] = 2.0 * (q[0] - viewport[0]) / viewport[2] - 1;
q[1] = 2.0 * (q[1] - viewport[1]) / viewport[3] - 1;
}
void fromRetinaToCamera(const Vec3r& p,
Vec3r& q,
real focal,
const real projection_matrix[4][4]) {
if( projection_matrix[3][3] == 0.0 ) // perspective
{
q[0] = (-p[0] * focal) / projection_matrix[0][0];
q[1] = (-p[1] * focal) / projection_matrix[1][1];
q[2] = focal;
}
else // orthogonal
{
q[0] = p[0] / projection_matrix[0][0];
q[1] = p[1] / projection_matrix[1][1];
q[2] = focal;
}
}
void fromCameraToWorld(const Vec3r& p,
Vec3r& q,
const real model_view_matrix[4][4]) {
real translation[3] = { model_view_matrix[0][3],
model_view_matrix[1][3],
model_view_matrix[2][3] };
for (unsigned i = 0; i < 3; i++) {
q[i] = 0.0;
for (unsigned short j = 0; j < 3; j++)
q[i] += model_view_matrix[j][i] * (p[j] - translation[j]);
}
}
//
// Internal code
//
/////////////////////////////////////////////////////////////////////////////
// Copyright 2001, softSurfer (www.softsurfer.com)
// This code may be freely used and modified for any purpose
// providing that this copyright notice is included with it.
// SoftSurfer makes no warranty for this code, and cannot be held
// liable for any real or imagined damage resulting from its use.
// Users of this code must verify correctness for their application.
#define perp(u,v) ((u)[0] * (v)[1] - (u)[1] * (v)[0]) // 2D perp product
inline bool intersect2dSegPoly(Vec2r* seg,
Vec2r* poly,
unsigned n) {
if (seg[0] == seg[1])
return false;
real tE = 0; // the maximum entering segment parameter
real tL = 1; // the minimum leaving segment parameter
real t, N, D; // intersect parameter t = N / D
Vec2r dseg; // the segment direction vector
dseg = seg[1] - seg[0];
Vec2r e; // edge vector
for (unsigned i = 0; i < n; i++) { // process polygon edge poly[i]poly[i+1]
e = poly[i+1] - poly[i];
N = perp(e, seg[0] - poly[i]);
D = -perp(e, dseg);
if (fabs(D) < M_EPSILON) {
if (N < 0)
return false;
else
continue;
}
t = N / D;
if (D < 0) { // segment seg is entering across this edge
if (t > tE) { // new max tE
tE = t;
if (tE > tL) // seg enters after leaving polygon
return false;
}
}
else { // segment seg is leaving across this edge
if (t < tL) { // new min tL
tL = t;
if (tL < tE) // seg leaves before entering polygon
return false;
}
}
}
// tE <= tL implies that there is a valid intersection subsegment
return true;
}
inline bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox) {
Vec3r vmin, vmax;
for(unsigned q = X; q <= Z; q++) {
if(normal[q] > 0.0f) {
vmin[q] = -maxbox[q];
vmax[q] = maxbox[q];
}
else {
vmin[q] = maxbox[q];
vmax[q] = -maxbox[q];
}
}
if((normal * vmin) + d > 0.0f)
return false;
if((normal * vmax) + d >= 0.0f)
return true;
return false;
}
inline void fromCoordAToCoordB(const Vec3r&p,
Vec3r& q,
const real transform[4][4]) {
HVec3r hp(p);
HVec3r hq(0, 0, 0, 0);
for (unsigned i = 0; i < 4; i++)
for (unsigned j = 0; j < 4; j++)
hq[i] += transform[i][j] * hp[j];
if(hq[3] == 0) {
q = p;
return;
}
for (unsigned k = 0; k < 3; k++)
q[k] = hq[k] / hq[3];
}
} // end of namespace GeomUtils