00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "quad.h"
00025 #include "paramset.h"
00026 #include "dynload.h"
00027
00028 using namespace lux;
00029
00030
00031 Quad::Quad(const lux::Transform &o2w, bool ro, int nq, int nv,
00032 const int *vi, const Point *P) : Shape(o2w, ro) {
00033
00034 mesh = new QuadMesh(o2w, ro, nq, nv, vi, P);
00035 quad = new Quadrilateral(o2w, ro, mesh, &mesh->idx[0]);
00036
00037 }
00038
00039 Quad::~Quad() {
00040 delete quad;
00041 delete mesh;
00042 }
00043
00044 BBox Quad::ObjectBound() const {
00045 return quad->ObjectBound();
00046 }
00047
00048 BBox Quad::WorldBound() const {
00049 return quad->WorldBound();
00050 }
00051
00052 bool Quad::Intersect(const Ray &ray, float *tHit,
00053 DifferentialGeometry *dg) const {
00054
00055 return quad->Intersect(ray, tHit, dg);
00056 }
00057
00058 bool Quad::IntersectP(const Ray &ray) const {
00059
00060 return quad->IntersectP(ray);
00061 }
00062
00063 float Quad::Area() const {
00064
00065 return quad->Area();
00066 }
00067
00068
00069 bool IsDegenerate(const Point &p0, const Point &p1, const Point &p2, const Point &p3) {
00070
00071 Vector e0 = p1 - p0;
00072 Vector e1 = p2 - p1;
00073 Vector e2 = p3 - p2;
00074 Vector e3 = p0 - p3;
00075
00076 return (e0.Length() < 1e-6f || e1.Length() < 1e-6f ||
00077 e2.Length() < 1e-6f || e3.Length() < 1e-6f);
00078 }
00079
00080
00081
00082 bool IsPlanar(const Point &p0, const Point &p1, const Point &p2, const Point &p3) {
00083
00084
00085 Vector e0 = Normalize(p1 - p0);
00086 Vector e1 = Normalize(p3 - p0);
00087
00088 if (1.f - fabsf(Dot(e0, e1)) < 1e-6) {
00089
00090 e1 = Normalize(p2 - p0);
00091 }
00092
00093 Vector n = Normalize(Cross(e0, e1));
00094
00095
00096 float proj = fabsf(Dot(Vector(p3), n));
00097
00098
00099 return proj < 1e-6f;
00100 }
00101
00102
00103 bool IsConvex(const Point &p0, const Point &p1, const Point &p2, const Point &p3) {
00104
00105
00106 Vector b0 = Normalize(p1 - p0);
00107 Vector b1 = p3 - p0;
00108
00109 b1 = Normalize(b1 - b0 * Dot(b1, b0));
00110
00111 if (1.f - fabsf(Dot(b0, b1)) < 1e-6) {
00112
00113 b1 = p2 - p0;
00114
00115 b1 = Normalize(b1 - b0 * Dot(b1, b0));
00116 }
00117
00118
00119 Vector e[4];
00120
00121 e[0] = p1 - p0;
00122 e[1] = p2 - p1;
00123 e[2] = p3 - p2;
00124 e[3] = p0 - p3;
00125
00126
00127 for (int i = 0; i < 4; i++)
00128 e[i] = Vector(Dot(e[i], b0), Dot(e[i], b1), 0);
00129
00130
00131
00132 int altCount = 0;
00133 int curd, prevd;
00134
00135
00136
00137
00138 curd = 1;
00139 for (int i = 1; i <= 4; i++) {
00140 prevd = curd;
00141
00142
00143 curd = (e[i & 3].x < 1e-6) ? (e[i & 3].x > -1e-6f ? prevd : -1) : 1;
00144 altCount += prevd != curd ? 1 : 0;
00145 }
00146
00147 if (altCount != 2)
00148 return false;
00149
00150
00151
00152
00153 int curs, prevs;
00154 altCount = 0;
00155
00156 curs = (Cross(e[1], e[0]).z < 0) ? -1 : 1;
00157 for (int i = 1; i < 4; i++) {
00158 prevs = curs;
00159 curs = (Cross(e[(i + 1) & 3], e[i]).z < 0) ? -1 : 1;
00160 altCount += prevs != curs ? 1 : 0;
00161 }
00162
00163 return altCount == 0;
00164 }
00165
00166 Shape* Quad::CreateShape(const Transform &o2w,
00167 bool reverseOrientation, const ParamSet ¶ms) {
00168
00169 int np = 0;
00170 const Point *P = params.FindPoint("P", &np);
00171
00172 if (P == NULL) {
00173 float hw = params.FindOneFloat("width", 1.f) / 2.f;
00174 float hh = params.FindOneFloat("height", 1.f) / 2.f;
00175
00176 Point p[4];
00177
00178 p[0] = Point(-hw, -hh, 0.f);
00179 p[1] = Point( hw, -hh, 0.f);
00180 p[2] = Point( hw, hh, 0.f);
00181 p[3] = Point(-hw, hh, 0.f);
00182
00183 P = p;
00184 }
00185 else if (np != 4) {
00186 std::stringstream ss;
00187 ss<<"Number of vertices for quad must be 4";
00188 luxError(LUX_CONSISTENCY,LUX_ERROR,ss.str().c_str());
00189 return NULL;
00190 }
00191
00192 const Point &p0 = P[0];
00193 const Point &p1 = P[1];
00194 const Point &p2 = P[2];
00195 const Point &p3 = P[3];
00196
00197 if (IsDegenerate(p0, p1, p2, p3)) {
00198 std::stringstream ss;
00199 ss<<"Degenerate quad detected";
00200 luxError(LUX_CONSISTENCY,LUX_ERROR,ss.str().c_str());
00201 return NULL;
00202 }
00203
00204 if (!IsPlanar(p0, p1, p2, p3)) {
00205 std::stringstream ss;
00206 ss<<"Non-planar quad detected";
00207 luxError(LUX_CONSISTENCY,LUX_ERROR,ss.str().c_str());
00208 return NULL;
00209 }
00210
00211 if (!IsConvex(p0, p1, p2, p3)) {
00212 std::stringstream ss;
00213 ss<<"Non-convex quad detected";
00214 luxError(LUX_CONSISTENCY,LUX_ERROR,ss.str().c_str());
00215 return NULL;
00216 }
00217
00218 int vi[4];
00219 for (int i = 0; i < 4; i++)
00220 vi[i] = i;
00221
00222 return new Quad(o2w, reverseOrientation, 1, 4, vi, P);
00223 }
00224
00225 static DynamicLoader::RegisterShape<Quad> r("quad");