1 // This is brl/bseg/boxm2/pro/processes/boxm2_paint_mesh_process.cxx
2 #include <iostream>
3 #include <fstream>
4 #include <bprb/bprb_func_process.h>
5 //:
6 // \file
7 // \brief  A process for assigning colors to the vertices of a given mesh.
8 // There is also a threshold prob_t on probability of points to output.
9 // Points with lower probability than prob_t are assigned a color of (0,0,0).
10 //
11 // \author Ali Osman Ulusoy
12 // \date Mar 02, 2012
13 
14 #include <boxm2/boxm2_scene.h>
15 #include <boxm2/boxm2_util.h>
16 #include <boxm2/io/boxm2_cache.h>
17 
18 #include <bvrml/bvrml_write.h>
19 #include <boxm2/cpp/algo/boxm2_gauss_rgb_processor.h>
20 
21 #include <bmsh3d/algo/bmsh3d_fileio.h>
22 #include <boct/boct_bit_tree.h>
23 
24 #ifdef _MSC_VER
25 #  include "vcl_msvc_warnings.h"
26 #endif
27 #include <cassert>
28 
29 #include <rply.h>
30 
31 namespace boxm2_paint_mesh_process_globals
32 {
33   constexpr unsigned n_inputs_ = 5;
34   constexpr unsigned n_outputs_ = 0;
35 }
36 
boxm2_paint_mesh_process_cons(bprb_func_process & pro)37 bool boxm2_paint_mesh_process_cons(bprb_func_process& pro)
38 {
39   using namespace boxm2_paint_mesh_process_globals;
40 
41   //process takes 4 or 5 inputs and no outputs
42   std::vector<std::string> input_types_(n_inputs_);
43   input_types_[0] = "boxm2_scene_sptr";
44   input_types_[1] = "boxm2_cache_sptr";
45   input_types_[2] = "vcl_string"; //input mesh filename
46   input_types_[3] = "vcl_string"; //output mesh filename
47   input_types_[4] = "float"; //prob threshold
48 
49   brdb_value_sptr prob_t = new brdb_value_t<float>(0.0);
50   pro.set_input(4, prob_t);
51 
52   std::vector<std::string>  output_types_(n_outputs_);
53   return pro.set_input_types(input_types_)
54       && pro.set_output_types(output_types_);
55 }
56 
boxm2_paint_mesh_process(bprb_func_process & pro)57 bool boxm2_paint_mesh_process(bprb_func_process& pro)
58 {
59   using namespace boxm2_paint_mesh_process_globals;
60 
61   if ( pro.n_inputs() < n_inputs_ ) {
62     std::cout << pro.name() << ": The input number should be " << n_inputs_<< std::endl;
63     return false;
64   }
65 
66   //get the inputs
67   unsigned i = 0;
68   boxm2_scene_sptr scene = pro.get_input<boxm2_scene_sptr>(i++);
69   boxm2_cache_sptr cache = pro.get_input<boxm2_cache_sptr>(i++);
70   std::string input_mesh_filename = pro.get_input<std::string>(i++);
71   std::string output_mesh_filename = pro.get_input<std::string>(i++);
72   auto prob_t = pro.get_input<float>(i++);
73 
74   bool foundDataType = false;
75 
76   std::string data_type;
77   std::vector<std::string> apps = scene->appearances();
78   for (const auto & app : apps) {
79       if ( app == boxm2_data_traits<BOXM2_GAUSS_RGB>::prefix() )
80       {
81           data_type = app;
82           foundDataType = true;
83           // boxm2_data_info::datasize(boxm2_data_traits<BOXM2_GAUSS_RGB>::prefix());
84       }
85   }
86 
87   if (!foundDataType) {
88       std::cout<<"BOXM2_PAINT_MESH_PROCESS ERROR: scene doesn't have GAUSS_RGB appearance..."<<std::endl;
89       return false;
90   }
91 
92   //read incoming mesh
93   bmsh3d_mesh input_mesh;
94   bmsh3d_load_ply (&input_mesh, input_mesh_filename.c_str());
95   input_mesh.assign_IFS_vertex_vid_by_vertex_order();
96 
97   //print input mesh summary
98   input_mesh.print_summary(std::cout);
99 
100   //write outgoing mesh header
101   p_ply oply = ply_create(output_mesh_filename.c_str(), PLY_ASCII, nullptr, 0, nullptr);
102 
103   // HEADER SECTION
104   // vertex
105   ply_add_element(oply, "vertex", input_mesh.vertexmap().size());
106   ply_add_scalar_property(oply, "x", PLY_FLOAT); //PLY_FLOAT
107   ply_add_scalar_property(oply, "y", PLY_FLOAT); //PLY_FLOAT
108   ply_add_scalar_property(oply, "z", PLY_FLOAT); //PLY_FLOAT
109   ply_add_scalar_property(oply, "diffuse_red", PLY_UCHAR); //PLY_UCHAR
110   ply_add_scalar_property(oply, "diffuse_green", PLY_UCHAR); //PLY_UCHAR
111   ply_add_scalar_property(oply, "diffuse_blue", PLY_UCHAR); //PLY_UCHAR
112 
113   // face
114   ply_add_element(oply, "face", input_mesh.facemap().size());
115   ply_add_list_property(oply, "vertex_indices", PLY_UCHAR, PLY_INT);
116 
117   // end header
118   ply_write_header(oply);
119 
120   std::cout << "Start iterating over pts..." << std::endl;
121   //zip thru points
122   float prob;
123   vnl_vector_fixed<float,3> intensity;
124   vgl_point_3d<double> local;
125   boxm2_block_id id;
126   for (unsigned  i = 0; i < input_mesh.num_vertices(); i++) {
127     const vgl_point_3d<double> pt = input_mesh.vertexmap(i)->pt();
128 
129     if (!scene->contains(pt, id, local)) {
130       std::cout << "ERROR: point: " << pt << " isn't in scene. Exiting...." << std::endl;
131       return false;
132     }
133 
134     int index_x=(int)std::floor(local.x());
135     int index_y=(int)std::floor(local.y());
136     int index_z=(int)std::floor(local.z());
137     boxm2_block * blk=cache->get_block(scene,id);
138     boxm2_block_metadata mdata = scene->get_block_metadata_const(id);
139     vnl_vector_fixed<unsigned char,16> treebits=blk->trees()(index_x,index_y,index_z);
140     boct_bit_tree tree(treebits.data_block(),mdata.max_level_);
141     int bit_index=tree.traverse(local);
142 
143     int depth=tree.depth_at(bit_index);
144 
145     int data_offset=tree.get_data_index(bit_index,false);
146     boxm2_data_base *  alpha_base = cache->get_data_base(scene,id,boxm2_data_traits<BOXM2_ALPHA>::prefix());
147     boxm2_data<BOXM2_ALPHA> *alpha_data=new boxm2_data<BOXM2_ALPHA>(alpha_base->data_buffer(),alpha_base->buffer_length(),alpha_base->block_id());
148 
149     float alpha=(alpha_data->data())[data_offset];
150     double side_len = 1.0 / (double) (1 << depth);
151     //store cell probability
152     prob = 1.0f - (float)std::exp(-alpha * side_len * mdata.sub_block_dim_.x());
153 
154     boxm2_data_base *  int_base = cache->get_data_base(scene,id, data_type);
155     if (data_type.find(boxm2_data_traits<BOXM2_GAUSS_RGB>::prefix()) != std::string::npos) {
156       boxm2_data<BOXM2_GAUSS_RGB> *int_data = new boxm2_data<BOXM2_GAUSS_RGB>(int_base->data_buffer(),int_base->buffer_length(),int_base->block_id());
157       intensity = boxm2_gauss_rgb_processor::expected_color( (int_data->data())[data_offset]);
158     }
159 
160     ply_write(oply, pt.x());
161     ply_write(oply, pt.y());
162     ply_write(oply, pt.z());
163 
164     if (prob >= prob_t) {
165       ply_write(oply, (unsigned char)(intensity[0]*255.0f) );
166       ply_write(oply, (unsigned char)(intensity[1]*255.0f) );
167       ply_write(oply, (unsigned char)(intensity[2]*255.0f) );
168     }
169     else {
170       ply_write(oply, 0 );
171       ply_write(oply, 0 );
172       ply_write(oply, 0 );
173     }
174   }
175   std::cout << "Done iterating over pts..." << std::endl;
176 
177   // faces
178   auto fit = input_mesh.facemap().begin();
179   for (; fit != input_mesh.facemap().end(); fit++)
180   {
181     bmsh3d_face* f = (*fit).second;
182 
183     // a. write the number of vertices of the face
184     ply_write(oply,f->vertices().size());
185 
186     // b. write id's of the vertices
187     for (unsigned int j=0; j< f->vertices().size(); ++j)
188     {
189       bmsh3d_vertex* v = f->vertices(j);
190       assert(v);
191       ply_write(oply, v->vid());
192     }
193   }
194 
195   // CLOSE PLY FILE
196   ply_close(oply);
197 
198   return true;
199 }
200