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 class BaryTriangleMesh : public Shape {
00032 public:
00033
00034 BaryTriangleMesh(const Transform &o2w, bool ro,
00035 int ntris, int nverts, const int *vptr,
00036 const Point *P, const Normal *N,
00037 const Vector *S, const float *uv);
00038 ~BaryTriangleMesh();
00039 BBox ObjectBound() const;
00040 BBox WorldBound() const;
00041 bool CanIntersect() const { return false; }
00042 void Refine(vector<boost::shared_ptr<Shape> > &refined) const;
00043 friend class BaryTriangle;
00044 template <class T> friend class VertexTexture;
00045
00046 static Shape* CreateShape(const Transform &o2w, bool reverseOrientation, const ParamSet ¶ms);
00047 protected:
00048
00049 int ntris, nverts;
00050 int *vertexIndex;
00051 Point *p;
00052 Normal *n;
00053 Vector *s;
00054 float *uvs;
00055 vector<boost::shared_ptr<Shape> > triPtrs;
00056 };
00057
00058 class BaryTriangle : public Shape {
00059 public:
00060
00061 BaryTriangle(const Transform &o2w, bool ro,
00062 BaryTriangleMesh *m, int n)
00063 : Shape(o2w, ro) {
00064 mesh = m;
00065 v = &mesh->vertexIndex[3*n];
00066
00067
00068
00069 }
00070 BBox ObjectBound() const;
00071 BBox WorldBound() const;
00072 bool Intersect(const Ray &ray, float *tHit,
00073 DifferentialGeometry *dg) const;
00074 bool IntersectP(const Ray &ray) const;
00075 void GetUVs(float uv[3][2]) const;
00076 float Area() const;
00077 virtual void GetShadingGeometry(const Transform &obj2world,
00078 const DifferentialGeometry &dg,
00079 DifferentialGeometry *dgShading) const {
00080 if (!mesh->n && !mesh->s) {
00081 *dgShading = dg;
00082 return;
00083 }
00084
00085
00086
00087 float b[3];
00088
00089 float uv[3][2];
00090 GetUVs(uv);
00091 float A[2][2] = {
00092 { uv[1][0] - uv[0][0], uv[2][0] - uv[0][0] },
00093 { uv[1][1] - uv[0][1], uv[2][1] - uv[0][1] }
00094 };
00095 float C[2] = { dg.u - uv[0][0], dg.v - uv[0][1] };
00096
00097 if (!SolveLinearSystem2x2(A, C, &b[1])) {
00098
00099 b[0] = b[1] = b[2] = 1.f/3.f;
00100 } else
00101 b[0] = 1.f - b[1] - b[2];
00102
00103
00104 Normal ns;
00105 Vector ss, ts;
00106 if (mesh->n)
00107 ns = Normalize(obj2world(b[0] * mesh->n[v[0]] +
00108 b[1] * mesh->n[v[1]] + b[2] * mesh->n[v[2]]));
00109 else
00110 ns = dg.nn;
00111 if (mesh->s)
00112 ss = Normalize(obj2world(b[0] * mesh->s[v[0]] +
00113 b[1] * mesh->s[v[1]] + b[2] * mesh->s[v[2]]));
00114 else
00115 ss = Normalize(dg.dpdu);
00116
00117 ts = Normalize(Cross(ss, ns));
00118 ss = Cross(ts, ns);
00119 Vector dndu, dndv;
00120 if (mesh->n) {
00121
00122 float uvs[3][2];
00123 GetUVs(uvs);
00124
00125
00126 float du1 = uvs[0][0] - uvs[2][0];
00127 float du2 = uvs[1][0] - uvs[2][0];
00128 float dv1 = uvs[0][1] - uvs[2][1];
00129 float dv2 = uvs[1][1] - uvs[2][1];
00130 Vector dn1 = Vector(mesh->n[v[0]] - mesh->n[v[2]]);
00131 Vector dn2 = Vector(mesh->n[v[1]] - mesh->n[v[2]]);
00132 float determinant = du1 * dv2 - dv1 * du2;
00133
00134 if (determinant == 0)
00135 dndu = dndv = Vector(0, 0, 0);
00136 else {
00137 float invdet = 1.f / determinant;
00138 dndu = ( dv2 * dn1 - dv1 * dn2) * invdet;
00139 dndv = (-du2 * dn1 + du1 * dn2) * invdet;
00140 }
00141 } else
00142 dndu = dndv = Vector(0, 0, 0);
00143
00144 *dgShading = DifferentialGeometry(dg.p, ss, ts,
00145 ObjectToWorld(dndu), ObjectToWorld(dndv), dg.u, dg.v, dg.shape);
00146 dgShading->dudx = dg.dudx; dgShading->dvdx = dg.dvdx;
00147 dgShading->dudy = dg.dudy; dgShading->dvdy = dg.dvdy;
00148 dgShading->dpdx = dg.dpdx; dgShading->dpdy = dg.dpdy;
00149 }
00150 Point Sample(float u1, float u2, Normal *Ns) const;
00151 private:
00152
00153 BaryTriangleMesh* mesh;
00154 int *v;
00155 };
00156
00157 }