diff --git a/point-cloud-jni-example/app/src/main/jni/tango_pointcloud.cpp b/point-cloud-jni-example/app/src/main/jni/tango_pointcloud.cpp index 3e292bf9..e9cac5e1 100644 --- a/point-cloud-jni-example/app/src/main/jni/tango_pointcloud.cpp +++ b/point-cloud-jni-example/app/src/main/jni/tango_pointcloud.cpp @@ -248,10 +248,12 @@ bool RenderFrame() { axis->Render(cam->GetProjectionMatrix(), cam->GetViewMatrix()); // Render point cloud based on depth buffer and depth frame transformation. - pointcloud->Render( - cam->GetProjectionMatrix(), cam->GetViewMatrix(), oc_2_ow_mat_depth, - TangoData::GetInstance().depth_buffer_size * 3, - static_cast(TangoData::GetInstance().depth_buffer)); + if (TangoData::GetInstance().cur_pose_data.status_code == TANGO_POSE_VALID) { + pointcloud->Render( + cam->GetProjectionMatrix(), cam->GetViewMatrix(), oc_2_ow_mat_depth, + TangoData::GetInstance().depth_buffer_size * 3, + static_cast(TangoData::GetInstance().depth_buffer)); + } grid->SetPosition(glm::vec3(0.0f, 0.0f, 0.0f) - kHeightOffset); // Render grid. diff --git a/tango-gl/cube.cpp b/tango-gl/cube.cpp index 71c96cf1..6480fec1 100644 --- a/tango-gl/cube.cpp +++ b/tango-gl/cube.cpp @@ -19,21 +19,38 @@ namespace tango_gl { static const GLfloat const_vertices[] = { - -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f}; + -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f}; -static const GLushort const_indices[] = {0, 1, 2, 2, 3, 0, 3, 2, 6, 6, 7, 3, - 7, 6, 5, 5, 4, 7, 4, 0, 3, 3, 7, 4, - 0, 4, 5, 5, 1, 0, 1, 5, 6, 6, 2, 1}; +static const GLfloat const_normals[] = { + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, -1.0f, + 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f}; Cube::Cube() { - SetShader(); + SetShader(true); std::vector vertices( const_vertices, const_vertices + sizeof(const_vertices) / sizeof(GLfloat)); - std::vector indices( - const_indices, const_indices + sizeof(const_indices) / sizeof(GLushort)); - SetVertices(vertices, indices); + std::vector normals( + const_normals, const_normals + sizeof(const_normals) / sizeof(GLfloat)); + SetVertices(vertices, normals); + glm::vec3 point_light = glm::vec3(0.5f, 2, 0.5f); + SetLightPosition(point_light); } } // namespace tango_gl diff --git a/tango-gl/drawable_object.cpp b/tango-gl/drawable_object.cpp index 47d28dd8..9c328eb5 100644 --- a/tango-gl/drawable_object.cpp +++ b/tango-gl/drawable_object.cpp @@ -53,4 +53,10 @@ void DrawableObject::SetVertices(const std::vector& vertices, vertices_ = vertices; indices_ = indices; } + +void DrawableObject::SetVertices(const std::vector& vertices, + const std::vector& normals) { + vertices_ = vertices; + normals_ = normals; } +} // namespace tango_gl diff --git a/tango-gl/include/tango-gl/drawable_object.h b/tango-gl/include/tango-gl/drawable_object.h index 0217f971..8944d731 100644 --- a/tango-gl/include/tango-gl/drawable_object.h +++ b/tango-gl/include/tango-gl/drawable_object.h @@ -38,6 +38,8 @@ class DrawableObject : public Transform { void SetVertices(const std::vector& vertices); void SetVertices(const std::vector& vertices, const std::vector& indices); + void SetVertices(const std::vector& vertices, + const std::vector& normals); virtual void Render(const glm::mat4& projection_mat, const glm::mat4& view_mat) const = 0; @@ -48,10 +50,13 @@ class DrawableObject : public Transform { float alpha_; std::vector indices_; std::vector vertices_; + std::vector normals_; + GLuint shader_program_; GLuint uniform_color_; GLuint uniform_mvp_mat_; GLuint attrib_vertices_; + GLuint attrib_normals_; }; } // namespace tango_gl #endif // TANGO_GL_DRAWABLE_OBJECT_H_ diff --git a/tango-gl/include/tango-gl/mesh.h b/tango-gl/include/tango-gl/mesh.h index 27685f79..9db1f97e 100644 --- a/tango-gl/include/tango-gl/mesh.h +++ b/tango-gl/include/tango-gl/mesh.h @@ -22,7 +22,16 @@ namespace tango_gl { class Mesh : public DrawableObject { public: + void SetShader(); + void SetShader(bool is_lighting_on); + void SetLightPosition(const glm::vec3& light_position); void Render(const glm::mat4& projection_mat, const glm::mat4& view_mat) const; + + protected: + bool is_lighting_on_; + glm::vec3 light_position_; + GLuint uniform_mv_mat_; + GLuint uniform_light_pos_; }; } // namespace tango_gl #endif // TANGO_GL_MESH_H_ diff --git a/tango-gl/include/tango-gl/obj_loader.h b/tango-gl/include/tango-gl/obj_loader.h index 1aaf7f74..4cc8a83a 100644 --- a/tango-gl/include/tango-gl/obj_loader.h +++ b/tango-gl/include/tango-gl/obj_loader.h @@ -23,27 +23,38 @@ namespace tango_gl { namespace obj_loader { -// Load standard .obj file into vertices, indices and normals vectors, +// Load standard .obj file into vertices, indices or normals vectors, // OBJ file can be exported from 3D tools like 3ds Max, when exporting, -// faces must be triangulated. A readable file should look like +// faces must be triangulated. +// A readable file with only vertices should look like // "v 1.00 2.00 3.00 // ... // f 1 2 3 +// ..." +// +// If exported with normals, file should look like +// "v 1.00 2.00 3.00 +// ... +// f 1//1 2//3 3//4 // ... // vn 1.00 2.00 3.00 // ..." -// -// this can be used with Polygon: +// this can be used with Mesh: // // std::vector vertices; // std::vector indices; // std::vector normals; -// tango_gl::obj_loader::LoadOBJData("/sdcard/model.obj", vertices, indices, -// normals); -// polygon->SetMeshData(vertices, indices); -// +// tango_gl::obj_loader::LoadOBJData("/sdcard/model.obj", vertices, indices); +// mesh->SetVertices(vertices, indices); +// or +// tango_gl::obj_loader::LoadOBJData("/sdcard/model.obj", vertices, normals); +// mesh->SetVertices(vertices, normals); + +bool LoadOBJData(const char* path, std::vector& vertices, + std::vector& indices); + bool LoadOBJData(const char* path, std::vector& vertices, - std::vector& indices, std::vector& normals); + std::vector& normals); } // namespace obj_loader } // namespace tango_gl #endif // TANGO_GL_OBJ_LOADER diff --git a/tango-gl/include/tango-gl/shaders.h b/tango-gl/include/tango-gl/shaders.h index 9ea46dc7..2d8d6160 100644 --- a/tango-gl/include/tango-gl/shaders.h +++ b/tango-gl/include/tango-gl/shaders.h @@ -26,6 +26,7 @@ std::string GetBasicFragmentShader(); std::string GetColorVertexShader(); std::string GetVideoOverlayVertexShader(); std::string GetVideoOverlayFragmentShader(); +std::string GetShadedVertexShader(); } // namespace shaders } // namespace tango_gl #endif // TANGO_GL_SHADERS_H_ diff --git a/tango-gl/mesh.cpp b/tango-gl/mesh.cpp index c40e9a9e..6c251587 100644 --- a/tango-gl/mesh.cpp +++ b/tango-gl/mesh.cpp @@ -15,26 +15,78 @@ */ #include "tango-gl/mesh.h" +#include "tango-gl/shaders.h" namespace tango_gl { +void Mesh::SetShader() { + DrawableObject::SetShader(); + is_lighting_on_ = false; +} + +void Mesh::SetShader(bool is_lighting_on) { + if (is_lighting_on) { + shader_program_ = + util::CreateProgram(shaders::GetShadedVertexShader().c_str(), + shaders::GetBasicFragmentShader().c_str()); + if (!shader_program_) { + LOGE("Could not create program."); + } + uniform_mvp_mat_ = glGetUniformLocation(shader_program_, "mvp"); + uniform_mv_mat_ = glGetUniformLocation(shader_program_, "mv"); + uniform_light_pos_ = glGetUniformLocation(shader_program_, "lightPos"); + uniform_color_ = glGetUniformLocation(shader_program_, "color"); + + attrib_vertices_ = glGetAttribLocation(shader_program_, "vertex"); + attrib_normals_ = glGetAttribLocation(shader_program_, "normal"); + is_lighting_on_ = true; + } else { + SetShader(); + } +} + +void Mesh::SetLightPosition(const glm::vec3& light_position) { + light_position_ = light_position; +} void Mesh::Render(const glm::mat4& projection_mat, const glm::mat4& view_mat) const { - if (indices_.empty()) return; glUseProgram(shader_program_); glm::mat4 model_mat = GetTransformationMatrix(); - glm::mat4 mvp_mat = projection_mat * view_mat * model_mat; + glm::mat4 mv_mat = view_mat * model_mat; + glm::mat4 mvp_mat = projection_mat * mv_mat; glUniformMatrix4fv(uniform_mvp_mat_, 1, GL_FALSE, glm::value_ptr(mvp_mat)); + glUniform4f(uniform_color_, red_, green_, blue_, alpha_); + + if (is_lighting_on_) { + glUniformMatrix4fv(uniform_mv_mat_, 1, GL_FALSE, glm::value_ptr(mv_mat)); + + glEnableVertexAttribArray(attrib_normals_); + glVertexAttribPointer(attrib_normals_, 3, GL_FLOAT, GL_FALSE, + 3 * sizeof(GLfloat), &normals_[0]); + + glm::vec4 light = glm::vec4(light_position_.x, light_position_.y, + light_position_.z, 1.0f); + glm::vec4 transformed_light = view_mat * light; + glUniform3fv(uniform_light_pos_, 1, glm::value_ptr(transformed_light)); + } glEnableVertexAttribArray(attrib_vertices_); - glVertexAttribPointer(attrib_vertices_, 3, GL_FLOAT, GL_FALSE, - 3 * sizeof(GLfloat), vertices_.data()); - glUniform4f(uniform_color_, red_, green_, blue_, alpha_); - glDrawElements(GL_TRIANGLES, indices_.size(), GL_UNSIGNED_SHORT, - indices_.data()); + + if (!indices_.empty()) { + glVertexAttribPointer(attrib_vertices_, 3, GL_FLOAT, GL_FALSE, + 3 * sizeof(GLfloat), vertices_.data()); + glDrawElements(GL_TRIANGLES, indices_.size(), GL_UNSIGNED_SHORT, + indices_.data()); + } else { + glVertexAttribPointer(attrib_vertices_, 3, GL_FLOAT, GL_FALSE, + 3 * sizeof(GLfloat), &vertices_[0]); + glDrawArrays(GL_TRIANGLES, 0, vertices_.size() / 3); + } glDisableVertexAttribArray(attrib_vertices_); + if (is_lighting_on_) { + glDisableVertexAttribArray(attrib_normals_); + } glUseProgram(0); } - } // namespace tango_gl diff --git a/tango-gl/obj_loader.cpp b/tango-gl/obj_loader.cpp index 19576ea3..3bb43aed 100644 --- a/tango-gl/obj_loader.cpp +++ b/tango-gl/obj_loader.cpp @@ -18,8 +18,8 @@ #include "tango-gl/obj_loader.h" namespace tango_gl { -bool obj_loader::LoadOBJData(const char *path, std::vector& vertices, - std::vector& indices, std::vector& normals) { +bool obj_loader::LoadOBJData(const char* path, std::vector& vertices, + std::vector& indices) { FILE *file = fopen(path, "r"); if (file == NULL) { LOGE("Failed to open file: %s", path); @@ -43,8 +43,8 @@ bool obj_loader::LoadOBJData(const char *path, std::vector& vertices, vertices.push_back(vertex[2]); } else if (strcmp(lineHeader, "f") == 0) { GLushort vertexIndex[3]; - int matches = fscanf(file, "%hu %hu %hu\n", &vertexIndex[0], &vertexIndex[1], - &vertexIndex[2]); + int matches = fscanf(file, "%hu %hu %hu\n", &vertexIndex[0], + &vertexIndex[1], &vertexIndex[2]); if (matches != 3) { LOGE("Format of 'f int int int' required for each face line"); return false; @@ -52,6 +52,42 @@ bool obj_loader::LoadOBJData(const char *path, std::vector& vertices, indices.push_back(vertexIndex[0] - 1); indices.push_back(vertexIndex[1] - 1); indices.push_back(vertexIndex[2] - 1); + } + else { + char comments_buffer[1000]; + fgets(comments_buffer, 1000, file); + } + } + fclose(file); + return true; +} + +bool obj_loader::LoadOBJData(const char* path, std::vector& vertices, + std::vector& normals) { + std::vector vertexIndices, normalIndices; + std::vector temp_vertices, temp_normals; + + FILE* file = fopen(path, "r"); + if (file == NULL) { + LOGE("Failed to open file: %s", path); + return false; + } + + while (1) { + char lineHeader[128]; + int res = fscanf(file, "%s", lineHeader); + if (res == EOF) break; + if (strcmp(lineHeader, "v") == 0) { + GLfloat vertex[3]; + int matches = + fscanf(file, "%f %f %f\n", &vertex[0], &vertex[1], &vertex[2]); + if (matches != 3) { + LOGE("Format of 'v float float float' required for each vertice line"); + return false; + } + temp_vertices.push_back(vertex[0]); + temp_vertices.push_back(vertex[1]); + temp_vertices.push_back(vertex[2]); } else if (strcmp(lineHeader, "vn") == 0) { GLfloat normal[3]; int matches = @@ -60,18 +96,44 @@ bool obj_loader::LoadOBJData(const char *path, std::vector& vertices, LOGE("Format of 'vn float float float' required for each normal line"); return false; } - normals.push_back(normal[0]); - normals.push_back(normal[1]); - normals.push_back(normal[2]); - } - else { + temp_normals.push_back(normal[0]); + temp_normals.push_back(normal[1]); + temp_normals.push_back(normal[2]); + } else if (strcmp(lineHeader, "f") == 0) { + GLushort vertexIndex[3]; + GLushort normalIndex[3]; + int matches = fscanf(file, "%hu//%hu %hu//%hu %hu//%hu\n", + &vertexIndex[0], &normalIndex[0], &vertexIndex[1], + &normalIndex[1], &vertexIndex[2], &normalIndex[2]); + if (matches != 6) { + LOGE("Format of 'f int//int int//int int//int' required for each face"); + return false; + } + // .obj file is 1-indexed, so subtract 1 from all indices. + vertexIndices.push_back(vertexIndex[0] - 1); + vertexIndices.push_back(vertexIndex[1] - 1); + vertexIndices.push_back(vertexIndex[2] - 1); + normalIndices.push_back(normalIndex[0] - 1); + normalIndices.push_back(normalIndex[1] - 1); + normalIndices.push_back(normalIndex[2] - 1); + } else { char comments_buffer[1000]; fgets(comments_buffer, 1000, file); } } + for (unsigned int i = 0; i < vertexIndices.size(); i++) { + unsigned int vertexIndex = vertexIndices[i]; + unsigned int normalIndex = normalIndices[i]; + + vertices.push_back(temp_vertices[vertexIndex * 3]); + vertices.push_back(temp_vertices[vertexIndex * 3 + 1]); + vertices.push_back(temp_vertices[vertexIndex * 3 + 2]); + normals.push_back(temp_normals[normalIndex * 3]); + normals.push_back(temp_normals[normalIndex * 3 + 1]); + normals.push_back(temp_normals[normalIndex * 3 + 2]); + } fclose(file); return true; } - } // namespace tango_gl diff --git a/tango-gl/shaders.cpp b/tango-gl/shaders.cpp index 813e00ef..b47aed63 100644 --- a/tango-gl/shaders.cpp +++ b/tango-gl/shaders.cpp @@ -70,5 +70,25 @@ std::string GetVideoOverlayFragmentShader() { " gl_FragColor = texture2D(texture, f_textureCoords);\n" "}\n"; } + +std::string GetShadedVertexShader() { + return "attribute vec4 vertex;\n" + "attribute vec3 normal;\n" + "uniform mat4 mvp;\n" + "uniform mat4 mv;\n" + "uniform vec4 color;\n" + "uniform vec3 lightPos;\n" + "varying vec4 v_color;\n" + "void main() {\n" + " vec3 mvVertex = vec3(mv * vertex);\n" + " vec3 mvNormal = vec3(mv * vec4(normal, 0.0));\n" + " float distance = length(lightPos-mvVertex);\n" + " vec3 lightVec = normalize(lightPos-mvVertex);\n" + " float diffuse = max(dot(mvNormal, lightVec), 1.0);\n" + " diffuse = diffuse * (1.0/(1.0 + (0.4 * distance * distance)));\n" + " v_color = color * diffuse;\n" + " gl_Position = mvp*vertex;\n" + "}\n"; +} } // namespace shaders } // namespace tango_gl diff --git a/tango_client_api/lib/libtango_client_api.so b/tango_client_api/lib/libtango_client_api.so index 9a08993c..1ffcd2ae 100755 Binary files a/tango_client_api/lib/libtango_client_api.so and b/tango_client_api/lib/libtango_client_api.so differ