Initial Commit

This commit is contained in:
Fred 2025-01-09 01:57:18 +01:00
commit 85583a8880
38 changed files with 2166 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
ExternalResources

39
Notes.md Normal file
View File

@ -0,0 +1,39 @@
# Projekt
### Rubics Cube mit diversen Anforderungen
Wichtigkeit der einzelnen vorgegebenen Anforderungen:
- 4.0 Logische Repräsentation, Rendering, simple Steuerung
- -1 Animation
- -1.3 Maussteuerung Steuerung vorne nach Konzept wie in Vorlesung
- -0.3 Maussteuerung für Kamera
- -0.3 Sound
- -0.3 bis -0.7 Aufwendige Graphik-Programmierung
( Vorlesung 1 _ 8:00 )
Ordner Struktur:
- ExternalResources
- glm
- glfw
- stb
- glew
- RubiksCube
Console
Additional Include Directories
$(SolutionDir)/../ExternalResources/glew/include
$(SolutionDir)/../ExternalResources/glfw/include
$(SolutionDir)/../ExternalResources/glm/glm
$(SolutionDir)/../ExternalResources/stb
Additional Library Directories
$(SolutionDir)/../ExternalResources/glew/lib/Release/x64
$(SolutionDir)/../ExternalResources/glfw/lib-vc2017 # Fragen welche Version
Additional Dependencies
opengl32.lib
glfw3.lib
glew32s.lib

433
RubiksCube/.gitignore vendored Normal file
View File

@ -0,0 +1,433 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
# but not Directory.Build.rsp, as it configures directory-level build defaults
!Directory.Build.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml

8
RubiksCube/.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

8
RubiksCube/.idea/RubiksCube.iml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
RubiksCube/.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/RubiksCube.iml" filepath="$PROJECT_DIR$/.idea/RubiksCube.iml" />
</modules>
</component>
</project>

6
RubiksCube/.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

1
RubiksCube/Color.cpp Normal file
View File

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

33
RubiksCube/Color.h Normal file
View File

@ -0,0 +1,33 @@
#pragma once
#include <stdint.h>
struct Color {
private:
public:
float r, g, b, a;
constexpr Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) {
}
static constexpr Color FromRGBA8(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
return Color((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f);
}
Color() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {
}
static constexpr Color AQUA() { return Color(0.0f, 0.0f, 0.0f, 1.0f); }
static constexpr Color RED() { return Color(1.0f, 0.0f, 0.0f, 1.0f); }
static constexpr Color GREEN() { return Color(0.0f, 1.0f, 0.0f, 1.0f); }
static constexpr Color BLUE() { return Color(0.0f, 0.0f, 1.0f, 1.0f); }
static constexpr Color BLACK() { return Color(0.0f, 0.0f, 0.0f, 1.0f); }
static constexpr Color WHITE() { return Color(1.0f, 1.0f, 1.0f, 1.0f); }
static constexpr Color MAGENTA() { return Color(1.0f, 0.0f, 1.0f, 1.0f); }
static constexpr Color YELLOW() { return Color(1.0f, 1.0f, 0.0f, 1.0f); }
static constexpr Color ORANGE() { return FromRGBA8(255, 165, 0, 255); }
static constexpr Color TRANSPARENT() { return Color(0.0f, 0.0f, 0.0f, 0.0f); }
};

142
RubiksCube/Cube.cpp Normal file
View File

