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 "shape.h"
00025 #include "paramset.h"
00026 #include "mc.h"
00027
00028 namespace lux
00029 {
00030
00031
00032 class WaldTriangleMesh : public Shape {
00033 public:
00034
00035 WaldTriangleMesh(const Transform &o2w, bool ro,
00036 int ntris, int nverts, const int *vptr,
00037 const Point *P, const Normal *N,
00038 const Vector *S, const float *uv);
00039 ~WaldTriangleMesh();
00040 BBox ObjectBound() const;
00041 BBox WorldBound() const;
00042 bool CanIntersect() const { return false; }
00043 void Refine(vector<boost::shared_ptr<Shape> > &refined) const;
00044 friend class WaldTriangle;
00045 template <class T> friend class VertexTexture;
00046
00047 static Shape* CreateShape(const Transform &o2w, bool reverseOrientation, const ParamSet ¶ms);
00048
00049 protected:
00050
00051 int ntris, nverts;
00052 int *vertexIndex;
00053 Point *p;
00054 Normal *n;
00055 Vector *s;
00056 float *uvs;
00057 vector<boost::shared_ptr<Shape> > triPtrs;
00058 };
00059
00060 class WaldTriangle : public Shape {
00061 public:
00062
00063 WaldTriangle(const Transform &o2w, bool ro,
00064 WaldTriangleMesh *m, int n);
00065 BBox ObjectBound() const;
00066 BBox WorldBound() const;
00067 bool Intersect(const Ray &ray, float *tHit,
00068 DifferentialGeometry *dg) const;
00069 bool IntersectP(const Ray &ray) const;
00070
00071 void GetUVs(float uv[3][2]) const {
00072 if (mesh->uvs) {
00073 uv[0][0] = mesh->uvs[2*v[0]];
00074 uv[0][1] = mesh->uvs[2*v[0]+1];
00075 uv[1][0] = mesh->uvs[2*v[1]];
00076 uv[1][1] = mesh->uvs[2*v[1]+1];
00077 uv[2][0] = mesh->uvs[2*v[2]];
00078 uv[2][1] = mesh->uvs[2*v[2]+1];
00079 } else {
00080 uv[0][0] = mesh->p[v[0]].x;
00081 uv[0][1] = mesh->p[v[0]].y;
00082 uv[1][0] = mesh->p[v[1]].x;
00083 uv[1][1] = mesh->p[v[1]].y;
00084 uv[2][0] = mesh->p[v[2]].x;
00085 uv[2][1] = mesh->p[v[2]].y;
00086 }
00087 }
00088
00089 float Area() const;
00090 virtual void GetShadingGeometry(const Transform &obj2world,
00091 const DifferentialGeometry &dg,
00092 DifferentialGeometry *dgShading) const {
00093 if (!mesh->n && !mesh->s) {
00094 *dgShading = dg;
00095 return;
00096 }
00097
00098
00099
00100 float b[3];
00101
00102 float uv[3][2];
00103 GetUVs(uv);
00104 float A[2][2] = {
00105 { uv[1][0] - uv[0][0], uv[2][0] - uv[0][0] },
00106 { uv[1][1] - uv[0][1], uv[2][1] - uv[0][1] }
00107 };
00108 float C[2] = { dg.u - uv[0][0], dg.v - uv[0][1] };
00109
00110 if (!SolveLinearSystem2x2(A, C, &b[1])) {
00111
00112 b[0] = b[1] = b[2] = 1.f/3.f;
00113 } else
00114 b[0] = 1.f - b[1] - b[2];
00115
00116
00117 Normal ns;
00118 Vector ss, ts;
00119 if (mesh->n)
00120 ns = Normalize(obj2world(b[0] * mesh->n[v[0]] +
00121 b[1] * mesh->n[v[1]] + b[2] * mesh->n[v[2]]));
00122 else
00123 ns = dg.nn;
00124 if (mesh->s)
00125 ss = Normalize(obj2world(b[0] * mesh->s[v[0]] +
00126 b[1] * mesh->s[v[1]] + b[2] * mesh->s[v[2]]));
00127 else
00128 ss = Normalize(dg.dpdu);
00129
00130 ts = Normalize(Cross(ss, ns));
00131 ss = Cross(ts, ns);
00132 Vector dndu, dndv;
00133 if (mesh->n) {
00134
00135 float uvs[3][2];
00136 GetUVs(uvs);
00137
00138
00139 float du1 = uvs[0][0] - uvs[2][0];
00140 float du2 = uvs[1][0] - uvs[2][0];
00141 float dv1 = uvs[0][1] - uvs[2][1];
00142 float dv2 = uvs[1][1] - uvs[2][1];
00143 Vector dn1 = Vector(mesh->n[v[0]] - mesh->n[v[2]]);
00144 Vector dn2 = Vector(mesh->n[v[1]] - mesh->n[v[2]]);
00145 float determinant = du1 * dv2 - dv1 * du2;
00146
00147 if (determinant == 0)
00148 dndu = dndv = Vector(0, 0, 0);
00149 else {
00150 float invdet = 1.f / determinant;
00151 dndu = ( dv2 * dn1 - dv1 * dn2) * invdet;
00152 dndv = (-du2 * dn1 + du1 * dn2) * invdet;
00153
00154 dndu = ObjectToWorld(dndu);
00155 dndv = ObjectToWorld(dndu);
00156 }
00157 } else
00158 dndu = dndv = Vector(0, 0, 0);
00159
00160 *dgShading = DifferentialGeometry(dg.p,
00161 ss, ts,
00162 dndu, dndv,
00163 dg.u, dg.v, dg.shape);
00164 dgShading->dudx = dg.dudx; dgShading->dvdx = dg.dvdx;
00165 dgShading->dudy = dg.dudy; dgShading->dvdy = dg.dvdy;
00166 dgShading->dpdx = dg.dpdx; dgShading->dpdy = dg.dpdy;
00167 }
00168
00169 Point Sample(float u1, float u2, Normal *Ns) const;
00170
00171 private:
00172
00173 WaldTriangleMesh* mesh;
00174 int *v;
00175
00176
00177 enum IntersectionType {
00178 DOMINANT_X,
00179 DOMINANT_Y,
00180 DOMINANT_Z,
00181 ORTHOGONAL_X,
00182 ORTHOGONAL_Y,
00183 ORTHOGONAL_Z,
00184 DEGENERATE
00185 };
00186
00187 IntersectionType intersectionType;
00188 float nu, nv, nd;
00189 float bnu, bnv, bnd;
00190 float cnu, cnv, cnd;
00191
00192
00193 Vector dpdu, dpdv;
00194 Normal normalizedNormal;
00195 };
00196
00197 }