PDA

View Full Version : Generating UV coordinates



Ellusion
02-01-2016, 03:43 PM
First of all - the code:

std::vector<glm::vec3> verticescopy;
std::vector<glm::vec2> newUVs;

/*Generating new UV Coordinates*/
void keyfunction(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_R && action == GLFW_PRESS)
{
glm::vec3 coords2D;
GLdouble point2DX, point2DY, point2DZ;

GLdouble model_view[16];
glGetDoublev(GL_MODELVIEW_MATRIX, model_view);

GLdouble projection[16];
glGetDoublev(GL_PROJECTION_MATRIX, projection);

GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);

for (int i = 0; i < verticescopy.size(); i++)
{
gluProject((double)verticescopy[i].x, (double)verticescopy[i].y, (double)verticescopy[i].z,
model_view, projection, viewport,
&point2DX, &point2DY, &point2DZ);

glm::vec2 UV;

UV.x = point2DX / 600;
UV.y = (point2DY - 800) / 800; /* I make Y - 800, because values from glProject are generated from (0,1), not (0,0) */

newUVs.push_back(UV);

}
}
}

int main(void)
{
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
getchar();
return -1;
}

glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);

window = glfwCreateWindow(600, 800, "Window", NULL, NULL);
if (window == NULL)
{
fprintf(stderr, "Nie utworzono okna GLFW.\n");
getchar();
glfwTerminate();
return -1;
}

glfwMakeContextCurrent(window);

glewExperimental = true;
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Blad GLEW.\n");
getchar();
glfwTerminate();
return -1;
}

glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

glfwPollEvents();
glfwSetCursorPos(window, 1024 / 2, 768 / 2);

glClearColor(0.0f, 0.0f, 0.4f, 0.0f);

glEnable(GL_DEPTH_TEST);

glDepthFunc(GL_LESS);

glEnable(GL_CULL_FACE);

GLuint VertexArrayID;

glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);

GLuint programID = LoadShaders("TransformVertexShader.vertexshader", "TextureFragmentShader.fragmentshader");

GLuint MatrixID = glGetUniformLocation(programID, "MVP");

GLuint Texture = loadBMP_custom("skull-xray.bmp");

GLuint TextureID = glGetUniformLocation(programID, "myTextureSampler");

std::vector<glm::vec3> vertices;
std::vector<glm::vec2> uvs;
std::vector<glm::vec3> normals;
bool res = loadOBJ("czaszkazeby.obj", vertices, uvs, normals);

for (int i = 0; i < vertices.size(); i++)
{
verticescopy.push_back(vertices[i]);
}

GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);

unsigned int Texture2DTextureID = loadBMP_custom("skull1.bmp");
unsigned int Texture2DVertexBufferID;
unsigned int Texture2DUVBufferID;
unsigned int Texture2DShaderID = LoadShaders("TextVertexShader.vertexshader", "TextVertexShader.fragmentshader");
unsigned int Texture2DUniformID = glGetUniformLocation(Texture2DShaderID, "myTextureSampler");

glGenBuffers(1, &Texture2DVertexBufferID);
glGenBuffers(1, &Texture2DUVBufferID);

glfwSetKeyCallback(window, keyfunction);


do{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glUseProgram(programID);

computeMatricesFromInputs();
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;

glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, newUVs.size() * sizeof(glm::vec2), &newUVs[0], GL_DYNAMIC_DRAW);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
glUniform1i(TextureID, 0);

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);


glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

glDrawArrays(GL_TRIANGLES, 0, vertices.size());

/* HUD drawing, not really important for the problem (I know this is bad, but this is not the main problem) */

std::vector<glm::vec2> verticesTexture;
std::vector<glm::vec2> UVsTexture;

glm::vec2 vertex_up_left = glm::vec2(0, 600);
glm::vec2 vertex_up_right = glm::vec2(800, 600);
glm::vec2 vertex_down_right = glm::vec2(800, 0);
glm::vec2 vertex_down_left = glm::vec2(0, 0);

verticesTexture.push_back(vertex_up_left);
verticesTexture.push_back(vertex_down_left);
verticesTexture.push_back(vertex_up_right);

verticesTexture.push_back(vertex_down_right);
verticesTexture.push_back(vertex_up_right);
verticesTexture.push_back(vertex_down_left);

glm::vec2 uv_up_left = glm::vec2(0, 1);
glm::vec2 uv_up_right = glm::vec2(1, 1);
glm::vec2 uv_down_right = glm::vec2(1, 0);
glm::vec2 uv_down_left = glm::vec2(0, 0);
UVsTexture.push_back(uv_up_left);
UVsTexture.push_back(uv_down_left);
UVsTexture.push_back(uv_up_right);

UVsTexture.push_back(uv_down_right);
UVsTexture.push_back(uv_up_right);
UVsTexture.push_back(uv_down_left);

glBindBuffer(GL_ARRAY_BUFFER, Texture2DVertexBufferID);
glBufferData(GL_ARRAY_BUFFER, verticesTexture.size() * sizeof(glm::vec2), &verticesTexture[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, Texture2DUVBufferID);
glBufferData(GL_ARRAY_BUFFER, UVsTexture.size() * sizeof(glm::vec2), &UVsTexture[0], GL_STATIC_DRAW);

glUseProgram(Texture2DShaderID);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, Texture2DTextureID);
glUniform1i(Texture2DUniformID, 0);

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, Texture2DVertexBufferID);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, Texture2DUVBufferID);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glDrawArrays(GL_TRIANGLES, 0, verticesTexture.size());

/* End of HUD code */

glDisable(GL_BLEND);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);

glfwSwapBuffers(window);
glfwPollEvents();

}
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);

glDeleteBuffers(1, &vertexbuffer);
glDeleteProgram(programID);
glDeleteTextures(1, &TextureID);
glDeleteVertexArrays(1, &VertexArrayID);

glfwTerminate();

return 0;
}

The result of this code is available in attachment.

As you can think this isn't effect which I'm looking for. What I want is to put skull X-ray texture, which you can see on image, on front of skull model (just like people paint their faces for Halloween etc.)
I used gluProject to convert 3D coordinates to 2D coordinates (world to screen). When I get 2D coordiantes of point I just divide it by width or height of texture (depends on coordinates type) which gets me UV coordinate for this point. Is there some hole in my thinking which causes this strange looking texturing?