1 // This is brl/bbas/imesh/algo/imesh_render.h
2 #ifndef imesh_render_h_
3 #define imesh_render_h_
4 //:
5 // \file
6 // \brief Functions to render the faces of a mesh with projected coordinates
7 // \author Matt Leotta (mleotta@lems.brown.edu)
8 // \date June 2, 2008
9 //
10 // \verbatim
11 // Modifications
12 // <none yet>
13 // \endverbatim
14
15 #include <imesh/imesh_mesh.h>
16 #include <vil/vil_image_view.h>
17 #include <vgl/vgl_point_3d.h>
18 #include <vgl/vgl_vector_3d.h>
19 #include <vgl/vgl_triangle_scan_iterator.h>
20 #include <vpgl/vpgl_proj_camera.h>
21 #include <cassert>
22 #ifdef _MSC_VER
23 # include <vcl_msvc_warnings.h>
24 #endif
25
26 //: Render a triangle defined by its vertices.
27 // For each 3d point, X and Y map to image coordinates and Z maps to depth.
28 // Assign label to each pixel in image such that the pixel is within
29 // the triangle and the interpolated depth is less than the value in depth_img.
30 // The depth is also updated for each pixel that is labeled
31 template <class T>
imesh_render_triangle_label(const vgl_point_3d<double> & v1,const vgl_point_3d<double> & v2,const vgl_point_3d<double> & v3,const T & label,vil_image_view<T> & image,vil_image_view<double> & depth_img)32 void imesh_render_triangle_label(const vgl_point_3d<double>& v1,
33 const vgl_point_3d<double>& v2,
34 const vgl_point_3d<double>& v3,
35 const T& label,
36 vil_image_view<T>& image,
37 vil_image_view<double>& depth_img)
38 {
39 assert(depth_img.ni() == image.ni());
40 assert(depth_img.nj() == image.nj());
41
42 vgl_triangle_scan_iterator<double> tsi;
43 tsi.a.x = v1.x(); tsi.a.y = v1.y();
44 tsi.b.x = v2.x(); tsi.b.y = v2.y();
45 tsi.c.x = v3.x(); tsi.c.y = v3.y();
46 vgl_vector_3d<double> b1(v2.x()-v1.x(), v2.y()-v1.y(), v2.z()-v1.z());
47 vgl_vector_3d<double> b2(v3.x()-v1.x(), v3.y()-v1.y(), v3.z()-v1.z());
48 vgl_vector_3d<double> n = cross_product(b1,b2);
49 double A = -n.x()/n.z();
50 double B = -n.y()/n.z();
51 double C = (v1.x()*n.x() + v1.y()*n.y() + v1.z()*n.z())/n.z();
52 for (tsi.reset(); tsi.next(); ) {
53 int y = tsi.scany();
54 if (y<0 || y>=int(image.nj())) continue;
55 int min_x = tsi.startx();
56 int max_x = tsi.endx();
57 if (min_x >= (int)image.ni() || max_x < 0)
58 continue;
59 if (min_x < 0) min_x = 0;
60 if (max_x >= (int)image.ni()) max_x = image.ni()-1;
61 double new_i = B*y+C;
62 for (int x = min_x; x <= max_x; ++x) {
63 double depth = new_i + A*x;
64 if (depth < depth_img(x,y)) {
65 depth_img(x,y) = depth;
66 image(x,y) = label;
67 }
68 }
69 }
70 }
71
72
73 //: Render a textured triangle defined by its vertices
74 // \p v1,v2,v3 are coordinates in the projected image (plus depth)
75 // \p t1,t2,t3 are corresponding texture coordinates (in the unit square)
76 void imesh_render_triangle_texture(const vgl_point_3d<double>& v1,
77 const vgl_point_3d<double>& v2,
78 const vgl_point_3d<double>& v3,
79 const vgl_point_2d<double>& t1,
80 const vgl_point_2d<double>& t2,
81 const vgl_point_2d<double>& t3,
82 const vil_image_view<vxl_byte>& texture,
83 vil_image_view<vxl_byte>& image,
84 vil_image_view<double>& depth_img);
85
86
87 //: Render the mesh using the camera and a texture image
88 // A depth map is also computed and used for occlusion.
89 // Texture mapping uses interpolates from the texture image with no
90 // additional lighting calculations.
91 void imesh_render_textured(const imesh_mesh& mesh,
92 const vpgl_proj_camera<double>& camera,
93 const vil_image_view<vxl_byte>& texture,
94 vil_image_view<vxl_byte>& image,
95 vil_image_view<double>& depth_img);
96
97 #endif // imesh_render_h_
98