@ -0,0 +1,142 @@
#include "Cube.h"
Cube::Cube()
{
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++) {
Side side = Side::Forward;
Color sideColors[6];
if (x == -1) {
sideColors[Side::Left] = SideColor[Side::Left];
}
if (x == 1) {
sideColors[Side::Right] = SideColor[Side::Right];
}
if (y == -1) {
sideColors[Side::Bottom] = SideColor[Side::Bottom];
}
if (y == 1) {
sideColors[Side::Top] = SideColor[Side::Top];
}
if (z == -1) {
sideColors[Side::Back] = SideColor[Side::Back];
}
if (z == 1) {
sideColors[Side::Forward] = SideColor[Side::Forward];
}
PartitionedCube* cubeAtIndex = new PartitionedCube(glm::vec3(x, y, z), sideColors);
this->_children[x + 1][y + 1][z + 1] = cubeAtIndex;
}
}
}
}
Cube::~Cube() {
for(int x=0;x<3;x++) {
for(int y=0;y<3;y++) {
for(int z=0;z<3;z++) {
delete _children[x][y][z];
}
}
}
}
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,
glm::ivec3(axis[1], axis[2], axis[0]),
glm::ivec3(axis[2], axis[0], axis[1])
};
for(int x = -1;x<=1;x++) {
for(int y = -1;y<=1;y++) {
glm::ivec3 position = axis * index + orientationBuffer[1] * x + orientationBuffer[2] * y;
result.push_back(position);
}
}
}
void Cube::_TransformData(const glm::ivec3& axis, int index, const glm::mat3& transform) {
PartitionedCube* previousCubeList[3][3][3];
memcpy(previousCubeList, this->_children, sizeof(this->_children));
std::vector<glm::ivec3> result;
_FindAxisChildren(axis, index, result);
for(auto& position : result) {
glm::ivec3 newPosition = transform * position;
position += glm::ivec3(1);
newPosition += glm::ivec3(1);
_children[newPosition.x][newPosition.y][newPosition.z] = previousCubeList[position.x][position.y][position.z];
}
}
void Cube::Transform(const glm::ivec3& axis, int index, const glm::mat3& transform) {
_TransformData(axis, index, transform);
std::vector<glm::ivec3> result;
_FindAxisChildren(transform * axis, index, result);
for(auto& position : result) {
PartitionedCube* cube = _children[position.x + 1][position.y + 1][position.z + 1];
cube->Transform(glm::mat4(transform));
}
}
void Cube::TransformTemp(const glm::ivec3& axis, int index, const glm::mat3& transform) {
std::vector<glm::ivec3> 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));
}
}
void Cube::TransformAnimation(const glm::ivec3& axis, int index, const glm::mat3& transform, float duration) {
_TransformData(axis, index, transform);
std::vector<glm::ivec3> result;
_FindAxisChildren(transform * axis, index, result);
for(auto& position : result) {
PartitionedCube* cube = _children[position.x + 1][position.y + 1][position.z + 1];
cube->TransformAnimation(glm::mat4(transform), duration);
}
}

43
RubiksCube/Cube.h Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#include <glm.hpp>
#include "PartitionedCube.h"
// Colors according to https://ruwix.com/the-rubiks-cube/japanese-western-color-schemes/
class Cube
{
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);
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 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);
static constexpr Color SideColor[6] = {
Color::ORANGE(),
Color::RED(),
Color::YELLOW(),
Color::WHITE(),
Color::GREEN(),
Color::BLUE()
};
};

View File

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

View File

@ -0,0 +1,18 @@
#pragma once
struct GLFWwindow;
class GameInterface
{
private:
public:
virtual void Initialize() { };
virtual void Initialize(GLFWwindow* window) { Initialize(); };
virtual void Update(float deltaTime) { };
virtual void Render(float aspectRatio) { };
virtual void ClearResources() { };
};

View File

