00001
00002 #include "imesh_render.h"
00003
00004
00005
00006 #include <vcl_limits.h>
00007 #include <vcl_cassert.h>
00008 #include <imesh/algo/imesh_project.h>
00009 #include <imesh/imesh_operations.h>
00010 #include <vil/vil_bilin_interp.h>
00011
00012
00013
00014
00015 void imesh_render_triangle_texture(const vgl_point_3d<double>& v1,
00016 const vgl_point_3d<double>& v2,
00017 const vgl_point_3d<double>& v3,
00018 const vgl_point_2d<double>& t1,
00019 const vgl_point_2d<double>& t2,
00020 const vgl_point_2d<double>& t3,
00021 const vil_image_view<vxl_byte>& texture,
00022 vil_image_view<vxl_byte>& image,
00023 vil_image_view<double>& depth_img)
00024 {
00025 assert(depth_img.ni() == image.ni());
00026 assert(depth_img.nj() == image.nj());
00027
00028 unsigned tw = texture.ni();
00029 unsigned th = texture.nj();
00030 vnl_matrix_fixed<double,3,3> texmap =
00031 imesh_affine_map(vgl_point_2d<double>(v1.x(),v1.y()),
00032 vgl_point_2d<double>(v2.x(),v2.y()),
00033 vgl_point_2d<double>(v3.x(),v3.y()),
00034 vgl_point_2d<double>(t1.x()*tw,(1-t1.y())*th),
00035 vgl_point_2d<double>(t2.x()*tw,(1-t2.y())*th),
00036 vgl_point_2d<double>(t3.x()*tw,(1-t3.y())*th));
00037
00038 vgl_triangle_scan_iterator<double> tsi;
00039 tsi.a.x = v1.x(); tsi.a.y = v1.y();
00040 tsi.b.x = v2.x(); tsi.b.y = v2.y();
00041 tsi.c.x = v3.x(); tsi.c.y = v3.y();
00042 vgl_vector_3d<double> b1(v2.x()-v1.x(), v2.y()-v1.y(), v2.z()-v1.z());
00043 vgl_vector_3d<double> b2(v3.x()-v1.x(), v3.y()-v1.y(), v3.z()-v1.z());
00044 vgl_vector_3d<double> n = cross_product(b1,b2);
00045 double A = -n.x()/n.z();
00046 double B = -n.y()/n.z();
00047 double C = (v1.x()*n.x() + v1.y()*n.y() + v1.z()*n.z())/n.z();
00048 for (tsi.reset(); tsi.next(); ) {
00049 int y = tsi.scany();
00050 if (y<0 || y>=int(image.nj())) continue;
00051 int min_x = tsi.startx();
00052 int max_x = tsi.endx();
00053 if (min_x >= (int)image.ni() || max_x < 0)
00054 continue;
00055 if (min_x < 0) min_x = 0;
00056 if (max_x >= (int)image.ni()) max_x = image.ni()-1;
00057 double new_i = B*y+C;
00058 for (int x = min_x; x <= max_x; ++x) {
00059 double depth = new_i + A*x;
00060 if (depth < depth_img(x,y)) {
00061 depth_img(x,y) = depth;
00062 double tx = texmap[0][0]*x + texmap[0][1]*y + texmap[0][2];
00063 double ty = texmap[1][0]*x + texmap[1][1]*y + texmap[1][2];
00064 for (unsigned p=0; p<texture.nplanes(); ++p) {
00065 image(x,y,p) = (vxl_byte)vil_bilin_interp_safe(texture,tx,ty,p);
00066 }
00067 }
00068 }
00069 }
00070 }
00071
00072
00073
00074
00075
00076
00077 void imesh_render_textured(const imesh_mesh& mesh,
00078 const vpgl_proj_camera<double>& camera,
00079 const vil_image_view<vxl_byte>& texture,
00080 vil_image_view<vxl_byte>& image,
00081 vil_image_view<double>& depth_img)
00082 {
00083 assert(mesh.vertices().dim() == 3);
00084 assert(mesh.has_tex_coords() == imesh_mesh::TEX_COORD_ON_VERT);
00085 const vcl_vector<vgl_point_2d<double> >& tex_coords = mesh.tex_coords();
00086
00087 vcl_vector<vgl_point_2d<double> > verts2d;
00088 vcl_vector<double> depths;
00089 depth_img.fill(vcl_numeric_limits<double>::infinity());
00090 imesh_project_verts(mesh.vertices<3>(), camera, verts2d, depths);
00091 assert(tex_coords.size() == verts2d.size());
00092
00093 const imesh_face_array_base& faces = mesh.faces();
00094 vcl_auto_ptr<imesh_regular_face_array<3> > tri_data;
00095 const imesh_regular_face_array<3>* tris;
00096 if (faces.regularity() != 3) {
00097 tri_data = imesh_triangulate(faces);
00098 tris = tri_data.get();
00099 }
00100 else {
00101 tris = static_cast<const imesh_regular_face_array<3>*>(&faces);
00102 }
00103
00104 for (unsigned i=0; i<tris->size(); ++i) {
00105 const imesh_regular_face<3>& tri = (*tris)[i];
00106 const vgl_point_2d<double>& v1 = verts2d[tri[0]];
00107 const vgl_point_2d<double>& v2 = verts2d[tri[1]];
00108 const vgl_point_2d<double>& v3 = verts2d[tri[2]];
00109 const vgl_point_2d<double>& t1 = tex_coords[tri[0]];
00110 const vgl_point_2d<double>& t2 = tex_coords[tri[1]];
00111 const vgl_point_2d<double>& t3 = tex_coords[tri[2]];
00112
00113 vgl_point_3d<double> p1(v1.x(),v1.y(),depths[tri[0]]);
00114 vgl_point_3d<double> p2(v2.x(),v2.y(),depths[tri[1]]);
00115 vgl_point_3d<double> p3(v3.x(),v3.y(),depths[tri[2]]);
00116 imesh_render_triangle_texture(p1,p2,p3,t1,t2,t3,texture,image,depth_img);
00117 }
00118 }