Feature Complete Private

This commit is contained in:
fred 2025-01-19 14:17:36 +01:00
parent 85583a8880
commit 3887733e67
37 changed files with 1481 additions and 297 deletions

8
.gitignore vendored
View File

@ -1 +1,7 @@
ExternalResources
ExternalResources
Abgabe
963830_rohmenf.zip
bugs.md

112
RubiksCube/Camera.h Normal file
View File

@ -0,0 +1,112 @@
#pragma once
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include "Entity.h"
#include <GLFW/glfw3.h>
class Camera : public Entity {
private:
GLFWwindow* _window;
InputSystem* _inputSystem;
glm::mat4 _view;
glm::mat4 _projection;
glm::quat _orientation;
glm::vec2 _dragStart;
bool _wasMouseClicked;
float _scrollPositionPrevious;
float _scrollPositionDelta;
static inline float cameraDistance = 8.15f;
static inline Camera* _instance;
public:
const glm::mat4& View() const { return _view * glm::mat4_cast(_orientation); }
const glm::mat4& Projection() const { return _projection; }
public:
Camera(GLFWwindow* window, InputSystem* inputSystem) : Entity(nullptr) {
_instance = this;
_window = window;
_inputSystem = inputSystem;
_wasMouseClicked = false;
_view = glm::lookAt(glm::vec3(0.0f, 0.0f, cameraDistance), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
_projection = glm::mat4(1.0f);
}
void Update(double deltaTime) override {
int screenWidth;
int screenHeight;
glfwGetFramebufferSize(_window, &screenWidth, &screenHeight);
float aspec = (float)screenWidth / (float)screenHeight;
_projection = glm::perspective(glm::radians(45.0f), aspec, 0.1f, 100.0f);
if (_inputSystem->WasKeyPressed(GLFW_KEY_SPACE))
_orientation = glm::quat(1.0f, glm::vec3(0.0f, 0.0f, 0.0f));
glm::fvec2 velocity(0.0f, 0.0f);
if (_inputSystem->IsKeyPressed(GLFW_KEY_UP))
velocity.x = glm::radians(90.0f);
if (_inputSystem->IsKeyPressed(GLFW_KEY_DOWN))
velocity.x = glm::radians(-90.0f);
if (_inputSystem->IsKeyPressed(GLFW_KEY_RIGHT))
velocity.y = glm::radians(90.0f);
if (_inputSystem->IsKeyPressed(GLFW_KEY_LEFT))
velocity.y = glm::radians(-90.0f);
if (!_wasMouseClicked && _inputSystem->IsRightMouseDown()) {
_inputSystem->GetMousePos(_dragStart);
}
if (_wasMouseClicked && _inputSystem->IsRightMouseDown()) {
glm::vec2 currentMousePositions;
_inputSystem->GetMousePos(currentMousePositions);
glm::vec2 dragDiff = currentMousePositions - _dragStart;
_dragStart = currentMousePositions;
_orientation = glm::quat(1.0f, glm::vec3(dragDiff.y, dragDiff.x, 0.0f) * 0.008f) * _orientation;
_orientation = glm::normalize(_orientation);
}
_wasMouseClicked = _inputSystem->IsRightMouseDown();
glm::quat velocityQuaternion = glm::quat(0.0f, glm::vec3(velocity.x, velocity.y, 0.0f));
_orientation += 0.5f * (float)deltaTime * velocityQuaternion * _orientation;
_orientation = glm::normalize(_orientation);
_view = glm::translate(_view, glm::vec3(0.0f, 0.0f, _scrollPositionDelta));
_scrollPositionDelta = 0.0f;
// since callbacks need to be static use a singleton
glfwSetScrollCallback(_window, Camera::scrollCallbackGlobal);
}
static void scrollCallbackGlobal(GLFWwindow* window, double xOffset, double yOffset) {
_instance->scrollCallback(window, xOffset, yOffset);
}
void scrollCallback(GLFWwindow* window, double xOffset, double yOffset) {
_scrollPositionDelta = yOffset;
}
void SetAspectRatio(float aspec) {
_projection = glm::perspective(glm::radians(45.0f), aspec, 0.1f, 100.0f);
}
};

View File

@ -1,9 +1,7 @@
#include "Cube.h"
Cube::Cube()
Cube::Cube() : Entity(nullptr)
{
this->_transform = glm::mat4(1.0f);
for(int x=-1;x<=1;x++) {
for(int y=-1;y<=1;y++) {
for(int z=-1;z<=1;z++) {
@ -35,7 +33,7 @@ Cube::Cube()
sideColors[Side::Forward] = SideColor[Side::Forward];
}
PartitionedCube* cubeAtIndex = new PartitionedCube(glm::vec3(x, y, z), sideColors);
PartitionedCube* cubeAtIndex = new PartitionedCube(this, glm::vec3(x, y, z), sideColors);
this->_children[x + 1][y + 1][z + 1] = cubeAtIndex;
}
@ -53,20 +51,6 @@ Cube::~Cube() {
}
}
void Cube::Update(double deltaTime) {
for(int x=0;x<3;x++) {
for(int y=0;y<3;y++) {
for(int z=0;z<3;z++) {
_children[x][y][z]->Update(deltaTime);
}
}
}
}
void Cube::Transform(glm::mat4 transform) {
this->_transform *= transform;
}
void Cube::_FindAxisChildren(const glm::ivec3& axis, int index, std::vector<glm::ivec3>& result) const {
glm::ivec3 orientationBuffer[3] = {
axis,
@ -83,12 +67,20 @@ void Cube::_FindAxisChildren(const glm::ivec3& axis, int index, std::vector<glm:
}
}
void Cube::_TransformData(const glm::ivec3& axis, int index, const glm::mat3& transform) {
void Cube::TransformData(const glm::ivec3& axis, int index, int turns) {
PartitionedCube* previousCubeList[3][3][3];
memcpy(previousCubeList, this->_children, sizeof(this->_children));
std::vector<glm::ivec3> result;
glm::mat3 transform = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f) * turns, glm::vec3(axis));
for(int x=0;x<3;x++) {
for(int y=0;y<3;y++) {
transform[x][y] = lroundf(transform[x][y]);
}
}
_FindAxisChildren(axis, index, result);
for(auto& position : result) {
@ -98,20 +90,22 @@ void Cube::_TransformData(const glm::ivec3& axis, int index, const glm::mat3& tr
newPosition += glm::ivec3(1);
_children[newPosition.x][newPosition.y][newPosition.z] = previousCubeList[position.x][position.y][position.z];
_children[newPosition.x][newPosition.y][newPosition.z]->TransformData(axis, turns);
}
}
void Cube::Transform(const glm::ivec3& axis, int index, const glm::mat3& transform) {
_TransformData(axis, index, transform);
// _TransformData(axis, index, transform);
std::vector<glm::ivec3> result;
_FindAxisChildren(transform * axis, index, result);
_FindAxisChildren(axis, index, result);
for(auto& position : result) {
PartitionedCube* cube = _children[position.x + 1][position.y + 1][position.z + 1];
cube->Transform(glm::mat4(transform));
cube->TransformLocal(glm::mat4(transform));
}
}
@ -123,16 +117,29 @@ void Cube::TransformTemp(const glm::ivec3& axis, int index, const glm::mat3& tra
for(auto& position : result) {
PartitionedCube* cube = _children[position.x + 1][position.y + 1][position.z + 1];
cube->Transform(glm::mat4(transform));
cube->TransformTemp(glm::mat4(transform));
}
}
void Cube::TransformAnimation(const glm::ivec3& axis, int index, const glm::mat3& transform, float duration) {
_TransformData(axis, index, transform);
void Cube::UndoTransformTemp()
{
for(int x=0;x<3;x++) {
for(int y=0;y<3;y++) {
for(int z=0;z<3;z++) {
_children[x][y][z]->UndoTransformTemp();
}
}
}
}
void Cube::TransformAnimation(const glm::ivec3& axis, int index, float angle, float duration) {
// _TransformData(axis, index, transform);
std::vector<glm::ivec3> result;
_FindAxisChildren(transform * axis, index, result);
_FindAxisChildren(axis, index, result);
glm::quat transform = glm::angleAxis(angle, glm::vec3(axis));
for(auto& position : result) {
PartitionedCube* cube = _children[position.x + 1][position.y + 1][position.z + 1];

View File

@ -1,36 +1,33 @@
#pragma once
#include <glm.hpp>
#include <glm/glm.hpp>
#include <iostream>
#include "Entity.h"
#include "PartitionedCube.h"
// Colors according to https://ruwix.com/the-rubiks-cube/japanese-western-color-schemes/
class Cube
class Cube : public Entity
{
private:
glm::mat4 _transform;
PartitionedCube* _children[3][3][3];
void _TransformData(const glm::ivec3& axis, int index, const glm::mat3& transform);
void _FindAxisChildren(const glm::ivec3& axis, int index, std::vector<glm::ivec3>& result) const;
public:
Cube();
~Cube();
void Update(double deltaTime);
virtual ~Cube();
const int ChildPartitionsCount = 27;
PartitionedCube** Children() { return &(_children[0][0][0]); }
const glm::mat4& Transform() const { return _transform; }
void TransformAnimation(const glm::ivec3& axis, int index, const glm::mat3& transform, float duration);
void TransformData(const glm::ivec3& axis, int index, int turns);
void TransformAnimation(const glm::ivec3& axis, int index, float angle, float duration);
void Transform(const glm::ivec3& axis, int index, const glm::mat3& transform);
void TransformTemp(const glm::ivec3& axis, int index, const glm::mat3& transform);
void Transform(glm::mat4 transform);
void UndoTransformTemp();
static constexpr Color SideColor[6] = {
Color::ORANGE(),

68
RubiksCube/Debug.cpp Normal file
View File

@ -0,0 +1,68 @@
#include "Debug.h"
#include <GLFW/glfw3.h>
#include <glm/ext.hpp>
void Debug::Render(DefaultUniform& uniform)
{
RenderLines(uniform);
_lines.clear();
}
void Debug::RenderLines(DefaultUniform& uniform) const
{
glUseProgram(_shader);
glBindVertexArray(_vba);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
int vertexCount = _lines.size() * 6;
int viewportWidth, viewportHeight;
glfwGetFramebufferSize(_window, &viewportWidth, &viewportHeight);
glm::vec2 viewport = glm::vec2(viewportWidth, viewportHeight);
glUniform2fv(_uniformViewportRes, 1, glm::value_ptr(viewport));
glUniformMatrix4fv(_uniformModel, 1, GL_FALSE, glm::value_ptr(uniform.model));
glUniformMatrix4fv(_uniformView, 1, GL_FALSE, glm::value_ptr(uniform.view));
glUniformMatrix4fv(_uniformProjection, 1, GL_FALSE, glm::value_ptr(uniform.projection));
DebugVertexData* data = new DebugVertexData[vertexCount];
int index = 0;
for(const auto& line : _lines) {
int vertexIndex = index * 6;
glm::vec3 quad[4] = {
line.positionFirst,
line.positionFirst,
line.positionLast,
line.positionLast
};
glm::vec3 direction = line.positionLast - line.positionFirst;
data[ vertexIndex + 0 ] = DebugVertexData { quad[0], direction, line.color, line.lineWidth };
data[ vertexIndex + 1 ] = DebugVertexData { quad[1], direction, line.color, line.lineWidth };
data[ vertexIndex + 2 ] = DebugVertexData { quad[2], direction, line.color, line.lineWidth };
data[ vertexIndex + 3 ] = DebugVertexData { quad[1], direction, line.color, line.lineWidth };
data[ vertexIndex + 4 ] = DebugVertexData { quad[2], direction, line.color, line.lineWidth };
data[ vertexIndex + 5 ] = DebugVertexData { quad[3], direction, line.color, line.lineWidth };
index++;
}
glBufferData(GL_ARRAY_BUFFER, sizeof(DebugVertexData) * vertexCount, data, GL_STATIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glUseProgram(0);
delete[] data;
}

146
RubiksCube/Debug.h Normal file
View File

@ -0,0 +1,146 @@
#pragma once
#include "Color.h"
#include "ShaderUtil.h"
#include "Mesh.h"
#include "Entity.h"
#include <gl/glew.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include <vector>
struct GLFWwindow;
struct DebugLine {
glm::vec3 positionFirst;
glm::vec3 positionLast;
float lineWidth;
Color color;
};
struct DebugPoint {
glm::vec3 position;
Color color;
};
struct DebugDirection {
glm::vec3 origin;
glm::vec3 direction;
float lineWidth;
Color color;
};
struct DebugVertexData {
glm::vec3 v;
glm::vec3 tangent;
Color color;
float lineWidth;
};
class Debug : public Entity
{
private:
std::vector<DebugLine> _lines;
std::vector<DebugPoint> _points;
GLFWwindow* _window;
GLuint _vba;
GLuint _vbo;
GLuint _shader;
GLuint _uniformViewportRes;
GLuint _uniformModel;
GLuint _uniformView;
GLuint _uniformProjection;
public:
Debug() : Entity(nullptr) { }
Debug(GLFWwindow* window) : Entity(nullptr) {
_window = window;
glGenBuffers(1, &_vbo);
glGenVertexArrays(1, &_vba);
glBindVertexArray(_vba);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(DebugVertexData), (void*)offsetof(DebugVertexData, v));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(DebugVertexData), (void*)offsetof(DebugVertexData, tangent));
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(DebugVertexData), (void*)offsetof(DebugVertexData, color));
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(DebugVertexData), (void*)offsetof(DebugVertexData, lineWidth));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
_shader = ShaderUtil::CreateShaderProgram("line.vert", "line.frag");
_uniformViewportRes = glGetUniformLocation(_shader, "uViewportRes");
_uniformModel = glGetUniformLocation(_shader, "model");
_uniformView = glGetUniformLocation(_shader, "view");
_uniformProjection = glGetUniformLocation(_shader, "projection");
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
Instance = this;
}
~Debug() {
glDeleteVertexArrays(1, &_vba);
glDeleteBuffers(1, &_vbo);
glDeleteProgram(_shader);
}
void Render(DefaultUniform& uniform) override;
void RenderLines(DefaultUniform& uniform) const;
static inline Debug* Instance;
void Line(const glm::vec3& positionFirst, const glm::vec3& positionLast, const Color& color) {
_lines.push_back(DebugLine { positionFirst, positionLast, 1.0f, color });
}
void Direction(const glm::vec3& origin, const glm::vec3& direction, const Color& color) {
glm::vec4 capWorldPos = glm::vec4(origin + direction * 1.0f, 1.0f);
_lines.push_back(DebugLine { origin, capWorldPos, 8.0f, color });
glm::vec3 up = glm::vec3(direction[1], direction[2], direction[0]);
glm::vec3 capOffsets[4] = {
glm::vec3( 1.0f, 1.0f, -1.0f),
glm::vec3(-1.0f, 1.0f, -1.0f),
glm::vec3( 1.0f, -1.0f, -1.0f),
glm::vec3(-1.0f, -1.0f, -1.0f)
};
glm::mat4 capLocalTf = glm::lookAt(glm::vec3(capWorldPos), origin, up);
capLocalTf = glm::inverse(capLocalTf);
float extends = 0.05f;
for(const glm::vec3& offset : capOffsets) {
Line(capWorldPos, capLocalTf * glm::vec4(extends * offset, 1.0f), color);
}
}
void Point(const glm::vec3& position, const Color& color) {
for(int axis=0;axis<3;axis++) {
glm::vec3 forward = glm::vec3(0.0f);
forward[axis] = 1.0f;
glm::vec3 lineOrigin = position - forward;
glm::vec3 lineDestinatio = position + forward;
Line(lineOrigin, lineDestinatio, color);
}
}
};

81
RubiksCube/Entity.cpp Normal file
View File

@ -0,0 +1,81 @@
#include "Entity.h"
void Entity::_UpdateChildTransform() const {
for(auto& child : _children) {
child->_localToWorld = _localToWorld * child->_transform;
child->_worldToLocal = glm::inverse(child->_transform);
child->_UpdateChildTransform();
}
}
Entity::Entity(Entity* parent) : _localToWorld(1.0f), _worldToLocal(1.0f)
{
_parent = parent;
_transform = glm::mat4(1.0f);
if (parent == nullptr)
return;
parent->AddChild(this);
_localToWorld = _parent->_localToWorld;
_worldToLocal = glm::inverse(_localToWorld);
}
Entity::~Entity() {
_parent->RemoveChild(this);
}
void Entity::AddChild(Entity* entity) {
_children.insert(entity);
}
void Entity::RemoveChild(Entity* entity) {
_children.erase(entity);
}
void Entity::Transform(const glm::mat4& transform) {
glm::mat4 transformLocalBasis = _worldToLocal * transform;
_transform = transformLocalBasis * _transform;
if (_parent == nullptr) {
_localToWorld = _transform;
}
else {
_localToWorld = _parent->LocalToWorld() * _transform;
}
_worldToLocal = glm::inverse(_localToWorld);
_UpdateChildTransform();
}
void Entity::TransformLocal(const glm::mat4& transform)
{
_transform = transform * _transform;
if (_parent == nullptr) {
_localToWorld = _transform;
}
else {
_localToWorld = _parent->LocalToWorld() * _transform;
}
_worldToLocal = glm::inverse(_localToWorld);
_UpdateChildTransform();
}
void Entity::SetTransform(const glm::mat4& transform) {
_transform = transform;
if (_parent != nullptr) {
_localToWorld = transform * _parent->_localToWorld;
_worldToLocal = glm::inverse(transform) * _parent->_worldToLocal;
}
else {
_localToWorld = transform;
_worldToLocal = glm::inverse(transform);
}
_UpdateChildTransform();
}

40
RubiksCube/Entity.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include <unordered_set>
#include <glm/glm.hpp>
#include "Mesh.h"
class Entity {
private:
glm::mat4 _transform;
glm::mat4 _localToWorld;
glm::mat4 _worldToLocal;
Entity* _parent;
std::unordered_set<Entity*> _children;
void _UpdateChildTransform() const;
public:
Entity(Entity* parent);
virtual ~Entity();
void AddChild(Entity* entity);
void RemoveChild(Entity* entity);
Entity* Parent() const { return _parent; }
void Transform(const glm::mat4& transform);
void TransformLocal(const glm::mat4& transform);
void SetTransform(const glm::mat4& transform);
const glm::mat4& LocalToWorld() const { return _localToWorld; }
const glm::mat4& WorldToLocal() const { return _worldToLocal; }
const glm::mat4& LocalObjectTransform() const { return _transform; }
virtual void Render(DefaultUniform& uniform) { };
virtual void Update(double deltaTime) { };
};

View File

@ -4,9 +4,9 @@
#include <iostream>
#include <glm.hpp>
#include <glm/glm.hpp>
#include <ext.hpp>
#include <glm/ext.hpp>
void InputSystem::ObserveKey(int key) {
_keyCodeDictionaryObserver.emplace(key, KeyObserver(_window, key));

View File

@ -2,7 +2,7 @@
#include <map>
#include <glm.hpp>
#include <glm/glm.hpp>
#include "KeyObserver.h"

1
RubiksCube/Mesh.cpp Normal file
View File

@ -0,0 +1 @@
#include "Mesh.h"

97
RubiksCube/Mesh.h Normal file
View File

@ -0,0 +1,97 @@
#pragma once
#include <vector>
#include <gl/glew.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include "Shader.h"
class DefaultUniform {
private:
public:
glm::mat4 model;
glm::mat4 view;
glm::mat4 projection;
};
template<class TVertexData, class TUniform = DefaultUniform>
class Mesh
{
private:
TUniform _uniform;
GLuint _uniformModel;
GLuint _uniformView;
GLuint _uniformProjection;
protected:
std::vector<TVertexData> _vertexData;
GLuint _vba;
GLuint _vbo;
Shader* shader;
bool _isVertexDirty;
public:
TUniform& Uniform() { return _uniform; }
public:
Mesh(Shader* shader) : shader(shader), _isVertexDirty(true) {
shader->Initialize();
glCreateVertexArrays(1, &_vba);
glCreateBuffers(1, &_vbo);
_uniformModel = glGetUniformLocation(shader->Reference(), "model");
_uniformView = glGetUniformLocation(shader->Reference(), "view");
_uniformProjection = glGetUniformLocation(shader->Reference(), "projection");
}
~Mesh() {
glDeleteVertexArrays(1, &_vba);
glDeleteBuffers(1, &_vbo);
}
void AddTriangle(const TVertexData& p0, const TVertexData& p1, const TVertexData& p2) {
_vertexData.push_back(p0);
_vertexData.push_back(p1);
_vertexData.push_back(p2);
_isVertexDirty = true;
}
void AddQuad(const TVertexData& p0, const TVertexData& p1, const TVertexData& p2, const TVertexData& p3) {
AddTriangle(p0, p1, p2);
AddTriangle(p1, p2, p3);
}
virtual void Render(const TUniform& uniform) {
shader->Use();
glUniformMatrix4fv(_uniformModel, 1, GL_FALSE, glm::value_ptr(uniform.model));
glUniformMatrix4fv(_uniformView, 1, GL_FALSE, glm::value_ptr(uniform.view));
glUniformMatrix4fv(_uniformProjection, 1, GL_FALSE, glm::value_ptr(uniform.projection));
glBindVertexArray(_vba);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
if (_isVertexDirty) {
glBufferData(GL_ARRAY_BUFFER, sizeof(TVertexData) * _vertexData.size(), _vertexData.data(), GL_STATIC_DRAW);
_isVertexDirty = false;
}
glDrawArrays(GL_TRIANGLES, 0, _vertexData.size());
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
shader->Disable();
}
};

View File

@ -1 +0,0 @@
#pragma once

View File

@ -1,23 +1,30 @@
#include "PartitionedCube.h"
#include "Debug.h"
#include "Cube.h"
#include <glm.hpp>
#include <ext.hpp>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
PartitionedCube::PartitionedCube(const glm::vec3& position, Color* sideColors) : _faces {
sideColors[0],
sideColors[1],
sideColors[2],
sideColors[3],
sideColors[4],
sideColors[5],
}
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->_transform = glm::translate(glm::mat4(1.0f), position);
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;
_animationTransformInvoke = _transform;
_animationTransform = glm::quat(1.0f, 0.0f, 0.0f, 0.0f);
_animationFinished = true;
@ -33,7 +40,7 @@ PartitionedCube::PartitionedCube(const glm::vec3& position, Color* sideColors) :
z[axis] = factor;
x[(axis+1)%3] = 1.0f;
y[(axis+2)%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;
@ -42,37 +49,109 @@ PartitionedCube::PartitionedCube(const glm::vec3& position, Color* sideColors) :
int s = 2 * axis + reverse; // (-x, +x, -y, +y, -z, +z)
_meshData.addFace(v0, v1, v2, v3, sideColors[s]);
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) {
_animationFinished = true;
_animationTime = 0.0f;
_transform = glm::mat4_cast(_animationTransform) * _animationTransformInvoke;
const glm::mat4 finishedAnimationTransform = TransformCustom();
SetTransform(finishedAnimationTransform);
_animationFinished = true;
}
}
void PartitionedCube::Transform(glm::mat4 transformation)
{
this->_transform = transformation * this->_transform;
_animationTransformInvoke = transformation * _animationTransformInvoke;
_animationTransform = glm::quat_cast(transformation * glm::mat4_cast(_animationTransform));
void PartitionedCube::Render(DefaultUniform& uniform) {
uniform.model = TransformCustom();
_mesh.Render(uniform);
}
void PartitionedCube::TransformAnimation(const glm::mat4& transform, float duration) {
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)
_transform = glm::mat4_cast(_animationTransform) * _animationTransformInvoke;
this->_animationTransformInvoke = this->_transform;
this->_animationTransform = glm::quat_cast(transform);
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);
}

View File

@ -4,47 +4,121 @@
#include <stdint.h>
#include <glm.hpp>
#include <ext.hpp>
#include <ext/quaternion_float.hpp>
#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() : position(glm::vec3(0.0f, 0.0f, 0.0f)), color(Color::WHITE()) {
}
VertexData(const glm::vec3& position, Color color) : position(position), 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) {
}
};
struct MeshData {
int vertexIndex;
std::vector<VertexData> data;
int triangleIndex;
class PartitionedCubeMesh : public Mesh<VertexData> {
private:
static Shader _shader;
static Texture _diffuse;
static Texture _roughness;
static Texture _normal;
MeshData() {
vertexIndex = 0;
triangleIndex = 0;
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();
}
void addTriangle(glm::vec3 v0, glm::vec3 v1, glm::vec3 v2, Color color) {
data.push_back(VertexData(v0, color));
data.push_back(VertexData(v1, color));
data.push_back(VertexData(v2, color));
vertexIndex += 3;
virtual void Render(const DefaultUniform& uniform) override {
_shader.Use();
triangleIndex ++;
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);
}
void addFace(glm::vec3 v0, glm::vec3 v1, glm::vec3 v2, glm::vec3 v3, Color color) {
addTriangle(v0, v1, v2, color);
addTriangle(v3, v2, v1, color);
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;
}
}
};
@ -61,40 +135,45 @@ constexpr glm::vec3 SideToDirection[6] = {
glm::vec3(0.0f, 0.0f, 1.0f),
};
class PartitionedCube
class Cube;
class PartitionedCube : public Entity
{
private:
glm::mat4 _transform;
glm::mat4 _transformTem;
glm::mat4 _animationTransformInvoke;
glm::quat _animationTransform;
float _animationTime;
float _animationTimeExtend;
bool _animationFinished;
Color _faces[6];
MeshData _meshData;
PartitionedCubeMesh _mesh;
public:
PartitionedCube(const glm::vec3& position, Color sideColors[6]);
PartitionedCube(Cube* parent, const glm::vec3& position, Color* sideColors);
void Update(double deltaTime);
void Update(double deltaTime) override;
void Render(DefaultUniform& uniform) override;
const glm::mat4 Transform() const {
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::slerp(glm::quat(1.0f, 0.0f, 0.0f, 0.0f), _animationTransform, lerpFactor));
glm::mat4 animationView = glm::mat4_cast(glm::normalize(glm::lerp(glm::quat(1.0f, 0.0f, 0.0f, 0.0f), _animationTransform, lerpFactor)));
return animationView * _animationTransformInvoke;
return Parent()->LocalToWorld() * animationView * LocalObjectTransform();
}
return _transform;
return Parent()->LocalToWorld() * _transformTem * LocalObjectTransform();
}
const MeshData& MeshData() const { return _meshData; };
void Transform(glm::mat4 transformation);
void TransformAnimation(const glm::mat4& transform, float duration);
void TransformData(const glm::ivec3& axis, int turns);
void TransformAnimation(const glm::quat& transform, float duration);
void TransformTemp(const glm::mat4& transform);
void UndoTransformTemp();
};

