draw_mesh.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "draw_mesh.h"
  9. #ifndef IGL_NO_OPENGL
  10. IGL_INLINE void igl::draw_mesh(
  11. const Eigen::MatrixXd & V,
  12. const Eigen::MatrixXi & F,
  13. const Eigen::MatrixXd & N)
  14. {
  15. using namespace Eigen;
  16. MatrixXd _d;
  17. MatrixXi _i;
  18. return draw_mesh(V,F,N,_i,_d,_d,_i,_d,0,_i,0);
  19. }
  20. IGL_INLINE void igl::draw_mesh(
  21. const Eigen::MatrixXd & V,
  22. const Eigen::MatrixXi & F,
  23. const Eigen::MatrixXd & N,
  24. const Eigen::MatrixXd & C)
  25. {
  26. using namespace Eigen;
  27. MatrixXd _d;
  28. MatrixXi _i;
  29. return draw_mesh(V,F,N,_i,C,_d,_i,_d,0,_i,0);
  30. }
  31. IGL_INLINE void igl::draw_mesh(
  32. const Eigen::MatrixXd & V,
  33. const Eigen::MatrixXi & F,
  34. const Eigen::MatrixXd & N,
  35. const Eigen::MatrixXd & C,
  36. const Eigen::MatrixXd & TC)
  37. {
  38. using namespace Eigen;
  39. MatrixXd _d;
  40. MatrixXi _i;
  41. return draw_mesh(V,F,N,_i,C,TC,_i,_d,0,_i,0);
  42. }
  43. IGL_INLINE void igl::draw_mesh(
  44. const Eigen::MatrixXd & V,
  45. const Eigen::MatrixXi & F,
  46. const Eigen::MatrixXd & N,
  47. const Eigen::MatrixXd & C,
  48. const Eigen::MatrixXd & TC,
  49. const Eigen::MatrixXd & W,
  50. const GLuint W_index,
  51. const Eigen::MatrixXi & WI,
  52. const GLuint WI_index)
  53. {
  54. using namespace Eigen;
  55. return draw_mesh(V,F,N,MatrixXi(),C,TC,MatrixXi(),W,W_index,WI,WI_index);
  56. }
  57. IGL_INLINE void igl::draw_mesh(
  58. const Eigen::MatrixXd & V,
  59. const Eigen::MatrixXi & F,
  60. const Eigen::MatrixXd & N,
  61. const Eigen::MatrixXi & NF,
  62. const Eigen::MatrixXd & C,
  63. const Eigen::MatrixXd & TC,
  64. const Eigen::MatrixXi & TF,
  65. const Eigen::MatrixXd & W,
  66. const GLuint W_index,
  67. const Eigen::MatrixXi & WI,
  68. const GLuint WI_index)
  69. {
  70. using namespace std;
  71. using namespace Eigen;
  72. const int rF = F.rows();
  73. const int cF = F.cols();
  74. const int cC = C.cols();
  75. const int rC = C.rows();
  76. const int cW = W.cols();
  77. const int rW = W.rows();
  78. const int rV = V.rows();
  79. const int rTC = TC.rows();
  80. const int rTF = TF.rows();
  81. const int rNF = NF.rows();
  82. const int rN = N.rows();
  83. if(F.size() > 0)
  84. {
  85. assert(F.maxCoeff() < V.rows());
  86. assert(V.cols() == 3);
  87. assert(rC == rV || rC == rF || rC == rF*3 || rC==1 || C.size() == 0);
  88. assert(C.cols() >= 3 || C.size() == 0);
  89. assert(N.cols() == 3 || N.size() == 0);
  90. assert(TC.cols() == 2 || TC.size() == 0);
  91. assert(cF == 3 || cF == 4);
  92. assert(TF.size() == 0 || TF.cols() == F.cols());
  93. assert(NF.size() == 0 || NF.cols() == NF.cols());
  94. }
  95. if(W.size()>0)
  96. {
  97. assert(W.rows() == V.rows());
  98. assert(WI.rows() == V.rows());
  99. assert(W.cols() == WI.cols());
  100. }
  101. switch(F.cols())
  102. {
  103. default:
  104. case 3:
  105. glBegin(GL_TRIANGLES);
  106. break;
  107. case 4:
  108. glBegin(GL_QUADS);
  109. break;
  110. }
  111. // loop over faces
  112. for(int i = 0; i<rF;i++)
  113. {
  114. // loop over corners of triangle
  115. for(int j = 0;j<cF;j++)
  116. {
  117. int tc = -1;
  118. if(rTF != 0)
  119. {
  120. tc = TF(i,j);
  121. } else if(rTC == 1)
  122. {
  123. tc = 0;
  124. }else if(rTC == rV)
  125. {
  126. tc = F(i,j);
  127. }else if(rTC == rF*cF)
  128. {
  129. tc = i*cF + j;
  130. }else if(rTC == rF)
  131. {
  132. tc = i;
  133. }else
  134. {
  135. assert(TC.size() == 0);
  136. }
  137. // RGB(A)
  138. Matrix<MatrixXd::Scalar,1,Dynamic> color;
  139. if(rC == 1)
  140. {
  141. color = C.row(0);
  142. }else if(rC == rV)
  143. {
  144. color = C.row(F(i,j));
  145. }else if(rC == rF*cF)
  146. {
  147. color = C.row(i*cF+j);
  148. }else if(rC == rF)
  149. {
  150. color = C.row(i);
  151. }else
  152. {
  153. assert(C.size() == 0);
  154. }
  155. int n = -1;
  156. if(rNF != 0)
  157. {
  158. n = NF(i,j); // indexed normals
  159. } else if(rN == 1)
  160. {
  161. n = 0; // uniform normals
  162. }else if(rN == rF)
  163. {
  164. n = i; // face normals
  165. }else if(rN == rV)
  166. {
  167. n = F(i,j); // vertex normals
  168. }else if(rN == rF*cF)
  169. {
  170. n = i*cF + j; // corner normals
  171. }else
  172. {
  173. assert(N.size() == 0);
  174. }
  175. {
  176. if(rW>0 && W_index !=0 && WI_index != 0)
  177. {
  178. int weights_left = cW;
  179. while(weights_left != 0)
  180. {
  181. int pass_size = std::min(4,weights_left);
  182. int weights_already_passed = cW-weights_left;
  183. // Get attribute location of next 4 weights
  184. int pass_W_index = W_index + weights_already_passed/4;
  185. int pass_WI_index = WI_index + weights_already_passed/4;
  186. switch(pass_size)
  187. {
  188. case 1:
  189. glVertexAttrib1d(
  190. pass_W_index,
  191. W(F(i,j),0+weights_already_passed));
  192. glVertexAttrib1d(
  193. pass_WI_index,
  194. WI(F(i,j),0+weights_already_passed));
  195. break;
  196. case 2:
  197. glVertexAttrib2d(
  198. pass_W_index,
  199. W(F(i,j),0+weights_already_passed),
  200. W(F(i,j),1+weights_already_passed));
  201. glVertexAttrib2d(
  202. pass_WI_index,
  203. WI(F(i,j),0+weights_already_passed),
  204. WI(F(i,j),1+weights_already_passed));
  205. break;
  206. case 3:
  207. glVertexAttrib3d(
  208. pass_W_index,
  209. W(F(i,j),0+weights_already_passed),
  210. W(F(i,j),1+weights_already_passed),
  211. W(F(i,j),2+weights_already_passed));
  212. glVertexAttrib3d(
  213. pass_WI_index,
  214. WI(F(i,j),0+weights_already_passed),
  215. WI(F(i,j),1+weights_already_passed),
  216. WI(F(i,j),2+weights_already_passed));
  217. break;
  218. default:
  219. glVertexAttrib4d(
  220. pass_W_index,
  221. W(F(i,j),0+weights_already_passed),
  222. W(F(i,j),1+weights_already_passed),
  223. W(F(i,j),2+weights_already_passed),
  224. W(F(i,j),3+weights_already_passed));
  225. glVertexAttrib4d(
  226. pass_WI_index,
  227. WI(F(i,j),0+weights_already_passed),
  228. WI(F(i,j),1+weights_already_passed),
  229. WI(F(i,j),2+weights_already_passed),
  230. WI(F(i,j),3+weights_already_passed));
  231. break;
  232. }
  233. weights_left -= pass_size;
  234. }
  235. }
  236. if(tc != -1)
  237. {
  238. glTexCoord2d(TC(tc,0),TC(tc,1));
  239. }
  240. if(rC>0)
  241. {
  242. switch(cC)
  243. {
  244. case 3:
  245. glColor3dv(color.data());
  246. break;
  247. case 4:
  248. glColor4dv(color.data());
  249. break;
  250. default:
  251. break;
  252. }
  253. }
  254. if(n != -1)
  255. {
  256. glNormal3d(N(n,0),N(n,1),N(n,2));
  257. }
  258. glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
  259. }
  260. }
  261. }
  262. glEnd();
  263. }
  264. #endif