@ -0,0 +1,70 @@
#include "InputSystem.h"
#include <GLFW/glfw3.h>
#include <iostream>
#include <glm.hpp>
#include <ext.hpp>
void InputSystem::ObserveKey(int key) {
_keyCodeDictionaryObserver.emplace(key, KeyObserver(_window, key));
}
void InputSystem::Update() {
for(auto& observer : _keyCodeDictionaryObserver) {
observer.second.Update();
}
}
void InputSystem::SetWindow(GLFWwindow* window) {
_window = window;
}
bool InputSystem::IsLeftMouseDown() const
{
return glfwGetMouseButton(_window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;
}
bool InputSystem::IsRightMouseDown() const
{
return glfwGetMouseButton(_window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS;
}
void InputSystem::GetMousePos(glm::vec2& position) const
{
double x, y;
glfwGetCursorPos(_window, &x, &y);
position.x = x;
position.y = y;
}
void InputSystem::GetPickingRay(const glm::mat4& transform, glm::vec3& startingPoint, glm::vec3& direction) const {
glm::vec2 screenSpacePosition;
GetMousePos(screenSpacePosition);
int screenWidth, screenHeight;
glfwGetFramebufferSize(_window, &screenWidth, &screenHeight);
glm::vec2 clipSpacePosition = glm::vec2(
( screenSpacePosition.x / screenWidth ) * 2.0 - 1.0,
1.0 - ( screenSpacePosition.y / screenHeight ) * 2.0
);
glm::vec4 nearPoint = glm::vec4(clipSpacePosition.x, clipSpacePosition.y, 0.01f, 1.0f);
glm::vec4 farPoint = nearPoint;
farPoint.z = 0.99f;
glm::mat4 inverse = glm::inverse(transform);
nearPoint = inverse * nearPoint;
farPoint = inverse * farPoint;
nearPoint /= nearPoint.w;
farPoint /= farPoint.w;
startingPoint = nearPoint;
direction = farPoint - nearPoint;
}

39
RubiksCube/InputSystem.h Normal file
View File

@ -0,0 +1,39 @@
#pragma once
#include <map>
#include <glm.hpp>
#include "KeyObserver.h"
struct KeyState {
bool IsPressed;
bool WasPressed;
bool WasReleased;
};
class InputSystem
{
private:
GLFWwindow* _window;
std::map<int, KeyObserver> _keyCodeDictionaryObserver;
public:
InputSystem() { _window = nullptr; }
void ObserveKey(int key);
void Update();
void SetWindow(GLFWwindow* window);
bool IsLeftMouseDown() const;
bool IsRightMouseDown() const;
void GetMousePos(glm::vec2& position) const;
void GetPickingRay(const glm::mat4& tansform, glm::vec3& startingPoint, glm::vec3& direction) const;
bool IsKeyPressed(int key) { return _keyCodeDictionaryObserver[key].IsPressed; }
bool WasKeyPressed(int key) { return _keyCodeDictionaryObserver[key].WasPressed; }
bool WasKeyReleased(int key) { return _keyCodeDictionaryObserver[key].WasReleased; }
};

View File

@ -0,0 +1,23 @@
#include "KeyObserver.h"
#include <iostream>
#include <GLFW/glfw3.h>
KeyObserver::KeyObserver(GLFWwindow* window, int keyCode)
{
_window = window;
_key = keyCode;
IsPressed = false;
WasPressed = false;
WasReleased = false;
}
void KeyObserver::Update() {
bool isPressed = glfwGetKey(_window, _key) == GLFW_PRESS;
WasPressed = isPressed && !IsPressed;
WasReleased = !isPressed && IsPressed;
IsPressed = isPressed;
}

20
RubiksCube/KeyObserver.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
struct GLFWwindow;
class KeyObserver
{
private:
GLFWwindow* _window;
int _key;
public:
bool IsPressed;
bool WasPressed;
bool WasReleased;
KeyObserver() : _window(nullptr), _key(-1) { }
KeyObserver(GLFWwindow* window, int keyCode);
void Update();
};

1
RubiksCube/MeshData.h Normal file
View File

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

View File

0
RubiksCube/PartialCube.h Normal file
View File

View File

@ -0,0 +1,78 @@
#include "PartitionedCube.h"
#include "Cube.h"
#include <glm.hpp>
#include <ext.hpp>
PartitionedCube::PartitionedCube(const glm::vec3& position, Color* sideColors) : _faces {
sideColors[0],
sideColors[1],
sideColors[2],
sideColors[3],
sideColors[4],
sideColors[5],
}
{
this->_transform = glm::translate(glm::mat4(1.0f), position);
_animationTime = 0.0f;
_animationTimeExtend = 0.0f;
_animationTransformInvoke = _transform;
_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[(axis+2)%3] = 1.0f;
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)
_meshData.addFace(v0, v1, v2, v3, sideColors[s]);
factor = -factor;
}
}
}
void PartitionedCube::Update(double deltaTime) {
this->_animationTime -= deltaTime;
if (!_animationFinished && _animationTime <= 0.0f) {
_animationFinished = true;
_transform = glm::mat4_cast(_animationTransform) * _animationTransformInvoke;
}
}
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::TransformAnimation(const glm::mat4& transform, float duration) {
if (!_animationFinished)
_transform = glm::mat4_cast(_animationTransform) * _animationTransformInvoke;
this->_animationTransformInvoke = this->_transform;
this->_animationTransform = glm::quat_cast(transform);
this->_animationTime = duration;
this->_animationTimeExtend = duration;
_animationFinished = false;
}

