Exemplo n.º 1
0
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();
}
Exemplo n.º 2
0
/*!
  \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);
}
Exemplo n.º 3
0
/*!
  \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);
}
Exemplo n.º 4
0
/*!
  \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;
}
Exemplo n.º 5
0
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);
}