|
@@ -0,0 +1,177 @@
|
|
|
+#include "map_texture.h"
|
|
|
+#include "../create_shader_program.h"
|
|
|
+// Hopefully OpenGL/gl.h hasn't been included already
|
|
|
+#include <OpenGL/gl3.h>
|
|
|
+#define __gl_h_
|
|
|
+
|
|
|
+#define GLFW_INCLUDE_GLU
|
|
|
+#include <GLFW/glfw3.h>
|
|
|
+
|
|
|
+#include <iostream>
|
|
|
+#include <string>
|
|
|
+
|
|
|
+template <typename DerivedV, typename DerivedF, typename DerivedU>
|
|
|
+IGL_INLINE bool igl::opengl::glfw::map_texture(
|
|
|
+ const Eigen::MatrixBase<DerivedV> & _V,
|
|
|
+ const Eigen::MatrixBase<DerivedF> & _F,
|
|
|
+ const Eigen::MatrixBase<DerivedU> & _U,
|
|
|
+ const unsigned char * in_data,
|
|
|
+ const int w,
|
|
|
+ const int h,
|
|
|
+ const int nc,
|
|
|
+ std::vector<unsigned char> & out_data)
|
|
|
+{
|
|
|
+ const auto fail = [](const std::string msg)
|
|
|
+ {
|
|
|
+ std::cerr<<msg<<std::endl;
|
|
|
+ glfwTerminate();
|
|
|
+ return false;
|
|
|
+ };
|
|
|
+ // Force inputs to be RowMajor at the cost of a copy
|
|
|
+ Eigen::Matrix<
|
|
|
+ double,
|
|
|
+ DerivedV::RowsAtCompileTime,
|
|
|
+ DerivedV::ColsAtCompileTime,
|
|
|
+ Eigen::RowMajor> V = _V.template cast<double>();
|
|
|
+ Eigen::Matrix<
|
|
|
+ double,
|
|
|
+ DerivedU::RowsAtCompileTime,
|
|
|
+ DerivedU::ColsAtCompileTime,
|
|
|
+ Eigen::RowMajor> U = _U.template cast<double>();
|
|
|
+ Eigen::Matrix<
|
|
|
+ int,
|
|
|
+ DerivedF::RowsAtCompileTime,
|
|
|
+ DerivedF::ColsAtCompileTime,
|
|
|
+ Eigen::RowMajor> F = _F.template cast<int>();
|
|
|
+ // Set up glfw
|
|
|
+ if(!glfwInit()) fail("Could not initialize glfw");
|
|
|
+ glfwSetErrorCallback([](int id,const char* m){std::cerr<<m<<std::endl;});
|
|
|
+ glfwWindowHint(GLFW_SAMPLES, 4);
|
|
|
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
|
|
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
|
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
|
|
+ glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
|
|
|
+ GLFWwindow* window = glfwCreateWindow(1, 1,"", NULL, NULL);
|
|
|
+ if(!window) fail("Could not create glfw window");
|
|
|
+ glfwMakeContextCurrent(window);
|
|
|
+ // Compile each shader
|
|
|
+ std::string vertex_shader = R"(
|
|
|
+#version 330 core
|
|
|
+layout(location = 0) in vec2 position;
|
|
|
+layout(location = 1) in vec2 tex_coord_v;
|
|
|
+out vec2 tex_coord_f;
|
|
|
+void main()
|
|
|
+{
|
|
|
+ tex_coord_f = vec2(tex_coord_v.x,1.-tex_coord_v.y);
|
|
|
+ gl_Position = vec4( 2.*position.x-1., 2.*(1.-position.y)-1., 0.,1.);
|
|
|
+}
|
|
|
+)";
|
|
|
+ std::string fragment_shader = R"(
|
|
|
+#version 330 core
|
|
|
+layout(location = 0) out vec3 color;
|
|
|
+uniform sampler2D tex;
|
|
|
+in vec2 tex_coord_f;
|
|
|
+void main()
|
|
|
+{
|
|
|
+ color = texture(tex,tex_coord_f).rgb;
|
|
|
+}
|
|
|
+)";
|
|
|
+ GLuint prog_id =
|
|
|
+ igl::opengl::create_shader_program(vertex_shader,fragment_shader,{});
|
|
|
+ glUniform1i(glGetUniformLocation(prog_id, "tex"),0);
|
|
|
+ // Generate and attach buffers to vertex array
|
|
|
+ glDisable(GL_CULL_FACE);
|
|
|
+ GLuint VAO = 0;
|
|
|
+ glGenVertexArrays(1,&VAO);
|
|
|
+ glBindVertexArray(VAO);
|
|
|
+ GLuint ibo,vbo,tbo;
|
|
|
+ glGenBuffers(1,&ibo);
|
|
|
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
|
|
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*F.size(), F.data(), GL_STATIC_DRAW);
|
|
|
+ glGenBuffers(1,&vbo);
|
|
|
+ glEnableVertexAttribArray(0);
|
|
|
+ glBindBuffer(GL_ARRAY_BUFFER,vbo);
|
|
|
+ glBufferData(GL_ARRAY_BUFFER, sizeof(double)*U.size(), U.data(), GL_STATIC_DRAW);
|
|
|
+ glVertexAttribLPointer(0, U.cols(), GL_DOUBLE, V.cols() * sizeof(GLdouble), (GLvoid*)0);
|
|
|
+ glGenBuffers(1,&tbo);
|
|
|
+ glEnableVertexAttribArray(1);
|
|
|
+ glBindBuffer(GL_ARRAY_BUFFER,tbo);
|
|
|
+ glBufferData(GL_ARRAY_BUFFER, sizeof(double)*V.size(), V.data(), GL_STATIC_DRAW);
|
|
|
+ glVertexAttribLPointer(1, V.cols(), GL_DOUBLE, V.cols() * sizeof(GLdouble), (GLvoid*)0);
|
|
|
+ glBindVertexArray(0);
|
|
|
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
+ glBindVertexArray(0);
|
|
|
+ // Prepare texture
|
|
|
+ GLuint in_tex;
|
|
|
+ GLenum format;
|
|
|
+ {
|
|
|
+ format = nc==1 ? GL_RED : (nc==3 ? GL_RGB : (nc == 4 ? GL_RGBA : GL_FALSE));
|
|
|
+ glGenTextures(1, &in_tex);
|
|
|
+ glBindTexture(GL_TEXTURE_2D, in_tex);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
|
+ glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w, h, 0,format, GL_UNSIGNED_BYTE, in_data);
|
|
|
+ }
|
|
|
+ // Prepare framebuffer
|
|
|
+ GLuint fb = 0;
|
|
|
+ glGenFramebuffers(1, &fb);
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
|
|
+ GLuint out_tex;
|
|
|
+ glGenTextures(1, &out_tex);
|
|
|
+ glBindTexture(GL_TEXTURE_2D, out_tex);
|
|
|
+ // always use float for internal storage
|
|
|
+ glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w, h, 0,GL_RGB, GL_FLOAT, 0);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
+ glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, out_tex, 0);
|
|
|
+ {
|
|
|
+ GLenum bufs[1] = {GL_COLOR_ATTACHMENT0};
|
|
|
+ glDrawBuffers(1, bufs);
|
|
|
+ }
|
|
|
+ if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
|
|
+ {
|
|
|
+ fail("framebuffer setup failed.");
|
|
|
+ }
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
|
|
+ // clear screen and set viewport
|
|
|
+ glClearColor(0.0,1.0,0.0,0.);
|
|
|
+ glClear(GL_COLOR_BUFFER_BIT);
|
|
|
+ glViewport(0,0,w,h);
|
|
|
+ // Attach shader program
|
|
|
+ glUseProgram(prog_id);
|
|
|
+ glActiveTexture(GL_TEXTURE0 + 0);
|
|
|
+ glBindTexture(GL_TEXTURE_2D, in_tex);
|
|
|
+ // Draw mesh as wireframe
|
|
|
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
+ glBindVertexArray(VAO);
|
|
|
+ glDrawElements(GL_TRIANGLES, F.size(), GL_UNSIGNED_INT, 0);
|
|
|
+ glBindVertexArray(0);
|
|
|
+ // Write into memory
|
|
|
+ out_data.resize(nc*w*h);
|
|
|
+ glBindTexture(GL_TEXTURE_2D, out_tex);
|
|
|
+ glGetTexImage(GL_TEXTURE_2D, 0, format, GL_UNSIGNED_BYTE, &out_data[0]);
|
|
|
+ // OpenGL cleanup
|
|
|
+ glDeleteBuffers(1,&fb);
|
|
|
+ glDeleteBuffers(1,&ibo);
|
|
|
+ glDeleteBuffers(1,&vbo);
|
|
|
+ glDeleteBuffers(1,&tbo);
|
|
|
+ glDeleteTextures(1,&in_tex);
|
|
|
+ glDeleteTextures(1,&out_tex);
|
|
|
+ glDeleteVertexArrays(1,&VAO);
|
|
|
+ glUseProgram(0);
|
|
|
+ glDeleteProgram(prog_id);
|
|
|
+ // GLFW cleanup
|
|
|
+ glfwDestroyWindow(window);
|
|
|
+ glfwTerminate();
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef IGL_STATIC_LIBRARY
|
|
|
+// Explicit template instantiation
|
|
|
+// generated by autoexplicit.sh
|
|
|
+template bool igl::opengl::glfw::map_texture<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, -1, 1, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, unsigned char const*, int, int, int, std::vector<unsigned char, std::allocator<unsigned char> >&);
|
|
|
+#endif
|