View File

@ -0,0 +1,100 @@
#pragma once
#include "Color.h"
#include <stdint.h>
#include <glm.hpp>
#include <ext.hpp>
#include <ext/quaternion_float.hpp>
#include <math.h>
#include <vector>
struct VertexData {
glm::vec3 position;
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) {
}
};
struct MeshData {
int vertexIndex;
std::vector<VertexData> data;
int triangleIndex;
MeshData() {
vertexIndex = 0;
triangleIndex = 0;
}
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;
triangleIndex ++;
}
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);
}
};
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 PartitionedCube
{
private:
glm::mat4 _transform;
glm::mat4 _animationTransformInvoke;
glm::quat _animationTransform;
float _animationTime;
float _animationTimeExtend;
bool _animationFinished;
Color _faces[6];
MeshData _meshData;
public:
PartitionedCube(const glm::vec3& position, Color sideColors[6]);
void Update(double deltaTime);
const glm::mat4 Transform() const {
// Need to use slerp since rotations are non-linear and would not interpolate this way
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));
return animationView * _animationTransformInvoke;
}
return _transform;
}
const MeshData& MeshData() const { return _meshData; };
void Transform(glm::mat4 transformation);
void TransformAnimation(const glm::mat4& transform, float duration);
};

21
RubiksCube/Plane.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "Plane.h"
Plane::Plane(const glm::mat4& transform, int axis, int direction) {
// -x, +x, -y, +y, -z, +z
glm::vec3 worldNormal = glm::vec3(0.0f);
worldNormal[axis] = 1.0f;
worldNormal *= direction;
glm::vec4 origin = transform * glm::vec4(( worldNormal * 1.5f ), 1.0f);
glm::vec3 worldU = glm::vec3(worldNormal[1], worldNormal[2], worldNormal[0]);
glm::vec3 worldV = glm::vec3(worldNormal[2], worldNormal[0], worldNormal[1]);
glm::vec3 planeNormal = transform * glm::vec4(worldNormal, 0.0f);
glm::vec3 planeU = transform * glm::vec4(worldU, 0.0f);
glm::vec3 planeV = transform * glm::vec4(worldV, 0.0f);
_transform = glm::mat4(glm::vec4(planeU, 0.0f), glm::vec4(planeV, 0.0f), glm::vec4(planeNormal, 0.0f), origin);
}

21
RubiksCube/Plane.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <glm.hpp>
class Plane
{
private:
glm::mat4 _transform;
public:
Plane() : _transform(1.0f) { }
Plane(const glm::mat4& transform, int axis, int direction);
const glm::mat4& Transform() { return _transform; }
glm::vec4 Origin() { return _transform * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); }
glm::vec3 Normal() { return _transform * glm::vec4(0.0f, 0.0f, 1.0f, 0.0f); }
glm::vec3 U() { return _transform * glm::vec4(1.0f, 0.0f, 0.0f, 0.0f); }
glm::vec3 V() { return _transform * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f); }
};

114
RubiksCube/RubiksCube.cpp Normal file
View File

@ -0,0 +1,114 @@
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "GameInterface.h"
#include "SceneInterface.h"
SceneInterface sceneInterface;
GameInterface* gUsedInterface;
GLFWwindow* InitializeSystem() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(1024, 768, "Rubiks Cube", nullptr, nullptr);
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
glewInit();
gUsedInterface->Initialize(window);
return window;
}
void RunCoreLoop(GLFWwindow* window) {
double lastTime = glfwGetTime();
double deltaTime = 0.0;
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
gUsedInterface->Update(deltaTime);
int screenWidth;
int screenHeight;
glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
float aspectRatio = (float)screenWidth / (float)screenHeight;
glViewport(0, 0, screenWidth, screenHeight);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gUsedInterface->Render(aspectRatio);
glfwSwapBuffers(window);
double currentTime = glfwGetTime();
deltaTime = currentTime - lastTime;
lastTime = currentTime;
}
}
void ShutdownSystem() {
gUsedInterface->ClearResources();
glfwTerminate();
}
int main() {
gUsedInterface = &sceneInterface;
GLFWwindow* window = InitializeSystem();
RunCoreLoop(window);
ShutdownSystem();
}
/*
int main() {
std::cout << "Wonderfulnesolino!\n";
gUsedInterface = &sceneInterface;
GLFWwindow* window = InitializeSystem();
RunCoreLoop(window);
ShutdownSystem();
}
*/

