#pragma once #include #include #include // C++ importer interface #include // Output data structure #include // Post processing flags #include #include class PolygonModel { public: PolygonModel(const std::string &filename) : m_filename(filename) { clear(); } void clear() { // TODO: delete buffers if there's data m_loaded_from_file = false; m_loaded_to_opengl = false; m_data_position.clear(); m_data_normal.clear(); m_vbo_id_position = 0; m_vbo_id_normal = 0; m_numVertices = 0; } bool import() { clear(); // Create an instance of the Importer class Assimp::Importer importer; // And have it read the given file with some example postprocessing // Usually - if speed is not the most important aspect for you - you'll // propably to request more postprocessing than we do in this example. const aiScene* scene = importer.ReadFile(m_filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType); // If the import failed, report it if (!scene) { std::cout<<"[polygonmodel] loading file " << m_filename << " failed with: " << importer.GetErrorString() << std::endl; return false; } // Now we can access the file's contents. copyVertices(scene); m_loaded_from_file = true; // We're done. Everything will be cleaned up by the importer destructor return true; } bool uploadToOpenGl() { if (!m_loaded_from_file) { std::cerr<<"[polygonmodel] warning: try to upload model data " << "to OpenGL but no data is loaded!" << std::endl; exit(-1); return false; } glEnableVertexAttribArray(0); glGenBuffers(1, &m_vbo_id_position); // Generate buffer glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id_position); // Bind buffer glVertexAttribPointer(0, 3, // three floats per vertex GL_FLOAT, // Data is floating point type GL_FALSE, // No fixed point scaling 0, // stride: no NULL); // No offset // fill buffer with the loaded mesh position data glBufferData( GL_ARRAY_BUFFER, // Buffer target 3 * m_numVertices * sizeof(float), // Buffer data size m_data_position.data(), // Buffer data pointer GL_STATIC_DRAW); // Usage - Data never changes; // TODO #if 0 // 2 holds normal data glEnableVertexAttribArray(2); glGenBuffers(1, &(model->vbo_normal)); // Generate buffer glBindBuffer(GL_ARRAY_BUFFER, model->vbo_normal); // Bind buffer glVertexAttribPointer(2, 3, // three floats per normal GL_FLOAT, // Data is floating point type GL_FALSE, // No fixed point scaling 0, // stride: no NULL); // No offset // Fill bound buffer glBufferData( GL_ARRAY_BUFFER, // Buffer target 3*model->numVertices*sizeof(float), // Buffer data size model->normals, // Buffer data pointer GL_STATIC_DRAW); // Usage - Data never changes; #endif m_loaded_to_opengl = true; return true; } bool bind() { // TODO: check whether this vbo is bound! if (!m_loaded_to_opengl) { std::cout<<"[polygonmodel] warning: try to bind model vbo " << "which was not uploaded to OpenGL!" << std::endl; exit(-1); return false; } // bind position vbo glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id_position); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); // TODO #if 0 // bind normal vbo GLuint normalLoc = glGetAttribLocation(program, "attr_normal"); glEnableVertexAttribArray(normalLoc); glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo_normal); glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL); #endif m_binding_active = true; return true; } bool render() { if (!m_binding_active || !m_loaded_to_opengl) { std::cout<<"[polygonmodel] warning: try to render model without bind()" << std::endl; exit(-1); return false; } glDrawArrays(GL_TRIANGLES, 0, m_numVertices); return true; } private: bool copyVertices(const aiScene *scene) { if (scene->mMeshes == 0) { std::cout << "[polygonmodel : no meshes loaded for " << m_filename << std::endl; return false; } aiNode *node = scene->mRootNode; const aiMesh* mesh = scene->mMeshes[node->mMeshes[0]]; // 3 vertices per face, 3 floats per vertex m_numVertices = mesh->mNumFaces*3; m_data_position.reserve(m_numVertices); m_data_normal.reserve(m_numVertices); size_t t, i; for (t=0; tmNumFaces; ++t) { const aiFace* face = &mesh->mFaces[t]; if (face->mNumIndices != 3) { std::cout << "[polygonmodel] need triangles, got something different with: " << face->mNumIndices << " vertices" << std::endl; return false; } for (i=0; imNumIndices; i++) { const size_t index = face->mIndices[i]; m_data_position.push_back(mesh->mVertices[index].x); m_data_position.push_back(mesh->mVertices[index].y); m_data_position.push_back(mesh->mVertices[index].z); m_data_normal.push_back(mesh->mNormals[index].x); m_data_normal.push_back(mesh->mNormals[index].y); m_data_normal.push_back(mesh->mNormals[index].z); } } size_t totalBytes = 3*m_numVertices*sizeof(float); std::cout<<"[polygonmodel] loaded file " << m_filename << " with " << m_numVertices << " vertices (" << totalBytes << " bytes)" << std::endl; return true; } const std::string &filename() const { return m_filename; } private: std::string m_filename; bool m_loaded_from_file; bool m_loaded_to_opengl; bool m_binding_active; // both will hold 3 * numVertices floats std::vector m_data_position; std::vector m_data_normal; size_t m_numVertices; GLuint m_vbo_id_position; GLuint m_vbo_id_normal; };