View File

@ -1,6 +1,6 @@
#pragma once
#include <glm.hpp>
#include <glm/glm.hpp>
class Plane
{

View File

@ -8,6 +8,8 @@
#include "GameInterface.h"
#include "SceneInterface.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

View File

@ -71,10 +71,10 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ExternalIncludePath>$(SolutionDir)/../ExternalResources/glew/include;$(SolutionDir)/../ExternalResources/glfw/include;$(SolutionDir)/../ExternalResources/glm/glm;$(SolutionDir)/../ExternalResources/stb;$(ExternalIncludePath)</ExternalIncludePath>
<ExternalIncludePath>$(SolutionDir)/../ExternalResources/glew/include;$(SolutionDir)/../ExternalResources/glfw/include;$(SolutionDir)/../ExternalResources/glm;$(SolutionDir)/../ExternalResources/stb;$(ExternalIncludePath)</ExternalIncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ExternalIncludePath>$(SolutionDir)/../ExternalResources/glew/include;$(SolutionDir)/../ExternalResources/glfw/include;$(SolutionDir)/../ExternalResources/glm/glm;$(SolutionDir)/../ExternalResources/stb;$(ExternalIncludePath)</ExternalIncludePath>
<ExternalIncludePath>$(SolutionDir)/../ExternalResources/glew/include;$(SolutionDir)/../ExternalResources/glfw/include;$(SolutionDir)/../ExternalResources/glm;$(SolutionDir)/../ExternalResources/stb;$(ExternalIncludePath)</ExternalIncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -110,6 +110,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -126,6 +127,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -139,30 +141,36 @@
<ItemGroup>
<ClCompile Include="Color.cpp" />
<ClCompile Include="Cube.cpp" />
<ClCompile Include="Debug.cpp" />
<ClCompile Include="Entity.cpp" />
<ClCompile Include="GameInterface.cpp" />
<ClCompile Include="InputSystem.cpp" />
<ClCompile Include="KeyObserver.cpp" />
<ClCompile Include="Mesh.cpp" />
<ClCompile Include="PartitionedCube.cpp" />
<ClCompile Include="Plane.cpp" />
<ClCompile Include="RubiksCube.cpp" />
<ClCompile Include="SceneInterface.cpp" />
<ClCompile Include="Shader.cpp" />
<ClCompile Include="ShaderUtil.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Camera.h" />
<ClInclude Include="Color.h" />
<ClInclude Include="Cube.h" />
<ClInclude Include="Debug.h" />
<ClInclude Include="Entity.h" />
<ClInclude Include="GameInterface.h" />
<ClInclude Include="InputSystem.h" />
<ClInclude Include="KeyObserver.h" />
<ClInclude Include="MeshData.h" />
<ClInclude Include="Mesh.h" />
<ClInclude Include="PartitionedCube.h" />
<ClInclude Include="Plane.h" />
<ClInclude Include="SceneInterface.h" />
<ClInclude Include="Settings.h" />
<ClInclude Include="Shader.h" />
<ClInclude Include="ShaderUtil.h" />
<ClInclude Include="Side.h" />
<ClInclude Include="VertexData.h" />
<ClInclude Include="Texture.h" />
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="cube.frag">
@ -176,6 +184,40 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</CopyFileToFolders>
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="line.frag">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</CopyFileToFolders>
<CopyFileToFolders Include="line.vert">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</CopyFileToFolders>
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="normal.png">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</CopyFileToFolders>
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="diffuse.png">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</CopyFileToFolders>
<CopyFileToFolders Include="roughness.png">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</CopyFileToFolders>
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="diffuse_test.png">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</CopyFileToFolders>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -36,9 +36,6 @@
<ClCompile Include="Color.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="Shader.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="ShaderUtil.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
@ -51,6 +48,15 @@
<ClCompile Include="Plane.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="Debug.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="Mesh.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="Entity.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GameInterface.h">
@ -68,15 +74,6 @@
<ClInclude Include="Color.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Shader.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="VertexData.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="MeshData.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Side.h">
<Filter>Headerdateien</Filter>
</ClInclude>
@ -92,6 +89,27 @@
<ClInclude Include="Plane.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Debug.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Settings.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Mesh.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Texture.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Shader.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Entity.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Camera.h">
<Filter>Headerdateien</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="cube.frag">
@ -100,5 +118,23 @@
<CopyFileToFolders Include="cube.vert">
<Filter>Shaders</Filter>
</CopyFileToFolders>
<CopyFileToFolders Include="line.frag">
<Filter>Shaders</Filter>
</CopyFileToFolders>
<CopyFileToFolders Include="line.vert">
<Filter>Shaders</Filter>
</CopyFileToFolders>
<CopyFileToFolders Include="normal.png">
<Filter>Ressourcendateien</Filter>
</CopyFileToFolders>
<CopyFileToFolders Include="diffuse.png">
<Filter>Ressourcendateien</Filter>
</CopyFileToFolders>
<CopyFileToFolders Include="roughness.png">
<Filter>Ressourcendateien</Filter>
</CopyFileToFolders>
<CopyFileToFolders Include="diffuse_test.png">
<Filter>Ressourcendateien</Filter>
</CopyFileToFolders>
</ItemGroup>
</Project>

View File

@ -6,9 +6,10 @@
#include "Plane.h"
#include <glm.hpp>
#include <ext.hpp>
#include <gtx/string_cast.hpp>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include <glm/gtx/string_cast.hpp>
#include <GLFW/glfw3.h>
@ -16,6 +17,20 @@
#include <iostream>
SceneInterface::SceneInterface()
{
}
SceneInterface::~SceneInterface()
{
for(Entity* entity : _entities) {
delete entity;
}
delete currentAction;
}
void SceneInterface::Initialize(GLFWwindow* window)
{
_inputSystem.SetWindow(window);
@ -39,23 +54,31 @@ void SceneInterface::Initialize(GLFWwindow* window)
_inputSystem.ObserveKey(GLFW_KEY_KP_9);
_wasMouseDown = false;
this->_shaderProgram = ShaderUtil::CreateShaderProgram("cube.vert", "cube.frag");
this->_transformLocation = glGetUniformLocation(this->_shaderProgram, "transformation");
glGenVertexArrays(1, &this->_arrayBufferObject);
glGenBuffers(1, &this->_vertexBufferObject);
glBindVertexArray(_arrayBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, this->_vertexBufferObject);
glVertexAttribPointer(glGetAttribLocation(_shaderProgram, "position"), 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position));
glEnableVertexAttribArray(0);
glVertexAttribPointer(glGetAttribLocation(_shaderProgram, "color"), 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, color));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
_debug = new Debug(window);
PartitionedCubeMesh::LoadResources();
_camera = new Camera(window, &_inputSystem);
Cube* cube = new Cube();
_cube = cube;
_entities.push_back(_debug);
_entities.push_back(_camera);
_entities.push_back(_cube);
for(PartitionedCube** cube = _cube->Children();cube != _cube->Children() + _cube->ChildPartitionsCount;cube++) {
_entities.push_back(*cube);
}
std::cout << "Controls: " << std::endl;
std::cout << "Numpad 1, 2, 3, 7, 8, 9 + Shift Rotate X Axis Down Up View" << std::endl;
std::cout << "Numpad 1, 4, 7, 3, 6, 9 Rotate Y Axis Left Right View" << std::endl;
std::cout << "Arrows Up, Down, Right, Left Rotate Camera relative lookat" << std::endl;
std::cout << "Space Reset Look Changes" << std::endl;
std::cout << "Mouse Scroll Vertically Zoom" << std::endl;
std::cout << "Left Mouse Rotate Cube Planes" << std::endl;
std::cout << "Right Mouse Rotate Camera" << std::endl;
}
glm::vec3 basisCoordinateVectors[] = {
@ -113,33 +136,19 @@ void IntersectLinePlane(const glm::vec3& lineStart, const glm::vec3& lineDirecti
}
}
void SceneInterface::EnqueueAction(const Action& action) {
void SceneInterface::EnqueueAction(Action* action) {
_actions.push(action);
}
void SceneInterface::Update(float deltaTime)
{
_cube.Update(deltaTime);
_inputSystem.Update();
if (_inputSystem.WasKeyPressed(GLFW_KEY_SPACE))
_orientation = glm::quat(1.0f, glm::vec3(0.0f, 0.0f, 0.0f));
for(Entity* entity : _entities) {
entity->Update(deltaTime);
}
glm::fvec2 velocity(0.0f, 0.0f);
if (_inputSystem.IsKeyPressed(GLFW_KEY_UP))
velocity.x = glm::radians(90.0f);
if (_inputSystem.IsKeyPressed(GLFW_KEY_DOWN))
velocity.x = glm::radians(-90.0f);
if (_inputSystem.IsKeyPressed(GLFW_KEY_RIGHT))
velocity.y = glm::radians(90.0f);
if (_inputSystem.IsKeyPressed(GLFW_KEY_LEFT))
velocity.y = glm::radians(-90.0f);
glm::quat velocityQuaternion = glm::quat(0.0f, glm::vec3(velocity.x, velocity.y, 0.0f));
_orientation += 0.5f * (float)deltaTime * velocityQuaternion * _orientation;
_orientation = glm::normalize(_orientation);
// int spinIndex = 0;
@ -170,49 +179,98 @@ void SceneInterface::Update(float deltaTime)
int axisIndex = spinAxis.x == 0; // x => 0, y => 1
int spinIndex = keyToIndex[axisIndex][rotationKey - 1];
if (reverse)
spinAxis *= -1;
int reverseSign = reverse ? -1 : 1;
spinAxis *= reverseSign;
spinIndex *= reverseSign;
glm::mat3 cubeMat = glm::mat3(_cube->LocalToWorld()) * glm::mat3(_camera->View());
glm::mat3 orthogonalized = cubeMat;
for(int column=0;column<3;column++) {
int nearestCardinalisedAxis = 0;
for(int i=0;i<3;i++) {
if (glm::abs(orthogonalized[column][i]) > glm::abs(orthogonalized[column][nearestCardinalisedAxis])) {
nearestCardinalisedAxis = i;
}
}
for(int columnToPlace=0;columnToPlace<3;columnToPlace++) {
for(int i=0;i<3;i++) {
if (columnToPlace == column) {
if (nearestCardinalisedAxis == i) {
orthogonalized[columnToPlace][i] = glm::sign(orthogonalized[columnToPlace][i]);
}
else {
orthogonalized[columnToPlace][i] = 0.0f;
}
}
else {
if (nearestCardinalisedAxis == i) {
orthogonalized[columnToPlace][i] = 0.0f;
}
}
}
}
}
glm::mat3 screenToCube = glm::inverse(orthogonalized);
spinAxis = screenToCube * spinAxis;
int direction = spinAxis.x + spinAxis.y + spinAxis.z;
EnqueueAction(new ActionSpinDefault(_cube, spinAxis, spinIndex, 1.0f));
// _cube.TransformAnimation(cubeSpinAxis, spinIndex, rotation, 1.0f);
EnqueueAction(Action(spinAxis, spinIndex, 1.0f));
std::cout << glm::to_string(spinAxis) << " " << spinIndex << std::endl;
}
if (!_wasMouseDown && _inputSystem.IsLeftMouseDown()) {
OnDragStart();
if (currentAction == nullptr) {
if (!_wasMouseDown && _inputSystem.IsLeftMouseDown()) {
OnDragStart();
}
else if (_wasMouseDown && !_inputSystem.IsLeftMouseDown()) {
OnDragStop();
}
else if (_wasMouseDown && _inputSystem.IsLeftMouseDown()) {
OnDrag(deltaTime);
}
_wasMouseDown = _inputSystem.IsLeftMouseDown();
}
else if (_wasMouseDown && !_inputSystem.IsLeftMouseDown()) {
OnDragStop();
}
else if (_wasMouseDown && _inputSystem.IsLeftMouseDown()) {
OnDrag(deltaTime);
if (currentAction != nullptr) {
currentAction->duration -= deltaTime;
}
_wasMouseDown = _inputSystem.IsLeftMouseDown();
if (currentAction != nullptr && currentAction->duration > 0.0f) {
return;
}
currentAction.duration -= deltaTime;
if (currentAction.duration <= 0.0f && _actions.size() > 0) {
Action& action = _actions.front();
if (_actions.size() > 0) {
delete currentAction;
Action* action = _actions.front();
_actions.pop();
ApplyAction(action);
}
else {
currentAction = nullptr;
}
}
void SceneInterface::OnDragStart() {
_inputSystem.GetMousePos(_initialMouseLocation);
Plane planes[6];
glm::vec3 lineStart;
glm::vec3 lineDirection;
glm::mat4 viewPerspective = _perspective * _view;
glm::mat4 viewPerspective = _camera->Projection() * _camera->View();
_inputSystem.GetPickingRay(viewPerspective, lineStart, lineDirection);
glm::mat4 transform = glm::mat4(1.0f);
glm::mat4 transform = _cube->LocalToWorld();
for(int axis=0;axis<3;axis++) {
for(int direction=-1;direction<=1;direction+=2) {
@ -252,7 +310,7 @@ void SceneInterface::OnDrag(double deltaTime) {
glm::vec3 lineStart;
glm::vec3 lineDirection;
glm::mat4 transform = _perspective * _view;
glm::mat4 transform = _camera->Projection() * _camera->View();
_inputSystem.GetPickingRay(transform, lineStart, lineDirection);
float intersectionDistance = -1.0f;
@ -269,7 +327,7 @@ void SceneInterface::OnDrag(double deltaTime) {
float dragAbsDistance = abs(glm::distance(glm::vec2(0.0f), directionPlane));
if (dragAbsDistance >= MIN_DRAG_MAGNITUDE) {
glm::vec3 mousePosition = glm::inverse(planeTransform) * glm::vec4(_mousePositionPlane, 0.0f, 1.0f);
glm::vec3 mousePosition = planeTransform * glm::vec4(_mousePositionPlane, 0.0f, 1.0f);
glm::vec3 direction = glm::inverse(planeTransform) * glm::vec4(directionPlane, 0.0f, 0.0f);
@ -279,113 +337,76 @@ void SceneInterface::OnDrag(double deltaTime) {
axisSingle = orthogonalise(axisSingle);
float projection = glm::dot(mousePosition, axisSingle);
int index = floor((projection + 0.5f));
glm::ivec3 axis = orthogonalise(axisSingle);
std::cout << glm::to_string(axisSingle) << std::endl;
std::cout << glm::to_string(direction) << std::endl;
std::cout << glm::to_string(axis) << std::endl;
_cube->UndoTransformTemp();
_cube.TransformTemp(axis, index, glm::rotate(glm::mat4(1.0f), glm::radians(abs(glm::distance(glm::vec2(0.0f), directionPlane))), axisSingle));
float angle = glm::radians(90.0f * ( 1.0f / 3.0f ) * abs(glm::distance(glm::vec2(0.0f), directionPlane)));
_cube->TransformTemp(axis, index, glm::rotate(glm::mat4(1.0f), angle, axisSingle));
_spinIndex = index;
_spinAxis = axis;
_spinDelta = angle;
}
}
const float rotations = 2 * glm::pi<float>();
const float quarterRotation = rotations * 0.25f;
void SceneInterface::OnDragStop() {
// Undo any temporarilies
_cube->UndoTransformTemp();
// Transform Instantly to current angle
_cube->Transform(_spinAxis, _spinIndex, glm::rotate(glm::mat4(1.0f), _spinDelta, glm::vec3(_spinAxis)));
float angleNormalized = std::fmodf(_spinDelta, quarterRotation);
float remainingAngle = 0.5f - glm::abs(angleNormalized - quarterRotation * 0.5f);
float remainingFactor = remainingAngle / quarterRotation;
int rotations = round(_spinDelta / quarterRotation);
// remaining rotation animating
if (_spinDelta > 0.0f && rotations > 0) {
EnqueueAction(new ActionSpinAfterDragging(_cube, _spinAxis, _spinIndex, ( quarterRotation * rotations ) - _spinDelta, rotations, remainingFactor * 1.0f));
}
else {
EnqueueAction(new ActionSpinAfterDragging(_cube, _spinAxis, _spinIndex, -( _spinDelta ), rotations, remainingFactor * 1.0f));
}
}
void SceneInterface::ApplyAction(const Action& action) {
void SceneInterface::ApplyAction(Action* action) {
currentAction = action;
glm::mat3 cubeMat = _cube.Transform() * glm::mat4_cast(_orientation);
glm::mat3 orthogonalized = cubeMat;
for(int column=0;column<3;column++) {
int nearestCardinalisedAxis = 0;
for(int i=0;i<3;i++) {
if (glm::abs(orthogonalized[column][i]) > glm::abs(orthogonalized[column][nearestCardinalisedAxis])) {
nearestCardinalisedAxis = i;
}
}
for(int columnToPlace=0;columnToPlace<3;columnToPlace++) {
for(int i=0;i<3;i++) {
if (columnToPlace == column) {
if (nearestCardinalisedAxis == i) {
orthogonalized[columnToPlace][i] = glm::sign(orthogonalized[columnToPlace][i]);
}
else {
orthogonalized[columnToPlace][i] = 0.0f;
}
}
else {
if (nearestCardinalisedAxis == i) {
orthogonalized[columnToPlace][i] = 0.0f;
}
}
}
}
}
glm::vec3 axis = action.axis;
int direction = axis.x + axis.y + axis.z;
axis = glm::inverse(orthogonalized) * axis;
int index = action.index;
index *= direction;
glm::mat4 rotationMat = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), axis);
for(int i=0;i<3;i++) {
for(int g=0;g<3;g++) {
rotationMat[i][g] = round(rotationMat[i][g]);
}
}
glm::imat3x3 rotation = glm::imat3x3(rotationMat);
_cube.TransformAnimation(axis, index, rotation, action.duration);
action->Invoke();
}
void SceneInterface::Render(float aspectRatio) {
glUseProgram(_shaderProgram);
glBindVertexArray(this->_arrayBufferObject);
if (_camera == nullptr)
return;
glBindBuffer(GL_ARRAY_BUFFER, this->_vertexBufferObject);
DefaultUniform uniform;
uniform.view = _camera->View();
uniform.projection = _camera->Projection();
_view = glm::lookAt(glm::vec3(0.0f, 0.0f, 4.75f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)) * glm::mat4_cast(_orientation);
_perspective = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 100.0f);
for(Entity* entity : _entities) {
uniform.model = entity->LocalToWorld();
auto transformation = _perspective * _view;
entity->Render(uniform);
}
// std::cout << "perspective: " << glm::to_string(glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 100.0f)) << std::endl;
// std::cout << "view : " << glm::to_string(glm::lookAt(glm::vec3(0.0f, 0.0f, -3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f))) << std::endl;
// std::cout << "model : " << glm::to_string(_cube.Transform()) << std::endl;
for(int i=0;i<_cube.ChildPartitionsCount;i++) {
const PartitionedCube* cube = _cube.Children()[i];
const MeshData& meshData = cube->MeshData();
const glm::vec3& position = meshData.data[0].position;
auto localTransform = transformation * cube->Transform();
glUniformMatrix4fv(_transformLocation, 1, GL_FALSE, glm::value_ptr(localTransform));
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData) * meshData.vertexIndex, meshData.data.data(), GL_STATIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, meshData.vertexIndex);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glUseProgram(0);
}
void SceneInterface::ClearResources()
{
glDeleteBuffers(1, &_vertexBufferObject);
glDeleteVertexArrays(1, &_arrayBufferObject);
glDeleteProgram(_shaderProgram);
}

View File

@ -2,69 +2,109 @@
#include <queue>
#include "Debug.h"
#include "Plane.h"
#include "InputSystem.h"
#include "GameInterface.h"
#include "Camera.h"
#include "Shader.h"
#include "Cube.h"
#include <ext/quaternion_float.hpp>
#include <glm/ext/quaternion_float.hpp>
#include <gl/glew.h>
struct Action {
glm::ivec3 axis;
int index;
protected:
Cube* _cube;
public:
double duration;
Action() : axis(glm::ivec3(0)), index(0), duration(0.0f) { }
Action(Cube* cube, double duration) : _cube(cube), duration(duration) { }
virtual void Invoke() = 0;
};
Action(const glm::ivec3& axis, int index, double duration)
: axis(axis), index(index), duration(duration) {
struct ActionSpinDefault : public Action {
glm::ivec3 axis;
int index;
ActionSpinDefault() : Action(nullptr, 0.0f), axis(glm::ivec3(0)), index(0) { }
ActionSpinDefault(Cube* cube, const glm::ivec3& axis, int index, double duration)
: Action(cube, duration), axis(axis), index(index) {
}
void Invoke() override {
_cube->TransformAnimation(axis, index, glm::radians(90.0f), duration);
_cube->TransformData(axis, index, 1);
}
};
struct ActionSpinAfterDragging : public Action {
glm::ivec3 axis;
int index;
float angle;
int turns;
ActionSpinAfterDragging() : Action(nullptr, 0.0f), axis(glm::ivec3(0)), index(0), angle(0.0f), turns(0) { }
ActionSpinAfterDragging(Cube* cube, const glm::ivec3& axis, int index, float angle, int turns, double duration)
: Action(cube, duration), axis(axis), index(index), angle(angle), turns(turns) {
}
void Invoke() override {
_cube->TransformAnimation(axis, index, angle, duration);
_cube->TransformData(axis, index, turns);
}
};
class SceneInterface : public GameInterface
{
private:
Cube _cube;
std::queue<Action> _actions;
Action currentAction;
Cube* _cube;
Camera* _camera;
std::vector<Entity*> _entities;
std::queue<Action*> _actions;
Action* currentAction;
Debug* _debug;
InputSystem _inputSystem;
glm::quat _orientation;
bool _wasMouseDown;
glm::vec2 _initialMouseLocation;
Plane _plane;
glm::vec2 _mousePositionPlane;
glm::mat4 _view;
glm::mat4 _perspective;
GLuint _shaderProgram;
GLuint _transformLocation;
GLuint _arrayBufferObject;
GLuint _vertexBufferObject;
int _spinIndex;
glm::ivec3 _spinAxis;
float _spinDelta;
const float MIN_DRAG_MAGNITUDE = 0.16f;
void ApplyAction(const Action& action);
void ApplyAction(Action* action);
void OnDragStart();
void OnDrag(double deltaTime);
void OnDragStop();
public:
SceneInterface();
~SceneInterface();
void Initialize(GLFWwindow* window) override;
void Update(float deltaTime) override;
void Render(float aspectRatio) override;
void EnqueueAction(const Action& action);
void EnqueueAction(Action* action);
void ClearResources() override;
};

12
RubiksCube/Settings.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
const bool ENABLE_DEBUG = true;
namespace Settings {
const float TURN_ANIMATION_DURATION = 1.25f;
const float MIN_TURN_DISTANCE = 3.0f;
const float MIN_CAMERA_DISTANCE = 4.2f;
const float MAX_CAMERA_DISTANCE = 10.0f;
const float CAMERA_DISTANCE_START = 8.0f;
}

View File

@ -1 +0,0 @@
#include "Shader.h"

View File

@ -1,5 +1,45 @@
#pragma once
class Shader
{
};
#include <GL/glew.h>
#include "ShaderUtil.h"
class Shader {
private:
const char* _vert;
const char* _frag;
GLuint _id;
public:
Shader(const char* vert, const char* frag) : _vert(vert), _frag(frag), _id(0) {
}
~Shader() {
if (_id != 0) {
glDeleteProgram(_id);
}
}
GLuint Reference() const { return _id; }
void Initialize() {
if (_id != 0)
return;
_id = ShaderUtil::CreateShaderProgram(_vert, _frag);
}
void Use() {
Initialize();
glUseProgram(_id);
}
void Disable() {
Initialize();
glUseProgram(0);
}
};

97
RubiksCube/Texture.h Normal file
View File

@ -0,0 +1,97 @@
#pragma once
#include <stb_image.h>
#include <gl/glew.h>
#include <GLFW/glfw3.h>
class Texture {
private:
GLuint _id;
protected:
const char* _texture;
public:
GLuint Reference() const {
return _id;
}
public:
Texture() : _id(0) { }
Texture(const char* file) {
int width, height, len;
stbi_set_flip_vertically_on_load(1);
unsigned char* data = stbi_load(file, &width, &height, &len, STBI_rgb_alpha);
glGenTextures(1, &_id);
glBindTexture(GL_TEXTURE_2D, _id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(data);
}
Texture(const Texture& other) : Texture(other._texture) {
}
Texture& operator=(const Texture& other) {
if (this == &other)
return *this;
Texture copy(other._texture);
this->_id = other._id;
this->_texture = other._texture;
copy._id = 0;
copy._texture = nullptr;
return *this;
}
Texture(Texture&& other) noexcept {
_id = other._id;
_texture = other._texture;
other._id = 0;
other._texture = nullptr;
}
Texture& operator= (Texture&& other) noexcept {
if (this == &other)
return *this;
this->_id = other._id;
this->_texture = other._texture;
other._id = 0;
other._texture = nullptr;
}
~Texture() {
if (_id == 0)
return;
glDeleteTextures(1, &_id);
}
void Use() const {
glBindTexture(GL_TEXTURE_2D, _id);
}
void Disable() const {
glBindTexture(GL_TEXTURE_2D, 0);
}
};

View File

@ -1 +0,0 @@
#pragma once

View File

@ -1,9 +1,45 @@
#version 330
uniform mat4 view;
out vec4 color;
in vec4 vertexColor;
in mat3 TBN;
in vec3 fPos;
in vec2 TCordinate;
uniform sampler2D diffuse;
uniform sampler2D roughness;
uniform sampler2D normal;
const vec3 lightColor = vec3(1.0f, 1.0f, 1.0f);
const vec3 lightDir = vec3(-1.0f, -1.0f, 1.0f);
const float ambient = 0.24f;
const float specularValue = 1.0f;
void main() {
color = vertexColor;
vec4 diffuseBase = texture(diffuse, TCordinate);
vec3 normal = texture(normal, TCordinate).rgb;
normal = normal * 2.0f - 1.0f;
normal = normalize(mat3(view) * TBN * normal);
vec3 lightNormal = normalize(vec3(view * vec4(lightDir, 0.0f)));
float diffValue = max(dot(normal, lightNormal), 0.0f);
float diffuse = diffValue;
vec3 viewDir = normalize(-fPos);
vec3 reflectDir = reflect(-lightNormal, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0f), 16);
float specular = specularValue * spec;
float roughness = texture(roughness, TCordinate).g;
color = vertexColor * diffuseBase * vec4((ambient + diffuse) * lightColor, 1.0f) + vec4(roughness * specular * lightColor, 1.0f);
}

View File

@ -1,13 +1,34 @@
#version 330
uniform mat4 transformation;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
layout (location=0) in vec3 position;
layout (location=1) in vec4 color;
layout (location=1) in vec3 normal;
layout (location=2) in vec2 uv0;
layout (location=3) in vec3 tangent;
layout (location=4) in vec3 bitangent;
layout (location=5) in vec4 color;
out vec4 vertexColor;
out mat3 TBN;
out vec3 fPos;
out vec2 TCordinate;
void main() {
gl_Position = transformation * vec4(position, 1.0f);
gl_Position = projection * view * model * vec4(position, 1.0f);
fPos = vec3(view * model * vec4(position, 1.0f));
vertexColor = color;
vec3 T = normalize(vec3(model * vec4(tangent, 0.0f)));
vec3 B = normalize(vec3(model * vec4(bitangent, 0.0f)));
vec3 N = normalize(vec3(model * vec4(normal, 0.0f)));
TBN = mat3(T, B, N);
TCordinate = uv0;
}

BIN
RubiksCube/diffuse.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
RubiksCube/diffuse_test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

19
RubiksCube/line.frag Normal file
View File

@ -0,0 +1,19 @@
#version 330
const float blend = 1.5f;
in float lineStrength;
in vec4 color;
in float lineWidth;
out vec4 fragColor;
void main(void)
{
vec4 col = color;
float d = length(vec2(lineStrength) - gl_FragCoord.xy);
float w = lineWidth;
fragColor = col;
}

69
RubiksCube/line.vert Normal file
View File

@ -0,0 +1,69 @@
#version 330
uniform vec2 uViewportRes;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 tangent;
layout (location = 2) in vec4 iColor;
layout (location = 3) in float iLineWidth;
out vec4 color;
out float lineWidth;
out float lineStrength;
void main(void) {
int index = gl_VertexID % 6;
float orientation = 1.0f + ( (index % 2) * -2 );
vec4 positionScreen = projection * view * model * vec4(position, 1.0f);
vec4 directionScreen = projection * view * model * vec4(position + tangent, 0.0f);
vec4 normal = positionScreen - directionScreen;
positionScreen.xyz /= positionScreen.w;
positionScreen.xy *= (uViewportRes * 0.5f);
float aspectRatio = projection[1][1] / projection[0][0];
normal.xyz /= normal.w;
positionScreen += vec4(normalize(normal.yx * vec2(-1.0f, 1.0f) * orientation), 0.0f, 0.0f) * 0.5f * iLineWidth;
positionScreen.xy /= (uViewportRes * 0.5f);
positionScreen.xyz *= positionScreen.w;
gl_Position = positionScreen;
lineWidth = iLineWidth;
lineStrength = orientation;
color = iColor;
}
void mainBackup(void)
{
float aspectRatio = 0.0f;
int index = gl_VertexID % 6;
float orientation = 1 + ( (index % 2) * -2 );
vec4 positionCamera = view * model * vec4(position, 1.0f);
float distance = -position.z;
vec4 tv = projection * view * model * vec4(position + tangent, 0.0f);
vec4 v = vec4(normalize(tv.yx) * orientation * vec2(-1.0f, 1.0f), 0.0f, 0.0f) * distance;
vec4 direction = positionCamera - tv;
direction.xy = direction.yx * vec2(-1.0f, 1.0f) * orientation;
gl_Position = (projection * positionCamera) + vec4(direction.xy, 0.0f, 0.0f);
lineWidth = iLineWidth;
lineStrength = orientation;
color = vec4(iColor.xyz, 1.0f);
}

BIN
RubiksCube/normal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
RubiksCube/roughness.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

39
readme.txt Normal file
View File

@ -0,0 +1,39 @@
Rubiks Cube Projekt
Steuerung:
Linke Maustaste Halten und Ziehen Cube angeklickte Scheibe drehen
Rechte Maustaste Halten und Ziehen Kamera drehen
Scrollrad Zoom
Shift + Numpad 1, 2, 3 ( Numlock ausschalten! ) Cube Horizontal nach unten
Shift + Numpad 7, 8, 9 ( Numlock ausschalten! ) Cube Horizontal nach oben
Numpad 1, 4, 7 Cube vertikal links drehen
Numpad 9, 6, 3 Cube vertikal rechts drehen
Space Ansicht ( Drehung ) zurücksetzen
Kurze Übersicht der Welt:
Die Anwendung wird gestartet, mit der Kamera von vorne auf den Cube gerichtet.
Der Cube bleibt im World-Space ohne Veränderungen.
Die Kamera dreht sich um den Cube herum.
Die Lichtquelle leuchtet von unten links und von vorne.
Features:
- Logische Repräsentation
- Tastatursteuerung
- + Animations
- Kamerasteuerung
- Maussteuerung Kamerarelativ
- + Animations
Rendering:
- Directional Lighting
- Blinn-Shading
- Diffuse Texturierung
- Normal Map mit Textur als Normal
- Specular Map