In my program I am rendering a human body (phantom). Phantom data is stored in txt files vertices.txt (vertices files contain x, y and z coordinates of each vertice that should be drawn) and indices.txt. Currently I am trying to develop phantom selection so I could change object position in space or rotate around axis. But the problem is that I do not know how to determine if casted ray intersects with phantom.
Quesition: How can I determine if ray intersects with my phantom object?
Code for ray casting:
glm::vec3 MyGLCanvas::calculateMouseRay(glm::mat4 projectionMatrix)
{
GLfloat mouseX = wxGetMousePosition().x;
GLfloat mouseY = wxGetMousePosition().y;
glm::vec2 normalizedCoords = getNormmalizedDeviceCoords(mouseX, mouseY);
glm::vec4 clipCoords = glm::vec4(normalizedCoords.x, normalizedCoords.y, -1.0f, 1.0f);
glm::vec4 eyeCoords = toEyeCoords(clipCoords, projectionMatrix);
glm::vec3 worldRay = toWorldCoords(eyeCoords);
return worldRay;
}
glm::vec4 MyGLCanvas::toEyeCoords(glm::vec4 clipCoords, glm::mat4 projectionMatrix)
{
glm::mat4 invertedProjection = glm::inverse(projectionMatrix);
glm::vec4 eyeCoords = invertedProjection * clipCoords;
return glm::vec4(eyeCoords.x, eyeCoords.y, -1.0f, 0.0f);
}
glm::vec3 MyGLCanvas::toWorldCoords(glm::vec4 eyeCoords)
{
glm::mat4 invertedView = glm::inverse(fpsCamera->getViewMatrix());
glm::vec4 rayWorld = invertedView * eyeCoords;
glm::vec3 mouseRay = glm::vec3(rayWorld.x, rayWorld.y, rayWorld.z);
mouseRay = glm::normalize(mouseRay);
return mouseRay;
}
glm::vec2 MyGLCanvas::getNormmalizedDeviceCoords(GLfloat mouseX, GLfloat mouseY)
{
GLfloat x = (2.0f * mouseX) / windowWidth - 1.0f;
GLfloat y = 1.0f - (2.0f * mouseY) / windowHeight;
return glm::vec2(x, y);
}
Code for loading my phantom object:
#include <sstream>
#include <fstream>
#include <math.h>
Mesh::Mesh()
{
loaded = false;
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ibo);
}
void Mesh::loadVertices(std::string fileName)
{
double item = 0;
int n = 0, x = 0, y = 0;
bool dotEncountered = false;
int numbersAfterDot = 0;
std::ifstream is(fileName, std::ifstream::binary);
if (is) {
is.seekg(0, is.end);
int length = is.tellg();
is.seekg(0, is.beg);
char* buffer = new char[length];
is.read(buffer, length);
is.close();
for (unsigned int i = 0; i < is.gcount(); i++)
{
switch (buffer[i])
{
case '\r':
break;
case '\n':
{
vertices.push_back(glm::vec3(y, item, x));
dotEncountered = false;
numbersAfterDot = 0;
n = 0;
item = 0;
break;
}
case ' ':
{
n++;
if (n == 1)
{
x = item;
dotEncountered = false;
numbersAfterDot = 0;
}
else
{
dotEncountered = false;
numbersAfterDot = 0;
y = item;
}
dotEncountered = false;
numbersAfterDot = 0;
item = 0;
break;
}
case '.':
dotEncountered = true;
break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
case '8': case '9':
if (!dotEncountered)
{
item = 10 * item + buffer[i] - '0';
break;
}
else
{
numbersAfterDot++;
item += (double) (buffer[i] - '0') / pow(10, numbersAfterDot);
break;
}
default:
std::cerr << "Bad format\n";
}
}
delete[] buffer;
}
}
void Mesh::loadIndices(std::string fileName)
{
int item = 0;
std::ifstream is(fileName, std::ifstream::binary);
if (is) {
is.seekg(0, is.end);
int length = is.tellg();
is.seekg(0, is.beg);
char* buffer = new char[length];
is.read(buffer, length);
is.close();
for (unsigned int i = 0; i < is.gcount(); i++)
{
switch (buffer[i])
{
case '\r':
break;
case '\n':
{
indicies.push_back(item);
item = 0;
break;
}
case ' ':
{
indicies.push_back(item);
item = 0;
break;
}
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
case '8': case '9':
item = 10 * item + buffer[i] - '0';
break;
default:
std::cerr << "Bad format\n";
}
}
delete[] buffer;
}
}
bool Mesh::loadOBJ()
{
loadVertices("Phantom Data/FA_vertices.txt");
loadIndices("Phantom Data/FA_indices.txt");
initBuffers();
return (loaded = true);
}
void Mesh::draw()
{
if (!loaded) return;
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, indicies.size(), GL_UNSIGNED_INT, nullptr);
glBindVertexArray(0);
}
void Mesh::initBuffers()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), NULL);
glEnableVertexAttribArray(0);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicies.size() * sizeof(GLuint), &indicies[0], GL_STATIC_DRAW);
glBindVertexArray(0);
}
Image of phantom that is drawn:
Example from vertices.txt:
273.536 185.919 1752 // z, y and x coordinates. This file contains 2 million lines
273.536 185.919 1760
273.536 188.056 1752
273.536 188.056 1760
273.536 185.919 1752
273.536 185.919 1760
273.536 188.056 1752
273.536 188.056 1760
275.673 185.919 1752
275.673 185.919 1760
275.673 188.056 1752
Example from indices.txt:
4 5 7 4 6 7
2 3 7 2 6 7
0 4 6 0 2 6
8 10 11 8 9 11
12 13 15 12 14 15
10 11 15 10 14 15
8 12 14 8 10 14