use "ARCH=arch_name make" restructured project folder, implementations and headers together under sources/
160 lines
4.7 KiB
C++
Executable File
160 lines
4.7 KiB
C++
Executable File
#include "Model3D.hpp"
|
|
extern "C" {
|
|
#include "../GLES_3_1_compatibility.h"
|
|
}
|
|
#include "../UTILS/OnlyOnce.hpp"
|
|
#include "../UTILS/ShaderMaker.h"
|
|
#include "objloader.hpp"
|
|
#include "../UTILS/ResourceCache.h"
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
#include <iostream>
|
|
|
|
/* the gl**OES functions are calls which are not in the original OpenGL ES 2
|
|
OpenGL ES 3 would have supported them, ES 2 offers them as extensions
|
|
*/
|
|
|
|
Model3D::Model3D(const char* modelPath, bool smoothNormals) {
|
|
vector<vec3> points = loadVertexData(modelPath, smoothNormals);
|
|
computeBoundingBox(points);
|
|
}
|
|
|
|
void Model3D::computeBoundingBox(vector<vec3> points) {
|
|
boundingBoxLBN = points[0];
|
|
boundingBoxRTF = points[0];
|
|
for (const vec3& point : points) {
|
|
boundingBoxLBN.x = glm::min(boundingBoxLBN.x, point.x);
|
|
boundingBoxLBN.y = glm::min(boundingBoxLBN.y, point.y);
|
|
boundingBoxLBN.z = glm::max(boundingBoxLBN.z, point.z);
|
|
boundingBoxRTF.x = glm::max(boundingBoxRTF.x, point.x);
|
|
boundingBoxRTF.y = glm::max(boundingBoxRTF.y, point.y);
|
|
boundingBoxRTF.z = glm::min(boundingBoxRTF.z, point.z);
|
|
}
|
|
}
|
|
|
|
vector<vec3> Model3D::loadVertexData(const char* modelPath, bool smoothNormals) {
|
|
unsigned int vbo, vboUv, vboNor, vboTangent, vboBitangent;
|
|
vector<vec3> vertices;
|
|
vector<int> verticesIndex;
|
|
vector<vec2> verticesUv;
|
|
vector<vec3> verticesNor;
|
|
vector<vec3> verticesTangent;
|
|
vector<vec3> verticesBitangent;
|
|
|
|
loadOBJ(modelPath, vertices, verticesUv, verticesNor, smoothNormals);
|
|
/* the windows version was happy even with %d */
|
|
printf("Vertici : %ld\tUVcoord : %ld\tNormali : %ld\n", vertices.size(), verticesUv.size(), verticesNor.size() );
|
|
|
|
glGenVertexArrays(1, &vao);
|
|
glBindVertexArray(vao);
|
|
// VBO vertici
|
|
{
|
|
glGenBuffers(1, &vbo);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vec3), &vertices[0], GL_STATIC_DRAW);
|
|
glEnableVertexAttribArray(0);
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0/* 3 * sizeof(float)*/, 0);
|
|
Model3D::nVertices = vertices.size();
|
|
|
|
}
|
|
// VBO coordinate UV
|
|
{
|
|
|
|
glGenBuffers(1, &vboUv);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vboUv);
|
|
glBufferData(GL_ARRAY_BUFFER, verticesUv.size() * sizeof(vec2), &verticesUv[0], GL_STATIC_DRAW);
|
|
glEnableVertexAttribArray(1);
|
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,0 /*2 * sizeof(float)*/, 0);
|
|
|
|
}
|
|
// VBO normali
|
|
{
|
|
glGenBuffers(1, &vboNor);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vboNor);
|
|
glBufferData(GL_ARRAY_BUFFER, verticesNor.size() * sizeof(vec3), &verticesNor[0], GL_STATIC_DRAW);
|
|
glEnableVertexAttribArray(2);
|
|
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0/* 3 * sizeof(float)*/,0);
|
|
|
|
}
|
|
|
|
// VBO tangenti e VBO bitangenti
|
|
{
|
|
for (int i = 0; i < vertices.size(); i += 3) {
|
|
|
|
//erano del tipo vec2& =
|
|
// Shortcuts for vertices
|
|
vec3 v0 = vertices[i + 0];
|
|
vec3 v1 = vertices[i + 1];
|
|
vec3 v2 = vertices[i + 2];
|
|
|
|
// Shortcuts for UVs
|
|
vec2 uv0 = verticesUv[i + 0];
|
|
vec2 uv1 = verticesUv[i + 1];
|
|
vec2 uv2 = verticesUv[i + 2];
|
|
|
|
// Edges of the triangle : position delta
|
|
vec3 deltaPos1 = v1 - v0;
|
|
vec3 deltaPos2 = v2 - v0;
|
|
|
|
// UV delta
|
|
vec2 deltaUV1 = uv1 - uv0;
|
|
vec2 deltaUV2 = uv2 - uv0;
|
|
|
|
float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
|
|
vec3 tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r;
|
|
vec3 bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r;
|
|
|
|
// Set the same tangent for all three vertices of the triangle.
|
|
verticesTangent.push_back(tangent);
|
|
verticesTangent.push_back(tangent);
|
|
verticesTangent.push_back(tangent);
|
|
|
|
// Same thing for bitangents
|
|
verticesBitangent.push_back(bitangent);
|
|
verticesBitangent.push_back(bitangent);
|
|
verticesBitangent.push_back(bitangent);
|
|
|
|
}
|
|
|
|
glGenBuffers(1, &vboTangent);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vboTangent);
|
|
glBufferData(GL_ARRAY_BUFFER, verticesTangent.size() * sizeof(vec3), &verticesTangent[0], GL_STATIC_DRAW);
|
|
glEnableVertexAttribArray(3);
|
|
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
|
|
|
|
|
glGenBuffers(1, &vboBitangent);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vboBitangent);
|
|
glBufferData(GL_ARRAY_BUFFER, verticesBitangent.size() * sizeof(vec3), &verticesBitangent[0], GL_STATIC_DRAW);
|
|
glEnableVertexAttribArray(4);
|
|
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
return vertices;
|
|
}
|
|
|
|
void Model3D::draw() {
|
|
glBindVertexArray(vao);
|
|
glDrawArrays(GL_TRIANGLES, 0, nVertices);
|
|
glBindVertexArray(0);
|
|
}
|
|
|
|
GLuint Model3D::getVAO() {
|
|
return this->vao;
|
|
}
|
|
|
|
int Model3D::getTrisCount() {
|
|
return this->nVertices;
|
|
}
|
|
|
|
vec3 Model3D::getLBN() {
|
|
return boundingBoxLBN;
|
|
}
|
|
|
|
vec3 Model3D::getRTF() {
|
|
return boundingBoxRTF;
|
|
}
|