00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "shape.h"
00024 #include "paramset.h"
00025
00026 namespace lux
00027 {
00028
00029 class Mesh : public Shape {
00030 public:
00031 enum MeshTriangleType { TRI_WALD, TRI_BARY, TRI_AUTO };
00032 enum MeshQuadType { QUAD_QUADRILATERAL };
00033 enum MeshAccelType { ACCEL_KDTREE, ACCEL_QBVH, ACCEL_NONE, ACCEL_GRID, ACCEL_BRUTEFORCE, ACCEL_AUTO };
00034 enum MeshSubdivType { SUBDIV_LOOP };
00035
00036 Mesh(const Transform &o2w, bool ro,
00037 MeshAccelType acceltype,
00038 int nv, const Point *P, const Normal *N, const float *UV,
00039 MeshTriangleType tritype, int trisCount, const int *tris,
00040 MeshQuadType quadtype, int nquadsCount, const int *quads,
00041 MeshSubdivType subdivType, int nsubdivlevels,
00042 boost::shared_ptr<Texture<float> > displacementMap,
00043 float displacementMapScale, float displacementMapOffset,
00044 bool displacementMapNormalSmooth, bool displacementMapSharpBoundary);
00045 virtual ~Mesh();
00046
00047 virtual BBox ObjectBound() const;
00048 virtual BBox WorldBound() const;
00049 virtual bool CanIntersect() const { return false; }
00050 virtual void Refine(vector<boost::shared_ptr<Primitive> > &refined,
00051 const PrimitiveRefinementHints &refineHints,
00052 boost::shared_ptr<Primitive> thisPtr);
00053 virtual bool CanSample() const { return false; }
00054
00055 friend class MeshWaldTriangle;
00056 friend class MeshBaryTriangle;
00057 friend class MeshQuadrilateral;
00058
00059 static Shape* CreateShape(const Transform &o2w, bool reverseOrientation, const ParamSet ¶ms);
00060
00061 class BaryMesh {
00062 public:
00063 static Shape* CreateShape(const Transform &o2w, bool reverseOrientation, const ParamSet ¶ms);
00064 };
00065
00066 class WaldMesh {
00067 public:
00068 static Shape* CreateShape(const Transform &o2w, bool reverseOrientation, const ParamSet ¶ms);
00069 };
00070
00071 class LoopMesh {
00072 public:
00073 static Shape* CreateShape(const Transform &o2w, bool reverseOrientation, const ParamSet ¶ms);
00074 };
00075
00076 protected:
00077
00078 MeshAccelType accelType;
00079
00080
00081 int nverts;
00082 Point *p;
00083 Normal *n;
00084 float *uvs;
00085
00086
00087 MeshTriangleType triType;
00088 int ntris;
00089 int *triVertexIndex;
00090
00091
00092 MeshQuadType quadType;
00093 int nquads;
00094 int *quadVertexIndex;
00095
00096
00097 bool mustSubdivide;
00098 int nSubdivLevels;
00099 MeshSubdivType subdivType;
00100
00101 boost::shared_ptr<Texture<float> > displacementMap;
00102 float displacementMapScale;
00103 float displacementMapOffset;
00104 bool displacementMapNormalSmooth, displacementMapSharpBoundary;
00105 };
00106
00107
00108
00109
00110
00111 class MeshBaryTriangle : public Primitive {
00112 public:
00113
00114 MeshBaryTriangle(const Mesh *m, int n)
00115 : mesh(m), v(&(mesh->triVertexIndex[3 * n])) {
00116 if (mesh->reverseOrientation ^ mesh->transformSwapsHandedness)
00117 swap(const_cast<int *>(v)[1], const_cast<int *>(v)[2]);
00118 }
00119 virtual ~MeshBaryTriangle() { }
00120
00121 virtual BBox ObjectBound() const;
00122 virtual BBox WorldBound() const;
00123
00124 virtual bool CanIntersect() const { return true; }
00125 virtual bool Intersect(const Ray &ray, Intersection *isect) const;
00126 virtual bool IntersectP(const Ray &ray) const;
00127
00128 virtual void GetShadingGeometry(const Transform &obj2world,
00129 const DifferentialGeometry &dg,
00130 DifferentialGeometry *dgShading) const;
00131
00132 virtual bool CanSample() const { return true; }
00133 virtual float Area() const;
00134 virtual void Sample(float u1, float u2, float u3, DifferentialGeometry *dg) const;
00135
00136 virtual bool isDegenerate() const {
00137 return false;
00138 }
00139
00140 void GetUVs(float uv[3][2]) const {
00141 if (mesh->uvs) {
00142 uv[0][0] = mesh->uvs[2*v[0]];
00143 uv[0][1] = mesh->uvs[2*v[0]+1];
00144 uv[1][0] = mesh->uvs[2*v[1]];
00145 uv[1][1] = mesh->uvs[2*v[1]+1];
00146 uv[2][0] = mesh->uvs[2*v[2]];
00147 uv[2][1] = mesh->uvs[2*v[2]+1];
00148 } else {
00149 uv[0][0] = .5f;
00150 uv[0][1] = .5f;
00151 uv[1][0] = .5f;
00152 uv[1][1] = .5f;
00153 uv[2][0] = .5f;
00154 uv[2][1] = .5f;
00155 }
00156 }
00157 const Point &GetP(u_int i) const { return mesh->p[v[i]]; }
00158
00159
00160 const Mesh *mesh;
00161 const int *v;
00162 };
00163
00164 class MeshWaldTriangle : public MeshBaryTriangle {
00165 public:
00166
00167 MeshWaldTriangle(const Mesh *m, int n);
00168 virtual ~MeshWaldTriangle() { }
00169
00170 virtual bool Intersect(const Ray &ray, Intersection *isect) const;
00171 virtual bool IntersectP(const Ray &ray) const;
00172
00173 virtual void Sample(float u1, float u2, float u3, DifferentialGeometry *dg) const;
00174 virtual bool isDegenerate() const;
00175 private:
00176
00177
00178
00179 enum IntersectionType {
00180 DOMINANT_X,
00181 DOMINANT_Y,
00182 DOMINANT_Z,
00183 DEGENERATE
00184 };
00185 IntersectionType intersectionType;
00186 float nu, nv, nd;
00187 float bnu, bnv, bnd;
00188 float cnu, cnv, cnd;
00189
00190
00191 Vector dpdu, dpdv;
00192 Normal normalizedNormal;
00193 };
00194
00195
00196
00197
00198
00199
00200
00201 class MeshQuadrilateral : public Primitive {
00202 public:
00203
00204 MeshQuadrilateral(const Mesh *m, int n);
00205 virtual ~MeshQuadrilateral() { }
00206
00207 virtual BBox ObjectBound() const;
00208 virtual BBox WorldBound() const;
00209
00210 virtual bool CanIntersect() const { return true; }
00211 virtual bool Intersect(const Ray &ray, Intersection *isect) const;
00212 virtual bool IntersectP(const Ray &ray) const;
00213
00214 virtual void GetShadingGeometry(const Transform &obj2world,
00215 const DifferentialGeometry &dg,
00216 DifferentialGeometry *dgShading) const;
00217
00218 virtual bool CanSample() const { return true; }
00219 virtual float Area() const;
00220 virtual void Sample(float u1, float u2, float u3, DifferentialGeometry *dg) const {
00221 const Point &p0 = mesh->p[idx[0]];
00222 const Point &p1 = mesh->p[idx[1]];
00223 const Point &p2 = mesh->p[idx[2]];
00224 const Point &p3 = mesh->p[idx[3]];
00225
00226 float b0 = (1.f-u1)*(1.f-u2);
00227 float b1 = u1*(1.f-u2);
00228 float b2 = u1*u2;
00229 float b3 = (1.f-u1)*u2;
00230
00231 dg->p = b0*p0 + b1*p1 +b2*p2 + b3*p3;
00232
00233 Vector e0 = p1 - p0;
00234 Vector e1 = p2 - p0;
00235
00236 dg->nn = Normalize(Normal(Cross(e0, e1)));
00237 if (mesh->reverseOrientation ^ mesh->transformSwapsHandedness)
00238 dg->nn = -dg->nn;
00239 CoordinateSystem(Vector(dg->nn), &dg->dpdu, &dg->dpdv);
00240
00241 float uv[4][2];
00242 GetUVs(uv);
00243 dg->u = b0*uv[0][0] + b1*uv[1][0] + b2*uv[2][0] + b3*uv[3][0];
00244 dg->v = b0*uv[0][1] + b1*uv[1][1] + b2*uv[2][1] + b3*uv[3][1];
00245 }
00246
00247 bool isDegenerate() const {
00248 return false;
00249 }
00250
00251 static bool IsPlanar(const Point &p0, const Point &p1, const Point &p2, const Point &p3);
00252 static bool IsDegenerate(const Point &p0, const Point &p1, const Point &p2, const Point &p3);
00253 static bool IsConvex(const Point &p0, const Point &p1, const Point &p2, const Point &p3);
00254
00255 private:
00256 static int MajorAxis(const Vector &v);
00257
00258 static void ComputeV11BarycentricCoords(const Vector &e01, const Vector &e02, const Vector &e03, float *a11, float *b11);
00259
00260 void GetUVs(float uv[4][2]) const {
00261 if (mesh->uvs) {
00262 uv[0][0] = mesh->uvs[2 * idx[0]];
00263 uv[0][1] = mesh->uvs[2 * idx[0] + 1];
00264 uv[1][0] = mesh->uvs[2 * idx[1]];
00265 uv[1][1] = mesh->uvs[2 * idx[1] + 1];
00266 uv[2][0] = mesh->uvs[2 * idx[2]];
00267 uv[2][1] = mesh->uvs[2 * idx[2] + 1];
00268 uv[3][0] = mesh->uvs[2 * idx[3]];
00269 uv[3][1] = mesh->uvs[2 * idx[3] + 1];
00270 } else {
00271 uv[0][0] = mesh->p[idx[0]].x;
00272 uv[0][1] = mesh->p[idx[0]].y;
00273 uv[1][0] = mesh->p[idx[1]].x;
00274 uv[1][1] = mesh->p[idx[1]].y;
00275 uv[2][0] = mesh->p[idx[2]].x;
00276 uv[2][1] = mesh->p[idx[2]].y;
00277 uv[3][0] = mesh->p[idx[3]].x;
00278 uv[3][1] = mesh->p[idx[3]].y;
00279 }
00280 }
00281
00282
00283 const Mesh *mesh;
00284 const int *idx;
00285 };
00286
00287 }
00288