📄 sweep.cpp
字号:
/************************************************* * SWEEP.CPP * Andreas Leipelt, "Ray Tracing a Swept Sphere" * from "Graphics Gems", Academic Press * * This file contains the code to handle a swept sphere in * ray tracing */#include <math.h>#include "poly.h"#define rayeps 1E-8 // tolerance for intersection test// refer to Andrew Woo, "Fast Ray-Box Intersection",// "Graphics Gems I"extern char HitBoundingBox(double*,double*,double*,double*);// class of the swept sphere primitiveclass swept_sph { polynomial m[3]; // center of the sphere polynomial r; // radius of the sphere polynomial r2; // r2 = r*r double a, b; // the interval [a;b], where m and r live double minB[3], // lower left corner of the bounding box maxB[3]; // upper right corner of the bounding box double param; // parameter of last intersection, used for member // 'normal' public: swept_sph() {} swept_sph(polynomial*,polynomial,double,double); int intersect(double*,double*,double*); void normal(double*,double*); int inside(double*);};// constructor of the swept_sph-classswept_sph::swept_sph(polynomial *M, polynomial R, double A, double B)// M : trajectory of the center of the moving sphere.// An array of polynomials, which is interpreted as a// vector valued polynomial.// R : varying radius of the moving sphere. The radius is assumed// to be non-negative.{ for (int i=0; i < 3; i++) m[i] = M[i]; r = R; r2 = r*r; a = A; b = B; // Calculate the axis aligned bounding box for (i=0; i < 3; i++) { minB[i] = (m[i] - r).min(a, b); maxB[i] = (m[i] + r).max(a, b); }}int swept_sph::intersect(double *origin, double *dir, double *l)// origin : origin of the ray// dir : unit direction of the ray// t : intersection parameter of the ray{ polynomial p, q, dp, dq, s; double save[3]; double roots[MAX_DEGREE]; double p_val, q_val, D, test; if (!HitBoundingBox(minB, maxB, origin, dir)) return 0; // save the constant term of the trajectory for (int i=0; i < 3; i++) { save[i] = m[i].coef[0]; m[i].coef[0] -= origin[i]; } p = dir[0]*m[0] + dir[1]*m[1] + dir[2]*m[2]; q = m[0]*m[0] + m[1]*m[1] + m[2]*m[2] - r2; dp = p.derivative(); dq = q.derivative(); s = dq*dq + 4.0*dp*(dp*q - p*dq); int n = s.roots_between(a, b, roots); roots[n++] = a; roots[n] = b; *l = 1E20; // test all possible values for (i=0; i <= n; i++) { // calculate the real solutions of the equation // l = p_val +- sqrt(p_val*p_val - q_val) p_val = p.eval(roots[i]); q_val = q.eval(roots[i]); D = p_val*p_val - q_val; if (D >= 0.0) { // check, if the candidate roots[i] leads to a better // intersection value l D = sqrt(D); test = p_val - D; if (test < rayeps) test = p_val + D; if ((test >= rayeps) && (test < *l)) { param = roots[i]; *l = test; } } } // restore the constant term of the trajectory for (i=0; i < 3; i++) m[i].coef[0] = save[i]; if (*l < 1E20) return 1; else return 0;}void swept_sph::normal(double *IP, double* Nrm)// IP : intersection point// Nrm : normal at IP{ double R = r.eval(param); // if the radius is zero, return an arbitrary normal. if (R < polyeps) { Nrm[0] = Nrm[1] = 0.0; Nrm[2] = 1.0; return; } for (int i=0; i < 3; i++) Nrm[i] = (IP[i] - m[i].eval(param))/R;}// returns 1, if the point P lies inside.int swept_sph::inside(double *P){ double save[3]; int is_inside; for (int i=0; i < 3; i++) { save[i] = m[i].coef[0]; m[i].coef[0] -= P[i]; }; is_inside = ((m[0]*m[0]+m[1]*m[1]+m[2]*m[2]-r2).min(a, b) < rayeps); for (i=0; i < 3; i++) m[i].coef[0] = save[i]; return is_inside;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -