2
0

main.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include <igl/opengl/glfw/Viewer.h>
  2. #include <igl/read_triangle_mesh.h>
  3. #include <igl/triangulated_grid.h>
  4. #include <igl/stb/read_image.h>
  5. #include <igl/get_seconds.h>
  6. #include <igl/PI.h>
  7. #include <Eigen/Core>
  8. #include <algorithm>
  9. void floor(const Eigen::MatrixXd & V,
  10. Eigen::MatrixXd & fV,
  11. Eigen::MatrixXd & fU,
  12. Eigen::MatrixXi & fF)
  13. {
  14. igl::triangulated_grid(2,2,fU,fF);
  15. fV = fU;
  16. fV.array() -= 0.5;
  17. fV.array() *= 2 * 2 *
  18. (V.colwise().maxCoeff() - V.colwise().minCoeff()).norm();
  19. fV = (fV * (Eigen::Matrix<double,2,3>()<<1,0,0,0,0,-1).finished() ).eval();
  20. fV.col(0).array() += 0.5*(V.col(0).minCoeff()+ V.col(0).maxCoeff());
  21. fV.col(1).array() += V.col(1).minCoeff();
  22. fV.col(2).array() += 0.5*(V.col(2).minCoeff()+ V.col(2).maxCoeff());
  23. }
  24. void checker_texture(const int s, const int f,
  25. Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> & X,
  26. Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> & A)
  27. {
  28. X.resize(s*f,s*f);
  29. A.resize(s*f,s*f);
  30. for(int i = 0;i<s*f;i++)
  31. {
  32. const double x = double(i)/double(s*f-1)*2-1;
  33. for(int j = 0;j<s*f;j++)
  34. {
  35. const int u = i/f;
  36. const int v = j/f;
  37. const double y = double(j)/double(s*f-1)*2-1;
  38. const double r1 = std::min(std::max( (1.0 - sqrt(x*x+y*y))*1.0 ,0.0),1.0);
  39. const double r3 = std::min(std::max( (1.0 - sqrt(x*x+y*y))*3.0 ,0.0),1.0);
  40. //const double a = 3*r*r - 2*r*r*r;
  41. const auto smooth_step = [](const double w)
  42. {
  43. return ((w * (w * 6.0 - 15.0) + 10.0) * w * w * w) ;
  44. };
  45. double a3 = smooth_step(r1);
  46. double a1 = smooth_step(r1);
  47. X(i,j) = (0.75+0.25*a1) * (u%2 == v%2 ? 245 : 235);
  48. A(i,j) = a3 * 255;
  49. }
  50. }
  51. }
  52. int main(int argc, char *argv[])
  53. {
  54. igl::opengl::glfw::Viewer vr;
  55. Eigen::MatrixXd V;
  56. Eigen::MatrixXi F;
  57. igl::read_triangle_mesh(
  58. argc>1?argv[1]: TUTORIAL_SHARED_PATH "/armadillo.obj",V,F);
  59. // Create a floor
  60. Eigen::MatrixXd fV, fU;
  61. Eigen::MatrixXi fF;
  62. floor(V,fV,fU,fF);
  63. const int s = 16;
  64. const int f = 100;
  65. Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> X;
  66. Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> A;
  67. checker_texture(s,f,X,A);
  68. vr.data().set_mesh(fV,fF);
  69. vr.data().set_uv(fU);
  70. vr.data().uniform_colors(Eigen::Vector3d(0.3,0.3,0.3),Eigen::Vector3d(0.8,0.8,0.8),Eigen::Vector3d(0,0,0));
  71. vr.data().set_texture(X,X,X,A);
  72. vr.data().show_texture = true;
  73. vr.data().show_lines = false;
  74. // Move the light a bit off center to cast a more visible shadow.
  75. vr.core().light_position << 1.0f, 2.0f, 0.0f;
  76. // For now, the default is a positional light with no shadows. Meanwhile,
  77. // shadows only support a directional light. To best match the appearance of
  78. // current lighting use this conversion when turning on shadows. In the
  79. // future, hopefully this will reduce to just
  80. // core().is_shadow_mapping = true
  81. vr.core().is_directional_light = true;
  82. vr.core().light_position = vr.core().light_position + vr.core().camera_eye;
  83. vr.core().is_shadow_mapping = true;
  84. // Send the main object to the viewer
  85. vr.append_mesh();
  86. vr.data().set_mesh(V,F);
  87. vr.data().show_lines = false;
  88. vr.data().set_face_based(true);
  89. // If a second argument is present read it as a matcap
  90. if(argc>2)
  91. {
  92. Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R,G,B,A;
  93. igl::stb::read_image(argv[2],R,G,B,A);
  94. // If more args, read them as light direction
  95. if(argc>2+3)
  96. {
  97. Eigen::Vector3f D;
  98. D << std::atof(argv[3]), std::atof(argv[4]), std::atof(argv[5]);
  99. D.normalize();
  100. vr.core().light_position = D;
  101. Eigen::Vector3d Ka(0.14,0.14,0.14);
  102. if(argc>2+3+1 && std::atoi(argv[6]))
  103. {
  104. // Assume that color opposite D along umbra boundary is ambient color
  105. const double s = -D(2)*1.0/sqrt((D(0)*D(0)+D(1)*D(1))*(D(0)*D(0)+D(1)*D(1)+D(2)*D(2)));
  106. const int i = ((D(0)*s)*0.5+0.5)*R.cols();
  107. const int j = ((D(1)*s)*0.5+0.5)*R.rows();
  108. Ka << double(R(i,j))/255.0, double(G(i,j))/255.0, double(B(i,j))/255.0;
  109. }
  110. std::cout<<"Ka : "<<Ka<<std::endl;
  111. // viewer only exposes ambient color through per-face and per-vertex
  112. // materials
  113. vr.data().V_material_ambient.col(0).setConstant( Ka(0) );
  114. vr.data().V_material_ambient.col(1).setConstant( Ka(1) );
  115. vr.data().V_material_ambient.col(2).setConstant( Ka(2) );
  116. vr.data().F_material_ambient.col(0).setConstant( Ka(0) );
  117. vr.data().F_material_ambient.col(1).setConstant( Ka(1) );
  118. vr.data().F_material_ambient.col(2).setConstant( Ka(2) );
  119. }
  120. vr.data().set_texture(R,G,B,A);
  121. vr.data().use_matcap = true;
  122. }
  123. vr.core().is_animating = true;
  124. vr.core().camera_zoom *= 1.5;
  125. vr.callback_pre_draw = [&](decltype(vr)&)
  126. {
  127. if(vr.core().is_animating)
  128. {
  129. vr.core().trackball_angle = Eigen::AngleAxisf(
  130. sin(igl::get_seconds())*igl::PI*0.5,
  131. Eigen::Vector3f(0,1,0));
  132. }
  133. return false;
  134. };
  135. vr.launch();
  136. }