406 lines
12 KiB
C++
406 lines
12 KiB
C++
// This only works with opengl!!!!
|
|
|
|
|
|
#include "Rubiks.h"
|
|
|
|
#define STB_TRUETYPE_IMPLEMENTATION
|
|
#include <stb/stb_truetype.h>
|
|
|
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
#include <stb/stb_image_write.h>
|
|
|
|
#include <cstdlib>
|
|
#include <ctime>
|
|
|
|
#include <opencv2/core.hpp>
|
|
#include <opencv2/opencv.hpp>
|
|
|
|
Rubiks::Rubiks(Archimedes::App* a, void* h) : Archimedes::Module(a, h) {
|
|
|
|
name = "Rubiks";
|
|
|
|
WindowModule* wm = new WindowModule(a, h);
|
|
deps[*wm] = wm;
|
|
|
|
ImguiModule* im = new ImguiModule(a, h);
|
|
deps[*im] = im;
|
|
}
|
|
|
|
Rubiks::~Rubiks() {
|
|
|
|
if(app) {
|
|
WindowModule* wm; { wm = (WindowModule*) moduleInstances[WindowModule()]; }
|
|
|
|
ImguiModule* im; { im = (ImguiModule*) moduleInstances[ImguiModule()]; }
|
|
|
|
im->releaseContext(ImGui::GetCurrentContext());
|
|
|
|
wm->releaseWindow(window);
|
|
|
|
}
|
|
}
|
|
|
|
void Rubiks::onLoad() {
|
|
// get window
|
|
WindowModule* wm; { wm = (WindowModule*) moduleInstances[WindowModule()]; }
|
|
ImguiModule* im; { im = (ImguiModule*) moduleInstances[ImguiModule()]; }
|
|
|
|
if(!wm) {
|
|
std::cout << "No WindowModule for Rubiks!\n";
|
|
std::abort();
|
|
}
|
|
|
|
if(!im) {
|
|
std::cout << "No ImguiModule for Rubiks!\n";
|
|
std::abort();
|
|
}
|
|
|
|
window = wm->aquireWindow();
|
|
|
|
ImGui::SetCurrentContext(im->aquireContext());
|
|
|
|
window->getRenderer()->clearColor = { 0.2f, 0.2f, 0.2f, 1.0f };
|
|
|
|
int w, h;
|
|
window->getSize(w, h);
|
|
app->emitEvent(new Archimedes::ResizeWindowEvent(w, h));
|
|
|
|
camera.setTransform(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)
|
|
));
|
|
|
|
camera.setPerspective(glm::perspective(glm::radians(45.0f), (float)w/(float)h, 0.1f, 100.0f));
|
|
//camera.setPerspective(glm::ortho(-(float)w / 2.0f, (float)w / 2.0f, -(float)h / 2.0f, (float)h / 2.0f, 0.1f, 100.0f));
|
|
|
|
rubiksCube.init(window->getRenderer());
|
|
|
|
srand(time(0));
|
|
|
|
}
|
|
|
|
void Rubiks::run() {
|
|
|
|
static cv::VideoWriter video;
|
|
|
|
static bool rolling = false;
|
|
static int frames = 30 * 15;
|
|
|
|
static int delay = 30 * 3;
|
|
|
|
|
|
static float scale = 0.96f;
|
|
//static float scalePrev = 1.0f;
|
|
|
|
static glm::vec3 pos(0), rot(0);
|
|
//static glm::vec3 posPrev(0), rotPrev(0);
|
|
|
|
static glm::vec3 camPos(6.0f, 8.0f, 6.0f), camRot(-glm::pi<float>() / 4, 5.0 / 4.0 * glm::pi<float>(), 0.0f);
|
|
static glm::vec3 camPosPrev(0.0f, 0.0f, 10.0f), camRotPrev(0.0f, glm::pi<float>(), 0.0f);
|
|
|
|
static glm::vec4 color = { 0.4f, 3.0f, 0.4f, 1.0f };
|
|
|
|
static int w, h;
|
|
window->getSize(w, h);
|
|
//camPos = camera.moveRel(camPos - camPosPrev);
|
|
//camRot = camera.rotateRel(camRot - camRotPrev);
|
|
|
|
camera.setTransform(glm::lookAt(
|
|
camPos,
|
|
camPos + glm::normalize(glm::vec3(glm::cos(camRot.x) * glm::sin(camRot.y), glm::sin(camRot.x), glm::cos(camRot.x) * glm::cos(camRot.y))),
|
|
glm::vec3(0.0f, 1.0f, 0.0f)
|
|
));
|
|
|
|
camPosPrev = camPos;
|
|
camRotPrev = camRot;
|
|
|
|
|
|
for(auto& b : rubiksCube.getBlocks()) {
|
|
b.body.scaleTo(scale);
|
|
window->getRenderer()->draw(
|
|
b.body.getMesh(),
|
|
b.body.getTransform(),
|
|
camera.getTransform(),
|
|
camera.getPerspective(),
|
|
color
|
|
);
|
|
}
|
|
|
|
if(rolling && delay-- < 0) {
|
|
if(frames < 435) {
|
|
rubiksCube.update();
|
|
}
|
|
frames--;
|
|
|
|
rolling = frames > 0;
|
|
|
|
uint32_t rowStride = ((1920 + 63) & 0xFFFFFFC0) * sizeof(uint32_t);
|
|
|
|
long screenBufferSize = rowStride * 1080;
|
|
|
|
cv::Mat f(1080, 1920, CV_8UC3);
|
|
|
|
glReadPixels(0, 0, 1920, 1080, GL_RGB, GL_UNSIGNED_BYTE, f.data);
|
|
|
|
|
|
cv::Mat cv_pixels( 1080, 1920, CV_8UC3 );
|
|
|
|
for( int y=0; y<1080; y++ ) for( int x=0; x<1920; x++ ) {
|
|
|
|
cv_pixels.at<cv::Vec3b>(y,x)[2] = f.at<cv::Vec3b>(1080-y-1,x)[0];
|
|
cv_pixels.at<cv::Vec3b>(y,x)[1] = f.at<cv::Vec3b>(1080-y-1,x)[1];
|
|
cv_pixels.at<cv::Vec3b>(y,x)[0] = f.at<cv::Vec3b>(1080-y-1,x)[2];
|
|
}
|
|
|
|
video << cv_pixels;
|
|
//video << f;
|
|
|
|
} else if(frames <= 0) {
|
|
video.release();
|
|
//UpdateVideoStatus(WM_VIDEO_STATUS_FILE_CLOSED);
|
|
}
|
|
|
|
if(!rolling) {
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
static glm::vec4& clearColor = window->getRenderer()->clearColor;
|
|
|
|
ImGui::Begin("Rubiks Module");
|
|
|
|
ImGui::Text("Pick a clear color!");
|
|
|
|
ImGui::SliderFloat("clear r", &clearColor.r, 0.0f, 1.0f);
|
|
ImGui::SliderFloat("clear g", &clearColor.g, 0.0f, 1.0f);
|
|
ImGui::SliderFloat("clear b", &clearColor.b, 0.0f, 1.0f);
|
|
ImGui::SliderFloat("clear a", &clearColor.a, 0.0f, 1.0f);
|
|
|
|
ImGui::Text("Camera Properties");
|
|
|
|
ImGui::SliderFloat("cam pitch", &camRot.x, -glm::pi<float>(), glm::pi<float>());
|
|
ImGui::SliderFloat("cam yaw", &camRot.y, 0, 2 * glm::pi<float>());
|
|
ImGui::SliderFloat("cam roll", &camRot.z, -glm::pi<float>(), glm::pi<float>());
|
|
|
|
ImGui::SliderFloat("cam x", &camPos.x, -10.0f, 10.0f);
|
|
ImGui::SliderFloat("cam y", &camPos.y, -10.0f, 10.0f);
|
|
ImGui::SliderFloat("cam z", &camPos.z, -10.0f, 10.0f);
|
|
|
|
ImGui::Text("Rubiks Cube Properties");
|
|
|
|
ImGui::SliderFloat("cube pitch", &rot.x, -glm::pi<float>(), glm::pi<float>());
|
|
ImGui::SliderFloat("cube yaw", &rot.y, 0, 2 * glm::pi<float>());
|
|
ImGui::SliderFloat("cube roll", &rot.z, -glm::pi<float>(), glm::pi<float>());
|
|
|
|
ImGui::SliderFloat("cube x", &pos.x, -10.0f, 10.0f);
|
|
ImGui::SliderFloat("cube y", &pos.y, -10.0f, 10.0f);
|
|
ImGui::SliderFloat("cube z", &pos.z, -10.0f, 10.0f);
|
|
|
|
ImGui::SliderFloat("cube scale", &scale, 0.01f, 10.0f);
|
|
|
|
static bool updateCube = true;
|
|
ImGui::Checkbox("auto update cube", &updateCube);
|
|
if(updateCube) {
|
|
rubiksCube.update();
|
|
}
|
|
|
|
if(ImGui::Button("step cube")) {
|
|
rubiksCube.update();
|
|
}
|
|
|
|
if(ImGui::Button("record")) {
|
|
rolling = true;
|
|
frames = 450;
|
|
delay = 90;
|
|
|
|
RubiksCube::Turn prevMove;
|
|
|
|
for(int i = 0; i < 30; i++) {
|
|
|
|
RubiksCube::Turn move;
|
|
move.plate = (RubiksCube::Plate)(1 << (rand() % 9));
|
|
move.reverse = (bool)(rand() % 2);
|
|
|
|
while(move.plate == prevMove.plate && move.reverse != prevMove.reverse) {
|
|
move.plate = (RubiksCube::Plate)(1 << (rand() % 9));
|
|
move.reverse = (bool)(rand() % 2);
|
|
}
|
|
|
|
rubiksCube.doTurn(move.plate, move.reverse);
|
|
|
|
prevMove = move;
|
|
}
|
|
|
|
rubiksCube.solve();
|
|
|
|
video.open("Rubiks.mp4", cv::VideoWriter::fourcc('x', '2', '6', '4'), 30.0, cv::Size(1920, 1080), true);
|
|
if(!video.isOpened()) {
|
|
std::cout << "VIDEO DID NOT OPEN!\n";
|
|
std::abort();
|
|
}
|
|
|
|
//UpdateVideoStatus(WM_VIDEO_STATUS_FILE_OPENED);
|
|
}
|
|
|
|
if(ImGui::Button("randomize")) {
|
|
RubiksCube::Turn prevMove;
|
|
|
|
for(int i = 0; i < 30; i++) {
|
|
|
|
RubiksCube::Turn move;
|
|
move.plate = (RubiksCube::Plate)(1 << (rand() % 9));
|
|
move.reverse = (bool)(rand() % 2);
|
|
|
|
while(move.plate == prevMove.plate && move.reverse != prevMove.reverse) {
|
|
move.plate = (RubiksCube::Plate)(1 << (rand() % 9));
|
|
move.reverse = (bool)(rand() % 2);
|
|
}
|
|
|
|
rubiksCube.doTurn(move.plate, move.reverse);
|
|
|
|
prevMove = move;
|
|
}
|
|
}
|
|
|
|
if(ImGui::Button("solve")) {
|
|
rubiksCube.solve();
|
|
}
|
|
|
|
if(ImGui::Button("xb")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::X_Bottom, false);
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("xm")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::X_Middle, false);
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("xt")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::X_Top, false);
|
|
}
|
|
|
|
if(ImGui::Button("yb")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Y_Bottom, false);
|
|
}
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("ym")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Y_Middle, false);
|
|
}
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("yt")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Y_Top, false);
|
|
}
|
|
|
|
if(ImGui::Button("zb")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Z_Bottom, false);
|
|
}
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("zm")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Z_Middle, false);
|
|
}
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("zt")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Z_Top, false);
|
|
}
|
|
|
|
if(ImGui::Button("xbr")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::X_Bottom, true);
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("xmr")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::X_Middle, true);
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("xtr")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::X_Top, true);
|
|
}
|
|
|
|
if(ImGui::Button("ybr")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Y_Bottom, true);
|
|
}
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("ymr")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Y_Middle, true);
|
|
}
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("ytr")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Y_Top, true);
|
|
}
|
|
|
|
if(ImGui::Button("zbr")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Z_Bottom, true);
|
|
}
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("zmr")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Z_Middle, true);
|
|
}
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button("ztr")) {
|
|
rubiksCube.doTurn(RubiksCube::Plate::Z_Top, true);
|
|
}
|
|
|
|
if(ImGui::Button("Reset Window Size")) {
|
|
app->emitEvent(new Archimedes::ResizeWindowEvent(500, 500));
|
|
}
|
|
|
|
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
|
ImGui::End();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
bool Rubiks::onEvent(const Archimedes::Event& e) {
|
|
|
|
unsigned int type = app->getEventType(e);
|
|
|
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
|
|
|
if(type == app->getEventType(Archimedes::ResizeWindowEvent())) {
|
|
Archimedes::ResizeWindowEvent event = (Archimedes::ResizeWindowEvent&) e;
|
|
|
|
camera.setPerspective(glm::perspective(glm::radians(45.0f), (float)event.width/(float)event.height, 0.1f, 100.0f));
|
|
|
|
} else if(type == app->getEventType(Archimedes::KeyPressedWindowEvent()) && !io.WantCaptureKeyboard) {
|
|
|
|
return false;
|
|
} else if(type == app->getEventType(Archimedes::KeyReleasedWindowEvent()) && !io.WantCaptureKeyboard) {
|
|
|
|
return false;
|
|
} else if(type == app->getEventType(Archimedes::MouseButtonPressedWindowEvent()) && !io.WantCaptureMouse) {
|
|
|
|
return false;
|
|
} else if(type == app->getEventType(Archimedes::MouseButtonReleasedWindowEvent()) && !io.WantCaptureMouse) {
|
|
|
|
return false;
|
|
} else if(type == app->getEventType(Archimedes::ScrollWindowEvent()) && !io.WantCaptureMouse) {
|
|
|
|
Archimedes::ScrollWindowEvent event = (Archimedes::ScrollWindowEvent&) e;
|
|
|
|
//camera.moveRel(glm::vec3(0.0f, 0.0f, event.dy));
|
|
|
|
|
|
return true;
|
|
} else if(type == app->getEventType(Archimedes::MouseMovedWindowEvent()) && !io.WantCaptureMouse) {
|
|
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|