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 "mesh.h"
00025 #include "mc.h"
00026
00027 using namespace lux;
00028
00029 BBox MeshBaryTriangle::ObjectBound() const
00030 {
00031
00032 const Point &p1 = mesh->p[v[0]];
00033 const Point &p2 = mesh->p[v[1]];
00034 const Point &p3 = mesh->p[v[2]];
00035 return Union(BBox(mesh->WorldToObject(p1), mesh->WorldToObject(p2)),
00036 mesh->WorldToObject(p3));
00037 }
00038
00039 BBox MeshBaryTriangle::WorldBound() const
00040 {
00041
00042 const Point &p1 = mesh->p[v[0]];
00043 const Point &p2 = mesh->p[v[1]];
00044 const Point &p3 = mesh->p[v[2]];
00045 return Union(BBox(p1, p2), p3);
00046 }
00047
00048 bool MeshBaryTriangle::Intersect(const Ray &ray, Intersection* isect) const
00049 {
00050 Vector e1, e2, s1;
00051
00052
00053 const Point &p1 = mesh->p[v[0]];
00054 const Point &p2 = mesh->p[v[1]];
00055 const Point &p3 = mesh->p[v[2]];
00056 e1 = p2 - p1;
00057 e2 = p3 - p1;
00058 s1 = Cross(ray.d, e2);
00059 const float divisor = Dot(s1, e1);
00060 if (divisor == 0.f)
00061 return false;
00062 const float invDivisor = 1.f / divisor;
00063
00064 const Vector d = ray.o - p1;
00065 const float b1 = Dot(d, s1) * invDivisor;
00066 if (b1 < 0.f)
00067 return false;
00068
00069 const Vector s2 = Cross(d, e1);
00070 const float b2 = Dot(ray.d, s2) * invDivisor;
00071 if (b2 < 0.f)
00072 return false;
00073 const float b0 = 1.f - b1 - b2;
00074 if (b0 < 0.f)
00075 return false;
00076
00077 const float t = Dot(e2, s2) * invDivisor;
00078 if (t < ray.mint || t > ray.maxt)
00079 return false;
00080
00081
00082
00083 Vector dpdu, dpdv;
00084 float uvs[3][2];
00085 GetUVs(uvs);
00086
00087 const float du1 = uvs[0][0] - uvs[2][0];
00088 const float du2 = uvs[1][0] - uvs[2][0];
00089 const float dv1 = uvs[0][1] - uvs[2][1];
00090 const float dv2 = uvs[1][1] - uvs[2][1];
00091 const Vector dp1 = p1 - p3, dp2 = p2 - p3;
00092 const float determinant = du1 * dv2 - dv1 * du2;
00093 if (determinant == 0.f) {
00094
00095 CoordinateSystem(Normalize(Cross(e1, e2)), &dpdu, &dpdv);
00096 } else {
00097 const float invdet = 1.f / determinant;
00098 dpdu = ( dv2 * dp1 - dv1 * dp2) * invdet;
00099 dpdv = (-du2 * dp1 + du1 * dp2) * invdet;
00100 }
00101
00102
00103 const float tu = b0 * uvs[0][0] + b1 * uvs[1][0] + b2 * uvs[2][0];
00104 const float tv = b0 * uvs[0][1] + b1 * uvs[1][1] + b2 * uvs[2][1];
00105
00106 const Normal nn = Normal(Normalize(Cross(e1, e2)));
00107 const Point pp(p1 + b1 * e1 + b2 * e2);
00108
00109 isect->dg = DifferentialGeometry(pp, nn, dpdu, dpdv,
00110 Normal(0, 0, 0), Normal(0, 0, 0), tu, tv, this);
00111
00112 isect->Set(mesh->WorldToObject, this, mesh->GetMaterial().get());
00113 isect->dg.triangleBaryCoords[0] = b0;
00114 isect->dg.triangleBaryCoords[1] = b1;
00115 isect->dg.triangleBaryCoords[2] = b2;
00116 ray.maxt = t;
00117
00118 return true;
00119 }
00120
00121 bool MeshBaryTriangle::IntersectP(const Ray &ray) const
00122 {
00123
00124
00125 const Point &p1 = mesh->p[v[0]];
00126 const Point &p2 = mesh->p[v[1]];
00127 const Point &p3 = mesh->p[v[2]];
00128 Vector e1 = p2 - p1;
00129 Vector e2 = p3 - p1;
00130 Vector s1 = Cross(ray.d, e2);
00131 const float divisor = Dot(s1, e1);
00132 if (divisor == 0.f)
00133 return false;
00134 const float invDivisor = 1.f / divisor;
00135
00136 const Vector d = ray.o - p1;
00137 const float b1 = Dot(d, s1) * invDivisor;
00138 if (b1 < 0.f)
00139 return false;
00140
00141 const Vector s2 = Cross(d, e1);
00142 const float b2 = Dot(ray.d, s2) * invDivisor;
00143 if (b2 < 0.f)
00144 return false;
00145 if (b1 + b2 > 1.f)
00146 return false;
00147
00148 float t = Dot(e2, s2) * invDivisor;
00149 if (t < ray.mint || t > ray.maxt)
00150 return false;
00151
00152 return true;
00153 }
00154
00155 float MeshBaryTriangle::Area() const
00156 {
00157
00158 const Point &p1 = mesh->p[v[0]];
00159 const Point &p2 = mesh->p[v[1]];
00160 const Point &p3 = mesh->p[v[2]];
00161 return 0.5f * Cross(p2-p1, p3-p1).Length();
00162 }
00163
00164 void MeshBaryTriangle::Sample(float u1, float u2, float u3, DifferentialGeometry *dg) const
00165 {
00166 float b1, b2;
00167 UniformSampleTriangle(u1, u2, &b1, &b2);
00168
00169 const Point &p1 = mesh->p[v[0]];
00170 const Point &p2 = mesh->p[v[1]];
00171 const Point &p3 = mesh->p[v[2]];
00172 float b3 = 1.f - b1 - b2;
00173 dg->p = b1 * p1 + b2 * p2 + b3 * p3;
00174
00175 dg->nn = Normalize(Normal(Cross(p2-p1, p3-p1)));
00176 CoordinateSystem(Vector(dg->nn), &dg->dpdu, &dg->dpdv);
00177
00178 float uv[3][2];
00179 GetUVs(uv);
00180 dg->u = b1 * uv[0][0] + b2 * uv[1][0] + b3 * uv[2][0];
00181 dg->v = b1 * uv[0][1] + b2 * uv[1][1] + b3 * uv[2][1];
00182 }
00183
00184 void MeshBaryTriangle::GetShadingGeometry(const Transform &obj2world,
00185 const DifferentialGeometry &dg, DifferentialGeometry *dgShading) const
00186 {
00187 if (!mesh->n) {
00188 *dgShading = dg;
00189 return;
00190 }
00191
00192
00193 const Normal ns = Normalize(dg.triangleBaryCoords[0] * mesh->n[v[0]] +
00194 dg.triangleBaryCoords[1] * mesh->n[v[1]] + dg.triangleBaryCoords[2] * mesh->n[v[2]]);
00195
00196 Vector ts(Normalize(Cross(ns, dg.dpdu)));
00197 Vector ss(Cross(ts, ns));
00198
00199 ss *= dg.dpdu.Length();
00200 ts *= dg.dpdv.Length();
00201
00202 Normal dndu, dndv;
00203
00204 float uvs[3][2];
00205 GetUVs(uvs);
00206
00207
00208 const float du1 = uvs[0][0] - uvs[2][0];
00209 const float du2 = uvs[1][0] - uvs[2][0];
00210 const float dv1 = uvs[0][1] - uvs[2][1];
00211 const float dv2 = uvs[1][1] - uvs[2][1];
00212 const Normal dn1 = mesh->n[v[0]] - mesh->n[v[2]];
00213 const Normal dn2 = mesh->n[v[1]] - mesh->n[v[2]];
00214 const float determinant = du1 * dv2 - dv1 * du2;
00215
00216 if (determinant == 0.f)
00217 dndu = dndv = Normal(0, 0, 0);
00218 else {
00219 const float invdet = 1.f / determinant;
00220 dndu = ( dv2 * dn1 - dv1 * dn2) * invdet;
00221 dndv = (-du2 * dn1 + du1 * dn2) * invdet;
00222 }
00223
00224 *dgShading = DifferentialGeometry(dg.p, ns, ss, ts,
00225 dndu, dndv, dg.u, dg.v, this);
00226
00227 dgShading->dudx = dg.dudx; dgShading->dvdx = dg.dvdx;
00228 dgShading->dudy = dg.dudy; dgShading->dvdy = dg.dvdy;
00229 dgShading->dpdx = dg.dpdx; dgShading->dpdy = dg.dpdy;
00230 }