Spieleprogrammierung/RubiksCube/PartitionedCube.cpp
2025-01-19 14:17:36 +01:00

158 lines
3.9 KiB
C++

#include "PartitionedCube.h"
#include "Debug.h"
#include "Cube.h"
#include <glm/glm.hpp>
#include <glm/ext.hpp>
Shader PartitionedCubeMesh::_shader("cube.vert", "cube.frag");
Texture PartitionedCubeMesh::_diffuse;
Texture PartitionedCubeMesh::_roughness;
Texture PartitionedCubeMesh::_normal;
PartitionedCube::PartitionedCube(Cube* parent, const glm::vec3& position, Color* sideColors) : Entity(parent)
{
this->TransformLocal(glm::translate(glm::mat4(1.0f), position));
this->_transformTem = glm::mat4(1.0f);
for(int i=0;i<6;i++) {
_faces[i] = sideColors[i];
}
_animationTime = 0.0f;
_animationTimeExtend = 0.0f;
_animationTransform = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
_animationFinished = true;
for(int axis=0;axis<3;axis++) {
float factor = 1.0f * -1;
for(int reverse=0;reverse<2;reverse++) {
glm::vec3 x, y, z, v;
x = glm::vec3(0.0f);
y = glm::vec3(0.0f);
z = glm::vec3(0.0f);
z[axis] = factor;
x[(axis+1)%3] = 1.0f;
y = glm::cross(x, z);
glm::vec3 v0 = x * 0.5f + y * 0.5f + 0.5f * z;
glm::vec3 v1 = x * -0.5f + y * 0.5f + 0.5f * z;
glm::vec3 v2 = x * 0.5f + y * -0.5f + 0.5f * z;
glm::vec3 v3 = x * -0.5f + y * -0.5f + 0.5f * z;
int s = 2 * axis + reverse; // (-x, +x, -y, +y, -z, +z)
glm::vec2 uv0 = glm::vec2(1.0f, 1.0f);
glm::vec2 uv1 = glm::vec2(0.0f, 1.0f);
glm::vec2 uv2 = glm::vec2(1.0f, 0.0f);
glm::vec2 uv3 = glm::vec2(0.0f, 0.0f);
VertexData d0 = VertexData(v0, z, uv0, sideColors[s]);
VertexData d1 = VertexData(v1, z, uv1, sideColors[s]);
VertexData d2 = VertexData(v2, z, uv2, sideColors[s]);
VertexData d3 = VertexData(v3, z, uv3, sideColors[s]);
_mesh.AddQuad(d0, d1, d2, d3);
factor = -factor;
}
}
_mesh.CalculateTangents();
}
void PartitionedCube::Update(double deltaTime) {
this->_animationTime -= deltaTime;
if (!_animationFinished && _animationTime <= 0.0f) {
_animationTime = 0.0f;
const glm::mat4 finishedAnimationTransform = TransformCustom();
SetTransform(finishedAnimationTransform);
_animationFinished = true;
}
}
void PartitionedCube::Render(DefaultUniform& uniform) {
uniform.model = TransformCustom();
_mesh.Render(uniform);
}
int toIndex(const glm::ivec3& direction) {
int axis = glm::abs(direction.x * 1 + direction.y * 2 + direction.z * 3) - 1;
int allAxis = direction.x + direction.y + direction.z;
int x = glm::sign(allAxis);
int reverse = (x + 1) / 2;
return axis * 2 + reverse;
}
glm::ivec3 toDirection(int index) {
int axis = index / 2;
int reverse = index % 2;
glm::ivec3 direction = glm::ivec3(0);
direction[axis] = 1;
if (reverse == 0)
direction = -direction;
return direction;
}
void PartitionedCube::TransformData(const glm::ivec3& axis, int turns) {
Color previousListColors[6];
for(int i=0;i<6;i++) {
previousListColors[i] = _faces[i];
}
glm::mat3 rotations = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f) * turns, glm::vec3(axis));
for(int axis=0;axis<3;axis++) {
for(int direction=-1;direction<=1;direction+=2) {
glm::ivec3 position = glm::ivec3(0);
position[axis] = direction;
glm::vec3 newPosition = rotations * position;
glm::ivec3 newPositionStable;
newPositionStable.x = std::round(newPosition.x);
newPositionStable.y = std::round(newPosition.y);
newPositionStable.z = std::round(newPosition.z);
int newIndex = toIndex(newPositionStable);
int index = toIndex(position);
_faces[newIndex] = previousListColors[index];
}
}
}
void PartitionedCube::TransformAnimation(const glm::quat& transform, float duration) {
if (!_animationFinished)
SetTransform(TransformCustom());
this->_animationTransform = transform;
this->_animationTime = duration;
this->_animationTimeExtend = duration;
_animationFinished = false;
}
void PartitionedCube::TransformTemp(const glm::mat4& transform)
{
_transformTem = transform;
}
void PartitionedCube::UndoTransformTemp()
{
_transformTem = glm::mat4(1.0f);
}