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