Commit 5db14a389062b1e58193a036974d1f433dcbc683

Authored by David Mayerich
1 parent 1a31ffa0

added materials to the stim::obj object

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  
... ...
stim/visualization/obj/obj_material.h 0 → 100644
  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
... ...