void PlanarRectangle::InitUnit( const Rectangle & rect, const vec3f & integrationPoint ) { // copy src points here std::memcpy( &p0, &rect.p0, 4 * sizeof( vec3f ) ); // Normalize each vertex to get the inscribed triangle, // and find the average vertex plane vec3f bary( 0 ); vec3f *verts = &p0; for ( int i = 0; i < 4; ++i ) { verts[i] = Normalize( verts[i] - integrationPoint ); // put in intPos frame bary += verts[i]; } bary *= 0.25f; // project each point on the tangent plane at the barycenter f32 rayLenSq = Dot( bary, bary ); f32 rayLen = std::sqrt( rayLenSq ); ez = bary / rayLen; // plane normal // bary is in relative coordinates to the integration pt already const Plane P{ bary, ez }; for ( int i = 0; i < 4; ++i ) { // with 0 as origin since the vertices are in relative coordinates already verts[i] = P.RayIntersection( vec3f( 0 ), verts[i] ); } const vec3f d0 = p1 - p0; const vec3f d1 = p3 - p0; const vec3f d2 = p2 - p3; const vec3f d3 = p2 - p1; w = Len( d0 ); h = Len( d1 ); ex = d0 / w; ey = d1 / h; area = 0.5f * ( w * h + Len( d2 ) * Len( d3 ) ); }
void PlanarRectangle::InitBary( const Rectangle & rect, const vec3f & integrationPoint ) { // copy src points here std::memcpy( &p0, &rect.p0, 4 * sizeof( vec3f ) ); const vec3f bary = ( p0 + p1 + p2 + p3 ) * 0.25f; vec3f org = Normalize( bary - integrationPoint ); const f32 rayLenSqr = Dot( org, org ); const f32 rayLen = std::sqrt( rayLenSqr ); const vec3f nrm = org / rayLen; // org is bary in relative coordinates const Plane P{ org, nrm }; // project each point on the plane P vec3f *verts = &p0; for ( int i = 0; i < 4; ++i ) { vec3f rayDir = Normalize( verts[i] - integrationPoint ); // with 0 as origin since the vertices are in relative coordinates already verts[i] = P.RayIntersection( vec3f( 0 ), rayDir ); } const vec3f d0 = p1 - p0; const vec3f d1 = p3 - p0; const vec3f d2 = p2 - p3; const vec3f d3 = p2 - p1; w = Len( d0 ); h = Len( d1 ); ex = d0 / w; ey = d1 / h; ez = nrm; // normal pointing away from origin area = 0.5f * ( w * h + Len( d2 ) * Len( d3 ) ); }
f32 Rectangle::IntegrateMRP( const vec3f & integrationPos, const vec3f & integrationNrm ) const { const vec3f d0p = -ez; const vec3f d1p = integrationNrm; const f32 nDotpN = std::max( 0.f, Dot( integrationNrm, ez ) ); vec3f d0 = Normalize( d0p + integrationNrm * nDotpN ); vec3f d1 = Normalize( d1p - ez * nDotpN ); vec3f dh = Normalize( d0 + d1 ); Plane rectPlane = { position, ez }; vec3f pH = rectPlane.RayIntersection( integrationPos, dh ); pH = rectPlane.ClampPointInRect( *this, pH ); const f32 solidAngle = SolidAngle( integrationPos ); vec3f rayDir = Normalize( pH - integrationPos ); return solidAngle * std::max( 0.f, Dot( integrationNrm, rayDir ) ); }