180 lines
5.4 KiB
C++
180 lines
5.4 KiB
C++
#pragma once
|
|
|
|
#include "Color.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <glm/glm.hpp>
|
|
#include <glm/ext.hpp>
|
|
#include <glm/ext/quaternion_float.hpp>
|
|
#include <math.h>
|
|
#include <vector>
|
|
|
|
#include "Entity.h"
|
|
|
|
#include "Texture.h"
|
|
#include "Shader.h"
|
|
#include "Mesh.h"
|
|
|
|
struct VertexData {
|
|
glm::vec3 position;
|
|
glm::vec3 normal;
|
|
glm::vec2 uv0;
|
|
glm::vec3 tangent;
|
|
glm::vec3 bitangent;
|
|
Color color;
|
|
|
|
VertexData(const glm::vec3& position, const glm::vec3& normal, const glm::vec2 uv0, Color color) : position(position), color(color), normal(normal), uv0(uv0), tangent(0.0f), bitangent(0.0f) {
|
|
|
|
}
|
|
};
|
|
|
|
class PartitionedCubeMesh : public Mesh<VertexData> {
|
|
private:
|
|
static Shader _shader;
|
|
static Texture _diffuse;
|
|
static Texture _roughness;
|
|
static Texture _normal;
|
|
|
|
GLuint _uniformDiffuse;
|
|
GLuint _uniformRoughness;
|
|
GLuint _uniformNormal;
|
|
|
|
public:
|
|
PartitionedCubeMesh() : Mesh(&_shader) {
|
|
_shader.Use();
|
|
|
|
glBindVertexArray(_vba);
|
|
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
|
|
|
int shd = shader->Reference();
|
|
|
|
_uniformDiffuse = glGetUniformLocation(shd, "diffuse");
|
|
_uniformRoughness = glGetUniformLocation(shd, "roughness");
|
|
_uniformNormal = glGetUniformLocation(shd, "normal");
|
|
|
|
glUniform1i(_uniformDiffuse, 0);
|
|
glUniform1i(_uniformRoughness, 1);
|
|
glUniform1i(_uniformNormal, 2);
|
|
|
|
glVertexAttribPointer(glGetAttribLocation(shd, "position"), 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position));
|
|
glVertexAttribPointer(glGetAttribLocation(shd, "normal"), 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, normal));
|
|
glVertexAttribPointer(glGetAttribLocation(shd, "uv0"), 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, uv0));
|
|
glVertexAttribPointer(glGetAttribLocation(shd, "tangent"), 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, tangent));
|
|
glVertexAttribPointer(glGetAttribLocation(shd, "bitangent"), 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, bitangent));
|
|
glVertexAttribPointer(glGetAttribLocation(shd, "color"), 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, color));
|
|
glEnableVertexAttribArray(0);
|
|
glEnableVertexAttribArray(1);
|
|
glEnableVertexAttribArray(2);
|
|
glEnableVertexAttribArray(3);
|
|
glEnableVertexAttribArray(4);
|
|
glEnableVertexAttribArray(5);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
|
|
_shader.Disable();
|
|
}
|
|
|
|
virtual void Render(const DefaultUniform& uniform) override {
|
|
_shader.Use();
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_2D, _diffuse.Reference());
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
glBindTexture(GL_TEXTURE_2D, _roughness.Reference());
|
|
|
|
glActiveTexture(GL_TEXTURE2);
|
|
glBindTexture(GL_TEXTURE_2D, _normal.Reference());
|
|
|
|
_shader.Disable();
|
|
|
|
Mesh::Render(uniform);
|
|
}
|
|
|
|
static void LoadResources() {
|
|
_diffuse = Texture("diffuse.png");
|
|
_roughness = Texture("roughness.png");
|
|
_normal = Texture("normal.png");
|
|
}
|
|
|
|
void CalculateTangents() {
|
|
for(int i=0;i<_vertexData.size();i += 3) {
|
|
VertexData& d0 = _vertexData.at(i + 0);
|
|
VertexData& d1 = _vertexData.at(i + 1);
|
|
VertexData& d2 = _vertexData.at(i + 2);
|
|
|
|
glm::vec3 deltaPos1 = d1.position - d0.position;
|
|
glm::vec3 deltaPos2 = d2.position - d0.position;
|
|
|
|
glm::vec2 deltaUV1 = d1.uv0 - d0.uv0;
|
|
glm::vec2 deltaUV2 = d2.uv0 - d0.uv0;
|
|
|
|
float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
|
|
d0.tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r;
|
|
d0.bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r;
|
|
d1.tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r;
|
|
d1.bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r;
|
|
d2.tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r;
|
|
d2.bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r;
|
|
}
|
|
}
|
|
};
|
|
|
|
enum Side {
|
|
Left, Right, Bottom, Top, Back, Forward
|
|
};
|
|
|
|
constexpr glm::vec3 SideToDirection[6] = {
|
|
glm::vec3(-1.0f, 0.0f, 0.0f),
|
|
glm::vec3(1.0f, 0.0f, 0.0f),
|
|
glm::vec3(0.0f, -1.0f, 0.0f),
|
|
glm::vec3(0.0f, 1.0f, 0.0f),
|
|
glm::vec3(0.0f, 0.0f, -1.0f),
|
|
glm::vec3(0.0f, 0.0f, 1.0f),
|
|
};
|
|
|
|
class Cube;
|
|
|
|
class PartitionedCube : public Entity
|
|
{
|
|
private:
|
|
glm::mat4 _transformTem;
|
|
|
|
glm::quat _animationTransform;
|
|
float _animationTime;
|
|
float _animationTimeExtend;
|
|
bool _animationFinished;
|
|
|
|
Color _faces[6];
|
|
PartitionedCubeMesh _mesh;
|
|
|
|
public:
|
|
PartitionedCube(Cube* parent, const glm::vec3& position, Color* sideColors);
|
|
|
|
void Update(double deltaTime) override;
|
|
void Render(DefaultUniform& uniform) override;
|
|
|
|
const glm::mat4 TransformCustom() const {
|
|
// Need to use slerp since rotations are non-linear and would not interpolate this way
|
|
//
|
|
// However a lerp can be used and then normalized, with not that much of an
|
|
// error but being much more performant thus preferred function
|
|
if (false == _animationFinished) {
|
|
float lerpFactor = 1.0f - ( _animationTime / _animationTimeExtend);
|
|
|
|
glm::mat4 animationView = glm::mat4_cast(glm::normalize(glm::lerp(glm::quat(1.0f, 0.0f, 0.0f, 0.0f), _animationTransform, lerpFactor)));
|
|
|
|
return Parent()->LocalToWorld() * animationView * LocalObjectTransform();
|
|
}
|
|
|
|
return Parent()->LocalToWorld() * _transformTem * LocalObjectTransform();
|
|
}
|
|
|
|
void TransformData(const glm::ivec3& axis, int turns);
|
|
void TransformAnimation(const glm::quat& transform, float duration);
|
|
void TransformTemp(const glm::mat4& transform);
|
|
void UndoTransformTemp();
|
|
};
|