2#include <cgv/utils/file.h>
3#include <cgv/base/import.h>
4#include <cgv/type/standard_types.h>
6#include <cgv/utils/tokenizer.h>
7#include <cgv/base/import.h>
9using namespace cgv::math;
12using namespace cgv::media::illum;
15#pragma warning(disable:4996)
22 bool is_double_impl(
const char* begin,
const char* end,
float& value)
26 value = (float)valued;
30 bool is_double_impl(
const char* begin,
const char* end,
double& value)
37bool obj_reader_generic<T>::is_double(
const char* begin,
const char* end, coord_type& value)
39 return is_double_impl(begin, end, value);
65 float v[4] = {0,0,0,1};
67 is_double_impl(t[1+off].begin,t[1+off].end, v[0]) &&
68 is_double_impl(t[2+off].begin,t[2+off].end, v[1]) &&
69 is_double_impl(t[3+off].begin,t[3+off].end, v[2]);
71 is_double_impl(t[4+off].begin,t[4+off].end, v[3]);
72 return color_type((
float)v[0],(
float)v[1],(
float)v[2],(
float)v[3]);
87obj_reader_base::obj_reader_base()
94 mtl_lib_files.clear();
99 nr_normals = nr_texcoords = 0;
101 have_default_material =
false;
139 int *texcoords,
int *normals,
140 unsigned v,
unsigned n,
unsigned t)
142 for (
unsigned int i=0; i<vcount; ++i) {
146 if (texcoords[i] < 0)
180 process_vertex(parse_vec3(tokens));
184void obj_reader_generic<T>::parse_and_process_normal(
const std::vector<cgv::utils::token>& tokens)
186 process_normal(parse_vec3(tokens));
190void obj_reader_generic<T>::parse_and_process_texcoord(
const std::vector<cgv::utils::token>& tokens)
192 process_texcoord(parse_vec2(tokens));
209 std::vector<line> lines;
216 nr_normals = nr_texcoords = 0;
217 std::map<std::string,unsigned> group_index_lut;
218 std::vector<token> tokens;
219 for (
unsigned li=0; li<lines.size(); ++li) {
221 printf(
"%d Percent done.\r", (
int)(100.0*li/(lines.size()-1)) );
224 if (tokens.size() == 0)
227 switch (tokens[0][0]) {
229 if (tokens[0].size() == 1) {
230 parse_and_process_vertex(tokens);
231 if (tokens.size() >= 7)
235 switch (tokens[0][1]) {
237 parse_and_process_normal(tokens);
241 parse_and_process_texcoord(tokens);
264 have_default_material =
true;
275 parse_face(tokens,
true);
278 if (tokens.size() > 1) {
280 std::string parameters;
281 if (tokens.size() > 2)
282 parameters.assign(tokens[2].begin, tokens.back().end - tokens[2].begin);
284 std::map<std::string,unsigned>::iterator it =
285 group_index_lut.find(name);
287 if (it != group_index_lut.end())
299 parse_material(tokens);
300 else if (
to_string(tokens[0]) ==
"mtllib") {
301 if (tokens.size() > 1)
319 if (mtl_lib_files.find(fn) != mtl_lib_files.end())
323 if (!file::read(fn, content,
true))
326 mtl_lib_files.insert(fn);
328 std::vector<line> lines;
331 std::vector<token> tokens;
335 for (
unsigned li=0; li<lines.size(); ++li) {
338 if (tokens.size() == 0)
340 if (tokens[0] ==
"newmtl") {
354 if (tokens.size() > 1)
357 else if (tokens[0] ==
"map_Ka" && tokens.size() > 1)
359 else if (tokens[0] ==
"map_Kd" && tokens.size() > 1)
361 else if (tokens[0] ==
"map_d" && tokens.size() > 1)
363 else if (tokens[0] ==
"map_Ks" && tokens.size() > 1)
365 else if (tokens[0] ==
"map_Ke" && tokens.size() > 1)
367 else if (tokens[0] ==
"Ka")
369 else if (tokens[0] ==
"Kd")
371 else if (tokens[0] ==
"Ks")
373 else if (tokens[0] ==
"Ke")
375 else if (tokens[0] ==
"Ns")
376 mtl.set_shininess((
float)atof(
to_string(tokens.back()).c_str()));
377 else if (tokens[0] ==
"d")
379 else if (tokens[0] ==
"bump") {
380 for (
unsigned i=1; i<tokens.size(); ++i) {
381 if (tokens[i] ==
"-bm") {
382 if (i+1 < tokens.size()) {
407void obj_reader_base::parse_material(
const std::vector<token>& tokens)
409 if (tokens.size() < 2)
412 std::map<std::string,unsigned>::iterator it =
419void obj_reader_base::parse_face(
const std::vector<token>& tokens,
bool is_line)
421 std::vector<int> vertex_indices;
422 std::vector<int> normal_indices;
423 std::vector<int> texcoord_indices;
425 for(
unsigned i = 1; i < tokens.size(); i++) {
426 std::vector<token> smaller_tokens;
428 if (smaller_tokens.size() < 1)
430 int vi = atoi(
to_string(smaller_tokens[0]).c_str());
433 vertex_indices.push_back(vi);
434 if (smaller_tokens.size() == 1) {
435 if ((
int)nr_normals > vi)
436 normal_indices.push_back(vi);
437 if ((
int)nr_texcoords > vi)
438 texcoord_indices.push_back(vi);
441 if (smaller_tokens.size() < 3)
444 if (smaller_tokens[j] !=
"/") {
445 int ti = atoi(
to_string(smaller_tokens[j]).c_str());
448 if ((
int)nr_texcoords > ti)
449 texcoord_indices.push_back(ti);
452 if (smaller_tokens.size() < j+2)
454 int ni = atoi(
to_string(smaller_tokens[j+1]).c_str());
457 if ((
int)nr_normals > ni)
458 normal_indices.push_back(ni);
461 if (normal_indices.size() == vertex_indices.size())
462 nml_ptr = &normal_indices[0];
464 if (texcoord_indices.size() == vertex_indices.size())
465 tex_ptr = &texcoord_indices[0];
467 process_line((
unsigned)vertex_indices.size(), &vertex_indices[0], tex_ptr, nml_ptr);
469 process_face((
unsigned) vertex_indices.size(), &vertex_indices[0], tex_ptr, nml_ptr);
473template class obj_reader_generic < float >;
474template class obj_reader_generic < double >;
More advanced text processing for splitting text into lines or tokens.
the tokenizer allows to split text into tokens in a convenient way.
tokenizer & set_sep(const std::string &sep, bool merge)
set the list of separators and specify whether succeeding separators are merged into single tokens
bool read_data_file(const std::string &file_name, std::string &content, bool ascii)
read ascii file into a string
std::string find_data_file(const std::string &file_name, const std::string &strategy, const std::string &sub_directory, const std::string &master_path)
Find a file with the given strategy and return the file name extended by the necessary path.
namespace for compile time type information
namespace that holds tools that dont fit any other namespace
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
void split_to_lines(const char *global_begin, const char *global_end, std::vector< line > &lines, bool truncate_trailing_spaces)
this function splits a text range at the newline characters into single lines.
bool is_double(const char *begin, const char *end, double &value)
check if the text range (begin,end( defines a double value. If yes, store the value in the passed ref...