mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			137 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// This file is part of libigl, a simple c++ geometry processing library.
 | 
						|
// 
 | 
						|
// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
 | 
						|
// 
 | 
						|
// This Source Code Form is subject to the terms of the Mozilla Public License 
 | 
						|
// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 | 
						|
// obtain one at http://mozilla.org/MPL/2.0/.
 | 
						|
#include "ambient_occlusion.h"
 | 
						|
#include "random_dir.h"
 | 
						|
#include "ray_mesh_intersect.h"
 | 
						|
#include "EPS.h"
 | 
						|
#include "Hit.h"
 | 
						|
#include "parallel_for.h"
 | 
						|
#include <functional>
 | 
						|
#include <vector>
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
template <
 | 
						|
  typename DerivedP,
 | 
						|
  typename DerivedN,
 | 
						|
  typename DerivedS >
 | 
						|
IGL_INLINE void igl::ambient_occlusion(
 | 
						|
  const std::function<
 | 
						|
    bool(
 | 
						|
      const Eigen::Vector3f&,
 | 
						|
      const Eigen::Vector3f&)
 | 
						|
      > & shoot_ray,
 | 
						|
  const Eigen::PlainObjectBase<DerivedP> & P,
 | 
						|
  const Eigen::PlainObjectBase<DerivedN> & N,
 | 
						|
  const int num_samples,
 | 
						|
  Eigen::PlainObjectBase<DerivedS> & S)
 | 
						|
{
 | 
						|
  using namespace Eigen;
 | 
						|
  const int n = P.rows();
 | 
						|
  // Resize output
 | 
						|
  S.resize(n,1);
 | 
						|
  // Embree seems to be parallel when constructing but not when tracing rays
 | 
						|
  const MatrixXf D = random_dir_stratified(num_samples).cast<float>();
 | 
						|
 | 
						|
  const auto & inner = [&P,&N,&num_samples,&D,&S,&shoot_ray](const int p)
 | 
						|
  {
 | 
						|
    const Vector3f origin = P.row(p).template cast<float>();
 | 
						|
    const Vector3f normal = N.row(p).template cast<float>();
 | 
						|
    int num_hits = 0;
 | 
						|
    for(int s = 0;s<num_samples;s++)
 | 
						|
    {
 | 
						|
      Vector3f d = D.row(s);
 | 
						|
      if(d.dot(normal) < 0)
 | 
						|
      {
 | 
						|
        // reverse ray
 | 
						|
        d *= -1;
 | 
						|
      }
 | 
						|
      if(shoot_ray(origin,d))
 | 
						|
      {
 | 
						|
        num_hits++;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    S(p) = (double)num_hits/(double)num_samples;
 | 
						|
  };
 | 
						|
  parallel_for(n,inner,1000);
 | 
						|
}
 | 
						|
 | 
						|
template <
 | 
						|
  typename DerivedV,
 | 
						|
  int DIM,
 | 
						|
  typename DerivedF,
 | 
						|
  typename DerivedP,
 | 
						|
  typename DerivedN,
 | 
						|
  typename DerivedS >
 | 
						|
IGL_INLINE void igl::ambient_occlusion(
 | 
						|
  const igl::AABB<DerivedV,DIM> & aabb,
 | 
						|
  const Eigen::PlainObjectBase<DerivedV> & V,
 | 
						|
  const Eigen::PlainObjectBase<DerivedF> & F,
 | 
						|
  const Eigen::PlainObjectBase<DerivedP> & P,
 | 
						|
  const Eigen::PlainObjectBase<DerivedN> & N,
 | 
						|
  const int num_samples,
 | 
						|
  Eigen::PlainObjectBase<DerivedS> & S)
 | 
						|
{
 | 
						|
  const auto & shoot_ray = [&aabb,&V,&F](
 | 
						|
    const Eigen::Vector3f& _s,
 | 
						|
    const Eigen::Vector3f& dir)->bool
 | 
						|
  {
 | 
						|
    Eigen::Vector3f s = _s+1e-4*dir;
 | 
						|
    igl::Hit hit;
 | 
						|
    return aabb.intersect_ray(
 | 
						|
      V,
 | 
						|
      F,
 | 
						|
      s  .cast<typename DerivedV::Scalar>().eval(),
 | 
						|
      dir.cast<typename DerivedV::Scalar>().eval(),
 | 
						|
      hit);
 | 
						|
  };
 | 
						|
  return ambient_occlusion(shoot_ray,P,N,num_samples,S);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
template <
 | 
						|
  typename DerivedV,
 | 
						|
  typename DerivedF,
 | 
						|
  typename DerivedP,
 | 
						|
  typename DerivedN,
 | 
						|
  typename DerivedS >
 | 
						|
IGL_INLINE void igl::ambient_occlusion(
 | 
						|
  const Eigen::PlainObjectBase<DerivedV> & V,
 | 
						|
  const Eigen::PlainObjectBase<DerivedF> & F,
 | 
						|
  const Eigen::PlainObjectBase<DerivedP> & P,
 | 
						|
  const Eigen::PlainObjectBase<DerivedN> & N,
 | 
						|
  const int num_samples,
 | 
						|
  Eigen::PlainObjectBase<DerivedS> & S)
 | 
						|
{
 | 
						|
  if(F.rows() < 100)
 | 
						|
  {
 | 
						|
    // Super naive
 | 
						|
    const auto & shoot_ray = [&V,&F](
 | 
						|
      const Eigen::Vector3f& _s,
 | 
						|
      const Eigen::Vector3f& dir)->bool
 | 
						|
    {
 | 
						|
      Eigen::Vector3f s = _s+1e-4*dir;
 | 
						|
      igl::Hit hit;
 | 
						|
      return ray_mesh_intersect(s,dir,V,F,hit);
 | 
						|
    };
 | 
						|
    return ambient_occlusion(shoot_ray,P,N,num_samples,S);
 | 
						|
  }
 | 
						|
  AABB<DerivedV,3> aabb;
 | 
						|
  aabb.init(V,F);
 | 
						|
  return ambient_occlusion(aabb,V,F,P,N,num_samples,S);
 | 
						|
}
 | 
						|
 | 
						|
#ifdef IGL_STATIC_LIBRARY
 | 
						|
// Explicit template instantiation
 | 
						|
// generated by autoexplicit.sh
 | 
						|
template void igl::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 | 
						|
// generated by autoexplicit.sh
 | 
						|
template void igl::ambient_occlusion<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 | 
						|
// generated by autoexplicit.sh
 | 
						|
template void igl::ambient_occlusion<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 | 
						|
template void igl::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 | 
						|
#endif
 |