31
RubiksCube/RubiksCube.sln Normal file
View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34616.47
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RubiksCube", "RubiksCube.vcxproj", "{87EDB22B-5B80-4231-8B84-DF8AB061CCF0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{87EDB22B-5B80-4231-8B84-DF8AB061CCF0}.Debug|x64.ActiveCfg = Debug|x64
{87EDB22B-5B80-4231-8B84-DF8AB061CCF0}.Debug|x64.Build.0 = Debug|x64
{87EDB22B-5B80-4231-8B84-DF8AB061CCF0}.Debug|x86.ActiveCfg = Debug|Win32
{87EDB22B-5B80-4231-8B84-DF8AB061CCF0}.Debug|x86.Build.0 = Debug|Win32
{87EDB22B-5B80-4231-8B84-DF8AB061CCF0}.Release|x64.ActiveCfg = Release|x64
{87EDB22B-5B80-4231-8B84-DF8AB061CCF0}.Release|x64.Build.0 = Release|x64
{87EDB22B-5B80-4231-8B84-DF8AB061CCF0}.Release|x86.ActiveCfg = Release|Win32
{87EDB22B-5B80-4231-8B84-DF8AB061CCF0}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {ABE3B0EF-7548-4BB8-B17A-2B583693FE75}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,182 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{87edb22b-5b80-4231-8b84-df8ab061ccf0}</ProjectGuid>
<RootNamespace>RubiksCube</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</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>
</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>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)/../ExternalResources/glew/lib/Release/x64;$(SolutionDir)/../ExternalResources/glfw/lib-vc2019;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;glfw3.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(SolutionDir)/../ExternalResources/glew/lib/Release/x64;$(SolutionDir)/../ExternalResources/glfw/lib-vc2019;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;glfw3.lib;glew32s.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Color.cpp" />
<ClCompile Include="Cube.cpp" />
<ClCompile Include="GameInterface.cpp" />
<ClCompile Include="InputSystem.cpp" />
<ClCompile Include="KeyObserver.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="Color.h" />
<ClInclude Include="Cube.h" />
<ClInclude Include="GameInterface.h" />
<ClInclude Include="InputSystem.h" />
<ClInclude Include="KeyObserver.h" />
<ClInclude Include="MeshData.h" />
<ClInclude Include="PartitionedCube.h" />
<ClInclude Include="Plane.h" />
<ClInclude Include="SceneInterface.h" />
<ClInclude Include="Shader.h" />
<ClInclude Include="ShaderUtil.h" />
<ClInclude Include="Side.h" />
<ClInclude Include="VertexData.h" />
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="cube.frag">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</CopyFileToFolders>
<CopyFileToFolders Include="cube.vert">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</CopyFileToFolders>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Quelldateien">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headerdateien">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Ressourcendateien">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{e0ac6084-492f-4bb0-889c-7fc5792b3c94}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="RubiksCube.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="GameInterface.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="Cube.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="PartitionedCube.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="SceneInterface.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="Color.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="Shader.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="ShaderUtil.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="KeyObserver.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="InputSystem.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
<ClCompile Include="Plane.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GameInterface.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Cube.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="PartitionedCube.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="SceneInterface.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<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>
<ClInclude Include="ShaderUtil.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="KeyObserver.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="InputSystem.h">
<Filter>Headerdateien</Filter>
</ClInclude>
<ClInclude Include="Plane.h">
<Filter>Headerdateien</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="cube.frag">
<Filter>Shaders</Filter>
</CopyFileToFolders>
<CopyFileToFolders Include="cube.vert">
<Filter>Shaders</Filter>
</CopyFileToFolders>
</ItemGroup>
</Project>

View File

