Commit 5db14a389062b1e58193a036974d1f433dcbc683
1 parent
1a31ffa0
added materials to the stim::obj object
Showing
2 changed files
with
185 additions
and
12 deletions
Show diff stats
stim/visualization/obj.h
@@ -7,6 +7,8 @@ | @@ -7,6 +7,8 @@ | ||
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include <stim/parser/parser.h> | 8 | #include <stim/parser/parser.h> |
9 | #include <stim/math/vector.h> | 9 | #include <stim/math/vector.h> |
10 | +#include <stim/visualization/obj/obj_material.h> | ||
11 | +#include <stim/parser/filename.h> | ||
10 | #include <algorithm> | 12 | #include <algorithm> |
11 | 13 | ||
12 | #include <time.h> | 14 | #include <time.h> |
@@ -93,13 +95,13 @@ protected: | @@ -93,13 +95,13 @@ protected: | ||
93 | }; //end vertex | 95 | }; //end vertex |
94 | 96 | ||
95 | //triplet used to specify geometric vertices consisting of a position vertex, texture vertex, and normal | 97 | //triplet used to specify geometric vertices consisting of a position vertex, texture vertex, and normal |
96 | - struct triplet : public std::vector<unsigned int>{ | 98 | + struct triplet : public std::vector<size_t>{ |
97 | 99 | ||
98 | //default constructor, empty triplet | 100 | //default constructor, empty triplet |
99 | triplet(){} | 101 | triplet(){} |
100 | 102 | ||
101 | //create a triplet given a parameter list (OBJ indices start at 1, so 0 can be used to indicate no value) | 103 | //create a triplet given a parameter list (OBJ indices start at 1, so 0 can be used to indicate no value) |
102 | - triplet(unsigned int v, unsigned int vt = 0, unsigned int vn = 0){ | 104 | + triplet(size_t v, size_t vt = 0, size_t vn = 0){ |
103 | push_back(v); | 105 | push_back(v); |
104 | if(vn != 0){ | 106 | if(vn != 0){ |
105 | push_back(vt); | 107 | push_back(vt); |
@@ -140,12 +142,12 @@ protected: | @@ -140,12 +142,12 @@ protected: | ||
140 | 142 | ||
141 | if(size() == 3){ | 143 | if(size() == 3){ |
142 | if(at(1) == 0) | 144 | if(at(1) == 0) |
143 | - ss<<"\\\\"<<at(2); | 145 | + ss<<"//"<<at(2); |
144 | else | 146 | else |
145 | - ss<<'\\'<<at(1)<<'\\'<<at(2); | 147 | + ss<<'/'<<at(1)<<'/'<<at(2); |
146 | } | 148 | } |
147 | else if(size() == 2) | 149 | else if(size() == 2) |
148 | - ss<<"\\"<<at(1); | 150 | + ss<<"/"<<at(1); |
149 | 151 | ||
150 | return ss.str(); | 152 | return ss.str(); |
151 | } | 153 | } |
@@ -223,10 +225,16 @@ protected: | @@ -223,10 +225,16 @@ protected: | ||
223 | std::vector<geometry> P; //list of points structures | 225 | std::vector<geometry> P; //list of points structures |
224 | std::vector<geometry> F; //list of faces | 226 | std::vector<geometry> F; //list of faces |
225 | 227 | ||
228 | + //material lists | ||
229 | + std::vector< obj_material<T> > M; //list of material descriptors | ||
230 | + std::vector<size_t> Mf; //face index where each material begins | ||
231 | + | ||
226 | //information for the current geometric object | 232 | //information for the current geometric object |
227 | geometry current_geo; | 233 | geometry current_geo; |
228 | vertex current_vt; | 234 | vertex current_vt; |
229 | vertex current_vn; | 235 | vertex current_vn; |
236 | + obj_material<T> current_material; //stores the current material | ||
237 | + bool new_material; //flags if a material property has been changed since the last material was pushed | ||
230 | 238 | ||
231 | //flags for the current geometric object | 239 | //flags for the current geometric object |
232 | obj_type current_type; | 240 | obj_type current_type; |
@@ -258,9 +266,9 @@ protected: | @@ -258,9 +266,9 @@ protected: | ||
258 | //create a triple and add it to the current geometry | 266 | //create a triple and add it to the current geometry |
259 | void update_v(vertex vv){ | 267 | void update_v(vertex vv){ |
260 | 268 | ||
261 | - unsigned int v; | ||
262 | - unsigned int vt = 0; | ||
263 | - unsigned int vn = 0; | 269 | + size_t v; |
270 | + size_t vt = 0; | ||
271 | + size_t vn = 0; | ||
264 | 272 | ||
265 | //if the current geometry is using a texture coordinate, add the current texture coordinate to the geometry | 273 | //if the current geometry is using a texture coordinate, add the current texture coordinate to the geometry |
266 | if(geo_flag_vt){ | 274 | if(geo_flag_vt){ |
@@ -303,6 +311,8 @@ protected: | @@ -303,6 +311,8 @@ protected: | ||
303 | geo_flag_vn = false; | 311 | geo_flag_vn = false; |
304 | vert_flag_vt = false; | 312 | vert_flag_vt = false; |
305 | vert_flag_vn = false; | 313 | vert_flag_vn = false; |
314 | + | ||
315 | + new_material = false; //initialize a new material to false (start with no material) | ||
306 | } | 316 | } |
307 | 317 | ||
308 | //gets the type of token representing the entry in the OBJ file | 318 | //gets the type of token representing the entry in the OBJ file |
@@ -346,10 +356,80 @@ public: | @@ -346,10 +356,80 @@ public: | ||
346 | void Vertex(T x, T y, T z){ update_v(vertex(x, y, z));} | 356 | void Vertex(T x, T y, T z){ update_v(vertex(x, y, z));} |
347 | void Vertex(T x, T y, T z, T w){ update_v(vertex(x, y, z, w));} | 357 | void Vertex(T x, T y, T z, T w){ update_v(vertex(x, y, z, w));} |
348 | 358 | ||
359 | + ///Material functions | ||
360 | + void matKa(T r, T g, T b) { | ||
361 | + new_material = true; | ||
362 | + current_material.ka[0] = r; | ||
363 | + current_material.ka[1] = g; | ||
364 | + current_material.ka[2] = b; | ||
365 | + } | ||
366 | + void matKa(std::string tex = std::string()) { | ||
367 | + new_material = true; | ||
368 | + current_material.tex_ka = tex; | ||
369 | + } | ||
370 | + void matKd(T r, T g, T b) { | ||
371 | + new_material = true; | ||
372 | + current_material.kd[0] = r; | ||
373 | + current_material.kd[1] = g; | ||
374 | + current_material.kd[2] = b; | ||
375 | + } | ||
376 | + void matKd(std::string tex = std::string()) { | ||
377 | + new_material = true; | ||
378 | + current_material.tex_kd = tex; | ||
379 | + } | ||
380 | + void matKs(T r, T g, T b) { | ||
381 | + new_material = true; | ||
382 | + current_material.ks[0] = r; | ||
383 | + current_material.ks[1] = g; | ||
384 | + current_material.ks[2] = b; | ||
385 | + } | ||
386 | + void matKs(std::string tex = std::string()) { | ||
387 | + new_material = true; | ||
388 | + current_material.tex_ks = tex; | ||
389 | + } | ||
390 | + void matNs(T n) { | ||
391 | + new_material = true; | ||
392 | + current_material.ns = n; | ||
393 | + } | ||
394 | + void matNs(std::string tex = std::string()) { | ||
395 | + new_material = true; | ||
396 | + current_material.tex_ns = tex; | ||
397 | + } | ||
398 | + void matIllum(int i) { | ||
399 | + new_material = true; | ||
400 | + current_material.illum = i; | ||
401 | + } | ||
402 | + void matD(std::string tex = std::string()) { | ||
403 | + new_material = true; | ||
404 | + current_material.tex_alpha = tex; | ||
405 | + } | ||
406 | + void matBump(std::string tex = std::string()) { | ||
407 | + new_material = true; | ||
408 | + current_material.tex_bump = tex; | ||
409 | + } | ||
410 | + void matDisp(std::string tex = std::string()) { | ||
411 | + new_material = true; | ||
412 | + current_material.tex_disp = tex; | ||
413 | + } | ||
414 | + void matDecal(std::string tex = std::string()) { | ||
415 | + new_material = true; | ||
416 | + current_material.tex_decal = tex; | ||
417 | + } | ||
418 | + | ||
349 | ///This function starts drawing of a primitive object, such as a line, face, or point set | 419 | ///This function starts drawing of a primitive object, such as a line, face, or point set |
350 | 420 | ||
351 | /// @param t is the type of object to be drawn: OBJ_POINTS, OBJ_LINE, OBJ_FACE | 421 | /// @param t is the type of object to be drawn: OBJ_POINTS, OBJ_LINE, OBJ_FACE |
352 | void Begin(obj_type t){ | 422 | void Begin(obj_type t){ |
423 | + if (new_material) { //if a new material has been specified | ||
424 | + if (current_material.name == "") { //if a name wasn't given, create a new one | ||
425 | + std::stringstream ss; //create a name for it | ||
426 | + ss << "material" << M.size(); //base it on the material number | ||
427 | + current_material.name = ss.str(); | ||
428 | + } | ||
429 | + Mf.push_back(F.size()); //start the material at the current face index | ||
430 | + M.push_back(current_material); //push the current material | ||
431 | + current_material.name = ""; //reset the name of the current material | ||
432 | + } | ||
353 | current_type = t; | 433 | current_type = t; |
354 | } | 434 | } |
355 | 435 | ||
@@ -468,10 +548,15 @@ public: | @@ -468,10 +548,15 @@ public: | ||
468 | } | 548 | } |
469 | } | 549 | } |
470 | 550 | ||
471 | - //output all of the lines | 551 | + //output all of the faces |
472 | if(F.size()){ | 552 | if(F.size()){ |
473 | ss<<std::endl<<"#face structures"<<std::endl; | 553 | ss<<std::endl<<"#face structures"<<std::endl; |
554 | + size_t mi = 0; //start the current material index at 0 | ||
474 | for(i = 0; i < F.size(); i++){ | 555 | for(i = 0; i < F.size(); i++){ |
556 | + if (mi < M.size() && Mf[mi] == i) { | ||
557 | + ss << "usemtl " << M[mi].name << std::endl; | ||
558 | + mi++; | ||
559 | + } | ||
475 | ss<<"f "<<F[i].str()<<std::endl; | 560 | ss<<"f "<<F[i].str()<<std::endl; |
476 | } | 561 | } |
477 | } | 562 | } |
@@ -479,6 +564,14 @@ public: | @@ -479,6 +564,14 @@ public: | ||
479 | return ss.str(); //return the constructed string | 564 | return ss.str(); //return the constructed string |
480 | } | 565 | } |
481 | 566 | ||
567 | + ///Output the material file as a string | ||
568 | + std::string matstr() { | ||
569 | + std::stringstream ss; | ||
570 | + for (size_t i = 0; i < M.size(); i++) { | ||
571 | + ss << M[i].str() << std::endl; | ||
572 | + } | ||
573 | + } | ||
574 | + | ||
482 | obj(){ | 575 | obj(){ |
483 | init(); //private function that initializes everything | 576 | init(); //private function that initializes everything |
484 | } | 577 | } |
@@ -492,19 +585,42 @@ public: | @@ -492,19 +585,42 @@ public: | ||
492 | /// @param filename is the name of the file to be saved | 585 | /// @param filename is the name of the file to be saved |
493 | bool save(std::string filename){ | 586 | bool save(std::string filename){ |
494 | 587 | ||
495 | - std::ofstream outfile(filename.c_str()); | 588 | + |
496 | 589 | ||
497 | - if(!outfile){ | ||
498 | - std::cout<<"STIM::OBJ error opening file for writing"<<std::endl; | 590 | + std::string obj_ext = ".obj"; |
591 | + size_t ext_found = filename.find(obj_ext); | ||
592 | + if (ext_found != std::string::npos) //if the extension was found | ||
593 | + filename = filename.substr(0, ext_found); | ||
594 | + std::string obj_filename; | ||
595 | + std::string mtl_filename; | ||
596 | + obj_filename = filename + ".obj"; | ||
597 | + mtl_filename = filename + ".mtl"; | ||
598 | + | ||
599 | + | ||
600 | + std::ofstream outfile(obj_filename.c_str()); | ||
601 | + if (!outfile) { | ||
602 | + std::cout << "STIM::OBJ error opening file for writing" << std::endl; | ||
499 | return false; | 603 | return false; |
500 | } | 604 | } |
501 | 605 | ||
606 | + if (M.size()) //if there are any materials, there will be a corresponding material file | ||
607 | + outfile << "mtllib " << mtl_filename << std::endl; //output the material library name | ||
608 | + | ||
502 | //output the OBJ data to the file | 609 | //output the OBJ data to the file |
503 | outfile<<str(); | 610 | outfile<<str(); |
504 | 611 | ||
505 | //close the file | 612 | //close the file |
506 | outfile.close(); | 613 | outfile.close(); |
507 | 614 | ||
615 | + if (M.size()) { //if materials are used | ||
616 | + | ||
617 | + outfile.open(mtl_filename); //open the material file | ||
618 | + for (size_t i = 0; i < M.size(); i++) { //for each material | ||
619 | + outfile << M[i].str() << std::endl; //output the material name and properties | ||
620 | + } | ||
621 | + outfile.close(); | ||
622 | + } | ||
623 | + | ||
508 | return true; | 624 | return true; |
509 | } | 625 | } |
510 | 626 |
1 | +#ifndef OBJ_MATERIAL_H | ||
2 | +#define OBJ_MATERIAL_H | ||
3 | + | ||
4 | +#include <sstream> | ||
5 | + | ||
6 | +namespace stim { | ||
7 | + | ||
8 | +template<typename T> | ||
9 | +struct obj_material { | ||
10 | + std::string name; //material name | ||
11 | + T ka[3]; //ambient color | ||
12 | + T kd[3]; //diffuse color | ||
13 | + T ks[3]; //specular color | ||
14 | + T ns; //specular exponent | ||
15 | + | ||
16 | + int illum; //illumination model | ||
17 | + | ||
18 | + std::string tex_ka; //ambient texture | ||
19 | + std::string tex_kd; //diffuse texture | ||
20 | + std::string tex_ks; //specular texture | ||
21 | + std::string tex_ns; //texture map for the specular exponent | ||
22 | + std::string tex_alpha; //texture map for the alpha component | ||
23 | + std::string tex_bump; //bump map | ||
24 | + std::string tex_disp; //displacement map | ||
25 | + std::string tex_decal; //stencil decal | ||
26 | + | ||
27 | + obj_material() { //constructor | ||
28 | + memset(ka, 0, sizeof(T) * 3); | ||
29 | + memset(kd, 0, sizeof(T) * 3); | ||
30 | + memset(ks, 0, sizeof(T) * 3); | ||
31 | + ns = 10; | ||
32 | + illum = 2; | ||
33 | + | ||
34 | + } | ||
35 | + std::string str() { | ||
36 | + std::stringstream ss; | ||
37 | + ss << "newmtl " << name << std::endl; | ||
38 | + ss << "Ka " << ka[0] << " " << ka[1] << " " << ka[2] << std::endl; | ||
39 | + ss << "Kd " << kd[0] << " " << kd[1] << " " << kd[2] << std::endl; | ||
40 | + ss << "Ks " << ks[0] << " " << ks[1] << " " << ks[2] << std::endl; | ||
41 | + ss << "Ns " << ns << std::endl; | ||
42 | + ss << "illum " << illum << std::endl; | ||
43 | + if (tex_ka != "") ss << "map_Ka " << tex_ka << std::endl; | ||
44 | + if (tex_kd != "") ss << "map_Kd " << tex_kd << std::endl; | ||
45 | + if (tex_ks != "") ss << "map_Ks " << tex_ks << std::endl; | ||
46 | + if (tex_ns != "") ss << "map_Ns " << tex_ns << std::endl; | ||
47 | + if (tex_alpha != "") ss << "map_d " << tex_alpha << std::endl; | ||
48 | + if (tex_bump != "") ss << "bump " << tex_bump << std::endl; | ||
49 | + if (tex_disp != "") ss << "disp " << tex_disp << std::endl; | ||
50 | + if (tex_decal != "") ss << "decal " << tex_decal << std::endl; | ||
51 | + return ss.str(); | ||
52 | + } | ||
53 | +}; | ||
54 | + | ||
55 | +} //end namespace stim | ||
56 | + | ||
57 | +#endif | ||
0 | \ No newline at end of file | 58 | \ No newline at end of file |