double geometric(Vector4d s1, Vector4d n1, Vector4d s2, Vector4d n2) { ASSERT(isUnitVector(n1), "assumes the normals are normalized"); ASSERT(isUnitVector(n2), "assumes the normals are normalized"); Vector4d segment = s1 - s2; Vector4d seg_dir = segment.normalized(); double cos1 = n1.dot(seg_dir); double cos2 = n2.dot(-1 * seg_dir); return std::abs(cos1 * cos2) / segment.squaredNorm(); }
/*! \details No detailed. */ std::tuple<SampledDirection, SampledSpectra> GgxConductorBrdf::sample( const Vector3* vin, const WavelengthSamples& wavelengths, Sampler& sampler, PathState& path_state, const IntersectionInfo* info) const noexcept { const auto& point = info->shapePoint(); const auto vin_d = Transformation::toLocal(point.tangent(), point.bitangent(), point.normal(), -(*vin)); ZISC_ASSERT(zisc::isInClosedBounds(vin_d[2], 0.0, 1.0), "The vin isn't in the upper hemisphere."); ZISC_ASSERT(isUnitVector(vin_d), "The vin isn't unit vector."); // Sample a microfacet normal const auto m_normal = MicrofacetGgx::sampleNormal(roughness_x_, roughness_y_, vin_d, sampler, path_state); // Get the reflection direction auto vout = Microfacet::calcReflectionDirection(vin_d, m_normal); SampledSpectra weight{wavelengths}; const Float cos_no = vout.direction()[2]; if (0.0 < cos_no) { // Evaluate the fresnel term const Float cos_mi = zisc::dot(m_normal.direction(), vin_d); const auto fresnel = Fresnel::evalFresnel(n_, eta_, cos_mi); // Evaluate the weight weight = fresnel * MicrofacetGgx::evalWeight(roughness_x_, roughness_y_, vin_d, vout.direction(), m_normal.direction()); ZISC_ASSERT(!weight.hasNegative(), "The Weight contains negative."); // Transform the reflection direction const auto vout_dir = Transformation::fromLocal(point.tangent(), point.bitangent(), point.normal(), vout.direction()); ZISC_ASSERT(isUnitVector(vout_dir), "The vout isn't unit vector."); vout.setDirection(vout_dir); } else { vout.setPdf(0.0); } return std::make_tuple(vout, weight); }
/*! \details No detailed. */ std::tuple<SampledSpectra, Float> GgxConductorBrdf::evalRadianceAndPdf( const Vector3* vin, const Vector3* vout, const WavelengthSamples& /* wavelengths */, const IntersectionInfo* info) const noexcept { const auto& point = info->shapePoint(); const auto vin_d = Transformation::toLocal(point.tangent(), point.bitangent(), point.normal(), -(*vin)); ZISC_ASSERT(zisc::isInClosedBounds(vin_d[2], 0.0, 1.0), "The vin isn't in the upper hemisphere."); ZISC_ASSERT(isUnitVector(vin_d), "The vin isn't unit vector."); const auto vout_d = Transformation::toLocal(point.tangent(), point.bitangent(), point.normal(), *vout); ZISC_ASSERT(zisc::isInClosedBounds(vout_d[2], 0.0, 1.0), "The vout isn't in the upper hemisphere."); ZISC_ASSERT(isUnitVector(vout_d), "The vout isn't unit vector."); // Calculate the microfacet normal const auto m_normal = Microfacet::calcReflectionHalfVector(vin_d, vout_d); ZISC_ASSERT(zisc::isInClosedBounds(m_normal[2], 0.0, 1.0), "The microfacet normal isn't in the upper hemisphere."); // Evaluate the radiance and the pdf Float pdf = 0.0; const auto radiance = MicrofacetGgx::evalReflectance(roughness_x_, roughness_y_, vin_d, vout_d, m_normal, n_, eta_, &pdf); return std::make_tuple(radiance, pdf); }
/*! \details No detailed. */ Float GgxConductorBrdf::evalPdf( const Vector3* vin, const Vector3* vout, const WavelengthSamples& /* wavelengths */, const IntersectionInfo* info) const noexcept { const auto& point = info->shapePoint(); // Transform vectors const auto vin_d = Transformation::toLocal(point.tangent(), point.bitangent(), point.normal(), -(*vin)); ZISC_ASSERT(zisc::isInClosedBounds(vin_d[2], 0.0, 1.0), "The vin isn't in the upper hemisphere."); ZISC_ASSERT(isUnitVector(vin_d), "The vin isn't unit vector."); const auto vout_d = Transformation::toLocal(point.tangent(), point.bitangent(), point.normal(), *vout); ZISC_ASSERT(zisc::isInClosedBounds(vout_d[2], 0.0, 1.0), "The vout isn't in the upper hemisphere."); ZISC_ASSERT(isUnitVector(vout_d), "The vout isn't unit vector."); // Calculate the microfacet normal const auto m_normal = Microfacet::calcReflectionHalfVector(vin_d, vout_d); ZISC_ASSERT(zisc::isInClosedBounds(m_normal[2], 0.0, 1.0), "The microfacet normal isn't in the upper hemisphere."); // Evaluate the pdf const Float pdf = MicrofacetGgx::evalReflectionPdf(roughness_x_, roughness_y_, vin_d, m_normal); return pdf; }
int MultiBodyTree::addBody(int body_index, int parent_index, JointType joint_type, const vec3 &parent_r_parent_body_ref, const mat33 &body_T_parent_ref, const vec3 &body_axis_of_motion_, idScalar mass, const vec3 &body_r_body_com, const mat33 &body_I_body, const int user_int, void *user_ptr) { if (body_index < 0) { error_message("body index must be positive (got %d)\n", body_index); return -1; } vec3 body_axis_of_motion(body_axis_of_motion_); switch (joint_type) { case REVOLUTE: case PRISMATIC: // check if axis is unit vector if (!isUnitVector(body_axis_of_motion)) { warning_message( "axis of motion not a unit axis ([%f %f %f]), will use normalized vector\n", body_axis_of_motion(0), body_axis_of_motion(1), body_axis_of_motion(2)); idScalar length = std::sqrt(std::pow(body_axis_of_motion(0), 2) + std::pow(body_axis_of_motion(1), 2) + std::pow(body_axis_of_motion(2), 2)); if (length < std::sqrt(std::numeric_limits<idScalar>::min())) { error_message("axis of motion vector too short (%e)\n", length); return -1; } body_axis_of_motion = (1.0 / length) * body_axis_of_motion; } break; case FIXED: break; case FLOATING: break; default: error_message("unknown joint type %d\n", joint_type); return -1; } // sanity check for mass properties. Zero mass is OK. if (mass < 0) { m_mass_parameters_are_valid = false; error_message("Body %d has invalid mass %e\n", body_index, mass); if (!m_accept_invalid_mass_parameters) { return -1; } } if (!isValidInertiaMatrix(body_I_body, body_index, FIXED == joint_type)) { m_mass_parameters_are_valid = false; // error message printed in function call if (!m_accept_invalid_mass_parameters) { return -1; } } if (!isValidTransformMatrix(body_T_parent_ref)) { return -1; } return m_init_cache->addBody(body_index, parent_index, joint_type, parent_r_parent_body_ref, body_T_parent_ref, body_axis_of_motion, mass, body_r_body_com, body_I_body, user_int, user_ptr); }