@ -0,0 +1,391 @@
#include "SceneInterface.h"
#include "ShaderUtil.h"
#include "PartitionedCube.h"
#include "Plane.h"
#include <glm.hpp>
#include <ext.hpp>
#include <gtx/string_cast.hpp>
#include <GLFW/glfw3.h>
#include <iostream>
void SceneInterface::Initialize(GLFWwindow* window)
{
_inputSystem.SetWindow(window);
_inputSystem.ObserveKey(GLFW_KEY_SPACE);
_inputSystem.ObserveKey(GLFW_KEY_UP);
_inputSystem.ObserveKey(GLFW_KEY_DOWN);
_inputSystem.ObserveKey(GLFW_KEY_LEFT);
_inputSystem.ObserveKey(GLFW_KEY_RIGHT);
_inputSystem.ObserveKey(GLFW_KEY_LEFT_SHIFT);
_inputSystem.ObserveKey(GLFW_KEY_KP_1);
_inputSystem.ObserveKey(GLFW_KEY_KP_2);
_inputSystem.ObserveKey(GLFW_KEY_KP_3);
_inputSystem.ObserveKey(GLFW_KEY_KP_4);
_inputSystem.ObserveKey(GLFW_KEY_KP_5);
_inputSystem.ObserveKey(GLFW_KEY_KP_6);
_inputSystem.ObserveKey(GLFW_KEY_KP_7);
_inputSystem.ObserveKey(GLFW_KEY_KP_8);
_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);
}
glm::vec3 basisCoordinateVectors[] = {
glm::vec3(1.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f),
glm::vec3(0.0f, 0.0f, 1.0f)
};
glm::ivec3 orthogonalise(const glm::vec3& value) {
int minimum = 0;
for(int i=0;i<3;i++) {
if (abs(value[i])>abs(value[minimum]))
minimum = i;
}
glm::ivec3 orthogon = glm::vec3(0.0f);
orthogon[minimum] = glm::sign(value[minimum]);
return orthogon;
}
void roundAllScalars(glm::mat3& transforms) {
for(int x=0;x<3;x++) {
for(int y=0;y<3;y++) {
transforms[x][y] = round(transforms[x][y]);
}
}
}
glm::imat3x3 orthogonaliseMatrix(const glm::mat3& value) {
glm::mat3 temp = value;
roundAllScalars(temp);
glm::imat3x3 result;
for(int i=0;i<3;i++) {
result[i] = orthogonalise(value[i]);
for(int adjacent=i+1;adjacent<3;adjacent++) {
result[adjacent] = result[adjacent] * ( glm::abs(result[i]) * - 1 ) + 2;
}
}
return result;
}
void IntersectLinePlane(const glm::vec3& lineStart, const glm::vec3& lineDirection, const glm::vec3& planeOrigin, const glm::vec3& planeNormal, float& distance) {
glm::vec3 w = lineStart - planeOrigin;
float intersectionDistance = glm::dot(planeOrigin - lineStart, planeNormal) / glm::dot(lineDirection, planeNormal);
if (intersectionDistance > 0) {
distance = intersectionDistance;
}
}
void SceneInterface::EnqueueAction(const 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));
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;
// Gather Axis (+x, +y)
glm::ivec3 spinAxis;
if (_inputSystem.IsKeyPressed(GLFW_KEY_LEFT_SHIFT))
spinAxis = glm::ivec3(1, 0, 0);
else
spinAxis = glm::ivec3(0, 1, 0);
// Numpad
int rotationKey = -1;
for(int i=1;i<10;i++) {
if (_inputSystem.WasKeyPressed(GLFW_KEY_KP_0 + i)) {
rotationKey = i;
}
}
if (rotationKey != -1) {
bool reverseVertical = spinAxis.x == 1 && (rotationKey == 7 || rotationKey == 8 || rotationKey == 9);
bool reverseHorizontal = spinAxis.y == 1 && (rotationKey == 1 || rotationKey == 4 || rotationKey == 7);
static const int keyToIndex[2][9] = { { -1, 0, 1, 0, 0, 0, -1, 0, 1 }, { -1, 0, -1, 0, 0, 0, 1, 0, 1 } };
bool reverse = reverseVertical || reverseHorizontal;
// spin which lookup
int axisIndex = spinAxis.x == 0; // x => 0, y => 1
int spinIndex = keyToIndex[axisIndex][rotationKey - 1];
if (reverse)
spinAxis *= -1;
// _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();
}
else if (_wasMouseDown && !_inputSystem.IsLeftMouseDown()) {
OnDragStop();
}
else if (_wasMouseDown && _inputSystem.IsLeftMouseDown()) {
OnDrag(deltaTime);
}
_wasMouseDown = _inputSystem.IsLeftMouseDown();
currentAction.duration -= deltaTime;
if (currentAction.duration <= 0.0f && _actions.size() > 0) {
Action& action = _actions.front();
_actions.pop();
ApplyAction(action);
}
}
void SceneInterface::OnDragStart() {
_inputSystem.GetMousePos(_initialMouseLocation);
Plane planes[6];
glm::vec3 lineStart;
glm::vec3 lineDirection;
glm::mat4 viewPerspective = _perspective * _view;
_inputSystem.GetPickingRay(viewPerspective, lineStart, lineDirection);
glm::mat4 transform = glm::mat4(1.0f);
for(int axis=0;axis<3;axis++) {
for(int direction=-1;direction<=1;direction+=2) {
Plane plane(transform, axis, direction);
if (glm::dot(plane.Normal(), lineDirection) > 0)
continue;
float intersectionDistance = -1.0f;
IntersectLinePlane(lineStart, lineDirection, plane.Origin(), plane.Normal(), intersectionDistance);
if (intersectionDistance == -1.0f) {
continue;
}
const glm::mat4& planeTransform = plane.Transform();
glm::vec4 intersectionPoint = glm::vec4(lineStart + lineDirection * intersectionDistance, 1.0f);
glm::vec4 intersectionPlane = glm::inverse(planeTransform) * intersectionPoint;
bool onPlane = abs(intersectionPlane.x) < 1.501f && abs(intersectionPlane.y) < 1.501f;
if (!onPlane) {
continue;
}
_plane = plane;
_mousePositionPlane = intersectionPlane;
}
}
}
void SceneInterface::OnDrag(double deltaTime) {
glm::vec2 currentMousePosition;
_inputSystem.GetMousePos(currentMousePosition);
glm::vec3 lineStart;
glm::vec3 lineDirection;
glm::mat4 transform = _perspective * _view;
_inputSystem.GetPickingRay(transform, lineStart, lineDirection);
float intersectionDistance = -1.0f;
IntersectLinePlane(lineStart, lineDirection, _plane.Origin(), _plane.Normal(), intersectionDistance);
if (intersectionDistance == -1.0f) {
return;
}
const glm::mat4& planeTransform = _plane.Transform();
glm::vec2 intersectionPlane = glm::inverse(planeTransform) * (glm::vec4(lineStart + lineDirection * intersectionDistance, 1.0f));
glm::vec2 directionPlane = intersectionPlane - _mousePositionPlane;
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 direction = glm::inverse(planeTransform) * glm::vec4(directionPlane, 0.0f, 0.0f);
direction = glm::normalize(direction);
glm::vec3 axisSingle = glm::cross(_plane.Normal(), direction);
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.TransformTemp(axis, index, glm::rotate(glm::mat4(1.0f), glm::radians(abs(glm::distance(glm::vec2(0.0f), directionPlane))), axisSingle));
}
}
void SceneInterface::OnDragStop() {
}
void SceneInterface::ApplyAction(const 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);
}
void SceneInterface::Render(float aspectRatio) {
glUseProgram(_shaderProgram);
glBindVertexArray(this->_arrayBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, this->_vertexBufferObject);
_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);
auto transformation = _perspective * _view;
// 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

