diff --git a/CMakeLists.txt b/CMakeLists.txt index 2966fef..8b5dd82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,6 +194,7 @@ include_directories( ${TINYFD_INCLUDE_DIR} ${STB_INCLUDE_DIR} ${DIRENT_INCLUDE_DIR} + ${OBJLOADER_INCLUDE_DIR} ) @@ -235,7 +236,7 @@ set(VMIX_RSC_FILES ./rsc/images/busy.png ./rsc/images/icons.dds ./rsc/images/seed_512.jpg - ./rsc/images/shadow.jpg + ./rsc/models/shadow.png ./rsc/models/square_border.obj ./rsc/models/shadow.mtl ) diff --git a/Primitives.cpp b/Primitives.cpp index e607ee1..9a15137 100644 --- a/Primitives.cpp +++ b/Primitives.cpp @@ -4,6 +4,7 @@ #include "MediaPlayer.h" #include "Visitor.h" #include "Log.h" +#include "ObjLoader.h" #include @@ -71,14 +72,14 @@ void ImageSurface::init() } } -void ImageSurface::draw(glm::mat4 projection) +void ImageSurface::draw(glm::mat4 modelview, glm::mat4 projection) { if ( !initialized() ) init(); glBindTexture(GL_TEXTURE_2D, textureindex_); - Primitive::draw(projection); + Primitive::draw(modelview, projection); glBindTexture(GL_TEXTURE_2D, 0); } @@ -111,7 +112,7 @@ void MediaSurface::init() mediaplayer_->play(true); } -void MediaSurface::draw(glm::mat4 projection) +void MediaSurface::draw(glm::mat4 modelview, glm::mat4 projection) { if ( !initialized() ) init(); @@ -121,7 +122,7 @@ void MediaSurface::draw(glm::mat4 projection) else glBindTexture(GL_TEXTURE_2D, textureindex_); - Primitive::draw(projection); + Primitive::draw(modelview, projection); glBindTexture(GL_TEXTURE_2D, 0); } @@ -130,7 +131,13 @@ void MediaSurface::update( float dt ) { if ( mediaplayer_->isOpen() ) { mediaplayer_->update(); - scale_.x = mediaplayer_->aspectRatio(); + + if (parent_ != nullptr) { + parent_->transform_ = parent_->transform_ * glm::scale(glm::identity(), glm::vec3(mediaplayer_->aspectRatio(), 1.f, 1.f)); + scale_.x = 1.0; + } + else + scale_.x = mediaplayer_->aspectRatio(); } Primitive::update( dt ); @@ -161,13 +168,14 @@ void LineStrip::init() shader_ = new Shader(); } -void LineStrip::draw(glm::mat4 projection) +void LineStrip::draw(glm::mat4 modelview, glm::mat4 projection) { if ( !initialized() ) init(); glLineWidth(linewidth_); - Primitive::draw(projection); + + Primitive::draw(modelview, projection); } void LineStrip::accept(Visitor& v) @@ -223,3 +231,74 @@ void LineCircle::accept(Visitor& v) Primitive::accept(v); v.visit(*this); } + + +ObjModel::ObjModel(const std::string& path) : Primitive(), textureindex_(0) +{ + // for obj model + filename_ = path; + + // load geometry + std::vector normals; // ignored + std::string material_filename; + bool okay = loadObject( Resource::getText(filename_), points_, normals, texCoords_, indices_, material_filename, 1.0 ); + if ( !okay ) { + Log::Warning("Failed to load OBJ model %s", path.c_str()); + } + + // prepend path to the name of other files + std::string rsc_path = filename_.substr(0, filename_.rfind('/')) + "/"; + + // load materials + std::map material_library; + okay = loadMaterialLibrary(Resource::getText( rsc_path + material_filename ), material_library); + if (okay) { + Material *material_ = material_library.begin()->second; // default use first material + + // fill colors + for (int i = 0; i < points_.size(); i++) + colors_.push_back(material_->diffuse); + + if (!material_->diffuseTexture.empty()) { + texture_filename_ = rsc_path + material_->diffuseTexture; + } + delete material_; + } + + drawingPrimitive_ = GL_TRIANGLES; +} + +void ObjModel::init() +{ + Primitive::init(); + + if (!texture_filename_.empty()) + { + // create shader for textured image + textureindex_ = Resource::getTextureImage(texture_filename_); + shader_ = new ImageShader(); + } + else { + shader_ = new Shader(); + } + +} + +void ObjModel::draw(glm::mat4 modelview, glm::mat4 projection) +{ + if ( !initialized() ) + init(); + + if (textureindex_) + glBindTexture(GL_TEXTURE_2D, textureindex_); + + Primitive::draw(modelview, projection); + + glBindTexture(GL_TEXTURE_2D, 0); +} + +void ObjModel::accept(Visitor& v) +{ + Primitive::accept(v); + v.visit(*this); +} diff --git a/Primitives.h b/Primitives.h index ecaf7ba..1e40d30 100644 --- a/Primitives.h +++ b/Primitives.h @@ -14,10 +14,10 @@ public: ImageSurface(const std::string& path = "" ); void init () override; - void draw (glm::mat4 projection) override; + void draw (glm::mat4 modelview, glm::mat4 projection) override; void accept (Visitor& v) override; - std::string getFilename() { return filename_; } + inline std::string getFilename() const { return filename_; } protected: std::string filename_; @@ -37,7 +37,7 @@ public: ~MediaSurface(); void init () override; - void draw (glm::mat4 projection) override; + void draw (glm::mat4 modelview, glm::mat4 projection) override; void accept (Visitor& v) override; void update ( float dt ) override; @@ -67,12 +67,14 @@ public: LineStrip(std::vector points, glm::vec3 color, uint linewidth = 1); virtual void init() override; - virtual void draw(glm::mat4 projection) override; + virtual void draw(glm::mat4 modelview, glm::mat4 projection) override; virtual void accept(Visitor& v) override; std::vector getPoints() { return points_; } glm::vec3 getColor() { return colors_[0]; } - uint getLineWidth() { return linewidth_; } + + inline void setLineWidth(uint v) { linewidth_ = v; } + inline uint getLineWidth() const { return linewidth_; } }; class LineSquare : public LineStrip { @@ -93,22 +95,23 @@ public: }; -//// Draw a Rectangle (triangle strip) with a texture -//class ObjModel : public Primitive { +// Draw a Rectangle (triangle strip) with a texture +class ObjModel : public Primitive { -//public: -// ObjModel(const std::string& path = "" ); +public: + ObjModel(const std::string& path = "" ); -// void init () override; -// void draw (glm::mat4 projection) override; -// void accept (Visitor& v) override; + void init () override; + void draw (glm::mat4 modelview, glm::mat4 projection) override; + void accept (Visitor& v) override; -// std::string getFilename() { return filename_; } + inline std::string getFilename() const { return filename_; } -//protected: -// std::string filename_; -// uint textureindex_; -//}; +protected: + std::string filename_; + std::string texture_filename_; + uint textureindex_; +}; #endif // PRIMITIVES_H diff --git a/Resource.cpp b/Resource.cpp index d0b6d16..0e0bba6 100644 --- a/Resource.cpp +++ b/Resource.cpp @@ -225,7 +225,8 @@ uint Resource::getTextureImage(const std::string& path, float *aspect_ratio) glPixelStorei(GL_UNPACK_ALIGNMENT, 4); //glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, img); // free memory diff --git a/Scene.cpp b/Scene.cpp index b8f26d3..9db196f 100644 --- a/Scene.cpp +++ b/Scene.cpp @@ -36,9 +36,7 @@ Node::Node() : initialized_(false), parent_(nullptr), visible_(true) auto duration = std::chrono::system_clock::now().time_since_epoch(); id_ = std::chrono::duration_cast(duration).count() % 100000000; - localToRender_ = glm::identity(); - renderToLocal_ = glm::identity(); - + transform_ = glm::identity(); scale_ = glm::vec3(1.f); rotation_ = glm::vec3(0.f); translation_ = glm::vec3(0.f); @@ -47,16 +45,8 @@ Node::Node() : initialized_(false), parent_(nullptr), visible_(true) void Node::update( float dt ) { // update transform matrix from attributes - glm::mat4 T = transform(translation_, rotation_, scale_); + transform_ = transform(translation_, rotation_, scale_); - if ( parent_ ) { - localToRender_ = parent_->localToRender_ * T; - renderToLocal_ = glm::inverse(T) * parent_->renderToLocal_; - } - else { - localToRender_ = T; - renderToLocal_ = glm::inverse(T); - } } @@ -130,7 +120,7 @@ void Primitive::init() Node::init(); } -void Primitive::draw(glm::mat4 projection) +void Primitive::draw(glm::mat4 modelview, glm::mat4 projection) { if ( !initialized() ) init(); @@ -141,7 +131,7 @@ void Primitive::draw(glm::mat4 projection) // if (shader_) { shader_->projection = projection; - shader_->modelview = localToRender_; + shader_->modelview = modelview * transform_; shader_->use(); } // @@ -194,17 +184,20 @@ void Group::update( float dt ) } } -void Group::draw(glm::mat4 projection) +void Group::draw(glm::mat4 modelview, glm::mat4 projection) { if ( !initialized() ) init(); if ( visible_ ) { + // append the instance transform to the ctm + glm::mat4 ctm = modelview * transform_; + // draw every child node for (NodeSet::iterator node = children_.begin(); node != children_.end(); node++) { - (*node)->draw (projection ); + (*node)->draw ( ctm, projection ); } } } @@ -256,7 +249,7 @@ void Switch::update( float dt ) (*active_)->update( dt ); } -void Switch::draw(glm::mat4 projection) +void Switch::draw(glm::mat4 modelview, glm::mat4 projection) { if ( !initialized() ) init(); @@ -264,7 +257,7 @@ void Switch::draw(glm::mat4 projection) if ( visible_ ) { // draw current child if (active_ != children_.end()) - (*active_)->draw(projection); + (*active_)->draw( modelview * transform_, projection); } } diff --git a/Scene.h b/Scene.h index 12eb605..a0f5267 100644 --- a/Scene.h +++ b/Scene.h @@ -35,7 +35,7 @@ public: virtual bool initialized () { return initialized_; } // pure virtual draw : to be instanciated to define node behavior - virtual void draw (glm::mat4 projection) = 0; + virtual void draw (glm::mat4 modelview, glm::mat4 projection) = 0; // update every frame virtual void update (float dt); @@ -47,8 +47,7 @@ public: Node* parent_; bool visible_; - glm::mat4 localToRender_; - glm::mat4 renderToLocal_; + glm::mat4 transform_; glm::vec3 scale_, rotation_, translation_; }; @@ -83,10 +82,10 @@ public: virtual void init () override; virtual void accept (Visitor& v) override; - virtual void draw (glm::mat4 projection) override; + virtual void draw (glm::mat4 modelview, glm::mat4 projection) override; - Shader *getShader() { return shader_; } - void setShader( Shader* e ) { shader_ = e; } + inline Shader *getShader() const { return shader_; } + inline void setShader( Shader* e ) { shader_ = e; } protected: Shader* shader_; @@ -109,7 +108,7 @@ public: virtual void init () override; virtual void update (float dt) override; virtual void accept (Visitor& v) override; - virtual void draw (glm::mat4 projection) override; + virtual void draw (glm::mat4 modelview, glm::mat4 projection) override; virtual void addChild (Node *child); virtual void removeChild (Node *child); @@ -129,7 +128,7 @@ public: virtual void update (float dt) override; virtual void accept (Visitor& v) override; - virtual void draw (glm::mat4 projection) override; + virtual void draw (glm::mat4 modelview, glm::mat4 projection) override; void addChild (Node *child) override; void removeChild (Node *child) override; diff --git a/ext/obj/ObjLoader.cpp b/ext/obj/ObjLoader.cpp index 406716c..3566a63 100644 --- a/ext/obj/ObjLoader.cpp +++ b/ext/obj/ObjLoader.cpp @@ -139,21 +139,11 @@ makeMtlFilename ( std::string mtlfile, std::string objfile ) } -bool loadMaterialLibrary ( string mtlfilename, - string objfilename, +bool loadMaterialLibrary ( string mtlText, map &outMaterials) { - - string filename = makeMtlFilename( mtlfilename, objfilename ); - string path = filename; - ifstream ifs ( path.c_str(), ifstream::in ); - if (!ifs) { - std::cout << "can't open " << filename << std::endl; - // create a default texture - Material *m = new Material(); - outMaterials["dummy1"] = m; - return false; - } + Material *mat = nullptr; + stringstream ifs(mtlText); char buffer[512]; while (ifs.good()) { ifs.getline(buffer,512); @@ -161,64 +151,45 @@ bool loadMaterialLibrary ( string mtlfilename, istringstream iss(line); string token; vec3 color; - Material *mat; iss >> token; if (token.compare("newmtl") ==0) { // create a new material and store in map mat = new Material; iss >> token; outMaterials[token] = mat; - } else if (token.compare("Ka") == 0) { - mat->ambient = vec4 ( toVec3 ( iss ), 1.0 ); - } else if (token.compare("Kd") == 0) { - mat->diffuse = vec4 ( toVec3 ( iss ), 1.0); - } else if (token.compare("Ks") == 0) { - mat->specular = vec4 ( toVec3 ( iss ), 1.0); - } else if (token.compare("Ns") == 0) { - float shininess; + } else if (token.compare("Ka") == 0 && mat) { + mat->ambient = toVec3 ( iss ); + } else if (token.compare("Kd") == 0 && mat) { + mat->diffuse = toVec3 ( iss ); + } else if (token.compare("Ks") == 0 && mat) { + mat->specular = toVec3 ( iss ); + } else if (token.compare("Ns") == 0 && mat) { iss >> mat->shininess; - } else if (token.compare("map_Kd") == 0) { - string filename,path; - iss >> filename; - if (filename[0] == '/') { - mat->diffuseTexture = filename; // diffuse in unit 0 - } else { - path = makeMtlFilename ( filename, objfilename ); - mat->diffuseTexture = path; // diffuse in unit 0 - } - if (DEBUG) - std::cout << "map_Kd from " << filename << std::endl; - } else if (token.compare("map_Disp") == 0) { - string filename, path; - iss >> filename; - if ( filename[0] == '/' ) { - mat->bumpTexture = filename; // bump in unit 1 - } else { - path = makeMtlFilename ( filename, objfilename ); - mat->bumpTexture = path; // diffuse in unit 0 - } + } else if (token.compare("map_Kd") == 0 && mat) { + iss >> mat->diffuseTexture; + } else if (token.compare("map_Disp") == 0 && mat) { + iss >> mat->bumpTexture; } } - return true; + return (mat != nullptr); } -bool loadObject(string filename, +bool loadObject(string objText, vector &outPositions, vector &outNormal, vector &outUv, vector &outIndices, - Material *outMaterial, + std::string &outMtlfilename, float scale) { vector positions; vector normals; vector uvs; - - vector triangles; - ifstream ifs ( filename , ifstream::in ); + + stringstream ifs(objText); char buffer[512]; while (ifs.good()){ ifs.getline(buffer,512); @@ -231,14 +202,8 @@ bool loadObject(string filename, // does not support multiple objects } else if (token.compare("g")==0){ } else if (token.compare("mtllib")==0){ - // read the .mtl file and create the Materials - map materials; - string mtlfile; - iss >> mtlfile; - loadMaterialLibrary( mtlfile.c_str(), - filename, - materials); - outMaterial = materials[0]; + // read the name of .mtl file + iss >> outMtlfilename; } else if (token.compare("usemtl")==0){ // does not support multiple materials } else if (token.compare("v")==0){ @@ -266,8 +231,6 @@ bool loadObject(string filename, } } } - ifs.close(); - map cache; for (int i=0;iambient = vec4 ( 0.1, 0.1, 0.1, 1.0 ); - m->diffuse = vec4 ( 0.8, 0.8, 0.8, 1.0 ); - m->specular = vec4 ( 1.0, 1.0, 1.0, 1.0 ); + m->ambient = vec3 ( 0.1, 0.1, 0.1 ); + m->diffuse = vec3 ( 0.8, 0.8, 0.8 ); + m->specular = vec3 ( 1.0, 1.0, 1.0 ); m->shininess = 200.0f; return m; } @@ -371,9 +334,9 @@ bool loadObjectGroups ( string filename, // read the .mtl file and create the Materials string mtlfile; iss >> mtlfile; - loadMaterialLibrary( mtlfile.c_str(), - filename, - materials); +// loadMaterialLibrary( mtlfile.c_str(), +// filename, +// materials); } else if (token.compare("usemtl")==0){ // create group if none exists, or if this is a "usemtl" line without a preceding "g" line if ( currentGroupName=="" || groups[currentGroupName]->triangles.size() ) { diff --git a/ext/obj/ObjLoader.h b/ext/obj/ObjLoader.h index 5d5b504..07088e8 100644 --- a/ext/obj/ObjLoader.h +++ b/ext/obj/ObjLoader.h @@ -34,49 +34,55 @@ #include #include +#include #include struct Material { -Material() : - ambient (0.1, 0.1, 0.1, 1.0), - diffuse (0.8, 0.8, 0.8, 1.0), - specular(1.0, 1.0, 1.0, 1.0 ), - shininess(75.0) - {} - virtual ~Material() { } + Material() : + ambient (0.1, 0.1, 0.1), + diffuse (0.8, 0.8, 0.8), + specular(1.0, 1.0, 1.0), + shininess(75.0) + {} + virtual ~Material() { } - glm::vec4 ambient; - glm::vec4 diffuse; - glm::vec4 specular; - float shininess; + glm::vec3 ambient; + glm::vec3 diffuse; + glm::vec3 specular; + float shininess; - std::string diffuseTexture; - std::string bumpTexture; + std::string diffuseTexture; + std::string bumpTexture; }; // The original version, modified for glm. // Load an OBJ model into the out parameters. // Note only simple OBJ files are supported. -bool loadObject (std::string filename, - std::vector &outPositions, - std::vector &outNormal, - std::vector &outUv, - std::vector &outIndices, - Material *outMaterial, - float scale = 1.0f - ); +bool loadObject (std::string objText, + std::vector &outPositions, + std::vector &outNormal, + std::vector &outUv, + std::vector &outIndices, + std::string &outMtlfilename, + float scale = 1.0f + ); + + +bool loadMaterialLibrary ( std::string mtlText, + std::map &outMaterials + ); // this tries to handle multiple materials (w/textures) and groups of faces as per pcl_kinfu_largeScale, etc bool loadObjectGroups (std::string filename, - std::vector &outPositions, - std::vector &outNormal, - std::vector &outUv, - std::vector > &outIndices, // per group - std::vector &outMaterials, // per group (w/textures) - float scale=1.0f -); + std::vector &outPositions, + std::vector &outNormal, + std::vector &outUv, + std::vector > &outIndices, // per group + std::vector &outMaterials, // per group (w/textures) + float scale=1.0f + ); #endif diff --git a/main.cpp b/main.cpp index 6e62ada..296c8e0 100644 --- a/main.cpp +++ b/main.cpp @@ -58,7 +58,7 @@ Scene scene; FrameBuffer *output; MediaSurface testnode1("file:///home/bhbn/Videos/iss.mov"); MediaSurface testnode2("file:///home/bhbn/Videos/fish.mp4"); -ImageSurface testnode3("images/v-mix_256x256.png"); +ImageSurface testnode3("images/seed_512.jpg"); void drawMediaPlayer() @@ -183,13 +183,14 @@ void drawScene() scene.root_.update( static_cast( GST_TIME_AS_MSECONDS(dt)) * 0.001f ); // draw in output frame buffer + glm::mat4 MV = glm::identity(); glm::mat4 P = glm::scale( glm::ortho(-5.f, 5.f, -5.f, 5.f), glm::vec3(1.f, output->aspectRatio(), 1.f)); output->begin(); - scene.root_.draw(P); + scene.root_.draw(MV, P); output->end(); // draw in main view - scene.root_.draw(Rendering::manager().Projection()); + scene.root_.draw(MV, Rendering::manager().Projection()); // draw GUI tree scene ImGui::Begin(IMGUI_TITLE_MAINWINDOW); @@ -254,25 +255,28 @@ int main(int, char**) // init elements to the scene //testnode3.getShader()->blending = Shader::BLEND_OPACITY; - glm::vec3 color( 1.f, 1.f, 0.f ); - LineCircle border(color); -// LineSquare border(color); + glm::vec3 color( 0.8f, 0.8f, 0.f ); +// LineCircle border(color); + LineSquare border(color, 2); + ObjModel shadow("models/square_border.obj"); Group g1; g1.translation_ = glm::vec3(1.f, 1.f, 0.f); - g1.scale_ = glm::vec3(2.f, 2.f, 1.f); + g1.scale_ = glm::vec3(1.2f, 1.2f, 1.f); - Switch g2; + Group g2; g2.translation_ = glm::vec3(-1.f, -1.f, 0.f); // g2.rotation_ = glm::vec3(0.0f, 0.0f, 1.0f); // build tree + g1.addChild(&shadow); g1.addChild(&testnode3); g1.addChild(&border); scene.root_.addChild(&g1); + g2.addChild(&shadow); g2.addChild(&testnode1); - g2.addChild(&testnode2); + g2.addChild(&border); scene.root_.addChild(&g2); // init output FBO diff --git a/rsc/images/shadow.png b/rsc/images/shadow.png deleted file mode 100755 index 7448452..0000000 Binary files a/rsc/images/shadow.png and /dev/null differ diff --git a/rsc/models/shadow.mtl b/rsc/models/shadow.mtl index d48fd57..31f27fd 100644 --- a/rsc/models/shadow.mtl +++ b/rsc/models/shadow.mtl @@ -7,4 +7,4 @@ Ke 0.000000 0.000000 0.000000 Ni 1.450000 d 1.000000 illum 2 -map_Kd images/shadow.png +map_Kd shadow.png diff --git a/rsc/models/square_border.obj b/rsc/models/square_border.obj index ec0a35c..c4ad0d3 100644 --- a/rsc/models/square_border.obj +++ b/rsc/models/square_border.obj @@ -1,13 +1,13 @@ -mtllib shadow.mtl +mtllib shadow.mtl o square_border v -1.000000 -1.000000 0.000000 -v -1.300000 -1.300000 0.000000 +v -1.400000 -1.400000 0.000000 v 1.000000 -1.000000 0.000000 -v 1.300000 -1.300000 0.000000 +v 1.400000 -1.400000 0.000000 v -1.000000 1.000000 0.000000 -v -1.300000 1.300000 0.000000 +v -1.400000 1.400000 0.000000 v 1.000000 1.000000 0.000000 -v 1.300000 1.300000 0.000000 +v 1.400000 1.400000 0.000000 vt 0.2 0.80 vt 1.00 1.00 vt -0.00 1.00