diff --git a/include/mitsuba/core/triangle.h b/include/mitsuba/core/triangle.h index 2071d57b..2e971d25 100644 --- a/include/mitsuba/core/triangle.h +++ b/include/mitsuba/core/triangle.h @@ -58,9 +58,10 @@ struct MTS_EXPORT_CORE Triangle { */ AABB getClippedAABB(const Point *positions, const AABB &aabb) const; - /// Uniformly sample a point on the triangle and return its normal + /// Uniformly sample a point on the triangle and return its normal and UV coordinates Point sample(const Point *positions, const Normal *normals, - Normal &n, const Point2 &seed) const; + const Point2 *texCoords, Normal &n, Point2 &uv, + const Point2 &seed) const; /// Calculate the surface area of this triangle Float surfaceArea(const Point *positions) const; diff --git a/src/libcore/triangle.cpp b/src/libcore/triangle.cpp index fb761445..a1965bd2 100644 --- a/src/libcore/triangle.cpp +++ b/src/libcore/triangle.cpp @@ -22,7 +22,7 @@ MTS_NAMESPACE_BEGIN Point Triangle::sample(const Point *positions, const Normal *normals, - Normal &normal, const Point2 &sample) const { + const Point2 *texCoords, Normal &normal, Point2 &uv, const Point2 &sample) const { const Point &p0 = positions[idx[0]]; const Point &p1 = positions[idx[1]]; const Point &p2 = positions[idx[2]]; @@ -44,6 +44,17 @@ Point Triangle::sample(const Point *positions, const Normal *normals, normal = Normal(normalize(cross(sideA, sideB))); } + if (texCoords) { + const Point2 &uv0 = texCoords[idx[0]]; + const Point2 &uv1 = texCoords[idx[1]]; + const Point2 &uv2 = texCoords[idx[2]]; + + uv = uv0 * (1.0f - bary.x - bary.y) + + uv1 * bary.x + uv2 * bary.y; + } else { + uv = bary; + } + return p; } diff --git a/src/librender/trimesh.cpp b/src/librender/trimesh.cpp index 7a85e25f..56b747c4 100644 --- a/src/librender/trimesh.cpp +++ b/src/librender/trimesh.cpp @@ -367,7 +367,8 @@ void TriMesh::samplePosition(PositionSamplingRecord &pRec, Point2 sample(_sample); size_t index = m_areaDistr.sampleReuse(sample.y); - pRec.p = m_triangles[index].sample(m_positions, m_normals, pRec.n, sample); + pRec.p = m_triangles[index].sample(m_positions, m_normals, + m_texcoords, pRec.n, pRec.uv, sample); pRec.pdf = m_invSurfaceArea; pRec.measure = EArea; } diff --git a/src/shapes/cylinder.cpp b/src/shapes/cylinder.cpp index 065c6f17..13d91e6b 100644 --- a/src/shapes/cylinder.cpp +++ b/src/shapes/cylinder.cpp @@ -210,12 +210,12 @@ public: Vector dpdu = Vector(-local.y, local.x, 0) * (2*M_PI); Vector dpdv = Vector(0, 0, m_length); - if (m_flipNormals) - dpdu *= -1; its.shape = this; its.dpdu = m_objectToWorld(dpdu); its.dpdv = m_objectToWorld(dpdv); its.geoFrame.n = Normal(normalize(cross(its.dpdu, its.dpdv))); + if (m_flipNormals) + its.geoFrame.n *= -1; its.geoFrame.s = normalize(its.dpdu); its.geoFrame.t = normalize(its.dpdv); its.shFrame = its.geoFrame; diff --git a/src/shapes/sphere.cpp b/src/shapes/sphere.cpp index b85ea304..9871c845 100644 --- a/src/shapes/sphere.cpp +++ b/src/shapes/sphere.cpp @@ -273,7 +273,7 @@ public: void getNormalDerivative(const Intersection &its, Vector &dndu, Vector &dndv, bool shadingFrame) const { - Float invRadius = 1.0f / m_radius; + Float invRadius = (m_flipNormals ? -1.0f : 1.0f) / m_radius; dndu = its.dpdu * invRadius; dndv = its.dpdv * invRadius; }