@ -0,0 +1,70 @@
#pragma once
#include <queue>
#include "Plane.h"
#include "InputSystem.h"
#include "GameInterface.h"
#include "Shader.h"
#include "Cube.h"
#include <ext/quaternion_float.hpp>
#include <gl/glew.h>
struct Action {
glm::ivec3 axis;
int index;
double duration;
Action() : axis(glm::ivec3(0)), index(0), duration(0.0f) { }
Action(const glm::ivec3& axis, int index, double duration)
: axis(axis), index(index), duration(duration) {
}
};
class SceneInterface : public GameInterface
{
private:
Cube _cube;
std::queue<Action> _actions;
Action currentAction;
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;
const float MIN_DRAG_MAGNITUDE = 0.16f;
void ApplyAction(const Action& action);
void OnDragStart();
void OnDrag(double deltaTime);
void OnDragStop();
public:
void Initialize(GLFWwindow* window) override;
void Update(float deltaTime) override;
void Render(float aspectRatio) override;
void EnqueueAction(const Action& action);
void ClearResources() override;
};

1
RubiksCube/Shader.cpp Normal file
View File

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

5
RubiksCube/Shader.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
class Shader
{
};

113
RubiksCube/ShaderUtil.cpp Normal file
View File

@ -0,0 +1,113 @@
#include "ShaderUtil.h"
#include <iostream>
#include <fstream>
GLuint ShaderUtil::CreateShaderProgram(const char* vertexFilename, const char* fragmentFilename)
{
std::string vertexProgram = LoadFile(vertexFilename);
const char* vertexString = vertexProgram.c_str();
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexString, NULL);
PrintOGlErrors();
glCompileShader(vertexShader);
PrintOGlErrors();
int vertCompiled;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vertCompiled);
if (vertCompiled != 1)
{
std::cout << "Vertex shader error " << std::endl;
PrintShaderLog(vertexShader);
}
std::string fragmentProgram = LoadFile(fragmentFilename);
const char* fragmentString = fragmentProgram.c_str();
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentString, NULL);
PrintOGlErrors();
glCompileShader(fragmentShader);
PrintOGlErrors();
int fragCompiled;
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragCompiled);
if (fragCompiled != 1)
{
std::cout << "Fragment shader error " << std::endl;
PrintShaderLog(fragmentShader);
}
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
PrintOGlErrors();
int linked;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linked);
if (linked != 1)
{
std::cout << "Linking failed:" << std::endl;
PrintProgramLog(shaderProgram);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return shaderProgram;
}
std::string ShaderUtil::LoadFile(const char* fileName)
{
std::string result;
std::ifstream fileStream(fileName, std::ios::in);
while (!fileStream.eof())
{
std::string line;
std::getline(fileStream, line);
result.append(line + "\n");
}
fileStream.close();
return result;
}
void ShaderUtil::PrintShaderLog(GLuint shader)
{
int memLength;
int messageLength;
char* log;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &memLength);
if (memLength == 0)
return;
log = (char*)malloc(memLength);
glGetShaderInfoLog(shader, memLength, &messageLength, log);
std::cout << "Shader Info Log: " << log << std::endl;
free(log);
}
void ShaderUtil::PrintProgramLog(GLuint program)
{
int memLength;
int messageLength;
char* log;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &memLength);
if (memLength == 0)
return;
log = (char*)malloc(memLength);
glGetProgramInfoLog(program, memLength, &messageLength, log);
std::cout << "Program Info Log: " << log << std::endl;
free(log);
}
void ShaderUtil::PrintOGlErrors()
{
int error = glGetError();
while (error != GL_NO_ERROR)
{
std::cout << "OpenGL error: " << error << std::endl;
error = glGetError();
}
}

16
RubiksCube/ShaderUtil.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <GL/glew.h>
#include <string>
class ShaderUtil
{
public:
static GLuint CreateShaderProgram(const char* vertexFilename, const char* fragmentFilename);
private:
static std::string LoadFile(const char* fileName);
static void PrintShaderLog(GLuint shader);
static void PrintProgramLog(GLuint program);
static void PrintOGlErrors();
};

2
RubiksCube/Side.h Normal file
View File

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

1
RubiksCube/VertexData.h Normal file
View File

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

9
RubiksCube/cube.frag Normal file
View File

@ -0,0 +1,9 @@
#version 330
out vec4 color;
in vec4 vertexColor;
void main() {
color = vertexColor;
}

13
RubiksCube/cube.vert Normal file
View File

@ -0,0 +1,13 @@
#version 330
uniform mat4 transformation;
layout (location=0) in vec3 position;
layout (location=1) in vec4 color;
out vec4 vertexColor;
void main() {
gl_Position = transformation * vec4(position, 1.0f);
vertexColor = color;
}