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 | 7 | #include <stdlib.h> |
8 | 8 | #include <stim/parser/parser.h> |
9 | 9 | #include <stim/math/vector.h> |
10 | +#include <stim/visualization/obj/obj_material.h> | |
11 | +#include <stim/parser/filename.h> | |
10 | 12 | #include <algorithm> |
11 | 13 | |
12 | 14 | #include <time.h> |
... | ... | @@ -93,13 +95,13 @@ protected: |
93 | 95 | }; //end vertex |
94 | 96 | |
95 | 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 | 100 | //default constructor, empty triplet |
99 | 101 | triplet(){} |
100 | 102 | |
101 | 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 | 105 | push_back(v); |
104 | 106 | if(vn != 0){ |
105 | 107 | push_back(vt); |
... | ... | @@ -140,12 +142,12 @@ protected: |
140 | 142 | |
141 | 143 | if(size() == 3){ |
142 | 144 | if(at(1) == 0) |
143 | - ss<<"\\\\"<<at(2); | |
145 | + ss<<"//"<<at(2); | |
144 | 146 | else |
145 | - ss<<'\\'<<at(1)<<'\\'<<at(2); | |
147 | + ss<<'/'<<at(1)<<'/'<<at(2); | |
146 | 148 | } |
147 | 149 | else if(size() == 2) |
148 | - ss<<"\\"<<at(1); | |
150 | + ss<<"/"<<at(1); | |
149 | 151 | |
150 | 152 | return ss.str(); |
151 | 153 | } |
... | ... | @@ -223,10 +225,16 @@ protected: |
223 | 225 | std::vector<geometry> P; //list of points structures |
224 | 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 | 232 | //information for the current geometric object |
227 | 233 | geometry current_geo; |
228 | 234 | vertex current_vt; |
229 | 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 | 239 | //flags for the current geometric object |
232 | 240 | obj_type current_type; |
... | ... | @@ -258,9 +266,9 @@ protected: |
258 | 266 | //create a triple and add it to the current geometry |
259 | 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 | 273 | //if the current geometry is using a texture coordinate, add the current texture coordinate to the geometry |
266 | 274 | if(geo_flag_vt){ |
... | ... | @@ -303,6 +311,8 @@ protected: |
303 | 311 | geo_flag_vn = false; |
304 | 312 | vert_flag_vt = false; |
305 | 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 | 318 | //gets the type of token representing the entry in the OBJ file |
... | ... | @@ -346,10 +356,80 @@ public: |
346 | 356 | void Vertex(T x, T y, T z){ update_v(vertex(x, y, z));} |
347 | 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 | 419 | ///This function starts drawing of a primitive object, such as a line, face, or point set |
350 | 420 | |
351 | 421 | /// @param t is the type of object to be drawn: OBJ_POINTS, OBJ_LINE, OBJ_FACE |
352 | 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 | 433 | current_type = t; |
354 | 434 | } |
355 | 435 | |
... | ... | @@ -468,10 +548,15 @@ public: |
468 | 548 | } |
469 | 549 | } |
470 | 550 | |
471 | - //output all of the lines | |
551 | + //output all of the faces | |
472 | 552 | if(F.size()){ |
473 | 553 | ss<<std::endl<<"#face structures"<<std::endl; |
554 | + size_t mi = 0; //start the current material index at 0 | |
474 | 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 | 560 | ss<<"f "<<F[i].str()<<std::endl; |
476 | 561 | } |
477 | 562 | } |
... | ... | @@ -479,6 +564,14 @@ public: |
479 | 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 | 575 | obj(){ |
483 | 576 | init(); //private function that initializes everything |
484 | 577 | } |
... | ... | @@ -492,19 +585,42 @@ public: |
492 | 585 | /// @param filename is the name of the file to be saved |
493 | 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 | 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 | 609 | //output the OBJ data to the file |
503 | 610 | outfile<<str(); |
504 | 611 | |
505 | 612 | //close the file |
506 | 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 | 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 | 58 | \ No newline at end of file | ... | ... |