- First commit to gitea
This commit is contained in:
3
.gitignore
vendored
Executable file
3
.gitignore
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
build/*
|
||||
biomed
|
||||
biomed_debug
|
||||
34
Editor.cpp
Normal file
34
Editor.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "Editor.h"
|
||||
#include "Model.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
Mode mode {Mode::Cube};
|
||||
State state {State::None};
|
||||
char textureFilename[400] {"/<none>"};
|
||||
unsigned texture {0};
|
||||
char forcedAxis {-1};
|
||||
float t {0.0f};
|
||||
uint8_t bitmap[32*32*4] {255};
|
||||
|
||||
void SetMode(const Mode value)
|
||||
{
|
||||
mode = value;
|
||||
if (mode == Mode::Cube) {
|
||||
model.SelectAllFaces(false);
|
||||
} else if (mode == Mode::Face) {
|
||||
model.SelectAllCubes(false);
|
||||
}
|
||||
}
|
||||
|
||||
void SetState(const State value)
|
||||
{
|
||||
forcedAxis = -1;
|
||||
if (state == value) {
|
||||
state = State::None;
|
||||
} else {
|
||||
state = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
Editor.h
Normal file
19
Editor.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
enum class Mode { Face, Cube, Anim, Paint };
|
||||
enum class State { None, Grab, Scale, Rotate, Pivot };
|
||||
|
||||
extern Mode mode;
|
||||
extern State state;
|
||||
extern char textureFilename[400];
|
||||
extern unsigned texture;
|
||||
extern char forcedAxis;
|
||||
extern float t;
|
||||
|
||||
extern unsigned char bitmap[32*32*4];
|
||||
|
||||
void SetMode(const Mode value);
|
||||
void SetState(const State value);
|
||||
}
|
||||
941
GUI.cpp
Normal file
941
GUI.cpp
Normal file
@@ -0,0 +1,941 @@
|
||||
#include "GUI.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
#include "GUIDraw.h"
|
||||
#include "font.h"
|
||||
#include "GUIMouse.h"
|
||||
#include "GUIKeyboard.h"
|
||||
#include "GUIViewport.h"
|
||||
#include "Model.h"
|
||||
#include "renderer.h"
|
||||
#include "Editor.h"
|
||||
//#include "GUIDialogs.h"
|
||||
#include "texture.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
const Color winBack{30, 30, 30, 255};
|
||||
const Color panelBack{53, 53, 60, 255};
|
||||
const Color panel3DBack{40, 40, 43, 255};
|
||||
const Color textBoxBack{61, 61, 66, 255};
|
||||
const Color textBoxBorder{76, 77, 81, 255};
|
||||
const Color buttonBack{63, 63, 70, 255};
|
||||
const Color buttonPressed{62, 153, 247, 255};
|
||||
|
||||
namespace GUI
|
||||
{
|
||||
Font* font {nullptr};
|
||||
float viewPos{0};
|
||||
Vector4 viewSize{0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
|
||||
Vector4 viewStack[10];
|
||||
char viewStackPos{0};
|
||||
int focus{-1};
|
||||
int id{0};
|
||||
bool dot{false};
|
||||
bool empty{false};
|
||||
|
||||
bool menuVisible {false};
|
||||
Vector2 menuPos {0, 0};
|
||||
int subMenu{-1};
|
||||
Vector2 subMenuPos {0, 0};
|
||||
|
||||
bool comboBoxVisible {false};
|
||||
|
||||
int selectedViewport {0};
|
||||
bool zoomed {false};
|
||||
|
||||
Color currentColor {0, 0, 0, 255};
|
||||
|
||||
float a = 6.5f;
|
||||
float b = 12.0f;
|
||||
float c = 24.0f;
|
||||
|
||||
void ResetFocus()
|
||||
{
|
||||
focus = -1;
|
||||
dot = false;
|
||||
empty = false;
|
||||
menuVisible = false;
|
||||
}
|
||||
|
||||
void StartSplitV(const float& value)
|
||||
{
|
||||
assert(viewStackPos < 10);
|
||||
|
||||
viewPos = 0;
|
||||
viewStack[viewStackPos] = viewSize;
|
||||
if (value > 0) {
|
||||
viewStack[viewStackPos].w -= (value + 5);
|
||||
viewSize.w = value;
|
||||
} else {
|
||||
viewStack[viewStackPos].w = -value;
|
||||
viewSize.w -= (-value + 5);
|
||||
}
|
||||
viewStack[viewStackPos].y = viewSize.y + viewSize.w + 5;
|
||||
viewStackPos++;
|
||||
}
|
||||
|
||||
void StartSplitH(const float& value)
|
||||
{
|
||||
assert(viewStackPos < 10);
|
||||
|
||||
viewPos = 0;
|
||||
viewStack[viewStackPos] = viewSize;
|
||||
if (value > 0) {
|
||||
viewStack[viewStackPos].z -= (value + 5);
|
||||
viewSize.z = value;
|
||||
} else {
|
||||
viewStack[viewStackPos].z = -value;
|
||||
viewSize.z -= (-value + 5);
|
||||
}
|
||||
viewStack[viewStackPos].x = viewSize.x + viewSize.z + 5;
|
||||
viewStackPos++;
|
||||
}
|
||||
|
||||
void NextSplit()
|
||||
{
|
||||
assert(viewStackPos > 0);
|
||||
viewPos = 0;
|
||||
viewStackPos--;
|
||||
viewSize = viewStack[viewStackPos];
|
||||
}
|
||||
|
||||
void DrawPanel()
|
||||
{
|
||||
viewPos = 0;
|
||||
GUIDraw::FillRect(viewSize, panelBack);
|
||||
viewSize.x += 10;
|
||||
viewSize.y += 10;
|
||||
viewSize.z -= 20;
|
||||
viewSize.w -= 20;
|
||||
}
|
||||
|
||||
void Draw3DPanel(const int index)
|
||||
{
|
||||
if (not menuVisible and GUIMouse::position.inside(viewSize.GetPosition(), viewSize.GetSize())) {
|
||||
selectedViewport = index;
|
||||
if (GUIKeyboard::key == SDLK_z) {
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
zoomed = not zoomed;
|
||||
}
|
||||
}
|
||||
|
||||
const Color color = (index == selectedViewport ? Color(128, 0, 0, 255) : panel3DBack);
|
||||
viewPos = 0;
|
||||
GUIDraw::FillRect(viewSize, color);
|
||||
viewSize.x += 5;
|
||||
viewSize.y += 5;
|
||||
viewSize.z -= 10;
|
||||
viewSize.w -= 10;
|
||||
}
|
||||
|
||||
void DrawTitle(const char* title)
|
||||
{
|
||||
viewPos = 0;
|
||||
GUIDraw::FillRect({viewSize.x, viewSize.y, viewSize.z, 25}, winBack);
|
||||
Vector2 textSize = font->GetSize(title);
|
||||
const float pos = (viewSize.z-5) * 0.5f - textSize.x * 0.5f;
|
||||
|
||||
font->Print(viewSize.x+5+pos, viewSize.y+4, title);
|
||||
|
||||
viewSize.y += 30;
|
||||
viewSize.w -= 30;
|
||||
}
|
||||
|
||||
void DrawCaption(const char* title)
|
||||
{
|
||||
viewPos = 0;
|
||||
font->Print(viewSize.x, viewSize.y, title);
|
||||
|
||||
viewSize.y += 20;
|
||||
viewSize.w -= 20;
|
||||
}
|
||||
|
||||
const bool DrawComboBox(char* text)
|
||||
{
|
||||
bool retVal = false;
|
||||
Vector4 rect {viewPos+viewSize.x, viewSize.y, viewSize.z, 22};
|
||||
Color backColor = textBoxBack;
|
||||
if (text != nullptr and GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
|
||||
retVal = true;
|
||||
}
|
||||
backColor = textBoxBorder;
|
||||
}
|
||||
GUIDraw::FillRect(rect, backColor);
|
||||
GUIDraw::DrawRect(rect, textBoxBorder);
|
||||
|
||||
if (text != nullptr) font->Print(viewPos+viewSize.x+5, viewSize.y+2, text, 15);
|
||||
|
||||
viewPos = 0;
|
||||
viewSize.y += 27;
|
||||
viewSize.w -= 27;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void DrawTextBox(char* text)
|
||||
{
|
||||
Vector4 rect {viewPos+viewSize.x, viewSize.y, viewSize.z, 22};
|
||||
Color backColor = textBoxBack;
|
||||
if (text != nullptr and GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
|
||||
focus = id;
|
||||
}
|
||||
backColor = textBoxBorder;
|
||||
}
|
||||
GUIDraw::FillRect(rect, backColor);
|
||||
GUIDraw::DrawRect(rect, textBoxBorder);
|
||||
|
||||
if (text != nullptr) {
|
||||
char textColor = 15;
|
||||
if (focus == id) {
|
||||
textColor = 11;
|
||||
if (GUIKeyboard::key >= SDLK_SPACE and GUIKeyboard::key <= SDLK_z) {
|
||||
const size_t len = strlen(text);
|
||||
if (len < 9) {
|
||||
text[len] = GUIKeyboard::key;
|
||||
text[len+1] = '\0';
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
}
|
||||
} else if (GUIKeyboard::key == SDLK_BACKSPACE) {
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
const size_t len = strlen(text);
|
||||
if (len > 0) text[len-1] = '\0';
|
||||
} else if (GUIKeyboard::key == SDLK_RETURN) {
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
ResetFocus();
|
||||
textColor = 15;
|
||||
} else if (GUIKeyboard::key == SDLK_TAB) {
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
focus++;
|
||||
textColor = 15;
|
||||
}
|
||||
if (focus == id) {
|
||||
const Vector2 size = font->GetSize(text);
|
||||
font->Print(size.x+viewPos+viewSize.x+5, viewSize.y+2, "_", textColor);
|
||||
}
|
||||
}
|
||||
font->Print(viewPos+viewSize.x+5, viewSize.y+2, text, textColor);
|
||||
}
|
||||
|
||||
viewPos = 0;
|
||||
viewSize.y += 27;
|
||||
viewSize.w -= 27;
|
||||
id++;
|
||||
}
|
||||
|
||||
void DrawNumTextBox(float* number, const float size)
|
||||
{
|
||||
Vector4 rect {viewPos+viewSize.x, viewSize.y, size, 22};
|
||||
Color backColor = textBoxBack;
|
||||
|
||||
if (number != nullptr and GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
|
||||
dot = false;
|
||||
empty = false;
|
||||
focus = id;
|
||||
}
|
||||
backColor = textBoxBorder;
|
||||
}
|
||||
GUIDraw::FillRect(rect, backColor);
|
||||
GUIDraw::DrawRect(rect, textBoxBorder);
|
||||
|
||||
if (number != nullptr) {
|
||||
int i;
|
||||
char s1[20];
|
||||
char* s2;
|
||||
//sprintf(text, "%.f", number);
|
||||
|
||||
sprintf(s1, "%f", *number);
|
||||
s2 = strchr(s1, '.');
|
||||
i = int(s2 - s1);
|
||||
sprintf(s1, "%.*g", (i+2), *number);
|
||||
|
||||
char textColor = 15;
|
||||
if (focus == id) {
|
||||
textColor = 11;
|
||||
if (dot) strcat(s1, ".");
|
||||
if (empty) s1[0] = '\0';
|
||||
const bool dotAlready = (strchr(s1, '.') != nullptr);
|
||||
if (GUIKeyboard::key >= SDLK_0 and GUIKeyboard::key <= SDLK_9) {
|
||||
if (not empty and s1[0] == '0' and not (strlen(s1)>1 and s1[1] == '.' )) s1[0] = '\0';
|
||||
empty = false;
|
||||
const size_t len = strlen(s1);
|
||||
s1[len] = GUIKeyboard::key;
|
||||
s1[len+1] = '\0';
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
} else if (not dotAlready and GUIKeyboard::key == SDLK_PERIOD) {
|
||||
empty = false;
|
||||
const size_t len = strlen(s1);
|
||||
s1[len] = GUIKeyboard::key;
|
||||
s1[len+1] = '\0';
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
} else if (GUIKeyboard::key == SDLK_BACKSPACE) {
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
const size_t len = strlen(s1);
|
||||
if (len == 1) empty = true;
|
||||
s1[len-1] = '\0';
|
||||
} else if (GUIKeyboard::key == SDLK_RIGHT) {
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
(*number)++;
|
||||
sprintf(s1, "%f", *number);
|
||||
s2 = strchr(s1, '.');
|
||||
i = int(s2 - s1);
|
||||
sprintf(s1, "%.*g", (i+2), *number);
|
||||
} else if (GUIKeyboard::key == SDLK_LEFT) {
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
(*number)--;
|
||||
sprintf(s1, "%f", *number);
|
||||
s2 = strchr(s1, '.');
|
||||
i = int(s2 - s1);
|
||||
sprintf(s1, "%.*g", (i+2), *number);
|
||||
} else if (GUIKeyboard::key == SDLK_RETURN) {
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
ResetFocus();
|
||||
textColor = 15;
|
||||
const size_t len = strlen(s1);
|
||||
if (s1[len-1] == '.') s1[len-1] = '\0';
|
||||
} else if (GUIKeyboard::key == SDLK_TAB) {
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
focus++;
|
||||
textColor = 15;
|
||||
const size_t len = strlen(s1);
|
||||
if (s1[len-1] == '.') s1[len-1] = '\0';
|
||||
}
|
||||
if (focus == id) {
|
||||
const size_t len = strlen(s1);
|
||||
dot = (s1[len-1] == '.');
|
||||
*number = atof(s1);
|
||||
|
||||
const Vector2 size = font->GetSize(s1);
|
||||
font->Print(size.x+viewPos+viewSize.x+5, viewSize.y+2, "_", textColor);
|
||||
}
|
||||
}
|
||||
font->Print(viewPos+viewSize.x+5, viewSize.y+2, s1, textColor);
|
||||
}
|
||||
|
||||
int numElements = viewSize.z / size;
|
||||
float separation = (viewSize.z - (size*numElements)) / (numElements-1);
|
||||
viewPos += size+separation;
|
||||
|
||||
if (viewPos > viewSize.z) {
|
||||
viewPos = 0;
|
||||
viewSize.y += 27;
|
||||
viewSize.w -= 27;
|
||||
}
|
||||
id++;
|
||||
}
|
||||
|
||||
void DrawViewport(const int index)
|
||||
{
|
||||
glViewport(viewSize.x, SCREEN_HEIGHT-(viewSize.y+viewSize.w), viewSize.z, viewSize.w);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(viewSize.x, SCREEN_HEIGHT-(viewSize.y+viewSize.w), viewSize.z, viewSize.w);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
float zoom = viewports[index].zoom;
|
||||
if (zoom < 0) zoom = 1.0f/-zoom;
|
||||
const float x = (viewSize.z * 0.5f) / zoom;
|
||||
const float y = (viewSize.w * 0.5f) / zoom;
|
||||
glOrtho(-x, x, y, -y, 1000, -1000);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glTranslatef(viewports[index].offset.x, viewports[index].offset.y, 0);
|
||||
glRotatef(viewports[index].rotation.x, 1, 0, 0);
|
||||
glRotatef(viewports[index].rotation.y, 0, 1, 0);
|
||||
|
||||
|
||||
if (not menuVisible and GUIMouse::position.inside(viewSize.GetPosition(), viewSize.GetSize())) {
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Right] == GUIMouse::ButtonState::Down) {
|
||||
menuVisible = true;
|
||||
menuPos = GUIMouse::position;
|
||||
}
|
||||
if (not GUIKeyboard::alt and GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
|
||||
if (Editor::state == Editor::State::None) {
|
||||
if (Editor::mode == Editor::Mode::Paint) {
|
||||
if (viewports[index].renderMode == Viewport::RenderMode::UV) {
|
||||
Renderer::SetState(RENDER_FILL);
|
||||
Color color = model.PickPixel(GUIMouse::position.x, GUIMouse::position.y);
|
||||
Editor::bitmap[(color.x*4)+color.y*128] = currentColor.r;
|
||||
Editor::bitmap[(color.x*4)+1+color.y*128] = currentColor.g;
|
||||
Editor::bitmap[(color.x*4)+2+color.y*128] = currentColor.b;
|
||||
Editor::bitmap[(color.x*4)+3+color.y*128] = currentColor.a;
|
||||
Texture::Update(Editor::texture, 32, 32, Editor::bitmap);
|
||||
|
||||
} else {
|
||||
Renderer::SetState(RENDER_DEPTH | RENDER_FILL);
|
||||
Color color = model.PickPaint(GUIMouse::position.x, GUIMouse::position.y);
|
||||
Editor::bitmap[(color.y*4)+color.z*128] = currentColor.r;
|
||||
Editor::bitmap[(color.y*4)+1+color.z*128] = currentColor.g;
|
||||
Editor::bitmap[(color.y*4)+2+color.z*128] = currentColor.b;
|
||||
Editor::bitmap[(color.y*4)+3+color.z*128] = currentColor.a;
|
||||
Texture::Update(Editor::texture, 32, 32, Editor::bitmap);
|
||||
}
|
||||
} else {
|
||||
Renderer::SetState(RENDER_DEPTH | RENDER_FILL);
|
||||
Color color = model.Pick(GUIMouse::position.x, GUIMouse::position.y);
|
||||
if (Editor::mode == Editor::Mode::Cube) {
|
||||
model.SelectCube(color.r, GUIKeyboard::shift);
|
||||
} else if (Editor::mode == Editor::Mode::Face) {
|
||||
model.SelectFace(color.r, color.g, GUIKeyboard::shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
ResetFocus();
|
||||
}
|
||||
if (GUIMouse::delta.x != 0 or GUIMouse::delta.y != 0) {
|
||||
if (GUIKeyboard::alt or GUIMouse::buttons[GUIMouse::Button::Middle] == GUIMouse::ButtonState::Pressed) {
|
||||
if (GUIKeyboard::shift) {
|
||||
viewports[index].offset += GUIMouse::delta / viewports[index].zoom;
|
||||
} else {
|
||||
viewports[index].rotation += Vector2(GUIMouse::delta.y, -GUIMouse::delta.x)*1;
|
||||
if (viewports[index].rotation.x < -90) viewports[index].rotation.x = -90;
|
||||
if (viewports[index].rotation.x > 90) viewports[index].rotation.x = 90;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (GUIMouse::wheel.x != 0 or GUIMouse::wheel.y != 0) {
|
||||
if (GUIKeyboard::shift) {
|
||||
viewports[index].offset += GUIMouse::wheel / viewports[index].zoom;
|
||||
} else {
|
||||
viewports[index].zoom -= GUIMouse::wheel.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glClearColor(float(panel3DBack.r)/255.0f, float(panel3DBack.g)/255.0f, float(panel3DBack.b)/255.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
if (viewports[index].renderMode == Viewport::RenderMode::Solid) {
|
||||
Renderer::SetState(RENDER_DEPTH | RENDER_FILL);
|
||||
if (viewports[index].light) Renderer::Light(ON);
|
||||
model.DrawSolid();
|
||||
} else if (viewports[index].renderMode == Viewport::RenderMode::Textured) {
|
||||
Renderer::SetState(RENDER_DEPTH | RENDER_FILL | RENDER_TEXTURE);
|
||||
if (viewports[index].light) Renderer::Light(ON);
|
||||
glBindTexture(GL_TEXTURE_2D, Editor::texture);
|
||||
model.DrawSolid();
|
||||
} else if (viewports[index].renderMode == Viewport::RenderMode::Wire) {
|
||||
Renderer::SetState(RENDER_DEPTH);
|
||||
model.DrawWire();
|
||||
} else if (viewports[index].renderMode == Viewport::RenderMode::UV) {
|
||||
Renderer::SetState(RENDER_FILL | RENDER_TEXTURE);
|
||||
glBindTexture(GL_TEXTURE_2D, Editor::texture);
|
||||
model.DrawUV();
|
||||
}
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
|
||||
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
}
|
||||
|
||||
const bool DrawButton(const char* text, const SDL_Keycode key, const bool state, const float size = 85)
|
||||
{
|
||||
Vector4 rect {viewPos+viewSize.x, viewSize.y, size, 22};
|
||||
Color backColor = buttonBack;
|
||||
Color borders[4] = {textBoxBorder, winBack, winBack, textBoxBorder};
|
||||
bool retVal {false};
|
||||
ivec2 textPadding {5,2};
|
||||
|
||||
if (state) {
|
||||
backColor = textBoxBorder;
|
||||
borders[0] = borders[3] = winBack;
|
||||
borders[1] = borders[2] = textBoxBorder;
|
||||
textPadding += {1,1};
|
||||
}
|
||||
|
||||
if (GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Pressed) {
|
||||
borders[0] = borders[3] = winBack;
|
||||
borders[1] = borders[2] = textBoxBorder;
|
||||
textPadding += {1,1};
|
||||
}
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Up) {
|
||||
borders[0] = borders[3] = winBack;
|
||||
borders[1] = borders[2] = textBoxBorder;
|
||||
textPadding += {1,1};
|
||||
ResetFocus();
|
||||
retVal = true;
|
||||
}
|
||||
backColor = textBoxBorder;
|
||||
}
|
||||
if (focus == -1 and key != SDLK_UNKNOWN and GUIKeyboard::key == key) {
|
||||
ResetFocus();
|
||||
retVal = true;
|
||||
}
|
||||
|
||||
GUIDraw::FillRect({viewPos+viewSize.x, viewSize.y, size, 22}, backColor);
|
||||
GUIDraw::DrawRect({viewPos+viewSize.x, viewSize.y, size, 22}, borders);
|
||||
font->Print(viewPos+viewSize.x+textPadding.x, viewSize.y+textPadding.y, text, 15);
|
||||
|
||||
int numElements = viewSize.z / size;
|
||||
float separation = (viewSize.z - (size*numElements)) / (numElements-1);
|
||||
viewPos += size+separation;
|
||||
|
||||
if (viewPos > viewSize.z) {
|
||||
viewPos = 0;
|
||||
viewSize.y += 27;
|
||||
viewSize.w -= 27;
|
||||
}
|
||||
//id++;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void DrawStaticTextBox(const char* text, const float size = 85)
|
||||
{
|
||||
Vector4 rect {viewPos+viewSize.x, viewSize.y, size, 22};
|
||||
GUIDraw::FillRect(rect, textBoxBack);
|
||||
GUIDraw::DrawRect(rect, textBoxBorder);
|
||||
font->Print(viewPos+viewSize.x+5, viewSize.y+2, text, 7);
|
||||
|
||||
viewPos += size+10;
|
||||
|
||||
if (viewPos > viewSize.z) {
|
||||
viewPos = 0;
|
||||
viewSize.y += 27;
|
||||
viewSize.w -= 27;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSpace(const int space)
|
||||
{
|
||||
viewPos = 0;
|
||||
viewSize.y += space;
|
||||
viewSize.w -= space;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (font == nullptr) {
|
||||
font = new Font();
|
||||
font->Load("font");
|
||||
}
|
||||
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 100, -100);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
viewStackPos = 0;
|
||||
viewPos = 0;
|
||||
viewSize = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
|
||||
id = 0;
|
||||
}
|
||||
|
||||
void DrawMenu(const int numItems, const float size)
|
||||
{
|
||||
viewSize = Vector4(menuPos.x, menuPos.y, size, 25*numItems);
|
||||
if (menuPos.x+size > SCREEN_WIDTH) viewSize.x = SCREEN_WIDTH - size;
|
||||
if (menuPos.y+25*numItems > SCREEN_HEIGHT) viewSize.y = SCREEN_HEIGHT - 25*numItems;
|
||||
|
||||
GUIDraw::FillRect(viewSize, panelBack);
|
||||
GUIDraw::DrawRect(viewSize, winBack);
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
|
||||
if (not GUIMouse::position.inside(viewSize.GetPosition(), viewSize.GetSize())) {
|
||||
ResetFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSubMenu(const int numItems, const float size)
|
||||
{
|
||||
viewSize = Vector4(subMenuPos.x, subMenuPos.y, size, 25*numItems);
|
||||
if (subMenuPos.x+size > SCREEN_WIDTH) viewSize.x = subMenuPos.x - (size*2);
|
||||
if (subMenuPos.y+25*numItems > SCREEN_HEIGHT) viewSize.y = SCREEN_HEIGHT - 25*numItems;
|
||||
|
||||
GUIDraw::FillRect(viewSize, panelBack);
|
||||
GUIDraw::DrawRect(viewSize, winBack);
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
|
||||
if (not GUIMouse::position.inside(viewSize.GetPosition(), viewSize.GetSize())) {
|
||||
ResetFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool DrawMenuItem(const char* text, const bool state)
|
||||
{
|
||||
bool retVal = false;
|
||||
Vector4 rect {viewSize.x, viewSize.y, viewSize.z, 25};
|
||||
if (GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
|
||||
subMenu = -1;
|
||||
GUIDraw::FillRect(rect, textBoxBack);
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
|
||||
retVal = true;
|
||||
menuVisible = false;
|
||||
comboBoxVisible = false;
|
||||
}
|
||||
}
|
||||
if (state) font->Print(viewSize.x+3, viewSize.y+2, "+", 15);
|
||||
font->Print(viewSize.x+13, viewSize.y+2, text, 15);
|
||||
|
||||
viewSize.y += 25;
|
||||
viewSize.w -= 25;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void DrawMenuSubItem(const char* text, const int subMenuIndex)
|
||||
{
|
||||
Vector4 rect {viewSize.x, viewSize.y, viewSize.z, 25};
|
||||
if (GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
|
||||
GUIDraw::FillRect(rect, textBoxBack);
|
||||
subMenu = subMenuIndex;
|
||||
subMenuPos = Vector2(viewSize.x+viewSize.z, viewSize.y);
|
||||
} else if (subMenu == subMenuIndex) {
|
||||
GUIDraw::FillRect(rect, textBoxBack);
|
||||
}
|
||||
|
||||
font->Print(viewSize.x+viewSize.z-13, viewSize.y+2, ">", 15);
|
||||
font->Print(viewSize.x+13, viewSize.y+2, text, 15);
|
||||
|
||||
viewSize.y += 25;
|
||||
viewSize.w -= 25;
|
||||
}
|
||||
|
||||
const bool DrawSubMenuItem(const char* text, const bool state)
|
||||
{
|
||||
bool retVal = false;
|
||||
Vector4 rect {viewSize.x, viewSize.y, viewSize.z, 25};
|
||||
if (GUIMouse::position.inside(rect.GetPosition(), rect.GetSize())) {
|
||||
GUIDraw::FillRect(rect, textBoxBack);
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
|
||||
retVal = true;
|
||||
menuVisible = false;
|
||||
}
|
||||
}
|
||||
if (state) font->Print(viewSize.x+3, viewSize.y+2, "+", 15);
|
||||
font->Print(viewSize.x+13, viewSize.y+2, text, 15);
|
||||
|
||||
viewSize.y += 25;
|
||||
viewSize.w -= 25;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
Vector2 GetTransformedAxesUV(const float x, const float y)
|
||||
{
|
||||
Vector2 result {x, y};
|
||||
if (Editor::forcedAxis == 0) result.y = 0;
|
||||
else if (Editor::forcedAxis == 1) result.x = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3 GetTransformedAxes(const float x, const float y)
|
||||
{
|
||||
Vector3 result {0, 0, 0};
|
||||
|
||||
if (Editor::forcedAxis == 0) {
|
||||
result.x = x + y;
|
||||
result.y = 0;
|
||||
result.z = 0;
|
||||
} else if (Editor::forcedAxis == 1) {
|
||||
result.x = 0;
|
||||
result.y = x + y;
|
||||
result.z = 0;
|
||||
} else if (Editor::forcedAxis == 2) {
|
||||
result.x = 0;
|
||||
result.y = 0;
|
||||
result.z = x + y;
|
||||
} else {
|
||||
float rx = viewports[selectedViewport].rotation.x; while (rx >= 360) rx -= 360; while (rx < 0) rx += 360;
|
||||
float ry = viewports[selectedViewport].rotation.y; while (ry >= 360) ry -= 360; while (ry < 0) ry += 360;
|
||||
if (rx <= 45 or rx >= 315 ) {
|
||||
if (ry <= 45 or ry >= 315) {
|
||||
// x, y
|
||||
result.x = x;
|
||||
result.y = y;
|
||||
} else if (ry > 45 and ry < 135) {
|
||||
// z, y
|
||||
result.z = x;
|
||||
result.y = y;
|
||||
} else if (ry >= 135 and ry < 225) {
|
||||
// -x, y
|
||||
result.x = -x;
|
||||
result.y = y;
|
||||
} else {
|
||||
// -z, y
|
||||
result.z = -x;
|
||||
result.y = y;
|
||||
}
|
||||
} else if (rx > 45 and rx < 180) {
|
||||
if (ry <= 45 or ry >= 315) {
|
||||
// x, -z
|
||||
result.x = x;
|
||||
result.z = -y;
|
||||
} else if (ry > 45 and ry < 135) {
|
||||
// z, x
|
||||
result.z = x;
|
||||
result.x = y;
|
||||
} else if (ry >= 135 and ry < 225) {
|
||||
// -x, z
|
||||
result.x = -x;
|
||||
result.z = y;
|
||||
} else {
|
||||
// -z, -x
|
||||
result.z = -x;
|
||||
result.x = -y;
|
||||
}
|
||||
} else {
|
||||
if (ry <= 45 or ry >= 315) {
|
||||
// x, z
|
||||
result.x = x;
|
||||
result.z = y;
|
||||
} else if (ry > 45 and ry < 135) {
|
||||
// -z, x
|
||||
result.z = x;
|
||||
result.x = -y;
|
||||
} else if (ry >= 135 and ry < 225) {
|
||||
// -x, -z
|
||||
result.x = -x;
|
||||
result.z = -y;
|
||||
} else {
|
||||
// z, -x
|
||||
result.z = -x;
|
||||
result.x = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Draw()
|
||||
{
|
||||
if (Editor::state != Editor::State::None) {
|
||||
if (Editor::mode == Editor::Mode::Face) {
|
||||
if (GUIKeyboard::key == SDLK_x) { Editor::forcedAxis = 0; GUIKeyboard::key = SDLK_UNKNOWN; }
|
||||
if (GUIKeyboard::key == SDLK_y) { Editor::forcedAxis = 1; GUIKeyboard::key = SDLK_UNKNOWN; }
|
||||
if (GUIMouse::slowDelta.x != 0 or GUIMouse::slowDelta.y != 0) {
|
||||
Vector2 axes = GetTransformedAxesUV(GUIMouse::slowDelta.x, GUIMouse::slowDelta.y);
|
||||
if (Editor::state == Editor::State::Grab) model.GrabFaces(axes.x, axes.y);
|
||||
if (Editor::state == Editor::State::Scale) model.ScaleFaces(axes.x, axes.y);
|
||||
}
|
||||
} else if (Editor::mode == Editor::Mode::Cube) {
|
||||
if (GUIKeyboard::key == SDLK_x) { Editor::forcedAxis = 0; GUIKeyboard::key = SDLK_UNKNOWN; }
|
||||
if (GUIKeyboard::key == SDLK_y) { Editor::forcedAxis = 1; GUIKeyboard::key = SDLK_UNKNOWN; }
|
||||
if (GUIKeyboard::key == SDLK_z) { Editor::forcedAxis = 2; GUIKeyboard::key = SDLK_UNKNOWN; }
|
||||
if (GUIMouse::slowDelta.x != 0 or GUIMouse::slowDelta.y != 0) {
|
||||
Vector3 axes = GetTransformedAxes(GUIMouse::slowDelta.x, GUIMouse::slowDelta.y);
|
||||
if (Editor::state == Editor::State::Grab) model.GrabCubes(axes.x, axes.y, axes.z);
|
||||
if (Editor::state == Editor::State::Scale) model.ScaleCubes(axes.x, axes.y, axes.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reset();
|
||||
//model.cubes[0].selected = true;
|
||||
|
||||
StartSplitV(30); //TOOLBAR
|
||||
|
||||
DrawPanel();
|
||||
|
||||
NextSplit();
|
||||
StartSplitV(-30);
|
||||
StartSplitH(200);
|
||||
// INFO PANEL
|
||||
DrawPanel();
|
||||
DrawTitle("State");
|
||||
if (DrawButton("Cubes", SDLK_1, Editor::mode == Editor::Mode::Cube)) Editor::SetMode(Editor::Mode::Cube);
|
||||
if (DrawButton("Faces", SDLK_2, Editor::mode == Editor::Mode::Face)) Editor::SetMode(Editor::Mode::Face);
|
||||
if (DrawButton("Paint", SDLK_3, Editor::mode == Editor::Mode::Paint)) Editor::SetMode(Editor::Mode::Paint);
|
||||
if (DrawButton("Anim", SDLK_4, Editor::mode == Editor::Mode::Anim)) Editor::SetMode(Editor::Mode::Anim);
|
||||
|
||||
DrawSpace(20);
|
||||
if (Editor::mode == Editor::Mode::Cube) {
|
||||
int index = model.GetSelectedCube();
|
||||
DrawTitle("Cube Info");
|
||||
DrawCaption("Name:");
|
||||
DrawTextBox(index != -1 ? model.cubes[index].name : nullptr);
|
||||
|
||||
float* v[9] = {nullptr};
|
||||
if (index != -1) {
|
||||
v[0] = &model.cubes[index].position.x;
|
||||
v[1] = &model.cubes[index].position.y;
|
||||
v[2] = &model.cubes[index].position.z;
|
||||
v[3] = &model.cubes[index].size.x;
|
||||
v[4] = &model.cubes[index].size.y;
|
||||
v[5] = &model.cubes[index].size.z;
|
||||
v[6] = &model.cubes[index].pivot.x;
|
||||
v[7] = &model.cubes[index].pivot.y;
|
||||
v[8] = &model.cubes[index].pivot.z;
|
||||
}
|
||||
DrawCaption("Position:");
|
||||
DrawNumTextBox(v[0], 50);
|
||||
DrawNumTextBox(v[1], 50);
|
||||
DrawNumTextBox(v[2], 50);
|
||||
DrawCaption("Size:");
|
||||
DrawNumTextBox(v[3], 50);
|
||||
DrawNumTextBox(v[4], 50);
|
||||
DrawNumTextBox(v[5], 50);
|
||||
DrawCaption("Pivot:");
|
||||
DrawNumTextBox(v[6], 50);
|
||||
DrawNumTextBox(v[7], 50);
|
||||
DrawNumTextBox(v[8], 50);
|
||||
DrawCaption("Parent:");
|
||||
char parent[10] = "<none>";
|
||||
if (index != -1 and model.cubes[index].parent != -1) strcpy(parent, model.cubes[model.cubes[index].parent].name);
|
||||
if (DrawComboBox(index != -1 ? parent : nullptr)) {
|
||||
comboBoxVisible = not comboBoxVisible;
|
||||
if (comboBoxVisible) {
|
||||
subMenuPos.x = viewSize.z;
|
||||
menuPos = {viewSize.x, viewSize.y};
|
||||
}
|
||||
}
|
||||
|
||||
DrawSpace(20);
|
||||
DrawTitle("Cube Ops");
|
||||
if (DrawButton("New", SDLK_n, false)) model.NewCube();
|
||||
if (DrawButton("Delete", SDLK_BACKSPACE, false)) model.DeleteCube();
|
||||
if (DrawButton("Dup", SDLK_d, false)) {
|
||||
model.DupCube();
|
||||
Editor::SetState(Editor::State::Grab);
|
||||
}
|
||||
if (DrawButton("Grab", SDLK_g, Editor::state == Editor::State::Grab)) Editor::SetState(Editor::State::Grab);
|
||||
if (DrawButton("Scale", SDLK_s, Editor::state == Editor::State::Scale)) Editor::SetState(Editor::State::Scale);
|
||||
if (DrawButton("Pivot", SDLK_p, Editor::state == Editor::State::Pivot)) Editor::SetState(Editor::State::Pivot);
|
||||
|
||||
} else if (Editor::mode == Editor::Mode::Face) {
|
||||
DrawTitle("Face Info");
|
||||
float* v[8] = {nullptr};
|
||||
ivec2 index = model.GetSelectedFace();
|
||||
if (index.x != -1) {
|
||||
v[0] = &model.cubes[index.x].faces[index.y].uv[2].x;
|
||||
v[1] = &model.cubes[index.x].faces[index.y].uv[2].y;
|
||||
v[2] = &model.cubes[index.x].faces[index.y].uv[1].x;
|
||||
v[3] = &model.cubes[index.x].faces[index.y].uv[1].y;
|
||||
v[4] = &model.cubes[index.x].faces[index.y].uv[3].x;
|
||||
v[5] = &model.cubes[index.x].faces[index.y].uv[3].y;
|
||||
v[6] = &model.cubes[index.x].faces[index.y].uv[0].x;
|
||||
v[7] = &model.cubes[index.x].faces[index.y].uv[0].y;
|
||||
}
|
||||
DrawCaption("UV:");
|
||||
DrawNumTextBox(v[0], 42);
|
||||
DrawNumTextBox(v[1], 42);
|
||||
DrawNumTextBox(v[2], 42);
|
||||
DrawNumTextBox(v[3], 42);
|
||||
DrawNumTextBox(v[4], 42);
|
||||
DrawNumTextBox(v[5], 42);
|
||||
DrawNumTextBox(v[6], 42);
|
||||
DrawNumTextBox(v[7], 42);
|
||||
|
||||
DrawSpace(20);
|
||||
DrawTitle("Face Ops");
|
||||
if (DrawButton("Clear", SDLK_c, false)) model.ClearFaces();
|
||||
if (DrawButton("Rotate", SDLK_r, false)) model.RotateFaces();
|
||||
if (DrawButton("FlipH", SDLK_h, false)) model.FlipHFaces();
|
||||
if (DrawButton("FlipV", SDLK_v, false)) model.FlipVFaces();
|
||||
if (DrawButton("Grab", SDLK_g, Editor::state == Editor::State::Grab)) Editor::SetState(Editor::State::Grab);
|
||||
if (DrawButton("Scale", SDLK_s, Editor::state == Editor::State::Scale)) Editor::SetState(Editor::State::Scale);
|
||||
|
||||
}
|
||||
DrawSpace(20);
|
||||
DrawTitle("Texture");
|
||||
char* shortPath = strrchr(Editor::textureFilename, '/')+1;
|
||||
DrawStaticTextBox(shortPath, 145);
|
||||
if (DrawButton("...", SDLK_UNKNOWN, false, 25)) {
|
||||
char oldPath[400];
|
||||
strcpy(oldPath, Editor::textureFilename);
|
||||
const char* path = nullptr;//GUIDialogs::ChooseFile();
|
||||
if (path != nullptr) {
|
||||
strcpy(Editor::textureFilename, path);
|
||||
//free(path);
|
||||
uint8_t* data = Texture::Load(Editor::textureFilename);
|
||||
if (data == nullptr) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "File is not a correct PNG!", nullptr);
|
||||
strcpy(Editor::textureFilename, oldPath);
|
||||
} else {
|
||||
memcpy(Editor::bitmap, data, 32*32*4);
|
||||
free(data);
|
||||
Texture::Update(Editor::texture, 32, 32, Editor::bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NextSplit();
|
||||
// 3D VIEWS
|
||||
if (zoomed) {
|
||||
Draw3DPanel(selectedViewport);
|
||||
DrawViewport(selectedViewport);
|
||||
} else {
|
||||
StartSplitH(2.0f*viewSize.z/3.0f);
|
||||
Draw3DPanel(0);
|
||||
DrawViewport(0);
|
||||
NextSplit();
|
||||
StartSplitV(viewSize.w/2.0f);
|
||||
Draw3DPanel(1);
|
||||
DrawViewport(1);
|
||||
NextSplit();
|
||||
Draw3DPanel(2);
|
||||
DrawViewport(2);
|
||||
}
|
||||
NextSplit();
|
||||
// STATUS BAR
|
||||
DrawPanel();
|
||||
|
||||
if (comboBoxVisible) {
|
||||
int numItems = model.numCubes;
|
||||
DrawMenu(numItems, subMenuPos.x);
|
||||
int sel = model.GetSelectedCube();
|
||||
for (int i = 0; i < model.numCubes; i++) {
|
||||
if (i != sel and DrawMenuItem(model.cubes[i].name, model.cubes[sel].parent == i)) model.cubes[sel].parent = i;
|
||||
}
|
||||
if (DrawMenuItem("<none>", model.cubes[sel].parent == -1)) model.cubes[sel].parent = -1;
|
||||
}
|
||||
|
||||
if (menuVisible) {
|
||||
DrawMenu(6, 120);
|
||||
DrawMenuSubItem("Render", 0);
|
||||
DrawMenuSubItem("View", 1);
|
||||
DrawMenuSubItem("Projection", 2);
|
||||
if (DrawMenuItem("Light", viewports[selectedViewport].light)) viewports[selectedViewport].light = not viewports[selectedViewport].light;
|
||||
if (DrawMenuItem("Grid", viewports[selectedViewport].grid)) viewports[selectedViewport].grid = not viewports[selectedViewport].grid;
|
||||
if (DrawMenuItem("Zoomed", zoomed)) zoomed = not zoomed;
|
||||
|
||||
if (subMenu == 0) {
|
||||
DrawSubMenu(4, 120);
|
||||
if (DrawSubMenuItem("Wire", viewports[selectedViewport].renderMode == Viewport::RenderMode::Wire)) viewports[selectedViewport].renderMode = Viewport::RenderMode::Wire;
|
||||
if (DrawSubMenuItem("Solid", viewports[selectedViewport].renderMode == Viewport::RenderMode::Solid)) viewports[selectedViewport].renderMode = Viewport::RenderMode::Solid;
|
||||
if (DrawSubMenuItem("Textured", viewports[selectedViewport].renderMode == Viewport::RenderMode::Textured)) viewports[selectedViewport].renderMode = Viewport::RenderMode::Textured;
|
||||
if (DrawSubMenuItem("UV", viewports[selectedViewport].renderMode == Viewport::RenderMode::UV)) viewports[selectedViewport].renderMode = Viewport::RenderMode::UV;
|
||||
} else if (subMenu == 1) {
|
||||
DrawSubMenu(6, 120);
|
||||
if (DrawSubMenuItem("Front", viewports[selectedViewport].rotation.x == 0 and viewports[selectedViewport].rotation.y == 0)) {
|
||||
viewports[selectedViewport].rotation.x = 0;
|
||||
viewports[selectedViewport].rotation.y = 0;
|
||||
}
|
||||
DrawSubMenuItem("Left", false);
|
||||
DrawSubMenuItem("Top", false);
|
||||
DrawSubMenuItem("Back", false);
|
||||
DrawSubMenuItem("Right", false);
|
||||
DrawSubMenuItem("Bottom", false);
|
||||
} else if (subMenu == 2) {
|
||||
DrawSubMenu(2, 120);
|
||||
DrawSubMenuItem("Orthogonal", true);
|
||||
DrawSubMenuItem("Perspective", false);
|
||||
}
|
||||
}
|
||||
|
||||
if (Editor::state != Editor::State::None) {
|
||||
if (GUIKeyboard::key == SDLK_RETURN) {
|
||||
GUIKeyboard::key = SDLK_UNKNOWN;
|
||||
Editor::SetState(Editor::State::None);
|
||||
}
|
||||
if (GUIMouse::buttons[GUIMouse::Button::Left] == GUIMouse::ButtonState::Down) {
|
||||
Editor::SetState(Editor::State::None);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
6
GUIDialogs.h
Normal file
6
GUIDialogs.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace GUIDialogs
|
||||
{
|
||||
char* ChooseFile();
|
||||
}
|
||||
29
GUIDialogs.mm
Normal file
29
GUIDialogs.mm
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "GUIDialogs.h"
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
namespace GUIDialogs
|
||||
{
|
||||
char* ChooseFile()
|
||||
{
|
||||
NSWindow *keyWindow = [NSApp keyWindow];
|
||||
char* path = nullptr;
|
||||
NSOpenPanel *panel = [NSOpenPanel openPanel];
|
||||
[panel setCanChooseFiles:YES];
|
||||
[panel setCanChooseDirectories:NO];
|
||||
[panel setAllowsMultipleSelection:NO];
|
||||
|
||||
NSInteger clicked = [panel runModal];
|
||||
|
||||
if (clicked == NSFileHandlingPanelOKButton) {
|
||||
for (NSURL *url in [panel URLs]) {
|
||||
path = strdup([url fileSystemRepresentation]);
|
||||
//const char* urlPath = [url fileSystemRepresentation];
|
||||
//path = (char*)malloc(strlen(urlPath));
|
||||
//strcpy(path, urlPath);
|
||||
}
|
||||
}
|
||||
[keyWindow makeKeyWindow];
|
||||
return path;
|
||||
}
|
||||
}
|
||||
75
GUIDraw.cpp
Normal file
75
GUIDraw.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "GUIDraw.h"
|
||||
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
#include "renderer.h"
|
||||
|
||||
namespace GUIDraw
|
||||
{
|
||||
void DrawLine(const Vector2& a, const Vector2& b, const Color& color)
|
||||
{
|
||||
Renderer::SetState(RENDER_BLEND);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2i(a.x, a.y);
|
||||
glVertex2i(b.x, b.y);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void DrawRect(const Vector4& rect, const Color& color)
|
||||
{
|
||||
Renderer::SetState(RENDER_BLEND);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex2i(rect.x, rect.y);
|
||||
glVertex2i(rect.x, rect.y+rect.w);
|
||||
glVertex2i(rect.x+rect.z, rect.y+rect.w);
|
||||
glVertex2i(rect.x+rect.z, rect.y);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void DrawRect(const Vector4& rect, const Color* colors)
|
||||
{
|
||||
Renderer::SetState(RENDER_BLEND);
|
||||
glBegin(GL_LINES);
|
||||
glColor4ub(colors[0].r, colors[0].g, colors[0].b, colors[0].a);
|
||||
glVertex2i(rect.x, rect.y);
|
||||
glVertex2i(rect.x, rect.y+rect.w);
|
||||
glColor4ub(colors[1].r, colors[1].g, colors[1].b, colors[1].a);
|
||||
glVertex2i(rect.x, rect.y+rect.w);
|
||||
glVertex2i(rect.x+rect.z, rect.y+rect.w);
|
||||
glColor4ub(colors[2].r, colors[2].g, colors[2].b, colors[2].a);
|
||||
glVertex2i(rect.x+rect.z, rect.y+rect.w);
|
||||
glVertex2i(rect.x+rect.z, rect.y);
|
||||
glColor4ub(colors[3].r, colors[3].g, colors[3].b, colors[3].a);
|
||||
glVertex2i(rect.x+rect.z, rect.y);
|
||||
glVertex2i(rect.x, rect.y);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void FillRect(const Vector4& rect, const Color& color)
|
||||
{
|
||||
Renderer::SetState(RENDER_BLEND | RENDER_FILL);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2i(rect.x, rect.y);
|
||||
glVertex2i(rect.x, rect.y+rect.w);
|
||||
glVertex2i(rect.x+rect.z, rect.y+rect.w);
|
||||
glVertex2i(rect.x+rect.z, rect.y);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void FillRect(const Vector4& rect, const Color* colors)
|
||||
{
|
||||
Renderer::SetState(RENDER_BLEND | RENDER_FILL);
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(colors[0].r, colors[0].g, colors[0].b, colors[0].a);
|
||||
glVertex2i(rect.x, rect.y);
|
||||
glColor4ub(colors[1].r, colors[1].g, colors[1].b, colors[1].a);
|
||||
glVertex2i(rect.x, rect.y+rect.w);
|
||||
glColor4ub(colors[2].r, colors[2].g, colors[2].b, colors[2].a);
|
||||
glVertex2i(rect.x+rect.z, rect.y+rect.w);
|
||||
glColor4ub(colors[3].r, colors[3].g, colors[3].b, colors[3].a);
|
||||
glVertex2i(rect.x+rect.z, rect.y);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
14
GUIDraw.h
Normal file
14
GUIDraw.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace GUIDraw
|
||||
{
|
||||
void DrawLine(const Vector2& a, const Vector2& b, const Color& color);
|
||||
void DrawRect(const Vector4& rect, const Color& color);
|
||||
void DrawRect(const Vector4& rect, const Color* colors);
|
||||
void FillRect(const Vector4& rect, const Color& color);
|
||||
void FillRect(const Vector4& rect, const Color* colors);
|
||||
|
||||
//void DrawNumTextBox(const Vector4& rect, float& num);
|
||||
}
|
||||
27
GUIKeyboard.cpp
Normal file
27
GUIKeyboard.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "GUIKeyboard.h"
|
||||
|
||||
#include "application.h"
|
||||
|
||||
namespace GUIKeyboard
|
||||
{
|
||||
SDL_Keycode key {SDLK_UNKNOWN};
|
||||
bool shift {false};
|
||||
bool alt {false};
|
||||
bool cmd {false};
|
||||
|
||||
void ReceiveKeyboardEvent(const SDL_Keycode key)
|
||||
{
|
||||
GUIKeyboard::key = key;
|
||||
SDL_Keymod mod = SDL_GetModState();
|
||||
shift = ((mod & KMOD_SHIFT) != KMOD_NONE);
|
||||
alt = ((mod & KMOD_ALT ) != KMOD_NONE);
|
||||
cmd = ((mod & KMOD_GUI ) != KMOD_NONE);
|
||||
Application::NeedsUpdate();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
key = SDLK_UNKNOWN;
|
||||
//shift = alt = cmd = false;
|
||||
}
|
||||
}
|
||||
15
GUIKeyboard.h
Normal file
15
GUIKeyboard.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace GUIKeyboard
|
||||
{
|
||||
extern SDL_Keycode key;
|
||||
extern bool shift;
|
||||
extern bool alt;
|
||||
extern bool cmd;
|
||||
|
||||
void ReceiveKeyboardEvent(const SDL_Keycode key);
|
||||
void Reset();
|
||||
}
|
||||
72
GUIMouse.cpp
Normal file
72
GUIMouse.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "GUIMouse.h"
|
||||
|
||||
#include "application.h"
|
||||
|
||||
namespace GUIMouse
|
||||
{
|
||||
Vector2 position {0, 0};
|
||||
Vector2 delta {0, 0};
|
||||
Vector2 slowDelta {0, 0};
|
||||
Vector2 wheel {0, 0};
|
||||
ButtonState buttons[3] {ButtonState::Released, ButtonState::Released, ButtonState::Released};
|
||||
Gesture gesture {};
|
||||
|
||||
Vector2 slowAccum {0, 0};
|
||||
|
||||
void ReceiveMouseUpEvent(const Button button)
|
||||
{
|
||||
buttons[button] = ButtonState::Up;
|
||||
Application::NeedsUpdate();
|
||||
}
|
||||
|
||||
void ReceiveMouseDownEvent(const Button button)
|
||||
{
|
||||
buttons[button] = ButtonState::Down;
|
||||
Application::NeedsUpdate();
|
||||
}
|
||||
|
||||
void ReceiveMouseMoveEvent(const float x, const float y)
|
||||
{
|
||||
delta = {x-position.x, y-position.y};
|
||||
slowAccum += delta * 0.2f;
|
||||
if (slowAccum.x >= 1 or slowAccum.x <= -1) {
|
||||
slowDelta.x = int(slowAccum.x);
|
||||
slowAccum.x = slowAccum.x - int(slowAccum.x);
|
||||
}
|
||||
if (slowAccum.y >= 1 or slowAccum.y <= -1) {
|
||||
slowDelta.y = int(slowAccum.y);
|
||||
slowAccum.y = slowAccum.y - int(slowAccum.y);
|
||||
}
|
||||
position = Vector2(x, y);
|
||||
Application::NeedsUpdate();
|
||||
}
|
||||
|
||||
void ReceiveMouseWheelEvent(const float x, const float y)
|
||||
{
|
||||
wheel = Vector2(x, y);
|
||||
Application::NeedsUpdate();
|
||||
}
|
||||
|
||||
void ReceiveMultigestureEvent(const float theta, const float dist, const int numFingers)
|
||||
{
|
||||
gesture.theta = theta;
|
||||
gesture.dist = dist;
|
||||
gesture.numFingers = numFingers;
|
||||
Application::NeedsUpdate();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (buttons[i] == ButtonState::Down) {
|
||||
buttons[i] = ButtonState::Pressed;
|
||||
} else if (buttons[i] == ButtonState::Up) {
|
||||
buttons[i] = ButtonState::Released;
|
||||
}
|
||||
}
|
||||
wheel = {0,0};
|
||||
delta = {0,0};
|
||||
slowDelta = {0,0};
|
||||
gesture.theta = gesture.dist = gesture.numFingers = 0;
|
||||
}
|
||||
}
|
||||
30
GUIMouse.h
Normal file
30
GUIMouse.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace GUIMouse
|
||||
{
|
||||
enum class ButtonState { Released, Down, Pressed, Up };
|
||||
enum Button : char { Left = 0, Right = 1, Middle = 2 };
|
||||
|
||||
struct Gesture
|
||||
{
|
||||
float theta {0};
|
||||
float dist {0};
|
||||
int numFingers {0};
|
||||
};
|
||||
|
||||
extern Vector2 position;
|
||||
extern Vector2 delta;
|
||||
extern Vector2 slowDelta;
|
||||
extern Vector2 wheel;
|
||||
extern ButtonState buttons[3];
|
||||
extern Gesture gesture;
|
||||
|
||||
void ReceiveMouseUpEvent(const Button button);
|
||||
void ReceiveMouseDownEvent(const Button button);
|
||||
void ReceiveMouseMoveEvent(const float x, const float y);
|
||||
void ReceiveMouseWheelEvent(const float x, const float y);
|
||||
void ReceiveMultigestureEvent(const float theta, const float dist, const int numFingers);
|
||||
void Reset();
|
||||
}
|
||||
3
GUIViewport.cpp
Normal file
3
GUIViewport.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "GUIViewport.h"
|
||||
|
||||
Viewport viewports[3];
|
||||
18
GUIViewport.h
Normal file
18
GUIViewport.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
struct Viewport
|
||||
{
|
||||
enum RenderMode { Wire, Solid, Textured, UV };
|
||||
|
||||
Vector4 bounds {};
|
||||
RenderMode renderMode {Solid};
|
||||
Vector2 offset {0, 0};
|
||||
Vector2 rotation {10, 20};
|
||||
float zoom {10.0f};
|
||||
bool light {true};
|
||||
bool grid {true};
|
||||
};
|
||||
|
||||
extern Viewport viewports[3];
|
||||
777
Matrices.cpp
Executable file
777
Matrices.cpp
Executable file
@@ -0,0 +1,777 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Matrice.cpp
|
||||
// ===========
|
||||
// NxN Matrix Math classes
|
||||
//
|
||||
// The elements of the matrix are stored as column major order.
|
||||
// | 0 2 | | 0 3 6 | | 0 4 8 12 |
|
||||
// | 1 3 | | 1 4 7 | | 1 5 9 13 |
|
||||
// | 2 5 8 | | 2 6 10 14 |
|
||||
// | 3 7 11 15 |
|
||||
//
|
||||
// AUTHOR: Song Ho Ahn (song.ahn@gmail.com)
|
||||
// CREATED: 2005-06-24
|
||||
// UPDATED: 2014-09-21
|
||||
//
|
||||
// Copyright (C) 2005 Song Ho Ahn
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "Matrices.h"
|
||||
|
||||
const float DEG2RAD = 3.141593f / 180;
|
||||
const float EPSILON = 0.00001f;
|
||||
|
||||
bool closeEnough(const float& a, const float& b, const float& epsilon = std::numeric_limits<float>::epsilon()) {
|
||||
return (epsilon > std::abs(a - b));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// transpose 2x2 matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix2& Matrix2::transpose()
|
||||
{
|
||||
std::swap(m[1], m[2]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// return the determinant of 2x2 matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
float Matrix2::getDeterminant()
|
||||
{
|
||||
return m[0] * m[3] - m[1] * m[2];
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// inverse of 2x2 matrix
|
||||
// If cannot find inverse, set identity matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix2& Matrix2::invert()
|
||||
{
|
||||
float determinant = getDeterminant();
|
||||
if(fabs(determinant) <= EPSILON)
|
||||
{
|
||||
return identity();
|
||||
}
|
||||
|
||||
float tmp = m[0]; // copy the first element
|
||||
float invDeterminant = 1.0f / determinant;
|
||||
m[0] = invDeterminant * m[3];
|
||||
m[1] = -invDeterminant * m[1];
|
||||
m[2] = -invDeterminant * m[2];
|
||||
m[3] = invDeterminant * tmp;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// transpose 3x3 matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix3& Matrix3::transpose()
|
||||
{
|
||||
std::swap(m[1], m[3]);
|
||||
std::swap(m[2], m[6]);
|
||||
std::swap(m[5], m[7]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// return determinant of 3x3 matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
float Matrix3::getDeterminant()
|
||||
{
|
||||
return m[0] * (m[4] * m[8] - m[5] * m[7]) -
|
||||
m[1] * (m[3] * m[8] - m[5] * m[6]) +
|
||||
m[2] * (m[3] * m[7] - m[4] * m[6]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// inverse 3x3 matrix
|
||||
// If cannot find inverse, set identity matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix3& Matrix3::invert()
|
||||
{
|
||||
float determinant, invDeterminant;
|
||||
float tmp[9];
|
||||
|
||||
tmp[0] = m[4] * m[8] - m[5] * m[7];
|
||||
tmp[1] = m[2] * m[7] - m[1] * m[8];
|
||||
tmp[2] = m[1] * m[5] - m[2] * m[4];
|
||||
tmp[3] = m[5] * m[6] - m[3] * m[8];
|
||||
tmp[4] = m[0] * m[8] - m[2] * m[6];
|
||||
tmp[5] = m[2] * m[3] - m[0] * m[5];
|
||||
tmp[6] = m[3] * m[7] - m[4] * m[6];
|
||||
tmp[7] = m[1] * m[6] - m[0] * m[7];
|
||||
tmp[8] = m[0] * m[4] - m[1] * m[3];
|
||||
|
||||
// check determinant if it is 0
|
||||
determinant = m[0] * tmp[0] + m[1] * tmp[3] + m[2] * tmp[6];
|
||||
if(fabs(determinant) <= EPSILON)
|
||||
{
|
||||
return identity(); // cannot inverse, make it idenety matrix
|
||||
}
|
||||
|
||||
// divide by the determinant
|
||||
invDeterminant = 1.0f / determinant;
|
||||
m[0] = invDeterminant * tmp[0];
|
||||
m[1] = invDeterminant * tmp[1];
|
||||
m[2] = invDeterminant * tmp[2];
|
||||
m[3] = invDeterminant * tmp[3];
|
||||
m[4] = invDeterminant * tmp[4];
|
||||
m[5] = invDeterminant * tmp[5];
|
||||
m[6] = invDeterminant * tmp[6];
|
||||
m[7] = invDeterminant * tmp[7];
|
||||
m[8] = invDeterminant * tmp[8];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#define RAD2DEG 57.2957795f
|
||||
|
||||
const Vector3 Matrix4::eulerAngles() {
|
||||
|
||||
//check for gimbal lock
|
||||
if (closeEnough(m[0+2*4], -1.0f)) {
|
||||
float x = 0; //gimbal lock, value of x doesn't matter
|
||||
float y = M_PI / 2;
|
||||
float z = x + atan2(m[1+0*4], m[2+0*4]);
|
||||
return { -x*RAD2DEG, -y*RAD2DEG, -z*RAD2DEG };
|
||||
} else if (closeEnough(m[0+2*4], 1.0f)) {
|
||||
float x = 0;
|
||||
float y = -M_PI / 2;
|
||||
float z = -x + atan2(-m[1+0*4], -m[2+0*4]);
|
||||
return { -x*RAD2DEG, -y*RAD2DEG, -z*RAD2DEG };
|
||||
} else { //two solutions exist
|
||||
float x1 = -asin(m[0+2*4]);
|
||||
float x2 = M_PI - x1;
|
||||
|
||||
float y1 = atan2(m[1+2*4] / cos(x1), m[2+2*4] / cos(x1));
|
||||
float y2 = atan2(m[1+2*4] / cos(x2), m[2+2*4] / cos(x2));
|
||||
|
||||
float z1 = atan2(m[0+1*4] / cos(x1), m[0+0*4] / cos(x1));
|
||||
float z2 = atan2(m[0+1*4] / cos(x2), m[0+0*4] / cos(x2));
|
||||
|
||||
//choose one solution to return
|
||||
//for example the "shortest" rotation
|
||||
if ((std::abs(x1) + std::abs(y1) + std::abs(z1)) <= (std::abs(x2) + std::abs(y2) + std::abs(z2))) {
|
||||
return { -x1*RAD2DEG, -y1*RAD2DEG, -z1*RAD2DEG };
|
||||
} else {
|
||||
return { -x2*RAD2DEG, -y2*RAD2DEG, -z2*RAD2DEG };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// transpose 4x4 matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4& Matrix4::transpose()
|
||||
{
|
||||
std::swap(m[1], m[4]);
|
||||
std::swap(m[2], m[8]);
|
||||
std::swap(m[3], m[12]);
|
||||
std::swap(m[6], m[9]);
|
||||
std::swap(m[7], m[13]);
|
||||
std::swap(m[11], m[14]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// inverse 4x4 matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4& Matrix4::invert()
|
||||
{
|
||||
// If the 4th row is [0,0,0,1] then it is affine matrix and
|
||||
// it has no projective transformation.
|
||||
if(m[3] == 0 && m[7] == 0 && m[11] == 0 && m[15] == 1)
|
||||
this->invertAffine();
|
||||
else
|
||||
{
|
||||
this->invertGeneral();
|
||||
/*@@ invertProjective() is not optimized (slower than generic one)
|
||||
if(fabs(m[0]*m[5] - m[1]*m[4]) > EPSILON)
|
||||
this->invertProjective(); // inverse using matrix partition
|
||||
else
|
||||
this->invertGeneral(); // generalized inverse
|
||||
*/
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// compute the inverse of 4x4 Euclidean transformation matrix
|
||||
//
|
||||
// Euclidean transformation is translation, rotation, and reflection.
|
||||
// With Euclidean transform, only the position and orientation of the object
|
||||
// will be changed. Euclidean transform does not change the shape of an object
|
||||
// (no scaling). Length and angle are reserved.
|
||||
//
|
||||
// Use inverseAffine() if the matrix has scale and shear transformation.
|
||||
//
|
||||
// M = [ R | T ]
|
||||
// [ --+-- ] (R denotes 3x3 rotation/reflection matrix)
|
||||
// [ 0 | 1 ] (T denotes 1x3 translation matrix)
|
||||
//
|
||||
// y = M*x -> y = R*x + T -> x = R^-1*(y - T) -> x = R^T*y - R^T*T
|
||||
// (R is orthogonal, R^-1 = R^T)
|
||||
//
|
||||
// [ R | T ]-1 [ R^T | -R^T * T ] (R denotes 3x3 rotation matrix)
|
||||
// [ --+-- ] = [ ----+--------- ] (T denotes 1x3 translation)
|
||||
// [ 0 | 1 ] [ 0 | 1 ] (R^T denotes R-transpose)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4& Matrix4::invertEuclidean()
|
||||
{
|
||||
// transpose 3x3 rotation matrix part
|
||||
// | R^T | 0 |
|
||||
// | ----+-- |
|
||||
// | 0 | 1 |
|
||||
float tmp;
|
||||
tmp = m[1]; m[1] = m[4]; m[4] = tmp;
|
||||
tmp = m[2]; m[2] = m[8]; m[8] = tmp;
|
||||
tmp = m[6]; m[6] = m[9]; m[9] = tmp;
|
||||
|
||||
// compute translation part -R^T * T
|
||||
// | 0 | -R^T x |
|
||||
// | --+------- |
|
||||
// | 0 | 0 |
|
||||
float x = m[12];
|
||||
float y = m[13];
|
||||
float z = m[14];
|
||||
m[12] = -(m[0] * x + m[4] * y + m[8] * z);
|
||||
m[13] = -(m[1] * x + m[5] * y + m[9] * z);
|
||||
m[14] = -(m[2] * x + m[6] * y + m[10]* z);
|
||||
|
||||
// last row should be unchanged (0,0,0,1)
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// compute the inverse of a 4x4 affine transformation matrix
|
||||
//
|
||||
// Affine transformations are generalizations of Euclidean transformations.
|
||||
// Affine transformation includes translation, rotation, reflection, scaling,
|
||||
// and shearing. Length and angle are NOT preserved.
|
||||
// M = [ R | T ]
|
||||
// [ --+-- ] (R denotes 3x3 rotation/scale/shear matrix)
|
||||
// [ 0 | 1 ] (T denotes 1x3 translation matrix)
|
||||
//
|
||||
// y = M*x -> y = R*x + T -> x = R^-1*(y - T) -> x = R^-1*y - R^-1*T
|
||||
//
|
||||
// [ R | T ]-1 [ R^-1 | -R^-1 * T ]
|
||||
// [ --+-- ] = [ -----+---------- ]
|
||||
// [ 0 | 1 ] [ 0 + 1 ]
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4& Matrix4::invertAffine()
|
||||
{
|
||||
// R^-1
|
||||
Matrix3 r(m[0],m[1],m[2], m[4],m[5],m[6], m[8],m[9],m[10]);
|
||||
r.invert();
|
||||
m[0] = r[0]; m[1] = r[1]; m[2] = r[2];
|
||||
m[4] = r[3]; m[5] = r[4]; m[6] = r[5];
|
||||
m[8] = r[6]; m[9] = r[7]; m[10]= r[8];
|
||||
|
||||
// -R^-1 * T
|
||||
float x = m[12];
|
||||
float y = m[13];
|
||||
float z = m[14];
|
||||
m[12] = -(r[0] * x + r[3] * y + r[6] * z);
|
||||
m[13] = -(r[1] * x + r[4] * y + r[7] * z);
|
||||
m[14] = -(r[2] * x + r[5] * y + r[8] * z);
|
||||
|
||||
// last row should be unchanged (0,0,0,1)
|
||||
//m[3] = m[7] = m[11] = 0.0f;
|
||||
//m[15] = 1.0f;
|
||||
|
||||
return * this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// inverse matrix using matrix partitioning (blockwise inverse)
|
||||
// It devides a 4x4 matrix into 4 of 2x2 matrices. It works in case of where
|
||||
// det(A) != 0. If not, use the generic inverse method
|
||||
// inverse formula.
|
||||
// M = [ A | B ] A, B, C, D are 2x2 matrix blocks
|
||||
// [ --+-- ] det(M) = |A| * |D - ((C * A^-1) * B)|
|
||||
// [ C | D ]
|
||||
//
|
||||
// M^-1 = [ A' | B' ] A' = A^-1 - (A^-1 * B) * C'
|
||||
// [ ---+--- ] B' = (A^-1 * B) * -D'
|
||||
// [ C' | D' ] C' = -D' * (C * A^-1)
|
||||
// D' = (D - ((C * A^-1) * B))^-1
|
||||
//
|
||||
// NOTE: I wrap with () if it it used more than once.
|
||||
// The matrix is invertable even if det(A)=0, so must check det(A) before
|
||||
// calling this function, and use invertGeneric() instead.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4& Matrix4::invertProjective()
|
||||
{
|
||||
// partition
|
||||
Matrix2 a(m[0], m[1], m[4], m[5]);
|
||||
Matrix2 b(m[8], m[9], m[12], m[13]);
|
||||
Matrix2 c(m[2], m[3], m[6], m[7]);
|
||||
Matrix2 d(m[10], m[11], m[14], m[15]);
|
||||
|
||||
// pre-compute repeated parts
|
||||
a.invert(); // A^-1
|
||||
Matrix2 ab = a * b; // A^-1 * B
|
||||
Matrix2 ca = c * a; // C * A^-1
|
||||
Matrix2 cab = ca * b; // C * A^-1 * B
|
||||
Matrix2 dcab = d - cab; // D - C * A^-1 * B
|
||||
|
||||
// check determinant if |D - C * A^-1 * B| = 0
|
||||
//NOTE: this function assumes det(A) is already checked. if |A|=0 then,
|
||||
// cannot use this function.
|
||||
float determinant = dcab[0] * dcab[3] - dcab[1] * dcab[2];
|
||||
if(fabs(determinant) <= EPSILON)
|
||||
{
|
||||
return identity();
|
||||
}
|
||||
|
||||
// compute D' and -D'
|
||||
Matrix2 d1 = dcab; // (D - C * A^-1 * B)
|
||||
d1.invert(); // (D - C * A^-1 * B)^-1
|
||||
Matrix2 d2 = -d1; // -(D - C * A^-1 * B)^-1
|
||||
|
||||
// compute C'
|
||||
Matrix2 c1 = d2 * ca; // -D' * (C * A^-1)
|
||||
|
||||
// compute B'
|
||||
Matrix2 b1 = ab * d2; // (A^-1 * B) * -D'
|
||||
|
||||
// compute A'
|
||||
Matrix2 a1 = a - (ab * c1); // A^-1 - (A^-1 * B) * C'
|
||||
|
||||
// assemble inverse matrix
|
||||
m[0] = a1[0]; m[4] = a1[2]; /*|*/ m[8] = b1[0]; m[12]= b1[2];
|
||||
m[1] = a1[1]; m[5] = a1[3]; /*|*/ m[9] = b1[1]; m[13]= b1[3];
|
||||
/*-----------------------------+-----------------------------*/
|
||||
m[2] = c1[0]; m[6] = c1[2]; /*|*/ m[10]= d1[0]; m[14]= d1[2];
|
||||
m[3] = c1[1]; m[7] = c1[3]; /*|*/ m[11]= d1[1]; m[15]= d1[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// compute the inverse of a general 4x4 matrix using Cramer's Rule
|
||||
// If cannot find inverse, return indentity matrix
|
||||
// M^-1 = adj(M) / det(M)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4& Matrix4::invertGeneral()
|
||||
{
|
||||
// get cofactors of minor matrices
|
||||
float cofactor0 = getCofactor(m[5],m[6],m[7], m[9],m[10],m[11], m[13],m[14],m[15]);
|
||||
float cofactor1 = getCofactor(m[4],m[6],m[7], m[8],m[10],m[11], m[12],m[14],m[15]);
|
||||
float cofactor2 = getCofactor(m[4],m[5],m[7], m[8],m[9], m[11], m[12],m[13],m[15]);
|
||||
float cofactor3 = getCofactor(m[4],m[5],m[6], m[8],m[9], m[10], m[12],m[13],m[14]);
|
||||
|
||||
// get determinant
|
||||
float determinant = m[0] * cofactor0 - m[1] * cofactor1 + m[2] * cofactor2 - m[3] * cofactor3;
|
||||
if(fabs(determinant) <= EPSILON)
|
||||
{
|
||||
return identity();
|
||||
}
|
||||
|
||||
// get rest of cofactors for adj(M)
|
||||
float cofactor4 = getCofactor(m[1],m[2],m[3], m[9],m[10],m[11], m[13],m[14],m[15]);
|
||||
float cofactor5 = getCofactor(m[0],m[2],m[3], m[8],m[10],m[11], m[12],m[14],m[15]);
|
||||
float cofactor6 = getCofactor(m[0],m[1],m[3], m[8],m[9], m[11], m[12],m[13],m[15]);
|
||||
float cofactor7 = getCofactor(m[0],m[1],m[2], m[8],m[9], m[10], m[12],m[13],m[14]);
|
||||
|
||||
float cofactor8 = getCofactor(m[1],m[2],m[3], m[5],m[6], m[7], m[13],m[14],m[15]);
|
||||
float cofactor9 = getCofactor(m[0],m[2],m[3], m[4],m[6], m[7], m[12],m[14],m[15]);
|
||||
float cofactor10= getCofactor(m[0],m[1],m[3], m[4],m[5], m[7], m[12],m[13],m[15]);
|
||||
float cofactor11= getCofactor(m[0],m[1],m[2], m[4],m[5], m[6], m[12],m[13],m[14]);
|
||||
|
||||
float cofactor12= getCofactor(m[1],m[2],m[3], m[5],m[6], m[7], m[9], m[10],m[11]);
|
||||
float cofactor13= getCofactor(m[0],m[2],m[3], m[4],m[6], m[7], m[8], m[10],m[11]);
|
||||
float cofactor14= getCofactor(m[0],m[1],m[3], m[4],m[5], m[7], m[8], m[9], m[11]);
|
||||
float cofactor15= getCofactor(m[0],m[1],m[2], m[4],m[5], m[6], m[8], m[9], m[10]);
|
||||
|
||||
// build inverse matrix = adj(M) / det(M)
|
||||
// adjugate of M is the transpose of the cofactor matrix of M
|
||||
float invDeterminant = 1.0f / determinant;
|
||||
m[0] = invDeterminant * cofactor0;
|
||||
m[1] = -invDeterminant * cofactor4;
|
||||
m[2] = invDeterminant * cofactor8;
|
||||
m[3] = -invDeterminant * cofactor12;
|
||||
|
||||
m[4] = -invDeterminant * cofactor1;
|
||||
m[5] = invDeterminant * cofactor5;
|
||||
m[6] = -invDeterminant * cofactor9;
|
||||
m[7] = invDeterminant * cofactor13;
|
||||
|
||||
m[8] = invDeterminant * cofactor2;
|
||||
m[9] = -invDeterminant * cofactor6;
|
||||
m[10]= invDeterminant * cofactor10;
|
||||
m[11]= -invDeterminant * cofactor14;
|
||||
|
||||
m[12]= -invDeterminant * cofactor3;
|
||||
m[13]= invDeterminant * cofactor7;
|
||||
m[14]= -invDeterminant * cofactor11;
|
||||
m[15]= invDeterminant * cofactor15;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// return determinant of 4x4 matrix
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
float Matrix4::getDeterminant()
|
||||
{
|
||||
return m[0] * getCofactor(m[5],m[6],m[7], m[9],m[10],m[11], m[13],m[14],m[15]) -
|
||||
m[1] * getCofactor(m[4],m[6],m[7], m[8],m[10],m[11], m[12],m[14],m[15]) +
|
||||
m[2] * getCofactor(m[4],m[5],m[7], m[8],m[9], m[11], m[12],m[13],m[15]) -
|
||||
m[3] * getCofactor(m[4],m[5],m[6], m[8],m[9], m[10], m[12],m[13],m[14]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// compute cofactor of 3x3 minor matrix without sign
|
||||
// input params are 9 elements of the minor matrix
|
||||
// NOTE: The caller must know its sign.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
float Matrix4::getCofactor(float m0, float m1, float m2,
|
||||
float m3, float m4, float m5,
|
||||
float m6, float m7, float m8)
|
||||
{
|
||||
return m0 * (m4 * m8 - m5 * m7) -
|
||||
m1 * (m3 * m8 - m5 * m6) +
|
||||
m2 * (m3 * m7 - m4 * m6);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// translate this matrix by (x, y, z)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4& Matrix4::translate(const Vector3& v)
|
||||
{
|
||||
return translate(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
Matrix4& Matrix4::translate(float x, float y, float z)
|
||||
{
|
||||
m[0] += m[3] * x; m[4] += m[7] * x; m[8] += m[11]* x; m[12]+= m[15]* x;
|
||||
m[1] += m[3] * y; m[5] += m[7] * y; m[9] += m[11]* y; m[13]+= m[15]* y;
|
||||
m[2] += m[3] * z; m[6] += m[7] * z; m[10]+= m[11]* z; m[14]+= m[15]* z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// uniform scale
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4& Matrix4::scale(float s)
|
||||
{
|
||||
return scale(s, s, s);
|
||||
}
|
||||
|
||||
Matrix4& Matrix4::scale(float x, float y, float z)
|
||||
{
|
||||
m[0] *= x; m[4] *= x; m[8] *= x; m[12] *= x;
|
||||
m[1] *= y; m[5] *= y; m[9] *= y; m[13] *= y;
|
||||
m[2] *= z; m[6] *= z; m[10]*= z; m[14] *= z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// build a rotation matrix with given angle(degree) and rotation axis, then
|
||||
// multiply it with this object
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4& Matrix4::rotate(float angle, const Vector3& axis)
|
||||
{
|
||||
return rotate(angle, axis.x, axis.y, axis.z);
|
||||
}
|
||||
|
||||
Matrix4& Matrix4::rotate(float angle, float x, float y, float z)
|
||||
{
|
||||
float c = cosf(angle * DEG2RAD); // cosine
|
||||
float s = sinf(angle * DEG2RAD); // sine
|
||||
float c1 = 1.0f - c; // 1 - c
|
||||
float m0 = m[0], m4 = m[4], m8 = m[8], m12= m[12],
|
||||
m1 = m[1], m5 = m[5], m9 = m[9], m13= m[13],
|
||||
m2 = m[2], m6 = m[6], m10= m[10], m14= m[14];
|
||||
|
||||
// build rotation matrix
|
||||
float r0 = x * x * c1 + c;
|
||||
float r1 = x * y * c1 + z * s;
|
||||
float r2 = x * z * c1 - y * s;
|
||||
float r4 = x * y * c1 - z * s;
|
||||
float r5 = y * y * c1 + c;
|
||||
float r6 = y * z * c1 + x * s;
|
||||
float r8 = x * z * c1 + y * s;
|
||||
float r9 = y * z * c1 - x * s;
|
||||
float r10= z * z * c1 + c;
|
||||
|
||||
// multiply rotation matrix
|
||||
m[0] = r0 * m0 + r4 * m1 + r8 * m2;
|
||||
m[1] = r1 * m0 + r5 * m1 + r9 * m2;
|
||||
m[2] = r2 * m0 + r6 * m1 + r10* m2;
|
||||
m[4] = r0 * m4 + r4 * m5 + r8 * m6;
|
||||
m[5] = r1 * m4 + r5 * m5 + r9 * m6;
|
||||
m[6] = r2 * m4 + r6 * m5 + r10* m6;
|
||||
m[8] = r0 * m8 + r4 * m9 + r8 * m10;
|
||||
m[9] = r1 * m8 + r5 * m9 + r9 * m10;
|
||||
m[10]= r2 * m8 + r6 * m9 + r10* m10;
|
||||
m[12]= r0 * m12+ r4 * m13+ r8 * m14;
|
||||
m[13]= r1 * m12+ r5 * m13+ r9 * m14;
|
||||
m[14]= r2 * m12+ r6 * m13+ r10* m14;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matrix4& Matrix4::rotateX(float angle)
|
||||
{
|
||||
float c = cosf(angle * DEG2RAD);
|
||||
float s = sinf(angle * DEG2RAD);
|
||||
float m1 = m[1], m2 = m[2],
|
||||
m5 = m[5], m6 = m[6],
|
||||
m9 = m[9], m10= m[10],
|
||||
m13= m[13], m14= m[14];
|
||||
|
||||
m[1] = m1 * c + m2 *-s;
|
||||
m[2] = m1 * s + m2 * c;
|
||||
m[5] = m5 * c + m6 *-s;
|
||||
m[6] = m5 * s + m6 * c;
|
||||
m[9] = m9 * c + m10*-s;
|
||||
m[10]= m9 * s + m10* c;
|
||||
m[13]= m13* c + m14*-s;
|
||||
m[14]= m13* s + m14* c;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matrix4& Matrix4::rotateY(float angle)
|
||||
{
|
||||
float c = cosf(angle * DEG2RAD);
|
||||
float s = sinf(angle * DEG2RAD);
|
||||
float m0 = m[0], m2 = m[2],
|
||||
m4 = m[4], m6 = m[6],
|
||||
m8 = m[8], m10= m[10],
|
||||
m12= m[12], m14= m[14];
|
||||
|
||||
m[0] = m0 * c + m2 * s;
|
||||
m[2] = m0 *-s + m2 * c;
|
||||
m[4] = m4 * c + m6 * s;
|
||||
m[6] = m4 *-s + m6 * c;
|
||||
m[8] = m8 * c + m10* s;
|
||||
m[10]= m8 *-s + m10* c;
|
||||
m[12]= m12* c + m14* s;
|
||||
m[14]= m12*-s + m14* c;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matrix4& Matrix4::rotateZ(float angle)
|
||||
{
|
||||
float c = cosf(angle * DEG2RAD);
|
||||
float s = sinf(angle * DEG2RAD);
|
||||
float m0 = m[0], m1 = m[1],
|
||||
m4 = m[4], m5 = m[5],
|
||||
m8 = m[8], m9 = m[9],
|
||||
m12= m[12], m13= m[13];
|
||||
|
||||
m[0] = m0 * c + m1 *-s;
|
||||
m[1] = m0 * s + m1 * c;
|
||||
m[4] = m4 * c + m5 *-s;
|
||||
m[5] = m4 * s + m5 * c;
|
||||
m[8] = m8 * c + m9 *-s;
|
||||
m[9] = m8 * s + m9 * c;
|
||||
m[12]= m12* c + m13*-s;
|
||||
m[13]= m12* s + m13* c;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// glFrustum()
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4 setFrustum(float l, float r, float b, float t, float n, float f)
|
||||
{
|
||||
Matrix4 mat;
|
||||
mat[0] = 2 * n / (r - l);
|
||||
mat[5] = 2 * n / (t - b);
|
||||
mat[8] = (r + l) / (r - l);
|
||||
mat[9] = (t + b) / (t - b);
|
||||
mat[10] = -(f + n) / (f - n);
|
||||
mat[11] = -1;
|
||||
mat[14] = -(2 * f * n) / (f - n);
|
||||
mat[15] = 0;
|
||||
return mat;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// gluPerspective()
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4 setFrustum(float fovY, float aspect, float front, float back)
|
||||
{
|
||||
float tangent = tanf(fovY/2 * DEG2RAD); // tangent of half fovY
|
||||
float height = front * tangent; // half height of near plane
|
||||
float width = height * aspect; // half width of near plane
|
||||
|
||||
// params: left, right, bottom, top, near, far
|
||||
return setFrustum(-width, width, -height, height, front, back);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// glOrtho()
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
Matrix4 setOrthoFrustum(float l, float r, float b, float t, float n, float f)
|
||||
{
|
||||
Matrix4 mat;
|
||||
mat[0] = 2 / (r - l);
|
||||
mat[5] = 2 / (t - b);
|
||||
mat[10] = -2 / (f - n);
|
||||
mat[12] = -(r + l) / (r - l);
|
||||
mat[13] = -(t + b) / (t - b);
|
||||
mat[14] = -(f + n) / (f - n);
|
||||
return mat;
|
||||
}
|
||||
|
||||
Matrix4 lookAt(const Vector3& eye, const Vector3& center, const Vector3& up)
|
||||
{
|
||||
/*
|
||||
Matrix4 mat;
|
||||
Vector3 forward = (center - eye);
|
||||
forward.normalize();
|
||||
Vector3 side = (up.cross(forward));
|
||||
side.normalize();
|
||||
|
||||
// Recompute up as: up = side x forward
|
||||
const Vector3 up2 = forward.cross(side);
|
||||
|
||||
mat.identity();
|
||||
mat[0] = side.x;
|
||||
mat[4] = side.y;
|
||||
mat[8] = side.z;
|
||||
|
||||
mat[1] = up2.x;
|
||||
mat[5] = up2.y;
|
||||
mat[9] = up2.z;
|
||||
|
||||
mat[2] = forward.x;
|
||||
mat[6] = forward.y;
|
||||
mat[10] = forward.z;
|
||||
|
||||
//mat[3] = -side.dot(eye);
|
||||
//mat[7] = -up2.dot(eye);
|
||||
//mat[11] = forward.dot(eye);
|
||||
//mat[15] = 1.0f;
|
||||
Matrix4 trans;
|
||||
trans.identity();
|
||||
trans.translate(-eye.x, -eye.y, eye.z);
|
||||
mat = mat * trans;
|
||||
*/
|
||||
|
||||
float m[16];
|
||||
float x[3], y[3], z[3];
|
||||
float mag;
|
||||
|
||||
// Make rotation matrix
|
||||
|
||||
// Z vector
|
||||
z[0] = eye.x - center.x;
|
||||
z[1] = eye.y - center.y;
|
||||
z[2] = eye.z - center.z;
|
||||
mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
|
||||
if (mag) { // mpichler, 19950515
|
||||
z[0] /= mag;
|
||||
z[1] /= mag;
|
||||
z[2] /= mag;
|
||||
}
|
||||
|
||||
// Y vector
|
||||
y[0] = up.x;
|
||||
y[1] = up.y;
|
||||
y[2] = up.z;
|
||||
|
||||
// X vector = Y cross Z
|
||||
x[0] = y[1] * z[2] - y[2] * z[1];
|
||||
x[1] = -y[0] * z[2] + y[2] * z[0];
|
||||
x[2] = y[0] * z[1] - y[1] * z[0];
|
||||
|
||||
// Recompute Y = Z cross X
|
||||
y[0] = z[1] * x[2] - z[2] * x[1];
|
||||
y[1] = -z[0] * x[2] + z[2] * x[0];
|
||||
y[2] = z[0] * x[1] - z[1] * x[0];
|
||||
|
||||
// mpichler, 19950515
|
||||
// cross product gives area of parallelogram, which is < 1.0 for
|
||||
//non-perpendicular unit-length vectors; so normalize x, y here
|
||||
|
||||
mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
|
||||
if (mag) {
|
||||
x[0] /= mag;
|
||||
x[1] /= mag;
|
||||
x[2] /= mag;
|
||||
}
|
||||
|
||||
mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
|
||||
if (mag) {
|
||||
y[0] /= mag;
|
||||
y[1] /= mag;
|
||||
y[2] /= mag;
|
||||
}
|
||||
|
||||
#define M(row,col) m[col*4+row]
|
||||
M(0, 0) = x[0];
|
||||
M(0, 1) = x[1];
|
||||
M(0, 2) = x[2];
|
||||
M(0, 3) = 0.0;
|
||||
M(1, 0) = y[0];
|
||||
M(1, 1) = y[1];
|
||||
M(1, 2) = y[2];
|
||||
M(1, 3) = 0.0;
|
||||
M(2, 0) = z[0];
|
||||
M(2, 1) = z[1];
|
||||
M(2, 2) = z[2];
|
||||
M(2, 3) = 0.0;
|
||||
M(3, 0) = 0.0;
|
||||
M(3, 1) = 0.0;
|
||||
M(3, 2) = 0.0;
|
||||
M(3, 3) = 1.0;
|
||||
#undef M
|
||||
|
||||
Matrix4 mat(m);
|
||||
|
||||
// Translate Eye to Origin
|
||||
Matrix4 trans;
|
||||
trans.identity();
|
||||
trans.translate(-eye.x, -eye.y, -eye.z);
|
||||
mat = mat * trans;
|
||||
|
||||
return mat;
|
||||
}
|
||||
914
Matrices.h
Executable file
914
Matrices.h
Executable file
@@ -0,0 +1,914 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Matrice.h
|
||||
// =========
|
||||
// NxN Matrix Math classes
|
||||
//
|
||||
// The elements of the matrix are stored as column major order.
|
||||
// | 0 2 | | 0 3 6 | | 0 4 8 12 |
|
||||
// | 1 3 | | 1 4 7 | | 1 5 9 13 |
|
||||
// | 2 5 8 | | 2 6 10 14 |
|
||||
// | 3 7 11 15 |
|
||||
//
|
||||
// AUTHOR: Song Ho Ahn (song.ahn@gmail.com)
|
||||
// CREATED: 2005-06-24
|
||||
// UPDATED: 2013-09-30
|
||||
//
|
||||
// Copyright (C) 2005 Song Ho Ahn
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MATH_MATRICES_H
|
||||
#define MATH_MATRICES_H
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "Vectors.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 2x2 matrix
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
class Matrix2
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
Matrix2(); // init with identity
|
||||
Matrix2(const float src[4]);
|
||||
Matrix2(float m0, float m1, float m2, float m3);
|
||||
|
||||
void set(const float src[4]);
|
||||
void set(float m0, float m1, float m2, float m3);
|
||||
void setRow(int index, const float row[2]);
|
||||
void setRow(int index, const Vector2& v);
|
||||
void setColumn(int index, const float col[2]);
|
||||
void setColumn(int index, const Vector2& v);
|
||||
|
||||
const float* get() const;
|
||||
float getDeterminant();
|
||||
|
||||
Matrix2& identity();
|
||||
Matrix2& transpose(); // transpose itself and return reference
|
||||
Matrix2& invert();
|
||||
|
||||
// operators
|
||||
Matrix2 operator+(const Matrix2& rhs) const; // add rhs
|
||||
Matrix2 operator-(const Matrix2& rhs) const; // subtract rhs
|
||||
Matrix2& operator+=(const Matrix2& rhs); // add rhs and update this object
|
||||
Matrix2& operator-=(const Matrix2& rhs); // subtract rhs and update this object
|
||||
Vector2 operator*(const Vector2& rhs) const; // multiplication: v' = M * v
|
||||
Matrix2 operator*(const Matrix2& rhs) const; // multiplication: M3 = M1 * M2
|
||||
Matrix2& operator*=(const Matrix2& rhs); // multiplication: M1' = M1 * M2
|
||||
bool operator==(const Matrix2& rhs) const; // exact compare, no epsilon
|
||||
bool operator!=(const Matrix2& rhs) const; // exact compare, no epsilon
|
||||
float operator[](int index) const; // subscript operator v[0], v[1]
|
||||
float& operator[](int index); // subscript operator v[0], v[1]
|
||||
|
||||
friend Matrix2 operator-(const Matrix2& m); // unary operator (-)
|
||||
friend Matrix2 operator*(float scalar, const Matrix2& m); // pre-multiplication
|
||||
friend Vector2 operator*(const Vector2& vec, const Matrix2& m); // pre-multiplication
|
||||
friend std::ostream& operator<<(std::ostream& os, const Matrix2& m);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
float m[4];
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 3x3 matrix
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
class Matrix3
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
Matrix3(); // init with identity
|
||||
Matrix3(const float src[9]);
|
||||
Matrix3(float m0, float m1, float m2, // 1st column
|
||||
float m3, float m4, float m5, // 2nd column
|
||||
float m6, float m7, float m8); // 3rd column
|
||||
|
||||
void set(const float src[9]);
|
||||
void set(float m0, float m1, float m2, // 1st column
|
||||
float m3, float m4, float m5, // 2nd column
|
||||
float m6, float m7, float m8); // 3rd column
|
||||
void setRow(int index, const float row[3]);
|
||||
void setRow(int index, const Vector3& v);
|
||||
void setColumn(int index, const float col[3]);
|
||||
void setColumn(int index, const Vector3& v);
|
||||
|
||||
const float* get() const;
|
||||
float getDeterminant();
|
||||
|
||||
Matrix3& identity();
|
||||
Matrix3& transpose(); // transpose itself and return reference
|
||||
Matrix3& invert();
|
||||
|
||||
// operators
|
||||
Matrix3 operator+(const Matrix3& rhs) const; // add rhs
|
||||
Matrix3 operator-(const Matrix3& rhs) const; // subtract rhs
|
||||
Matrix3& operator+=(const Matrix3& rhs); // add rhs and update this object
|
||||
Matrix3& operator-=(const Matrix3& rhs); // subtract rhs and update this object
|
||||
Vector3 operator*(const Vector3& rhs) const; // multiplication: v' = M * v
|
||||
Matrix3 operator*(const Matrix3& rhs) const; // multiplication: M3 = M1 * M2
|
||||
Matrix3& operator*=(const Matrix3& rhs); // multiplication: M1' = M1 * M2
|
||||
bool operator==(const Matrix3& rhs) const; // exact compare, no epsilon
|
||||
bool operator!=(const Matrix3& rhs) const; // exact compare, no epsilon
|
||||
float operator[](int index) const; // subscript operator v[0], v[1]
|
||||
float& operator[](int index); // subscript operator v[0], v[1]
|
||||
|
||||
friend Matrix3 operator-(const Matrix3& m); // unary operator (-)
|
||||
friend Matrix3 operator*(float scalar, const Matrix3& m); // pre-multiplication
|
||||
friend Vector3 operator*(const Vector3& vec, const Matrix3& m); // pre-multiplication
|
||||
friend std::ostream& operator<<(std::ostream& os, const Matrix3& m);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
float m[9];
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 4x4 matrix
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
class Matrix4
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
Matrix4(); // init with identity
|
||||
Matrix4(const float src[16]);
|
||||
Matrix4(float m00, float m01, float m02, float m03, // 1st column
|
||||
float m04, float m05, float m06, float m07, // 2nd column
|
||||
float m08, float m09, float m10, float m11, // 3rd column
|
||||
float m12, float m13, float m14, float m15);// 4th column
|
||||
|
||||
void set(const float src[16]);
|
||||
void set(float m00, float m01, float m02, float m03, // 1st column
|
||||
float m04, float m05, float m06, float m07, // 2nd column
|
||||
float m08, float m09, float m10, float m11, // 3rd column
|
||||
float m12, float m13, float m14, float m15);// 4th column
|
||||
void setRow(int index, const float row[4]);
|
||||
void setRow(int index, const Vector4& v);
|
||||
void setRow(int index, const Vector3& v);
|
||||
void setColumn(int index, const float col[4]);
|
||||
void setColumn(int index, const Vector4& v);
|
||||
void setColumn(int index, const Vector3& v);
|
||||
|
||||
const float* get() const;
|
||||
const float* getTranspose(); // return transposed matrix
|
||||
float getDeterminant();
|
||||
|
||||
const Vector3 eulerAngles();
|
||||
Matrix4& identity();
|
||||
Matrix4& transpose(); // transpose itself and return reference
|
||||
Matrix4& invert(); // check best inverse method before inverse
|
||||
Matrix4& invertEuclidean(); // inverse of Euclidean transform matrix
|
||||
Matrix4& invertAffine(); // inverse of affine transform matrix
|
||||
Matrix4& invertProjective(); // inverse of projective matrix using partitioning
|
||||
Matrix4& invertGeneral(); // inverse of generic matrix
|
||||
|
||||
// transform matrix
|
||||
Matrix4& translate(float x, float y, float z); // translation by (x,y,z)
|
||||
Matrix4& translate(const Vector3& v); //
|
||||
Matrix4& rotate(float angle, const Vector3& axis); // rotate angle(degree) along the given axix
|
||||
Matrix4& rotate(float angle, float x, float y, float z);
|
||||
Matrix4& rotateX(float angle); // rotate on X-axis with degree
|
||||
Matrix4& rotateY(float angle); // rotate on Y-axis with degree
|
||||
Matrix4& rotateZ(float angle); // rotate on Z-axis with degree
|
||||
Matrix4& scale(float scale); // uniform scale
|
||||
Matrix4& scale(float sx, float sy, float sz); // scale by (sx, sy, sz) on each axis
|
||||
|
||||
// operators
|
||||
Matrix4 operator+(const Matrix4& rhs) const; // add rhs
|
||||
Matrix4 operator-(const Matrix4& rhs) const; // subtract rhs
|
||||
Matrix4& operator+=(const Matrix4& rhs); // add rhs and update this object
|
||||
Matrix4& operator-=(const Matrix4& rhs); // subtract rhs and update this object
|
||||
Vector4 operator*(const Vector4& rhs) const; // multiplication: v' = M * v
|
||||
Vector3 operator*(const Vector3& rhs) const; // multiplication: v' = M * v
|
||||
Matrix4 operator*(const Matrix4& rhs) const; // multiplication: M3 = M1 * M2
|
||||
Matrix4& operator*=(const Matrix4& rhs); // multiplication: M1' = M1 * M2
|
||||
bool operator==(const Matrix4& rhs) const; // exact compare, no epsilon
|
||||
bool operator!=(const Matrix4& rhs) const; // exact compare, no epsilon
|
||||
float operator[](int index) const; // subscript operator v[0], v[1]
|
||||
float& operator[](int index); // subscript operator v[0], v[1]
|
||||
|
||||
friend Matrix4 operator-(const Matrix4& m); // unary operator (-)
|
||||
friend Matrix4 operator*(float scalar, const Matrix4& m); // pre-multiplication
|
||||
friend Vector3 operator*(const Vector3& vec, const Matrix4& m); // pre-multiplication
|
||||
friend Vector4 operator*(const Vector4& vec, const Matrix4& m); // pre-multiplication
|
||||
friend std::ostream& operator<<(std::ostream& os, const Matrix4& m);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
float getCofactor(float m0, float m1, float m2,
|
||||
float m3, float m4, float m5,
|
||||
float m6, float m7, float m8);
|
||||
|
||||
float m[16];
|
||||
float tm[16]; // transpose m
|
||||
|
||||
};
|
||||
|
||||
Matrix4 setFrustum(float l, float r, float b, float t, float n, float f);
|
||||
Matrix4 setFrustum(float fovY, float aspect, float front, float back);
|
||||
Matrix4 setOrthoFrustum(float l, float r, float b, float t, float n, float f);
|
||||
Matrix4 lookAt(const Vector3& eye, const Vector3& center, const Vector3& up);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// inline functions for Matrix2
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
inline Matrix2::Matrix2()
|
||||
{
|
||||
// initially identity matrix
|
||||
identity();
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2::Matrix2(const float src[4])
|
||||
{
|
||||
set(src);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2::Matrix2(float m0, float m1, float m2, float m3)
|
||||
{
|
||||
set(m0, m1, m2, m3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix2::set(const float src[4])
|
||||
{
|
||||
m[0] = src[0]; m[1] = src[1]; m[2] = src[2]; m[3] = src[3];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix2::set(float m0, float m1, float m2, float m3)
|
||||
{
|
||||
m[0]= m0; m[1] = m1; m[2] = m2; m[3]= m3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix2::setRow(int index, const float row[2])
|
||||
{
|
||||
m[index] = row[0]; m[index + 2] = row[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix2::setRow(int index, const Vector2& v)
|
||||
{
|
||||
m[index] = v.x; m[index + 2] = v.y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix2::setColumn(int index, const float col[2])
|
||||
{
|
||||
m[index*2] = col[0]; m[index*2 + 1] = col[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix2::setColumn(int index, const Vector2& v)
|
||||
{
|
||||
m[index*2] = v.x; m[index*2 + 1] = v.y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline const float* Matrix2::get() const
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2& Matrix2::identity()
|
||||
{
|
||||
m[0] = m[3] = 1.0f;
|
||||
m[1] = m[2] = 0.0f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2 Matrix2::operator+(const Matrix2& rhs) const
|
||||
{
|
||||
return Matrix2(m[0]+rhs[0], m[1]+rhs[1], m[2]+rhs[2], m[3]+rhs[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2 Matrix2::operator-(const Matrix2& rhs) const
|
||||
{
|
||||
return Matrix2(m[0]-rhs[0], m[1]-rhs[1], m[2]-rhs[2], m[3]-rhs[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2& Matrix2::operator+=(const Matrix2& rhs)
|
||||
{
|
||||
m[0] += rhs[0]; m[1] += rhs[1]; m[2] += rhs[2]; m[3] += rhs[3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2& Matrix2::operator-=(const Matrix2& rhs)
|
||||
{
|
||||
m[0] -= rhs[0]; m[1] -= rhs[1]; m[2] -= rhs[2]; m[3] -= rhs[3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2 Matrix2::operator*(const Vector2& rhs) const
|
||||
{
|
||||
return Vector2(m[0]*rhs.x + m[2]*rhs.y, m[1]*rhs.x + m[3]*rhs.y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2 Matrix2::operator*(const Matrix2& rhs) const
|
||||
{
|
||||
return Matrix2(m[0]*rhs[0] + m[2]*rhs[1], m[1]*rhs[0] + m[3]*rhs[1],
|
||||
m[0]*rhs[2] + m[2]*rhs[3], m[1]*rhs[2] + m[3]*rhs[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2& Matrix2::operator*=(const Matrix2& rhs)
|
||||
{
|
||||
*this = *this * rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Matrix2::operator==(const Matrix2& rhs) const
|
||||
{
|
||||
return (m[0] == rhs[0]) && (m[1] == rhs[1]) && (m[2] == rhs[2]) && (m[3] == rhs[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Matrix2::operator!=(const Matrix2& rhs) const
|
||||
{
|
||||
return (m[0] != rhs[0]) || (m[1] != rhs[1]) || (m[2] != rhs[2]) || (m[3] != rhs[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline float Matrix2::operator[](int index) const
|
||||
{
|
||||
return m[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline float& Matrix2::operator[](int index)
|
||||
{
|
||||
return m[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2 operator-(const Matrix2& rhs)
|
||||
{
|
||||
return Matrix2(-rhs[0], -rhs[1], -rhs[2], -rhs[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix2 operator*(float s, const Matrix2& rhs)
|
||||
{
|
||||
return Matrix2(s*rhs[0], s*rhs[1], s*rhs[2], s*rhs[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector2 operator*(const Vector2& v, const Matrix2& rhs)
|
||||
{
|
||||
return Vector2(v.x*rhs[0] + v.y*rhs[1], v.x*rhs[2] + v.y*rhs[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Matrix2& m)
|
||||
{
|
||||
os << std::fixed << std::setprecision(5);
|
||||
os << "[" << std::setw(10) << m[0] << " " << std::setw(10) << m[2] << "]\n"
|
||||
<< "[" << std::setw(10) << m[1] << " " << std::setw(10) << m[3] << "]\n";
|
||||
os << std::resetiosflags(std::ios_base::fixed | std::ios_base::floatfield);
|
||||
return os;
|
||||
}
|
||||
// END OF MATRIX2 INLINE //////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// inline functions for Matrix3
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
inline Matrix3::Matrix3()
|
||||
{
|
||||
// initially identity matrix
|
||||
identity();
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3::Matrix3(const float src[9])
|
||||
{
|
||||
set(src);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3::Matrix3(float m0, float m1, float m2,
|
||||
float m3, float m4, float m5,
|
||||
float m6, float m7, float m8)
|
||||
{
|
||||
set(m0, m1, m2, m3, m4, m5, m6, m7, m8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix3::set(const float src[9])
|
||||
{
|
||||
m[0] = src[0]; m[1] = src[1]; m[2] = src[2];
|
||||
m[3] = src[3]; m[4] = src[4]; m[5] = src[5];
|
||||
m[6] = src[6]; m[7] = src[7]; m[8] = src[8];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix3::set(float m0, float m1, float m2,
|
||||
float m3, float m4, float m5,
|
||||
float m6, float m7, float m8)
|
||||
{
|
||||
m[0] = m0; m[1] = m1; m[2] = m2;
|
||||
m[3] = m3; m[4] = m4; m[5] = m5;
|
||||
m[6] = m6; m[7] = m7; m[8] = m8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix3::setRow(int index, const float row[3])
|
||||
{
|
||||
m[index] = row[0]; m[index + 3] = row[1]; m[index + 6] = row[2];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix3::setRow(int index, const Vector3& v)
|
||||
{
|
||||
m[index] = v.x; m[index + 3] = v.y; m[index + 6] = v.z;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix3::setColumn(int index, const float col[3])
|
||||
{
|
||||
m[index*3] = col[0]; m[index*3 + 1] = col[1]; m[index*3 + 2] = col[2];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix3::setColumn(int index, const Vector3& v)
|
||||
{
|
||||
m[index*3] = v.x; m[index*3 + 1] = v.y; m[index*3 + 2] = v.z;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline const float* Matrix3::get() const
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3& Matrix3::identity()
|
||||
{
|
||||
m[0] = m[4] = m[8] = 1.0f;
|
||||
m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0.0f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3 Matrix3::operator+(const Matrix3& rhs) const
|
||||
{
|
||||
return Matrix3(m[0]+rhs[0], m[1]+rhs[1], m[2]+rhs[2],
|
||||
m[3]+rhs[3], m[4]+rhs[4], m[5]+rhs[5],
|
||||
m[6]+rhs[6], m[7]+rhs[7], m[8]+rhs[8]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3 Matrix3::operator-(const Matrix3& rhs) const
|
||||
{
|
||||
return Matrix3(m[0]-rhs[0], m[1]-rhs[1], m[2]-rhs[2],
|
||||
m[3]-rhs[3], m[4]-rhs[4], m[5]-rhs[5],
|
||||
m[6]-rhs[6], m[7]-rhs[7], m[8]-rhs[8]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3& Matrix3::operator+=(const Matrix3& rhs)
|
||||
{
|
||||
m[0] += rhs[0]; m[1] += rhs[1]; m[2] += rhs[2];
|
||||
m[3] += rhs[3]; m[4] += rhs[4]; m[5] += rhs[5];
|
||||
m[6] += rhs[6]; m[7] += rhs[7]; m[8] += rhs[8];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3& Matrix3::operator-=(const Matrix3& rhs)
|
||||
{
|
||||
m[0] -= rhs[0]; m[1] -= rhs[1]; m[2] -= rhs[2];
|
||||
m[3] -= rhs[3]; m[4] -= rhs[4]; m[5] -= rhs[5];
|
||||
m[6] -= rhs[6]; m[7] -= rhs[7]; m[8] -= rhs[8];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector3 Matrix3::operator*(const Vector3& rhs) const
|
||||
{
|
||||
return Vector3(m[0]*rhs.x + m[3]*rhs.y + m[6]*rhs.z,
|
||||
m[1]*rhs.x + m[4]*rhs.y + m[7]*rhs.z,
|
||||
m[2]*rhs.x + m[5]*rhs.y + m[8]*rhs.z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3 Matrix3::operator*(const Matrix3& rhs) const
|
||||
{
|
||||
return Matrix3(m[0]*rhs[0] + m[3]*rhs[1] + m[6]*rhs[2], m[1]*rhs[0] + m[4]*rhs[1] + m[7]*rhs[2], m[2]*rhs[0] + m[5]*rhs[1] + m[8]*rhs[2],
|
||||
m[0]*rhs[3] + m[3]*rhs[4] + m[6]*rhs[5], m[1]*rhs[3] + m[4]*rhs[4] + m[7]*rhs[5], m[2]*rhs[3] + m[5]*rhs[4] + m[8]*rhs[5],
|
||||
m[0]*rhs[6] + m[3]*rhs[7] + m[6]*rhs[8], m[1]*rhs[6] + m[4]*rhs[7] + m[7]*rhs[8], m[2]*rhs[6] + m[5]*rhs[7] + m[8]*rhs[8]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3& Matrix3::operator*=(const Matrix3& rhs)
|
||||
{
|
||||
*this = *this * rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Matrix3::operator==(const Matrix3& rhs) const
|
||||
{
|
||||
return (m[0] == rhs[0]) && (m[1] == rhs[1]) && (m[2] == rhs[2]) &&
|
||||
(m[3] == rhs[3]) && (m[4] == rhs[4]) && (m[5] == rhs[5]) &&
|
||||
(m[6] == rhs[6]) && (m[7] == rhs[7]) && (m[8] == rhs[8]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Matrix3::operator!=(const Matrix3& rhs) const
|
||||
{
|
||||
return (m[0] != rhs[0]) || (m[1] != rhs[1]) || (m[2] != rhs[2]) ||
|
||||
(m[3] != rhs[3]) || (m[4] != rhs[4]) || (m[5] != rhs[5]) ||
|
||||
(m[6] != rhs[6]) || (m[7] != rhs[7]) || (m[8] != rhs[8]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline float Matrix3::operator[](int index) const
|
||||
{
|
||||
return m[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline float& Matrix3::operator[](int index)
|
||||
{
|
||||
return m[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3 operator-(const Matrix3& rhs)
|
||||
{
|
||||
return Matrix3(-rhs[0], -rhs[1], -rhs[2], -rhs[3], -rhs[4], -rhs[5], -rhs[6], -rhs[7], -rhs[8]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix3 operator*(float s, const Matrix3& rhs)
|
||||
{
|
||||
return Matrix3(s*rhs[0], s*rhs[1], s*rhs[2], s*rhs[3], s*rhs[4], s*rhs[5], s*rhs[6], s*rhs[7], s*rhs[8]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector3 operator*(const Vector3& v, const Matrix3& m)
|
||||
{
|
||||
return Vector3(v.x*m[0] + v.y*m[1] + v.z*m[2], v.x*m[3] + v.y*m[4] + v.z*m[5], v.x*m[6] + v.y*m[7] + v.z*m[8]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Matrix3& m)
|
||||
{
|
||||
os << std::fixed << std::setprecision(5);
|
||||
os << "[" << std::setw(10) << m[0] << " " << std::setw(10) << m[3] << " " << std::setw(10) << m[6] << "]\n"
|
||||
<< "[" << std::setw(10) << m[1] << " " << std::setw(10) << m[4] << " " << std::setw(10) << m[7] << "]\n"
|
||||
<< "[" << std::setw(10) << m[2] << " " << std::setw(10) << m[5] << " " << std::setw(10) << m[8] << "]\n";
|
||||
os << std::resetiosflags(std::ios_base::fixed | std::ios_base::floatfield);
|
||||
return os;
|
||||
}
|
||||
// END OF MATRIX3 INLINE //////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// inline functions for Matrix4
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
inline Matrix4::Matrix4()
|
||||
{
|
||||
// initially identity matrix
|
||||
identity();
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4::Matrix4(const float src[16])
|
||||
{
|
||||
set(src);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4::Matrix4(float m00, float m01, float m02, float m03,
|
||||
float m04, float m05, float m06, float m07,
|
||||
float m08, float m09, float m10, float m11,
|
||||
float m12, float m13, float m14, float m15)
|
||||
{
|
||||
set(m00, m01, m02, m03, m04, m05, m06, m07, m08, m09, m10, m11, m12, m13, m14, m15);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix4::set(const float src[16])
|
||||
{
|
||||
m[0] = src[0]; m[1] = src[1]; m[2] = src[2]; m[3] = src[3];
|
||||
m[4] = src[4]; m[5] = src[5]; m[6] = src[6]; m[7] = src[7];
|
||||
m[8] = src[8]; m[9] = src[9]; m[10]= src[10]; m[11]= src[11];
|
||||
m[12]= src[12]; m[13]= src[13]; m[14]= src[14]; m[15]= src[15];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix4::set(float m00, float m01, float m02, float m03,
|
||||
float m04, float m05, float m06, float m07,
|
||||
float m08, float m09, float m10, float m11,
|
||||
float m12, float m13, float m14, float m15)
|
||||
{
|
||||
m[0] = m00; m[1] = m01; m[2] = m02; m[3] = m03;
|
||||
m[4] = m04; m[5] = m05; m[6] = m06; m[7] = m07;
|
||||
m[8] = m08; m[9] = m09; m[10]= m10; m[11]= m11;
|
||||
m[12]= m12; m[13]= m13; m[14]= m14; m[15]= m15;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix4::setRow(int index, const float row[4])
|
||||
{
|
||||
m[index] = row[0]; m[index + 4] = row[1]; m[index + 8] = row[2]; m[index + 12] = row[3];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix4::setRow(int index, const Vector4& v)
|
||||
{
|
||||
m[index] = v.x; m[index + 4] = v.y; m[index + 8] = v.z; m[index + 12] = v.w;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix4::setRow(int index, const Vector3& v)
|
||||
{
|
||||
m[index] = v.x; m[index + 4] = v.y; m[index + 8] = v.z;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix4::setColumn(int index, const float col[4])
|
||||
{
|
||||
m[index*4] = col[0]; m[index*4 + 1] = col[1]; m[index*4 + 2] = col[2]; m[index*4 + 3] = col[3];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix4::setColumn(int index, const Vector4& v)
|
||||
{
|
||||
m[index*4] = v.x; m[index*4 + 1] = v.y; m[index*4 + 2] = v.z; m[index*4 + 3] = v.w;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Matrix4::setColumn(int index, const Vector3& v)
|
||||
{
|
||||
m[index*4] = v.x; m[index*4 + 1] = v.y; m[index*4 + 2] = v.z;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline const float* Matrix4::get() const
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline const float* Matrix4::getTranspose()
|
||||
{
|
||||
tm[0] = m[0]; tm[1] = m[4]; tm[2] = m[8]; tm[3] = m[12];
|
||||
tm[4] = m[1]; tm[5] = m[5]; tm[6] = m[9]; tm[7] = m[13];
|
||||
tm[8] = m[2]; tm[9] = m[6]; tm[10]= m[10]; tm[11]= m[14];
|
||||
tm[12]= m[3]; tm[13]= m[7]; tm[14]= m[11]; tm[15]= m[15];
|
||||
return tm;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4& Matrix4::identity()
|
||||
{
|
||||
m[0] = m[5] = m[10] = m[15] = 1.0f;
|
||||
m[1] = m[2] = m[3] = m[4] = m[6] = m[7] = m[8] = m[9] = m[11] = m[12] = m[13] = m[14] = 0.0f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4 Matrix4::operator+(const Matrix4& rhs) const
|
||||
{
|
||||
return Matrix4(m[0]+rhs[0], m[1]+rhs[1], m[2]+rhs[2], m[3]+rhs[3],
|
||||
m[4]+rhs[4], m[5]+rhs[5], m[6]+rhs[6], m[7]+rhs[7],
|
||||
m[8]+rhs[8], m[9]+rhs[9], m[10]+rhs[10], m[11]+rhs[11],
|
||||
m[12]+rhs[12], m[13]+rhs[13], m[14]+rhs[14], m[15]+rhs[15]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4 Matrix4::operator-(const Matrix4& rhs) const
|
||||
{
|
||||
return Matrix4(m[0]-rhs[0], m[1]-rhs[1], m[2]-rhs[2], m[3]-rhs[3],
|
||||
m[4]-rhs[4], m[5]-rhs[5], m[6]-rhs[6], m[7]-rhs[7],
|
||||
m[8]-rhs[8], m[9]-rhs[9], m[10]-rhs[10], m[11]-rhs[11],
|
||||
m[12]-rhs[12], m[13]-rhs[13], m[14]-rhs[14], m[15]-rhs[15]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4& Matrix4::operator+=(const Matrix4& rhs)
|
||||
{
|
||||
m[0] += rhs[0]; m[1] += rhs[1]; m[2] += rhs[2]; m[3] += rhs[3];
|
||||
m[4] += rhs[4]; m[5] += rhs[5]; m[6] += rhs[6]; m[7] += rhs[7];
|
||||
m[8] += rhs[8]; m[9] += rhs[9]; m[10]+= rhs[10]; m[11]+= rhs[11];
|
||||
m[12]+= rhs[12]; m[13]+= rhs[13]; m[14]+= rhs[14]; m[15]+= rhs[15];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4& Matrix4::operator-=(const Matrix4& rhs)
|
||||
{
|
||||
m[0] -= rhs[0]; m[1] -= rhs[1]; m[2] -= rhs[2]; m[3] -= rhs[3];
|
||||
m[4] -= rhs[4]; m[5] -= rhs[5]; m[6] -= rhs[6]; m[7] -= rhs[7];
|
||||
m[8] -= rhs[8]; m[9] -= rhs[9]; m[10]-= rhs[10]; m[11]-= rhs[11];
|
||||
m[12]-= rhs[12]; m[13]-= rhs[13]; m[14]-= rhs[14]; m[15]-= rhs[15];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector4 Matrix4::operator*(const Vector4& rhs) const
|
||||
{
|
||||
return Vector4(m[0]*rhs.x + m[4]*rhs.y + m[8]*rhs.z + m[12]*rhs.w,
|
||||
m[1]*rhs.x + m[5]*rhs.y + m[9]*rhs.z + m[13]*rhs.w,
|
||||
m[2]*rhs.x + m[6]*rhs.y + m[10]*rhs.z + m[14]*rhs.w,
|
||||
m[3]*rhs.x + m[7]*rhs.y + m[11]*rhs.z + m[15]*rhs.w);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector3 Matrix4::operator*(const Vector3& rhs) const
|
||||
{
|
||||
return Vector3(m[0]*rhs.x + m[4]*rhs.y + m[8]*rhs.z,
|
||||
m[1]*rhs.x + m[5]*rhs.y + m[9]*rhs.z,
|
||||
m[2]*rhs.x + m[6]*rhs.y + m[10]*rhs.z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4 Matrix4::operator*(const Matrix4& n) const
|
||||
{
|
||||
return Matrix4(m[0]*n[0] + m[4]*n[1] + m[8]*n[2] + m[12]*n[3], m[1]*n[0] + m[5]*n[1] + m[9]*n[2] + m[13]*n[3], m[2]*n[0] + m[6]*n[1] + m[10]*n[2] + m[14]*n[3], m[3]*n[0] + m[7]*n[1] + m[11]*n[2] + m[15]*n[3],
|
||||
m[0]*n[4] + m[4]*n[5] + m[8]*n[6] + m[12]*n[7], m[1]*n[4] + m[5]*n[5] + m[9]*n[6] + m[13]*n[7], m[2]*n[4] + m[6]*n[5] + m[10]*n[6] + m[14]*n[7], m[3]*n[4] + m[7]*n[5] + m[11]*n[6] + m[15]*n[7],
|
||||
m[0]*n[8] + m[4]*n[9] + m[8]*n[10] + m[12]*n[11], m[1]*n[8] + m[5]*n[9] + m[9]*n[10] + m[13]*n[11], m[2]*n[8] + m[6]*n[9] + m[10]*n[10] + m[14]*n[11], m[3]*n[8] + m[7]*n[9] + m[11]*n[10] + m[15]*n[11],
|
||||
m[0]*n[12] + m[4]*n[13] + m[8]*n[14] + m[12]*n[15], m[1]*n[12] + m[5]*n[13] + m[9]*n[14] + m[13]*n[15], m[2]*n[12] + m[6]*n[13] + m[10]*n[14] + m[14]*n[15], m[3]*n[12] + m[7]*n[13] + m[11]*n[14] + m[15]*n[15]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4& Matrix4::operator*=(const Matrix4& rhs)
|
||||
{
|
||||
*this = *this * rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Matrix4::operator==(const Matrix4& n) const
|
||||
{
|
||||
return (m[0] == n[0]) && (m[1] == n[1]) && (m[2] == n[2]) && (m[3] == n[3]) &&
|
||||
(m[4] == n[4]) && (m[5] == n[5]) && (m[6] == n[6]) && (m[7] == n[7]) &&
|
||||
(m[8] == n[8]) && (m[9] == n[9]) && (m[10]== n[10]) && (m[11]== n[11]) &&
|
||||
(m[12]== n[12]) && (m[13]== n[13]) && (m[14]== n[14]) && (m[15]== n[15]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Matrix4::operator!=(const Matrix4& n) const
|
||||
{
|
||||
return (m[0] != n[0]) || (m[1] != n[1]) || (m[2] != n[2]) || (m[3] != n[3]) ||
|
||||
(m[4] != n[4]) || (m[5] != n[5]) || (m[6] != n[6]) || (m[7] != n[7]) ||
|
||||
(m[8] != n[8]) || (m[9] != n[9]) || (m[10]!= n[10]) || (m[11]!= n[11]) ||
|
||||
(m[12]!= n[12]) || (m[13]!= n[13]) || (m[14]!= n[14]) || (m[15]!= n[15]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline float Matrix4::operator[](int index) const
|
||||
{
|
||||
return m[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline float& Matrix4::operator[](int index)
|
||||
{
|
||||
return m[index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4 operator-(const Matrix4& rhs)
|
||||
{
|
||||
return Matrix4(-rhs[0], -rhs[1], -rhs[2], -rhs[3], -rhs[4], -rhs[5], -rhs[6], -rhs[7], -rhs[8], -rhs[9], -rhs[10], -rhs[11], -rhs[12], -rhs[13], -rhs[14], -rhs[15]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Matrix4 operator*(float s, const Matrix4& rhs)
|
||||
{
|
||||
return Matrix4(s*rhs[0], s*rhs[1], s*rhs[2], s*rhs[3], s*rhs[4], s*rhs[5], s*rhs[6], s*rhs[7], s*rhs[8], s*rhs[9], s*rhs[10], s*rhs[11], s*rhs[12], s*rhs[13], s*rhs[14], s*rhs[15]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector4 operator*(const Vector4& v, const Matrix4& m)
|
||||
{
|
||||
return Vector4(v.x*m[0] + v.y*m[1] + v.z*m[2] + v.w*m[3], v.x*m[4] + v.y*m[5] + v.z*m[6] + v.w*m[7], v.x*m[8] + v.y*m[9] + v.z*m[10] + v.w*m[11], v.x*m[12] + v.y*m[13] + v.z*m[14] + v.w*m[15]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Vector3 operator*(const Vector3& v, const Matrix4& m)
|
||||
{
|
||||
return Vector3(v.x*m[0] + v.y*m[1] + v.z*m[2], v.x*m[4] + v.y*m[5] + v.z*m[6], v.x*m[8] + v.y*m[9] + v.z*m[10]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Matrix4& m)
|
||||
{
|
||||
os << std::fixed << std::setprecision(5);
|
||||
os << "[" << std::setw(10) << m[0] << " " << std::setw(10) << m[4] << " " << std::setw(10) << m[8] << " " << std::setw(10) << m[12] << "]\n"
|
||||
<< "[" << std::setw(10) << m[1] << " " << std::setw(10) << m[5] << " " << std::setw(10) << m[9] << " " << std::setw(10) << m[13] << "]\n"
|
||||
<< "[" << std::setw(10) << m[2] << " " << std::setw(10) << m[6] << " " << std::setw(10) << m[10] << " " << std::setw(10) << m[14] << "]\n"
|
||||
<< "[" << std::setw(10) << m[3] << " " << std::setw(10) << m[7] << " " << std::setw(10) << m[11] << " " << std::setw(10) << m[15] << "]\n";
|
||||
os << std::resetiosflags(std::ios_base::fixed | std::ios_base::floatfield);
|
||||
return os;
|
||||
}
|
||||
// END OF MATRIX4 INLINE //////////////////////////////////////////////////////
|
||||
#endif
|
||||
615
Model.cpp
Normal file
615
Model.cpp
Normal file
@@ -0,0 +1,615 @@
|
||||
#include "Model.h"
|
||||
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
#include "renderer.h"
|
||||
#include "screen.h"
|
||||
#include "Editor.h"
|
||||
|
||||
const float vb[8][3] = {{-0.5f, 0.5f, -0.5f},{-0.5f, 0.5f, 0.5f},{0.5f, 0.5f, 0.5f},{0.5f, 0.5f, -0.5f},{-0.5f, -0.5f, -0.5f},{-0.5f, -0.5f, 0.5f},{0.5f, -0.5f, 0.5f},{0.5f, -0.5f, -0.5f}};
|
||||
const char fb[6][4] = {{1, 5, 6, 2},{3, 7, 4, 0},{0, 1, 2, 3},{7, 6, 5, 4},{2, 6, 7, 3},{0, 4, 5, 1}};
|
||||
const char nb[6][3] = {{0, 0, 1},{0, 0, -1},{0, 1, 0},{0, -1, 0},{1, 0, 0},{-1, 0, 0}};
|
||||
//const char t[5][2] = {{0, 1},{0, 3},{2, 3},{2, 1},{0, 1}};
|
||||
|
||||
Model model;
|
||||
|
||||
#pragma mark Model::File Ops
|
||||
|
||||
void Model::Save(const char* filename)
|
||||
{
|
||||
}
|
||||
|
||||
void Model::Load(const char* filename)
|
||||
{
|
||||
}
|
||||
|
||||
#pragma mark Model::Calculations
|
||||
|
||||
const Vector3 Model::GetCurrentValue(const int& cube, const AnimKey::Type& type)
|
||||
{
|
||||
int currentAnim = 0;
|
||||
int i1 = -1;
|
||||
int i2 = -1;
|
||||
const Anim& anim = anims[currentAnim];
|
||||
for (int i = 0; i < anim.numKeys; i++) {
|
||||
const AnimKey& k = anim.keys[i];
|
||||
if (k.cube == cube && k.type == type) {
|
||||
if (k.t == Editor::t) {
|
||||
i1 = i2 = i;
|
||||
} else if (k.t < Editor::t) {
|
||||
i1 = i;
|
||||
} else if (k.t > Editor::t) {
|
||||
if (i1 == -1) {
|
||||
i1 = i2 = i;
|
||||
break;
|
||||
} else {
|
||||
i2 = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i1 == -1) {
|
||||
if (type == AnimKey::Type::Rotation) {
|
||||
return Vector3(0, 0, 0);
|
||||
} else if (type == AnimKey::Type::Position) {
|
||||
return cubes[cube].position;
|
||||
} else {
|
||||
return cubes[cube].size;
|
||||
}
|
||||
}
|
||||
if (i1 == i2 or i2 == -1) return anim.keys[i1].value;
|
||||
|
||||
// MUCH OBFUSCATED, SO DEBUGGABLE
|
||||
return anim.keys[i1].value + ((anim.keys[i2].value - anim.keys[i1].value) * (Editor::t - anim.keys[i1].t)/(anim.keys[i2].t - anim.keys[i1].t));
|
||||
}
|
||||
|
||||
void Model::GetCurrentTransformation(const int& cube, Vector3& position, Vector3& rotation, Vector3& scale)
|
||||
{
|
||||
position = GetCurrentValue(cube, AnimKey::Type::Position);
|
||||
rotation = GetCurrentValue(cube, AnimKey::Type::Rotation);
|
||||
scale = GetCurrentValue(cube, AnimKey::Type::Scale);
|
||||
}
|
||||
|
||||
void Model::Calculate()
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
Vector3 position, rotation, scale, pivot;
|
||||
GetCurrentTransformation(i, position, rotation, scale);
|
||||
pivot = cubes[i].pivot;
|
||||
localMatrix[i].identity();
|
||||
localMatrix[i].translate(pivot);
|
||||
localMatrix[i].scale(scale.x, scale.y, scale.z);
|
||||
localMatrix[i].rotateX(rotation.x);
|
||||
localMatrix[i].rotateY(rotation.y);
|
||||
localMatrix[i].rotateZ(rotation.z);
|
||||
localMatrix[i].translate(position-pivot);
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
finalMatrix[i] = localMatrix[i];
|
||||
int parent = cubes[i].parent;
|
||||
while (parent != -1) {
|
||||
finalMatrix[i] *= localMatrix[parent];
|
||||
parent = cubes[parent].parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Model::Draw
|
||||
|
||||
void Model::DrawSolid()
|
||||
{
|
||||
glColor4ub(255, 255, 255, 255);
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
if (cubes[c].selected) continue;
|
||||
const Cube& cube = cubes[c];
|
||||
glPushMatrix();
|
||||
glBegin(GL_QUADS);
|
||||
for (int f = 0; f<6; f++) {
|
||||
if (cube.faces[f].selected) continue;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glNormal3f(nb[f][0], nb[f][1], nb[f][2]);
|
||||
glTexCoord2f(float(cube.faces[f].uv[i].x)/32.0f, float(cube.faces[f].uv[i].y)/32.0f);
|
||||
glVertex3f(cube.position[0]+vb[fb[f][i]][0]*cube.size[0], cube.position[1]+vb[fb[f][i]][1]*cube.size[1], cube.position[2]+vb[fb[f][i]][2]*cube.size[2]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
glColor4ub(255, 0, 0, 255);
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
const Cube& cube = cubes[c];
|
||||
glPushMatrix();
|
||||
//glRotatef(cube.rot[0], 1, 0, 0);
|
||||
//glRotatef(cube.rot[1], 0, 1, 0);
|
||||
//glRotatef(cube.rot[2], 0, 0, 1);
|
||||
glBegin(GL_QUADS);
|
||||
for (int f = 0; f<6; f++) {
|
||||
if (!cube.selected and !cube.faces[f].selected) continue;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glNormal3f(nb[f][0], nb[f][1], nb[f][2]);
|
||||
glTexCoord2f(float(cube.faces[f].uv[i].x)/32.0f, float(cube.faces[f].uv[i].y)/32.0f);
|
||||
glVertex3f(cube.position[0]+vb[fb[f][i]][0]*cube.size[0], cube.position[1]+vb[fb[f][i]][1]*cube.size[1], cube.position[2]+vb[fb[f][i]][2]*cube.size[2]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void Model::DrawWire()
|
||||
{
|
||||
Renderer::SetState(RENDER_DEPTH);
|
||||
glCullFace(GL_FRONT);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
glColor4ub(128, 128, 128, 255);
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
if (cubes[c].selected) continue;
|
||||
const Cube& cube = cubes[c];
|
||||
glPushMatrix();
|
||||
//glRotatef(cube.rot[0], 1, 0, 0);
|
||||
//glRotatef(cube.rot[1], 0, 1, 0);
|
||||
//glRotatef(cube.rot[2], 0, 0, 1);
|
||||
glBegin(GL_QUADS);
|
||||
for (int f = 0; f<6; f++) {
|
||||
if (cube.faces[f].selected) continue;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glNormal3f(nb[f][0], nb[f][1], nb[f][2]);
|
||||
glVertex3f(cube.position[0]+vb[fb[f][i]][0]*cube.size[0], cube.position[1]+vb[fb[f][i]][1]*cube.size[1], cube.position[2]+vb[fb[f][i]][2]*cube.size[2]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
glColor4ub(128, 0, 0, 255);
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
const Cube& cube = cubes[c];
|
||||
glPushMatrix();
|
||||
//glRotatef(cube.rot[0], 1, 0, 0);
|
||||
//glRotatef(cube.rot[1], 0, 1, 0);
|
||||
//glRotatef(cube.rot[2], 0, 0, 1);
|
||||
glBegin(GL_QUADS);
|
||||
for (int f = 0; f<6; f++) {
|
||||
if (!cube.selected and !cube.faces[f].selected) continue;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glNormal3f(nb[f][0], nb[f][1], nb[f][2]);
|
||||
glVertex3f(cube.position[0]+vb[fb[f][i]][0]*cube.size[0], cube.position[1]+vb[fb[f][i]][1]*cube.size[1], cube.position[2]+vb[fb[f][i]][2]*cube.size[2]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
glColor4ub(255, 255, 255, 255);
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
if (cubes[c].selected) continue;
|
||||
const Cube& cube = cubes[c];
|
||||
glPushMatrix();
|
||||
//glRotatef(cube.rot[0], 1, 0, 0);
|
||||
//glRotatef(cube.rot[1], 0, 1, 0);
|
||||
//glRotatef(cube.rot[2], 0, 0, 1);
|
||||
glBegin(GL_QUADS);
|
||||
for (int f = 0; f<6; f++) {
|
||||
if (cube.faces[f].selected) continue;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glNormal3f(nb[f][0], nb[f][1], nb[f][2]);
|
||||
glVertex3f(cube.position[0]+vb[fb[f][i]][0]*cube.size[0], cube.position[1]+vb[fb[f][i]][1]*cube.size[1], cube.position[2]+vb[fb[f][i]][2]*cube.size[2]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
glColor4f(1, 0, 0, 1);
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
const Cube& cube = cubes[c];
|
||||
glPushMatrix();
|
||||
//glRotatef(cube.rot[0], 1, 0, 0);
|
||||
//glRotatef(cube.rot[1], 0, 1, 0);
|
||||
//glRotatef(cube.rot[2], 0, 0, 1);
|
||||
glBegin(GL_QUADS);
|
||||
for (int f = 0; f<6; f++) {
|
||||
if (!cube.selected and !cube.faces[f].selected) continue;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glNormal3f(nb[f][0], nb[f][1], nb[f][2]);
|
||||
glVertex3f(cube.position[0]+vb[fb[f][i]][0]*cube.size[0], cube.position[1]+vb[fb[f][i]][1]*cube.size[1], cube.position[2]+vb[fb[f][i]][2]*cube.size[2]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void Model::DrawUV()
|
||||
{
|
||||
glColor4ub(255, 255, 255, 255);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0f, 0.0f);
|
||||
glVertex2f(-16.0f, -16.0f);
|
||||
glTexCoord2f(0.0f, 1.0f);
|
||||
glVertex2f(-16.0f, 16.0f);
|
||||
glTexCoord2f(1.0f, 1.0f);
|
||||
glVertex2f(16.0f, 16.0f);
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glVertex2f(16.0f, -16.0f);
|
||||
glEnd();
|
||||
|
||||
Renderer::SetState(RENDER_NONE);
|
||||
|
||||
glColor4ub(255, 255, 255, 255);
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
if (cubes[c].selected) continue;
|
||||
const Cube& cube = cubes[c];
|
||||
glBegin(GL_QUADS);
|
||||
for (int f = 0; f<6; f++) {
|
||||
if (cube.faces[f].selected) continue;
|
||||
const CubeFace& face = cube.faces[f];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glVertex2f(-(16-face.uv[i].x), -(16-face.uv[i].y));
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
glColor4ub(255, 0, 0, 255);
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
const Cube& cube = cubes[c];
|
||||
glBegin(GL_QUADS);
|
||||
for (int f = 0; f<6; f++) {
|
||||
if (!cube.selected and !cube.faces[f].selected) continue;
|
||||
const CubeFace& face = cube.faces[f];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glVertex2f(-(16-face.uv[i].x), -(16-face.uv[i].y));
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Color Model::Pick(const float x, const float y)
|
||||
{
|
||||
glClearColor(1, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
const Cube& cube = cubes[c];
|
||||
glPushMatrix();
|
||||
glBegin(GL_QUADS);
|
||||
for (int f = 0; f < 6; f++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glColor4ub(c, f, 0, 255);
|
||||
//glNormal3f(nb[f][0], nb[f][1], nb[f][2]);
|
||||
//glTexCoord2f(float(cube.faces[f].uv[i].x)/32.0f, float(cube.faces[f].uv[i].y)/32.0f);
|
||||
glVertex3f(cube.position[0]+vb[fb[f][i]][0]*cube.size[0], cube.position[1]+vb[fb[f][i]][1]*cube.size[1], cube.position[2]+vb[fb[f][i]][2]*cube.size[2]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
Color color;
|
||||
glReadPixels(x, SCREEN_HEIGHT-y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color.r);
|
||||
printf("PICK: %i, %i, %i, %i\n", color.r, color.g, color.b, color.a);
|
||||
return color;
|
||||
}
|
||||
|
||||
Color Model::PickPaint(const float x, const float y)
|
||||
{
|
||||
glClearColor(1, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
const Cube& cube = cubes[c];
|
||||
glPushMatrix();
|
||||
glBegin(GL_QUADS);
|
||||
for (int f = 0; f < 6; f++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint8_t val = (c << 3) + f;
|
||||
glColor4ub(val, cube.faces[f].uv[i].x*4, cube.faces[f].uv[i].y*4, 255);
|
||||
//glNormal3f(nb[f][0], nb[f][1], nb[f][2]);
|
||||
//glTexCoord2f(float(cube.faces[f].uv[i].x)/32.0f, float(cube.faces[f].uv[i].y)/32.0f);
|
||||
glVertex3f(cube.position[0]+vb[fb[f][i]][0]*cube.size[0], cube.position[1]+vb[fb[f][i]][1]*cube.size[1], cube.position[2]+vb[fb[f][i]][2]*cube.size[2]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
}
|
||||
Color color;
|
||||
glReadPixels(x, SCREEN_HEIGHT-y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color.r);
|
||||
color /= 4;
|
||||
printf("PICK: %i, %i, %i, %i\n", color.r, color.g, color.b, color.a);
|
||||
return color;
|
||||
}
|
||||
|
||||
Color Model::PickPixel(const float x, const float y)
|
||||
{
|
||||
glClearColor(1, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glBegin(GL_QUADS);
|
||||
glColor4ub(0, 0, 255, 255);
|
||||
glVertex2f(-16.0f, -16.0f);
|
||||
glColor4ub(0, 128, 255, 255);
|
||||
glVertex2f(-16.0f, 16.0f);
|
||||
glColor4ub(128, 128, 255, 255);
|
||||
glVertex2f(16.0f, 16.0f);
|
||||
glColor4ub(128, 0, 255, 255);
|
||||
glVertex2f(16.0f, -16.0f);
|
||||
glEnd();
|
||||
|
||||
Color color;
|
||||
glReadPixels(x, SCREEN_HEIGHT-y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color.r);
|
||||
color /= 4;
|
||||
printf("PICK: %i, %i, %i, %i\n", color.r, color.g, color.b, color.a);
|
||||
return color;
|
||||
}
|
||||
|
||||
#pragma mark Model::Cubes
|
||||
|
||||
int Model::GetSelectedCube()
|
||||
{
|
||||
int selected = -1;
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
if (cubes[i].selected) {
|
||||
if (selected == -1) {
|
||||
selected = i;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
|
||||
void Model::SelectCube(const uint8_t index, const bool inclusive)
|
||||
{
|
||||
if (not inclusive) SelectAllCubes(false);
|
||||
if (index == 255) return;
|
||||
assert(index < numCubes);
|
||||
cubes[index].selected = not cubes[index].selected;
|
||||
}
|
||||
|
||||
void Model::SelectAllCubes(const bool select)
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
cubes[i].selected = select;
|
||||
}
|
||||
}
|
||||
|
||||
void Model::NewCube()
|
||||
{
|
||||
if (numCubes == MAX_CUBES) return;
|
||||
SelectAllCubes(false);
|
||||
cubes[numCubes].name[0] = '\0';
|
||||
cubes[numCubes].parent = -1;
|
||||
cubes[numCubes].pivot = {0, 0, 0};
|
||||
cubes[numCubes].position = {0, 0, 0};
|
||||
cubes[numCubes].size = {8, 8, 8};
|
||||
cubes[numCubes].selected = true;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
cubes[numCubes].faces[i].selected = false;
|
||||
cubes[numCubes].faces[i].uv[0] = {32, 32};
|
||||
cubes[numCubes].faces[i].uv[1] = {32, 0};
|
||||
cubes[numCubes].faces[i].uv[2] = {0, 0};
|
||||
cubes[numCubes].faces[i].uv[3] = {0, 32};
|
||||
}
|
||||
numCubes++;
|
||||
}
|
||||
|
||||
void Model::DeleteCube()
|
||||
{
|
||||
if (numCubes == 0) return;
|
||||
|
||||
int numCubesSelected = 0;
|
||||
for (int i = 0; i < numCubes; i++) if (cubes[i].selected) numCubesSelected++;
|
||||
if (numCubesSelected == 0) return;
|
||||
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
if (cubes[i].selected) {
|
||||
numCubes--;
|
||||
if (numCubes > 1 and i != numCubes) {
|
||||
cubes[i] = cubes[numCubes];
|
||||
for (int c = 0; c < numCubes; c++) {
|
||||
if (cubes[c].parent == i) {
|
||||
cubes[c].parent = -1;
|
||||
} else if (cubes[c].parent == numCubes) {
|
||||
cubes[c].parent = i;
|
||||
}
|
||||
}
|
||||
for (int a = 0; a < numAnims; a++) {
|
||||
for (int k = 0; k < anims[a].numKeys; k++) {
|
||||
if (anims[a].keys[k].cube == i) {
|
||||
anims[a].numKeys--;
|
||||
if (anims[a].numKeys > 1 and k != anims[a].numKeys) {
|
||||
anims[a].keys[k] = anims[a].keys[anims[a].numKeys];
|
||||
}
|
||||
k--;
|
||||
} else if (anims[a].keys[k].cube == anims[a].numKeys) {
|
||||
anims[a].keys[k].cube = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::DupCube()
|
||||
{
|
||||
int numCubesSelected = 0;
|
||||
for (int i = 0; i < numCubes; i++) if (cubes[i].selected) numCubesSelected++;
|
||||
if (numCubes+numCubesSelected > MAX_CUBES) return;
|
||||
|
||||
int numCubesBeforeEditing = numCubes;
|
||||
for (int c = 0; c < numCubesBeforeEditing; c++) {
|
||||
if (cubes[c].selected) {
|
||||
cubes[c].selected = false;
|
||||
cubes[numCubes].name[0] = '\0';
|
||||
cubes[numCubes].parent = cubes[c].parent;
|
||||
cubes[numCubes].pivot = cubes[c].pivot;
|
||||
cubes[numCubes].position = cubes[c].position;
|
||||
cubes[numCubes].size = cubes[c].size;
|
||||
cubes[numCubes].selected = true;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
cubes[numCubes].faces[i].selected = false;
|
||||
cubes[numCubes].faces[i].uv[0] = cubes[c].faces[i].uv[0];
|
||||
cubes[numCubes].faces[i].uv[1] = cubes[c].faces[i].uv[1];
|
||||
cubes[numCubes].faces[i].uv[2] = cubes[c].faces[i].uv[2];
|
||||
cubes[numCubes].faces[i].uv[3] = cubes[c].faces[i].uv[3];
|
||||
}
|
||||
numCubes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::GrabCubes(const float x, const float y, const float z)
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
if (cubes[i].selected) {
|
||||
cubes[i].position.x += x;
|
||||
cubes[i].position.y += y;
|
||||
cubes[i].position.z += z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::ScaleCubes(const float x, const float y, const float z)
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
if (cubes[i].selected) {
|
||||
cubes[i].size.x += x;
|
||||
cubes[i].size.y += y;
|
||||
cubes[i].size.z += z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Model::Faces
|
||||
|
||||
ivec2 Model::GetSelectedFace()
|
||||
{
|
||||
ivec2 selected {-1, -1};
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
if (cubes[i].faces[j].selected) {
|
||||
if (selected.x == -1) {
|
||||
selected = {i, j};
|
||||
} else {
|
||||
return {-1, -1};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
|
||||
|
||||
void Model::SelectFace(const uint8_t index, const uint8_t face, const bool inclusive)
|
||||
{
|
||||
if (not inclusive) SelectAllFaces(false);
|
||||
if (index == 255) return;
|
||||
assert(index < numCubes);
|
||||
assert(face < 6);
|
||||
cubes[index].faces[face].selected = not cubes[index].faces[face].selected;
|
||||
}
|
||||
|
||||
void Model::SelectAllFaces(const bool select)
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
cubes[i].faces[j].selected = select;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::ClearFaces()
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
if (cubes[i].faces[j].selected) cubes[i].faces[j].Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::RotateFaces()
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
if (cubes[i].faces[j].selected) cubes[i].faces[j].Rotate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::FlipHFaces()
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
if (cubes[i].faces[j].selected) cubes[i].faces[j].FlipH();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::FlipVFaces()
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
if (cubes[i].faces[j].selected) cubes[i].faces[j].FlipV();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::GrabFaces(const float x, const float y)
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
if (cubes[i].faces[j].selected) {
|
||||
for (int k = 0; k < 4; k++) {
|
||||
cubes[i].faces[j].uv[k].x += x;
|
||||
cubes[i].faces[j].uv[k].y += y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Model::ScaleFaces(const float x, const float y)
|
||||
{
|
||||
for (int i = 0; i < numCubes; i++) {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
if (cubes[i].faces[j].selected) {
|
||||
cubes[i].faces[j].uv[0].x += x;
|
||||
cubes[i].faces[j].uv[0].y += y;
|
||||
cubes[i].faces[j].uv[1].x += x;
|
||||
cubes[i].faces[j].uv[3].y += y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark CubeFace::Methods
|
||||
|
||||
void CubeFace::Clear()
|
||||
{
|
||||
uv[0] = uv[1] = {0,0};
|
||||
uv[2] = uv[3] = {32,32};
|
||||
}
|
||||
|
||||
void CubeFace::Rotate()
|
||||
{
|
||||
Swap(uv[0], uv[1]);
|
||||
Swap(uv[1], uv[2]);
|
||||
Swap(uv[2], uv[3]);
|
||||
}
|
||||
|
||||
void CubeFace::FlipH()
|
||||
{
|
||||
Swap(uv[0], uv[3]);
|
||||
Swap(uv[1], uv[2]);
|
||||
}
|
||||
|
||||
void CubeFace::FlipV()
|
||||
{
|
||||
Swap(uv[0], uv[1]);
|
||||
Swap(uv[2], uv[3]);
|
||||
}
|
||||
96
Model.h
Normal file
96
Model.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define MAX_CUBES 20
|
||||
#define MAX_ANIMS 40
|
||||
#define MAX_KEYS 256
|
||||
|
||||
struct CubeFace
|
||||
{
|
||||
Vector2 uv[4] {{32, 32}, {32, 0}, {0, 0}, {0, 32}};
|
||||
char rot {0};
|
||||
bool selected {false};
|
||||
|
||||
void Clear();
|
||||
void Rotate();
|
||||
void FlipH();
|
||||
void FlipV();
|
||||
};
|
||||
|
||||
struct Cube
|
||||
{
|
||||
char name[10] {""};
|
||||
CubeFace faces[6];
|
||||
Vector3 position {0, 0, 0};
|
||||
Vector3 pivot {0, 0, 0};
|
||||
Vector3 size {8, 8, 8};
|
||||
int8_t parent {-1};
|
||||
bool selected {false};
|
||||
};
|
||||
|
||||
struct AnimKey
|
||||
{
|
||||
enum class Type { Position, Rotation, Scale };
|
||||
|
||||
float t {0.0f};
|
||||
uint8_t cube {0};
|
||||
Type type {Type::Rotation};
|
||||
Vector3 value {0, 0, 0};
|
||||
};
|
||||
|
||||
struct Anim
|
||||
{
|
||||
char name[10] {""};
|
||||
uint8_t numKeys {0};
|
||||
AnimKey keys[MAX_KEYS];
|
||||
};
|
||||
|
||||
struct Model
|
||||
{
|
||||
uint8_t numCubes {1};
|
||||
Cube cubes[MAX_CUBES];
|
||||
uint8_t numAnims {1};
|
||||
Anim anims[MAX_ANIMS];
|
||||
|
||||
Matrix4 localMatrix[MAX_CUBES];
|
||||
Matrix4 finalMatrix[MAX_CUBES];
|
||||
|
||||
void Save(const char* filename);
|
||||
void Load(const char* filename);
|
||||
void Calculate();
|
||||
void DrawSolid();
|
||||
void DrawWire();
|
||||
void DrawUV();
|
||||
Color Pick(const float x, const float y);
|
||||
Color PickPaint(const float x, const float y);
|
||||
Color PickPixel(const float x, const float y);
|
||||
|
||||
int GetSelectedCube();
|
||||
void SelectCube(const uint8_t index, const bool inclusive);
|
||||
void SelectAllCubes(const bool select = true);
|
||||
void NewCube();
|
||||
void DeleteCube();
|
||||
void DupCube();
|
||||
void GrabCubes(const float x, const float y, const float z);
|
||||
void ScaleCubes(const float x, const float y, const float z);
|
||||
|
||||
ivec2 GetSelectedFace();
|
||||
void SelectFace(const uint8_t index, const uint8_t face, const bool inclusive);
|
||||
void SelectAllFaces(const bool select = true);
|
||||
void ClearFaces();
|
||||
void RotateFaces();
|
||||
void FlipHFaces();
|
||||
void FlipVFaces();
|
||||
void GrabFaces(const float x, const float y);
|
||||
void ScaleFaces(const float x, const float y);
|
||||
|
||||
void DeleteKey(const int anim, const int key);
|
||||
|
||||
private:
|
||||
|
||||
const Vector3 GetCurrentValue(const int& cube, const AnimKey::Type& type);
|
||||
void GetCurrentTransformation(const int& cube, Vector3& position, Vector3& rotation, Vector3& scale);
|
||||
};
|
||||
|
||||
extern Model model;
|
||||
687
Vectors.h
Executable file
687
Vectors.h
Executable file
@@ -0,0 +1,687 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Vectors.h
|
||||
// =========
|
||||
// 2D/3D/4D vectors
|
||||
//
|
||||
// AUTHOR: Song Ho Ahn (song.ahn@gmail.com)
|
||||
// CREATED: 2007-02-14
|
||||
// UPDATED: 2013-01-20
|
||||
//
|
||||
// Copyright (C) 2007-2013 Song Ho Ahn
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef VECTORS_H_DEF
|
||||
#define VECTORS_H_DEF
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
struct Rectangle {
|
||||
float x, y, w, h;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct generic_vec2
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
T x;
|
||||
T y;
|
||||
};
|
||||
struct {
|
||||
T r;
|
||||
T g;
|
||||
};
|
||||
struct {
|
||||
T u;
|
||||
T v;
|
||||
};
|
||||
};
|
||||
|
||||
generic_vec2() : x(0.0f), y(0.0f) {}
|
||||
generic_vec2(const T& x, const T& y) : x(x), y(y) {}
|
||||
|
||||
inline generic_vec2 operator-() const { return {-x,-y}; }
|
||||
inline generic_vec2 operator+(const generic_vec2& o) const { return {x+o.x, y+o.y}; }
|
||||
inline generic_vec2 operator-(const generic_vec2& o) const { return {x-o.x, y-o.y}; }
|
||||
inline generic_vec2 operator*(const generic_vec2& o) const { return {x*o.x, y*o.y}; }
|
||||
inline generic_vec2 operator/(const generic_vec2& o) const { return {x/o.x, y/o.y}; }
|
||||
inline generic_vec2& operator+=(const generic_vec2& o) { x+=o.x; y+=o.y; return *this; }
|
||||
inline generic_vec2& operator-=(const generic_vec2& o) { x-=o.x; y-=o.y; return *this; }
|
||||
inline generic_vec2& operator*=(const generic_vec2& o) { x*=o.x; y*=o.y; return *this; }
|
||||
inline generic_vec2& operator/=(const generic_vec2& o) { x/=o.x; y/=o.y; return *this; }
|
||||
|
||||
inline generic_vec2 operator+(const T& o) const { return {x+o, y+o}; }
|
||||
inline generic_vec2 operator-(const T& o) const { return {x-o, y-o}; }
|
||||
inline generic_vec2 operator*(const T& o) const { return {x*o, y*o}; }
|
||||
inline generic_vec2 operator/(const T& o) const { return {x/o, y/o}; }
|
||||
inline generic_vec2& operator+=(const T& o) { x+=o; y+=o; return *this; }
|
||||
inline generic_vec2& operator-=(const T& o) { x-=o; y-=o; return *this; }
|
||||
inline generic_vec2& operator*=(const T& o) { x*=o; y*=o; return *this; }
|
||||
inline generic_vec2& operator/=(const T& o) { x/=o; y/=o; return *this; }
|
||||
|
||||
inline bool operator==(const generic_vec2& o) const { return (x==o.x) and (y==o.y); }
|
||||
inline bool operator!=(const generic_vec2& o) const { return (x!=o.x) or (y!=o.y); }
|
||||
inline T operator[](int index) const { return (&x)[index]; }
|
||||
inline T& operator[](int index) { return (&x)[index]; }
|
||||
};
|
||||
typedef generic_vec2<bool> bvec2;
|
||||
typedef generic_vec2<int> ivec2;
|
||||
typedef generic_vec2<unsigned> uvec2;
|
||||
typedef generic_vec2<float> vec2;
|
||||
|
||||
template<typename T>
|
||||
struct generic_vec3
|
||||
{
|
||||
union {
|
||||
struct { T x, y, z; };
|
||||
struct { T r, g, b; };
|
||||
struct { T u, v, s; };
|
||||
};
|
||||
|
||||
generic_vec3(const T& x, const T& y, const T& z) : x(x), y(y), z(z) {}
|
||||
generic_vec3(const generic_vec2<T>& xy, const T& z) : x(xy.x), y(xy.y), z(z) {}
|
||||
generic_vec3(const T& x, const generic_vec2<T>& yz) : x(x), y(yz.x), z(yz.y) {}
|
||||
|
||||
inline generic_vec3 operator-() const { return {-x,-y,-z}; }
|
||||
inline generic_vec3 operator+(const generic_vec3& o) const { return {x+o.x, y+o.y, z+o.z}; }
|
||||
inline generic_vec3 operator-(const generic_vec3& o) const { return {x-o.x, y-o.y, z-o.z}; }
|
||||
inline generic_vec3 operator*(const generic_vec3& o) const { return {x*o.x, y*o.y, z*o.z}; }
|
||||
inline generic_vec3 operator/(const generic_vec3& o) const { return {x/o.x, y/o.y, z/o.z}; }
|
||||
inline generic_vec3& operator+=(const generic_vec3& o) { x+=o.x; y+=o.y; z+=o.z; return *this; }
|
||||
inline generic_vec3& operator-=(const generic_vec3& o) { x-=o.x; y-=o.y; z-=o.z; return *this; }
|
||||
inline generic_vec3& operator*=(const generic_vec3& o) { x*=o.x; y*=o.y; z*=o.z; return *this; }
|
||||
inline generic_vec3& operator/=(const generic_vec3& o) { x/=o.x; y/=o.y; z/=o.z; return *this; }
|
||||
|
||||
inline generic_vec3 operator+(const T& o) const { return {x+o, y+o, z+o}; }
|
||||
inline generic_vec3 operator-(const T& o) const { return {x-o, y-o, z-o}; }
|
||||
inline generic_vec3 operator*(const T& o) const { return {x*o, y*o, z*o}; }
|
||||
inline generic_vec3 operator/(const T& o) const { return {x/o, y/o, z/o}; }
|
||||
inline generic_vec3& operator+=(const T& o) { x+=o; y+=o; z+=o; return *this; }
|
||||
inline generic_vec3& operator-=(const T& o) { x-=o; y-=o; z-=o; return *this; }
|
||||
inline generic_vec3& operator*=(const T& o) { x*=o; y*=o; z*=o; return *this; }
|
||||
inline generic_vec3& operator/=(const T& o) { x/=o; y/=o; z/=o; return *this; }
|
||||
|
||||
inline bool operator==(const generic_vec3& o) const { return (x==o.x) and (y==o.y) and (z==o.z); }
|
||||
inline bool operator!=(const generic_vec3& o) const { return (x!=o.x) or (y!=o.y) or (z!=o.z); }
|
||||
inline T operator[](int index) const { return (&x)[index]; }
|
||||
inline T& operator[](int index) { return (&x)[index]; }
|
||||
};
|
||||
typedef generic_vec3<bool> bvec3;
|
||||
typedef generic_vec3<int> ivec3;
|
||||
typedef generic_vec3<unsigned> uvec3;
|
||||
typedef generic_vec3<float> vec3;
|
||||
|
||||
template<typename T>
|
||||
struct generic_vec4
|
||||
{
|
||||
union {
|
||||
struct { T x, y, z, w; };
|
||||
struct { T r, g, b, a; };
|
||||
struct { T u, v, s, t; };
|
||||
};
|
||||
|
||||
generic_vec4() : x(0), y(0), z(0), w(0) {}
|
||||
generic_vec4(const T& x,const T& y, const T& z, const T& w) : x(x), y(y), z(z), w(w) {}
|
||||
generic_vec4(const generic_vec2<T>& xy, const T& z, const T& w) : x(xy.x), y(xy.y), z(z), w(w) {}
|
||||
generic_vec4(const T& x, const generic_vec2<T>& yz, const T& w) : x(x), y(yz.x), z(yz.y), w(w) {}
|
||||
generic_vec4(const T& x, const T& y, const generic_vec2<T>& zw) : x(x), y(y), z(zw.x), w(zw.y) {}
|
||||
generic_vec4(const generic_vec2<T>& xy, const generic_vec2<T>& zw) : x(xy.x), y(xy.y), z(zw.x), w(zw.y) {}
|
||||
|
||||
generic_vec4(const generic_vec3<T>& xyz, const T& w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
|
||||
generic_vec4(const T& x, const generic_vec3<T>& yzw) : x(x), y(yzw.x), z(yzw.y), w(yzw.z) {}
|
||||
|
||||
|
||||
inline generic_vec4 operator-() const { return {-x,-y,-z, -w}; }
|
||||
inline generic_vec4 operator+(const generic_vec4& o) const { return {x+o.x, y+o.y, z+o.z, w+o.w}; }
|
||||
inline generic_vec4 operator-(const generic_vec4& o) const { return {x-o.x, y-o.y, z-o.z, w-o.w}; }
|
||||
inline generic_vec4 operator*(const generic_vec4& o) const { return {x*o.x, y*o.y, z*o.z, w*o.w}; }
|
||||
inline generic_vec4 operator/(const generic_vec4& o) const { return {x/o.x, y/o.y, z/o.z, w/o.w}; }
|
||||
inline generic_vec4& operator+=(const generic_vec4& o) { x+=o.x; y+=o.y; z+=o.z; w+=o.w; return *this; }
|
||||
inline generic_vec4& operator-=(const generic_vec4& o) { x-=o.x; y-=o.y; z-=o.z; w-=o.w; return *this; }
|
||||
inline generic_vec4& operator*=(const generic_vec4& o) { x*=o.x; y*=o.y; z*=o.z; w*=o.w; return *this; }
|
||||
inline generic_vec4& operator/=(const generic_vec4& o) { x/=o.x; y/=o.y; z/=o.z; w/=o.w; return *this; }
|
||||
|
||||
inline generic_vec4 operator+(const T& o) const { return {x+o, y+o, z+o, w+o}; }
|
||||
inline generic_vec4 operator-(const T& o) const { return {x-o, y-o, z-o, w-o}; }
|
||||
inline generic_vec4 operator*(const T& o) const { return {x*o, y*o, z*o, w*o}; }
|
||||
inline generic_vec4 operator/(const T& o) const { return {x/o, y/o, z/o, w/o}; }
|
||||
inline generic_vec4& operator+=(const T& o) { x+=o; y+=o; z+=o; w+=o; return *this; }
|
||||
inline generic_vec4& operator-=(const T& o) { x-=o; y-=o; z-=o; w-=o; return *this; }
|
||||
inline generic_vec4& operator*=(const T& o) { x*=o; y*=o; z*=o; w*=o; return *this; }
|
||||
inline generic_vec4& operator/=(const T& o) { x/=o; y/=o; z/=o; w/=o; return *this; }
|
||||
|
||||
inline bool operator==(const generic_vec4& o) const { return (x==o.x) and (y==o.y) and (z==o.z) and (w==o.w); }
|
||||
inline bool operator!=(const generic_vec4& o) const { return (x!=o.x) or (y!=o.y) or (z!=o.z) or (w!=o.w); }
|
||||
inline T operator[](int index) const { return (&x)[index]; }
|
||||
inline T& operator[](int index) { return (&x)[index]; }
|
||||
};
|
||||
typedef generic_vec4<bool> bvec4;
|
||||
typedef generic_vec4<int> ivec4;
|
||||
typedef generic_vec4<unsigned> uvec4;
|
||||
typedef generic_vec4<float> vec4;
|
||||
typedef generic_vec4<unsigned char> ubvec4;
|
||||
typedef ubvec4 Color;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 2D vector
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
struct Vector2
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
|
||||
// ctors
|
||||
Vector2() : x(0), y(0) {};
|
||||
Vector2(float x, float y) : x(x), y(y) {};
|
||||
|
||||
// utils functions
|
||||
void set(float x, float y);
|
||||
float length() const; //
|
||||
float distance(const Vector2& vec) const; // distance between two vectors
|
||||
Vector2& normalize(); //
|
||||
float dot(const Vector2& vec) const; // dot product
|
||||
bool equal(const Vector2& vec, float e) const; // compare with epsilon
|
||||
bool inside(const Vector2& pos, const Vector2& size) const;
|
||||
|
||||
// operators
|
||||
Vector2 operator-() const; // unary operator (negate)
|
||||
Vector2 operator+(const Vector2& rhs) const; // add rhs
|
||||
Vector2 operator-(const Vector2& rhs) const; // subtract rhs
|
||||
Vector2& operator+=(const Vector2& rhs); // add rhs and update this object
|
||||
Vector2& operator-=(const Vector2& rhs); // subtract rhs and update this object
|
||||
Vector2 operator*(const float scale) const; // scale
|
||||
Vector2 operator*(const Vector2& rhs) const; // multiply each element
|
||||
Vector2& operator*=(const float scale); // scale and update this object
|
||||
Vector2& operator*=(const Vector2& rhs); // multiply each element and update this object
|
||||
Vector2 operator/(const float scale) const; // inverse scale
|
||||
Vector2& operator/=(const float scale); // scale and update this object
|
||||
bool operator==(const Vector2& rhs) const; // exact compare, no epsilon
|
||||
bool operator!=(const Vector2& rhs) const; // exact compare, no epsilon
|
||||
bool operator<(const Vector2& rhs) const; // comparison for sort
|
||||
float operator[](int index) const; // subscript operator v[0], v[1]
|
||||
float& operator[](int index); // subscript operator v[0], v[1]
|
||||
|
||||
friend Vector2 operator*(const float a, const Vector2 vec);
|
||||
friend std::ostream& operator<<(std::ostream& os, const Vector2& vec);
|
||||
};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 3D vector
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
struct Vector3
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
// ctors
|
||||
Vector3() : x(0), y(0), z(0) {};
|
||||
Vector3(float x, float y, float z) : x(x), y(y), z(z) {};
|
||||
|
||||
// utils functions
|
||||
void set(float x, float y, float z);
|
||||
float length() const; //
|
||||
float distance(const Vector3& vec) const; // distance between two vectors
|
||||
Vector3& normalize(); //
|
||||
float dot(const Vector3& vec) const; // dot product
|
||||
Vector3 cross(const Vector3& vec) const; // cross product
|
||||
bool equal(const Vector3& vec, float e) const; // compare with epsilon
|
||||
|
||||
// operators
|
||||
Vector3 operator-() const; // unary operator (negate)
|
||||
Vector3 operator+(const Vector3& rhs) const; // add rhs
|
||||
Vector3 operator-(const Vector3& rhs) const; // subtract rhs
|
||||
Vector3& operator+=(const Vector3& rhs); // add rhs and update this object
|
||||
Vector3& operator-=(const Vector3& rhs); // subtract rhs and update this object
|
||||
Vector3 operator*(const float scale) const; // scale
|
||||
Vector3 operator*(const Vector3& rhs) const; // multiplay each element
|
||||
Vector3& operator*=(const float scale); // scale and update this object
|
||||
Vector3& operator*=(const Vector3& rhs); // product each element and update this object
|
||||
Vector3 operator/(const float scale) const; // inverse scale
|
||||
Vector3& operator/=(const float scale); // scale and update this object
|
||||
bool operator==(const Vector3& rhs) const; // exact compare, no epsilon
|
||||
bool operator!=(const Vector3& rhs) const; // exact compare, no epsilon
|
||||
bool operator<(const Vector3& rhs) const; // comparison for sort
|
||||
float operator[](int index) const; // subscript operator v[0], v[1]
|
||||
float& operator[](int index); // subscript operator v[0], v[1]
|
||||
|
||||
friend Vector3 operator*(const float a, const Vector3 vec);
|
||||
friend std::ostream& operator<<(std::ostream& os, const Vector3& vec);
|
||||
};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 4D vector
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
struct Vector4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
|
||||
// ctors
|
||||
Vector4() : x(0), y(0), z(0), w(0) {};
|
||||
Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {};
|
||||
Vector4(Vector3 v, float w = 1) : x(v.x), y(v.y), z(v.z), w(w) {};
|
||||
Vector4(Vector2 a, Vector2 b) : x(a.x), y(a.y), z(b.x), w(b.y) {};
|
||||
|
||||
// utils functions
|
||||
void set(float x, float y, float z, float w);
|
||||
float length() const; //
|
||||
float distance(const Vector4& vec) const; // distance between two vectors
|
||||
Vector4& normalize(); //
|
||||
float dot(const Vector4& vec) const; // dot product
|
||||
bool equal(const Vector4& vec, float e) const; // compare with epsilon
|
||||
|
||||
// operators
|
||||
Vector4 operator-() const; // unary operator (negate)
|
||||
Vector4 operator+(const Vector4& rhs) const; // add rhs
|
||||
Vector4 operator-(const Vector4& rhs) const; // subtract rhs
|
||||
Vector4& operator+=(const Vector4& rhs); // add rhs and update this object
|
||||
Vector4& operator-=(const Vector4& rhs); // subtract rhs and update this object
|
||||
Vector4 operator*(const float scale) const; // scale
|
||||
Vector4 operator*(const Vector4& rhs) const; // multiply each element
|
||||
Vector4& operator*=(const float scale); // scale and update this object
|
||||
Vector4& operator*=(const Vector4& rhs); // multiply each element and update this object
|
||||
Vector4 operator/(const float scale) const; // inverse scale
|
||||
Vector4& operator/=(const float scale); // scale and update this object
|
||||
bool operator==(const Vector4& rhs) const; // exact compare, no epsilon
|
||||
bool operator!=(const Vector4& rhs) const; // exact compare, no epsilon
|
||||
bool operator<(const Vector4& rhs) const; // comparison for sort
|
||||
float operator[](int index) const; // subscript operator v[0], v[1]
|
||||
float& operator[](int index); // subscript operator v[0], v[1]
|
||||
|
||||
Vector2 GetPosition() { return Vector2(x, y); }
|
||||
Vector2 GetSize() { return Vector2(z, w); }
|
||||
|
||||
friend Vector4 operator*(const float a, const Vector4 vec);
|
||||
friend std::ostream& operator<<(std::ostream& os, const Vector4& vec);
|
||||
};
|
||||
|
||||
|
||||
|
||||
// fast math routines from Doom3 SDK
|
||||
inline float invSqrt(float x)
|
||||
{
|
||||
float xhalf = 0.5f * x;
|
||||
int i = *(int*)&x; // get bits for floating value
|
||||
i = 0x5f3759df - (i>>1); // gives initial guess
|
||||
x = *(float*)&i; // convert bits back to float
|
||||
x = x * (1.5f - xhalf*x*x); // Newton step
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// inline functions for Vector2
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
inline Vector2 Vector2::operator-() const {
|
||||
return Vector2(-x, -y);
|
||||
}
|
||||
|
||||
inline Vector2 Vector2::operator+(const Vector2& rhs) const {
|
||||
return Vector2(x+rhs.x, y+rhs.y);
|
||||
}
|
||||
|
||||
inline Vector2 Vector2::operator-(const Vector2& rhs) const {
|
||||
return Vector2(x-rhs.x, y-rhs.y);
|
||||
}
|
||||
|
||||
inline Vector2& Vector2::operator+=(const Vector2& rhs) {
|
||||
x += rhs.x; y += rhs.y; return *this;
|
||||
}
|
||||
|
||||
inline Vector2& Vector2::operator-=(const Vector2& rhs) {
|
||||
x -= rhs.x; y -= rhs.y; return *this;
|
||||
}
|
||||
|
||||
inline Vector2 Vector2::operator*(const float a) const {
|
||||
return Vector2(x*a, y*a);
|
||||
}
|
||||
|
||||
inline Vector2 Vector2::operator*(const Vector2& rhs) const {
|
||||
return Vector2(x*rhs.x, y*rhs.y);
|
||||
}
|
||||
|
||||
inline Vector2& Vector2::operator*=(const float a) {
|
||||
x *= a; y *= a; return *this;
|
||||
}
|
||||
|
||||
inline Vector2& Vector2::operator*=(const Vector2& rhs) {
|
||||
x *= rhs.x; y *= rhs.y; return *this;
|
||||
}
|
||||
|
||||
inline Vector2 Vector2::operator/(const float a) const {
|
||||
return Vector2(x/a, y/a);
|
||||
}
|
||||
|
||||
inline Vector2& Vector2::operator/=(const float a) {
|
||||
x /= a; y /= a; return *this;
|
||||
}
|
||||
|
||||
inline bool Vector2::operator==(const Vector2& rhs) const {
|
||||
return (x == rhs.x) && (y == rhs.y);
|
||||
}
|
||||
|
||||
inline bool Vector2::operator!=(const Vector2& rhs) const {
|
||||
return (x != rhs.x) || (y != rhs.y);
|
||||
}
|
||||
|
||||
inline bool Vector2::operator<(const Vector2& rhs) const {
|
||||
if(x < rhs.x) return true;
|
||||
if(x > rhs.x) return false;
|
||||
if(y < rhs.y) return true;
|
||||
if(y > rhs.y) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline float Vector2::operator[](int index) const {
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
inline float& Vector2::operator[](int index) {
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
inline void Vector2::set(float x, float y) {
|
||||
this->x = x; this->y = y;
|
||||
}
|
||||
|
||||
inline float Vector2::length() const {
|
||||
return sqrtf(x*x + y*y);
|
||||
}
|
||||
|
||||
inline float Vector2::distance(const Vector2& vec) const {
|
||||
return sqrtf((vec.x-x)*(vec.x-x) + (vec.y-y)*(vec.y-y));
|
||||
}
|
||||
|
||||
inline Vector2& Vector2::normalize() {
|
||||
//@@const float EPSILON = 0.000001f;
|
||||
float xxyy = x*x + y*y;
|
||||
//@@if(xxyy < EPSILON)
|
||||
//@@ return *this;
|
||||
|
||||
//float invLength = invSqrt(xxyy);
|
||||
float invLength = 1.0f / sqrtf(xxyy);
|
||||
x *= invLength;
|
||||
y *= invLength;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline float Vector2::dot(const Vector2& rhs) const {
|
||||
return (x*rhs.x + y*rhs.y);
|
||||
}
|
||||
|
||||
inline bool Vector2::equal(const Vector2& rhs, float epsilon) const {
|
||||
return fabs(x - rhs.x) < epsilon && fabs(y - rhs.y) < epsilon;
|
||||
}
|
||||
|
||||
inline bool Vector2::inside(const Vector2& pos, const Vector2& size) const {
|
||||
return (x >= pos.x and y >= pos.y and x <= (pos.x+size.x) and y <= (pos.y+size.y));
|
||||
}
|
||||
|
||||
inline Vector2 operator*(const float a, const Vector2 vec) {
|
||||
return Vector2(a*vec.x, a*vec.y);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Vector2& vec) {
|
||||
os << "(" << vec.x << ", " << vec.y << ")";
|
||||
return os;
|
||||
}
|
||||
// END OF VECTOR2 /////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// inline functions for Vector3
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
inline Vector3 Vector3::operator-() const {
|
||||
return Vector3(-x, -y, -z);
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator+(const Vector3& rhs) const {
|
||||
return Vector3(x+rhs.x, y+rhs.y, z+rhs.z);
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator-(const Vector3& rhs) const {
|
||||
return Vector3(x-rhs.x, y-rhs.y, z-rhs.z);
|
||||
}
|
||||
|
||||
inline Vector3& Vector3::operator+=(const Vector3& rhs) {
|
||||
x += rhs.x; y += rhs.y; z += rhs.z; return *this;
|
||||
}
|
||||
|
||||
inline Vector3& Vector3::operator-=(const Vector3& rhs) {
|
||||
x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator*(const float a) const {
|
||||
return Vector3(x*a, y*a, z*a);
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator*(const Vector3& rhs) const {
|
||||
return Vector3(x*rhs.x, y*rhs.y, z*rhs.z);
|
||||
}
|
||||
|
||||
inline Vector3& Vector3::operator*=(const float a) {
|
||||
x *= a; y *= a; z *= a; return *this;
|
||||
}
|
||||
|
||||
inline Vector3& Vector3::operator*=(const Vector3& rhs) {
|
||||
x *= rhs.x; y *= rhs.y; z *= rhs.z; return *this;
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::operator/(const float a) const {
|
||||
return Vector3(x/a, y/a, z/a);
|
||||
}
|
||||
|
||||
inline Vector3& Vector3::operator/=(const float a) {
|
||||
x /= a; y /= a; z /= a; return *this;
|
||||
}
|
||||
|
||||
inline bool Vector3::operator==(const Vector3& rhs) const {
|
||||
return (x == rhs.x) && (y == rhs.y) && (z == rhs.z);
|
||||
}
|
||||
|
||||
inline bool Vector3::operator!=(const Vector3& rhs) const {
|
||||
return (x != rhs.x) || (y != rhs.y) || (z != rhs.z);
|
||||
}
|
||||
|
||||
inline bool Vector3::operator<(const Vector3& rhs) const {
|
||||
if(x < rhs.x) return true;
|
||||
if(x > rhs.x) return false;
|
||||
if(y < rhs.y) return true;
|
||||
if(y > rhs.y) return false;
|
||||
if(z < rhs.z) return true;
|
||||
if(z > rhs.z) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline float Vector3::operator[](int index) const {
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
inline float& Vector3::operator[](int index) {
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
inline void Vector3::set(float x, float y, float z) {
|
||||
this->x = x; this->y = y; this->z = z;
|
||||
}
|
||||
|
||||
inline float Vector3::length() const {
|
||||
return sqrtf(x*x + y*y + z*z);
|
||||
}
|
||||
|
||||
inline float Vector3::distance(const Vector3& vec) const {
|
||||
return sqrtf((vec.x-x)*(vec.x-x) + (vec.y-y)*(vec.y-y) + (vec.z-z)*(vec.z-z));
|
||||
}
|
||||
|
||||
inline Vector3& Vector3::normalize() {
|
||||
//@@const float EPSILON = 0.000001f;
|
||||
float xxyyzz = x*x + y*y + z*z;
|
||||
//@@if(xxyyzz < EPSILON)
|
||||
//@@ return *this; // do nothing if it is ~zero vector
|
||||
|
||||
//float invLength = invSqrt(xxyyzz);
|
||||
float invLength = 1.0f / sqrtf(xxyyzz);
|
||||
x *= invLength;
|
||||
y *= invLength;
|
||||
z *= invLength;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline float Vector3::dot(const Vector3& rhs) const {
|
||||
return (x*rhs.x + y*rhs.y + z*rhs.z);
|
||||
}
|
||||
|
||||
inline Vector3 Vector3::cross(const Vector3& rhs) const {
|
||||
return Vector3(y*rhs.z - z*rhs.y, z*rhs.x - x*rhs.z, x*rhs.y - y*rhs.x);
|
||||
}
|
||||
|
||||
inline bool Vector3::equal(const Vector3& rhs, float epsilon) const {
|
||||
return fabs(x - rhs.x) < epsilon && fabs(y - rhs.y) < epsilon && fabs(z - rhs.z) < epsilon;
|
||||
}
|
||||
|
||||
inline Vector3 operator*(const float a, const Vector3 vec) {
|
||||
return Vector3(a*vec.x, a*vec.y, a*vec.z);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Vector3& vec) {
|
||||
os << "(" << vec.x << ", " << vec.y << ", " << vec.z << ")";
|
||||
return os;
|
||||
}
|
||||
// END OF VECTOR3 /////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// inline functions for Vector4
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
inline Vector4 Vector4::operator-() const {
|
||||
return Vector4(-x, -y, -z, -w);
|
||||
}
|
||||
|
||||
inline Vector4 Vector4::operator+(const Vector4& rhs) const {
|
||||
return Vector4(x+rhs.x, y+rhs.y, z+rhs.z, w+rhs.w);
|
||||
}
|
||||
|
||||
inline Vector4 Vector4::operator-(const Vector4& rhs) const {
|
||||
return Vector4(x-rhs.x, y-rhs.y, z-rhs.z, w-rhs.w);
|
||||
}
|
||||
|
||||
inline Vector4& Vector4::operator+=(const Vector4& rhs) {
|
||||
x += rhs.x; y += rhs.y; z += rhs.z; w += rhs.w; return *this;
|
||||
}
|
||||
|
||||
inline Vector4& Vector4::operator-=(const Vector4& rhs) {
|
||||
x -= rhs.x; y -= rhs.y; z -= rhs.z; w -= rhs.w; return *this;
|
||||
}
|
||||
|
||||
inline Vector4 Vector4::operator*(const float a) const {
|
||||
return Vector4(x*a, y*a, z*a, w*a);
|
||||
}
|
||||
|
||||
inline Vector4 Vector4::operator*(const Vector4& rhs) const {
|
||||
return Vector4(x*rhs.x, y*rhs.y, z*rhs.z, w*rhs.w);
|
||||
}
|
||||
|
||||
inline Vector4& Vector4::operator*=(const float a) {
|
||||
x *= a; y *= a; z *= a; w *= a; return *this;
|
||||
}
|
||||
|
||||
inline Vector4& Vector4::operator*=(const Vector4& rhs) {
|
||||
x *= rhs.x; y *= rhs.y; z *= rhs.z; w *= rhs.w; return *this;
|
||||
}
|
||||
|
||||
inline Vector4 Vector4::operator/(const float a) const {
|
||||
return Vector4(x/a, y/a, z/a, w/a);
|
||||
}
|
||||
|
||||
inline Vector4& Vector4::operator/=(const float a) {
|
||||
x /= a; y /= a; z /= a; w /= a; return *this;
|
||||
}
|
||||
|
||||
inline bool Vector4::operator==(const Vector4& rhs) const {
|
||||
return (x == rhs.x) && (y == rhs.y) && (z == rhs.z) && (w == rhs.w);
|
||||
}
|
||||
|
||||
inline bool Vector4::operator!=(const Vector4& rhs) const {
|
||||
return (x != rhs.x) || (y != rhs.y) || (z != rhs.z) || (w != rhs.w);
|
||||
}
|
||||
|
||||
inline bool Vector4::operator<(const Vector4& rhs) const {
|
||||
if(x < rhs.x) return true;
|
||||
if(x > rhs.x) return false;
|
||||
if(y < rhs.y) return true;
|
||||
if(y > rhs.y) return false;
|
||||
if(z < rhs.z) return true;
|
||||
if(z > rhs.z) return false;
|
||||
if(w < rhs.w) return true;
|
||||
if(w > rhs.w) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline float Vector4::operator[](int index) const {
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
inline float& Vector4::operator[](int index) {
|
||||
return (&x)[index];
|
||||
}
|
||||
|
||||
inline void Vector4::set(float x, float y, float z, float w) {
|
||||
this->x = x; this->y = y; this->z = z; this->w = w;
|
||||
}
|
||||
|
||||
inline float Vector4::length() const {
|
||||
return sqrtf(x*x + y*y + z*z + w*w);
|
||||
}
|
||||
|
||||
inline float Vector4::distance(const Vector4& vec) const {
|
||||
return sqrtf((vec.x-x)*(vec.x-x) + (vec.y-y)*(vec.y-y) + (vec.z-z)*(vec.z-z) + (vec.w-w)*(vec.w-w));
|
||||
}
|
||||
|
||||
inline Vector4& Vector4::normalize() {
|
||||
//NOTE: leave w-component untouched
|
||||
//@@const float EPSILON = 0.000001f;
|
||||
float xxyyzz = x*x + y*y + z*z;
|
||||
//@@if(xxyyzz < EPSILON)
|
||||
//@@ return *this; // do nothing if it is zero vector
|
||||
|
||||
//float invLength = invSqrt(xxyyzz);
|
||||
float invLength = 1.0f / sqrtf(xxyyzz);
|
||||
x *= invLength;
|
||||
y *= invLength;
|
||||
z *= invLength;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline float Vector4::dot(const Vector4& rhs) const {
|
||||
return (x*rhs.x + y*rhs.y + z*rhs.z + w*rhs.w);
|
||||
}
|
||||
|
||||
inline bool Vector4::equal(const Vector4& rhs, float epsilon) const {
|
||||
return fabs(x - rhs.x) < epsilon && fabs(y - rhs.y) < epsilon &&
|
||||
fabs(z - rhs.z) < epsilon && fabs(w - rhs.w) < epsilon;
|
||||
}
|
||||
|
||||
inline Vector4 operator*(const float a, const Vector4 vec) {
|
||||
return Vector4(a*vec.x, a*vec.y, a*vec.z, a*vec.w);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Vector4& vec) {
|
||||
os << "(" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ")";
|
||||
return os;
|
||||
}
|
||||
// END OF VECTOR4 /////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
41
application.cpp
Normal file
41
application.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "application.h"
|
||||
|
||||
//#include "model.h"
|
||||
//#include "console.h"
|
||||
|
||||
namespace Application
|
||||
{
|
||||
bool quit {false};
|
||||
char dirty {1};
|
||||
|
||||
const bool& ShouldQuit()
|
||||
{
|
||||
return quit;
|
||||
}
|
||||
|
||||
void Quit()
|
||||
{
|
||||
//if (Model::IsModified()) {
|
||||
// Console::Ask("SAVE BEFORE QUITTING (YES/NO/CANCEL)?", Application::QuitHandler);
|
||||
//} else {
|
||||
quit = true;
|
||||
//}
|
||||
}
|
||||
|
||||
void QuitHandler(const char* reply)
|
||||
{
|
||||
//if (reply[0] == 'Y') {
|
||||
// Model::Save();
|
||||
//} else if (reply[0] == 'N') {
|
||||
// quit = true;
|
||||
//}
|
||||
}
|
||||
|
||||
bool NeedsUpdate(const char cycles)
|
||||
{
|
||||
if (cycles > 0 and cycles > dirty) dirty = cycles;
|
||||
return dirty > 0;
|
||||
}
|
||||
|
||||
void Updated() { if (dirty > 0) dirty--; }
|
||||
}
|
||||
10
application.h
Normal file
10
application.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace Application
|
||||
{
|
||||
void Quit();
|
||||
const bool& ShouldQuit();
|
||||
void QuitHandler(const char* reply);
|
||||
bool NeedsUpdate(const char cycles = 2);
|
||||
void Updated();
|
||||
}
|
||||
14
common.h
Normal file
14
common.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Vectors.h"
|
||||
#include "Matrices.h"
|
||||
#include "geometry.h"
|
||||
|
||||
#define QUERY 0
|
||||
#define ON 1
|
||||
#define OFF 2
|
||||
#define YES ON
|
||||
#define NO OFF
|
||||
|
||||
#define Swap(x, y) { x -= y = (x += y) - y; }
|
||||
108
font.cpp
Normal file
108
font.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "font.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
#include "texture.h"
|
||||
#include "renderer.h"
|
||||
|
||||
static float colors[16][4] = {
|
||||
{0, 0, 0, 1},
|
||||
{0.5f, 0, 0, 1},
|
||||
{0, 0.5f, 0, 1},
|
||||
{0.5f, 0.5f, 0, 1},
|
||||
{0, 0, 0.5f, 1},
|
||||
{0.5f, 0, 0.5f, 1},
|
||||
{0, 0.5f, 0.5f, 1},
|
||||
{0.75f, 0.75f, 0.75f, 1},
|
||||
{0.5f, 0.5f, 0.5f, 1},
|
||||
{1, 0, 0, 1},
|
||||
{0, 1, 0, 1},
|
||||
{1, 1, 0, 1},
|
||||
{0, 0, 1, 1},
|
||||
{1, 0, 1, 1},
|
||||
{0, 1, 1, 1},
|
||||
{1, 1, 1, 1},
|
||||
};
|
||||
|
||||
void Font::Load(const char* filename)
|
||||
{
|
||||
char name[16]; strcpy(name, filename); strcat(name, ".fnt");
|
||||
|
||||
FILE* fin = fopen(name, "ra");
|
||||
if (fin == NULL) return;
|
||||
|
||||
char line[256];
|
||||
|
||||
fgets(line, 255, fin);
|
||||
fgets(line, 255, fin);
|
||||
int lh, sw, sh;
|
||||
assert(sscanf(line, "common lineHeight=%i base=%*i scaleW=%i scaleH=%i", &lh, &sw, &sh) == 3);
|
||||
lineHeight = lh;
|
||||
bw = sw;
|
||||
bh = sh;
|
||||
|
||||
fgets(line, 255, fin);
|
||||
fgets(line, 255, fin);
|
||||
int numChars;
|
||||
assert(sscanf(line, "chars count=%i", &numChars) == 1);
|
||||
|
||||
for (int i = 0; i < numChars; i++) {
|
||||
fgets(line, 255, fin);
|
||||
int id, x, y, w, h, xo, yo, xa;
|
||||
assert(sscanf(line, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i", &id, &x, &y, &w, &h, &xo, &yo, &xa) == 8);
|
||||
FontChar& c = chars[id-32];
|
||||
c.w = w;
|
||||
c.h = h;
|
||||
c.x1 = float(x)/float(bw);
|
||||
c.y1 = float(y)/float(bh);
|
||||
c.x2 = c.x1 + float(w)/float(bw);
|
||||
c.y2 = c.y1 + float(h)/float(bh);;
|
||||
c.xo = xo;
|
||||
c.yo = yo;
|
||||
c.xa = xa;
|
||||
}
|
||||
|
||||
texture = Texture::Create();
|
||||
Texture::Load(texture, filename);
|
||||
fclose(fin);
|
||||
}
|
||||
|
||||
void Font::Print(int x, int y, const char* text, char color)
|
||||
{
|
||||
const unsigned long len = strlen(text);
|
||||
|
||||
Renderer::SetState(RENDER_FILL | RENDER_BLEND | RENDER_TEXTURE);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glBegin(GL_QUADS);
|
||||
glColor4fv(colors[color]);
|
||||
for (int i = 0; i < len; i++) {
|
||||
FontChar& c = chars[text[i]-32];
|
||||
glTexCoord2f(c.x1, c.y1);
|
||||
glVertex2i(x+c.xo, y+c.yo);
|
||||
glTexCoord2f(c.x1, c.y2);
|
||||
glVertex2i(x+c.xo, y+c.yo+c.h);
|
||||
glTexCoord2f(c.x2, c.y2);
|
||||
glVertex2i(x+c.xo+c.w, y+c.yo+c.h);
|
||||
glTexCoord2f(c.x2, c.y1);
|
||||
glVertex2i(x+c.xo+c.w, y+c.yo);
|
||||
x += c.xa;
|
||||
}
|
||||
glEnd();
|
||||
|
||||
}
|
||||
|
||||
Vector2 Font::GetSize(const char* text)
|
||||
{
|
||||
Vector2 size;
|
||||
size.y = lineHeight;
|
||||
const unsigned long len = strlen(text);
|
||||
for (int i = 0; i < len; i++) {
|
||||
//if (i == len-1) {
|
||||
// size.x += chars[text[i]-32].w;
|
||||
//} else {
|
||||
size.x += chars[text[i]-32].xa;
|
||||
//}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
99
font.fnt
Normal file
99
font.fnt
Normal file
@@ -0,0 +1,99 @@
|
||||
info face="Segoe UI" size=14 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=0,0
|
||||
common lineHeight=19 base=15 scaleW=128 scaleH=128 pages=1 packed=0
|
||||
page id=0 file="font.png"
|
||||
chars count=95
|
||||
char id=32 x=40 y=76 width=0 height=0 xoffset=0 yoffset=15 xadvance=4 page=0 chnl=0 letter="space"
|
||||
char id=33 x=58 y=54 width=4 height=12 xoffset=1 yoffset=3 xadvance=4 page=0 chnl=0 letter="!"
|
||||
char id=34 x=121 y=66 width=6 height=6 xoffset=1 yoffset=2 xadvance=5 page=0 chnl=0 letter="""
|
||||
char id=35 x=62 y=54 width=10 height=11 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=0 letter="#"
|
||||
char id=36 x=22 y=0 width=8 height=15 xoffset=1 yoffset=1 xadvance=8 page=0 chnl=0 letter="$"
|
||||
char id=37 x=94 y=0 width=13 height=13 xoffset=1 yoffset=2 xadvance=11 page=0 chnl=0 letter="%"
|
||||
char id=38 x=107 y=0 width=13 height=13 xoffset=1 yoffset=2 xadvance=11 page=0 chnl=0 letter="&"
|
||||
char id=39 x=4 y=76 width=4 height=6 xoffset=1 yoffset=2 xadvance=3 page=0 chnl=0 letter="'"
|
||||
char id=40 x=30 y=0 width=6 height=15 xoffset=1 yoffset=2 xadvance=4 page=0 chnl=0 letter="("
|
||||
char id=41 x=36 y=0 width=6 height=15 xoffset=0 yoffset=2 xadvance=4 page=0 chnl=0 letter=")"
|
||||
char id=42 x=105 y=66 width=7 height=7 xoffset=1 yoffset=3 xadvance=6 page=0 chnl=0 letter="*"
|
||||
char id=43 x=63 y=66 width=9 height=9 xoffset=2 yoffset=5 xadvance=10 page=0 chnl=0 letter="+"
|
||||
char id=44 x=0 y=76 width=4 height=6 xoffset=0 yoffset=11 xadvance=3 page=0 chnl=0 letter=","
|
||||
char id=45 x=34 y=76 width=6 height=3 xoffset=1 yoffset=9 xadvance=6 page=0 chnl=0 letter="-"
|
||||
char id=46 x=22 y=76 width=4 height=4 xoffset=1 yoffset=11 xadvance=3 page=0 chnl=0 letter="."
|
||||
char id=47 x=78 y=0 width=8 height=14 xoffset=-0 yoffset=3 xadvance=5 page=0 chnl=0 letter="/"
|
||||
char id=48 x=59 y=16 width=9 height=13 xoffset=1 yoffset=2 xadvance=8 page=0 chnl=0 letter="0"
|
||||
char id=49 x=32 y=29 width=8 height=13 xoffset=1 yoffset=2 xadvance=8 page=0 chnl=0 letter="1"
|
||||
char id=50 x=115 y=42 width=8 height=12 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=0 letter="2"
|
||||
char id=51 x=8 y=29 width=8 height=13 xoffset=1 yoffset=2 xadvance=8 page=0 chnl=0 letter="3"
|
||||
char id=52 x=88 y=42 width=9 height=12 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=0 letter="4"
|
||||
char id=53 x=8 y=54 width=8 height=12 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=0 letter="5"
|
||||
char id=54 x=68 y=16 width=9 height=13 xoffset=1 yoffset=2 xadvance=8 page=0 chnl=0 letter="6"
|
||||
char id=55 x=106 y=42 width=9 height=12 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=0 letter="7"
|
||||
char id=56 x=77 y=16 width=9 height=13 xoffset=1 yoffset=2 xadvance=8 page=0 chnl=0 letter="8"
|
||||
char id=57 x=86 y=16 width=9 height=13 xoffset=1 yoffset=2 xadvance=8 page=0 chnl=0 letter="9"
|
||||
char id=58 x=29 y=66 width=4 height=10 xoffset=1 yoffset=5 xadvance=3 page=0 chnl=0 letter=":"
|
||||
char id=59 x=72 y=54 width=5 height=11 xoffset=0 yoffset=6 xadvance=3 page=0 chnl=0 letter=";"
|
||||
char id=60 x=72 y=66 width=8 height=9 xoffset=2 yoffset=5 xadvance=10 page=0 chnl=0 letter="<"
|
||||
char id=61 x=112 y=66 width=9 height=6 xoffset=2 yoffset=7 xadvance=10 page=0 chnl=0 letter="="
|
||||
char id=62 x=80 y=66 width=8 height=9 xoffset=2 yoffset=5 xadvance=10 page=0 chnl=0 letter=">"
|
||||
char id=63 x=40 y=29 width=7 height=13 xoffset=1 yoffset=2 xadvance=6 page=0 chnl=0 letter="?"
|
||||
char id=64 x=64 y=0 width=14 height=14 xoffset=1 yoffset=2 xadvance=13 page=0 chnl=0 letter="@"
|
||||
char id=65 x=89 y=29 width=11 height=12 xoffset=0 yoffset=3 xadvance=9 page=0 chnl=0 letter="A"
|
||||
char id=66 x=97 y=42 width=9 height=12 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=0 letter="B"
|
||||
char id=67 x=22 y=16 width=10 height=13 xoffset=1 yoffset=2 xadvance=9 page=0 chnl=0 letter="C"
|
||||
char id=68 x=111 y=29 width=10 height=12 xoffset=1 yoffset=3 xadvance=10 page=0 chnl=0 letter="D"
|
||||
char id=69 x=16 y=54 width=8 height=12 xoffset=1 yoffset=3 xadvance=7 page=0 chnl=0 letter="E"
|
||||
char id=70 x=32 y=54 width=7 height=12 xoffset=1 yoffset=3 xadvance=7 page=0 chnl=0 letter="F"
|
||||
char id=71 x=12 y=16 width=10 height=13 xoffset=1 yoffset=2 xadvance=10 page=0 chnl=0 letter="G"
|
||||
char id=72 x=40 y=42 width=10 height=12 xoffset=1 yoffset=3 xadvance=10 page=0 chnl=0 letter="H"
|
||||
char id=73 x=52 y=54 width=6 height=12 xoffset=0 yoffset=3 xadvance=4 page=0 chnl=0 letter="I"
|
||||
char id=74 x=46 y=54 width=6 height=12 xoffset=0 yoffset=3 xadvance=5 page=0 chnl=0 letter="J"
|
||||
char id=75 x=79 y=42 width=9 height=12 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=0 letter="K"
|
||||
char id=76 x=24 y=54 width=8 height=12 xoffset=1 yoffset=3 xadvance=7 page=0 chnl=0 letter="L"
|
||||
char id=77 x=77 y=29 width=12 height=12 xoffset=1 yoffset=3 xadvance=13 page=0 chnl=0 letter="M"
|
||||
char id=78 x=0 y=42 width=10 height=12 xoffset=1 yoffset=3 xadvance=10 page=0 chnl=0 letter="N"
|
||||
char id=79 x=0 y=16 width=12 height=13 xoffset=1 yoffset=2 xadvance=11 page=0 chnl=0 letter="O"
|
||||
char id=80 x=0 y=54 width=8 height=12 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=0 letter="P"
|
||||
char id=81 x=10 y=0 width=12 height=15 xoffset=1 yoffset=3 xadvance=11 page=0 chnl=0 letter="Q"
|
||||
char id=82 x=50 y=42 width=10 height=12 xoffset=1 yoffset=3 xadvance=8 page=0 chnl=0 letter="R"
|
||||
char id=83 x=0 y=29 width=8 height=13 xoffset=1 yoffset=2 xadvance=7 page=0 chnl=0 letter="S"
|
||||
char id=84 x=70 y=42 width=9 height=12 xoffset=0 yoffset=3 xadvance=7 page=0 chnl=0 letter="T"
|
||||
char id=85 x=20 y=42 width=10 height=12 xoffset=1 yoffset=3 xadvance=10 page=0 chnl=0 letter="U"
|
||||
char id=86 x=100 y=29 width=11 height=12 xoffset=0 yoffset=3 xadvance=9 page=0 chnl=0 letter="V"
|
||||
char id=87 x=62 y=29 width=15 height=12 xoffset=0 yoffset=3 xadvance=13 page=0 chnl=0 letter="W"
|
||||
char id=88 x=10 y=42 width=10 height=12 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=0 letter="X"
|
||||
char id=89 x=30 y=42 width=10 height=12 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=0 letter="Y"
|
||||
char id=90 x=60 y=42 width=10 height=12 xoffset=0 yoffset=3 xadvance=8 page=0 chnl=0 letter="Z"
|
||||
char id=91 x=54 y=0 width=5 height=15 xoffset=1 yoffset=2 xadvance=4 page=0 chnl=0 letter="["
|
||||
char id=92 x=86 y=0 width=8 height=14 xoffset=-0 yoffset=3 xadvance=5 page=0 chnl=0 letter="\"
|
||||
char id=93 x=59 y=0 width=5 height=15 xoffset=0 yoffset=2 xadvance=4 page=0 chnl=0 letter="]"
|
||||
char id=94 x=96 y=66 width=9 height=8 xoffset=2 yoffset=3 xadvance=10 page=0 chnl=0 letter="^"
|
||||
char id=95 x=26 y=76 width=8 height=3 xoffset=0 yoffset=14 xadvance=6 page=0 chnl=0 letter="_"
|
||||
char id=96 x=17 y=76 width=5 height=5 xoffset=1 yoffset=2 xadvance=4 page=0 chnl=0 letter="`"
|
||||
char id=97 x=107 y=54 width=8 height=10 xoffset=1 yoffset=5 xadvance=7 page=0 chnl=0 letter="a"
|
||||
char id=98 x=41 y=16 width=9 height=13 xoffset=1 yoffset=2 xadvance=8 page=0 chnl=0 letter="b"
|
||||
char id=99 x=8 y=66 width=8 height=10 xoffset=1 yoffset=5 xadvance=6 page=0 chnl=0 letter="c"
|
||||
char id=100 x=50 y=16 width=9 height=13 xoffset=1 yoffset=2 xadvance=8 page=0 chnl=0 letter="d"
|
||||
char id=101 x=98 y=54 width=9 height=10 xoffset=1 yoffset=5 xadvance=7 page=0 chnl=0 letter="e"
|
||||
char id=102 x=47 y=29 width=7 height=13 xoffset=0 yoffset=2 xadvance=4 page=0 chnl=0 letter="f"
|
||||
char id=103 x=95 y=16 width=9 height=13 xoffset=1 yoffset=5 xadvance=8 page=0 chnl=0 letter="g"
|
||||
char id=104 x=24 y=29 width=8 height=13 xoffset=1 yoffset=2 xadvance=8 page=0 chnl=0 letter="h"
|
||||
char id=105 x=54 y=29 width=4 height=13 xoffset=1 yoffset=2 xadvance=3 page=0 chnl=0 letter="i"
|
||||
char id=106 x=0 y=0 width=6 height=16 xoffset=-1 yoffset=2 xadvance=3 page=0 chnl=0 letter="j"
|
||||
char id=107 x=16 y=29 width=8 height=13 xoffset=1 yoffset=2 xadvance=7 page=0 chnl=0 letter="k"
|
||||
char id=108 x=58 y=29 width=4 height=13 xoffset=1 yoffset=2 xadvance=3 page=0 chnl=0 letter="l"
|
||||
char id=109 x=77 y=54 width=12 height=10 xoffset=1 yoffset=5 xadvance=12 page=0 chnl=0 letter="m"
|
||||
char id=110 x=115 y=54 width=8 height=10 xoffset=1 yoffset=5 xadvance=8 page=0 chnl=0 letter="n"
|
||||
char id=111 x=89 y=54 width=9 height=10 xoffset=1 yoffset=5 xadvance=8 page=0 chnl=0 letter="o"
|
||||
char id=112 x=104 y=16 width=9 height=13 xoffset=1 yoffset=5 xadvance=8 page=0 chnl=0 letter="p"
|
||||
char id=113 x=113 y=16 width=9 height=13 xoffset=1 yoffset=5 xadvance=8 page=0 chnl=0 letter="q"
|
||||
char id=114 x=23 y=66 width=6 height=10 xoffset=1 yoffset=5 xadvance=5 page=0 chnl=0 letter="r"
|
||||
char id=115 x=16 y=66 width=7 height=10 xoffset=1 yoffset=5 xadvance=6 page=0 chnl=0 letter="s"
|
||||
char id=116 x=39 y=54 width=7 height=12 xoffset=0 yoffset=3 xadvance=5 page=0 chnl=0 letter="t"
|
||||
char id=117 x=0 y=66 width=8 height=10 xoffset=1 yoffset=5 xadvance=8 page=0 chnl=0 letter="u"
|
||||
char id=118 x=45 y=66 width=9 height=9 xoffset=0 yoffset=6 xadvance=7 page=0 chnl=0 letter="v"
|
||||
char id=119 x=33 y=66 width=12 height=9 xoffset=0 yoffset=6 xadvance=10 page=0 chnl=0 letter="w"
|
||||
char id=120 x=54 y=66 width=9 height=9 xoffset=0 yoffset=6 xadvance=6 page=0 chnl=0 letter="x"
|
||||
char id=121 x=32 y=16 width=9 height=13 xoffset=0 yoffset=5 xadvance=7 page=0 chnl=0 letter="y"
|
||||
char id=122 x=88 y=66 width=8 height=9 xoffset=0 yoffset=6 xadvance=6 page=0 chnl=0 letter="z"
|
||||
char id=123 x=42 y=0 width=6 height=15 xoffset=1 yoffset=2 xadvance=4 page=0 chnl=0 letter="{"
|
||||
char id=124 x=6 y=0 width=4 height=16 xoffset=1 yoffset=2 xadvance=3 page=0 chnl=0 letter="|"
|
||||
char id=125 x=48 y=0 width=6 height=15 xoffset=0 yoffset=2 xadvance=4 page=0 chnl=0 letter="}"
|
||||
char id=126 x=8 y=76 width=9 height=5 xoffset=1 yoffset=7 xadvance=10 page=0 chnl=0 letter="~"
|
||||
21
font.h
Normal file
21
font.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
struct FontChar
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
char w, h, xo, yo, xa;
|
||||
};
|
||||
|
||||
struct Font
|
||||
{
|
||||
char lineHeight;
|
||||
unsigned char bw, bh;
|
||||
FontChar chars[96];
|
||||
unsigned texture;
|
||||
|
||||
void Load(const char* filename);
|
||||
void Print(int x, int y, const char* text, char color = 15);
|
||||
Vector2 GetSize(const char* text);
|
||||
};
|
||||
26
geometry.cpp
Normal file
26
geometry.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "geometry.h"
|
||||
|
||||
Vector3 calculate_normal(const Vector3& v1, const Vector3& v2, const Vector3& v3)
|
||||
{
|
||||
Vector3 normal;
|
||||
const Vector3 U = v2 - v1;
|
||||
const Vector3 V = v3 - v1;
|
||||
|
||||
normal.x = U.y * V.z - U.z * V.y;
|
||||
normal.y = U.z * V.x - U.x * V.z;
|
||||
normal.z = U.x * V.y - U.y * V.x;
|
||||
|
||||
return normal.normalize();
|
||||
}
|
||||
|
||||
const float random(const float& rangeMin, const float& rangeMax)
|
||||
{
|
||||
const float range = rangeMax - rangeMin;
|
||||
return rangeMin + (float(rand())/float(RAND_MAX))*range;
|
||||
}
|
||||
|
||||
const float random_int(const int& rangeMin, const int& rangeMax)
|
||||
{
|
||||
const int range = rangeMax - rangeMin;
|
||||
return rangeMin + (rand() % range);
|
||||
}
|
||||
85
geometry.h
Normal file
85
geometry.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include "Vectors.h"
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
#include <list>
|
||||
|
||||
#define MAX(x, y) x > y ? x : y
|
||||
#define MIN(x, y) x < y ? x : y
|
||||
|
||||
#define List std::list
|
||||
|
||||
template<typename T>
|
||||
class Array
|
||||
{
|
||||
public:
|
||||
Array() : m_allocated(1000), m_dynamic(true)
|
||||
{
|
||||
m_values = (T*)malloc(sizeof(T)*m_allocated);
|
||||
}
|
||||
Array(int size, bool dynamic) : m_allocated(size), m_dynamic(dynamic)
|
||||
{
|
||||
m_values = (T*)malloc(sizeof(T)*m_allocated);
|
||||
}
|
||||
Array(const Array<T>& other) : m_allocated(other.m_filled), m_dynamic(other.m_dynamic)
|
||||
{
|
||||
m_filled = other.m_filled;
|
||||
m_allocated = other.m_filled;
|
||||
m_values = (T*)malloc(sizeof(T)*m_allocated);
|
||||
memcpy((T*)m_values, (T*)other.m_values, sizeof(T)*m_filled);
|
||||
}
|
||||
~Array() { free(m_values); }
|
||||
void Prealloc(int size)
|
||||
{
|
||||
m_allocated = size;
|
||||
m_values = (T*)realloc(m_values, sizeof(T)*m_allocated);
|
||||
}
|
||||
const int push_back(const T& value)
|
||||
{
|
||||
if (m_filled >= m_allocated) {
|
||||
if (not m_dynamic) {assert(false); }
|
||||
if (m_allocated == 0) m_allocated = 1; else m_allocated*=2;
|
||||
m_values = (T*)realloc(m_values, sizeof(T)*m_allocated);
|
||||
}
|
||||
m_values[m_filled++] = value;
|
||||
|
||||
return m_filled-1;
|
||||
}
|
||||
void remove_simple(int index)
|
||||
{
|
||||
assert(index < m_filled);
|
||||
m_filled--;
|
||||
if (index != m_filled) m_values[index] = m_values[m_filled];
|
||||
}
|
||||
const int exists(const T& value) const
|
||||
{
|
||||
for (int i = 0; i < m_filled; i++) if (m_values[i] == value) return i;
|
||||
return -1;
|
||||
}
|
||||
void clear() { m_filled = 0; }
|
||||
const unsigned size() const { return m_filled; }
|
||||
const bool empty() const { return m_filled == 0; }
|
||||
T operator[](int index) const { return m_values[index]; }
|
||||
T& operator[](int index) { return m_values[index]; }
|
||||
Array<T>& operator=( const Array<T>& other ) {
|
||||
if (other.m_filled > m_allocated) {
|
||||
m_values = (T*)realloc(m_values, sizeof(T)*other.m_filled);
|
||||
}
|
||||
m_allocated = other.m_filled;
|
||||
m_filled = other.m_filled;
|
||||
m_dynamic = other.m_dynamic;
|
||||
memcpy(m_values, other.m_values, sizeof(T)*m_filled);
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
unsigned m_allocated{0};
|
||||
unsigned m_filled{0};
|
||||
bool m_dynamic{true};
|
||||
T* m_values{nullptr};
|
||||
};
|
||||
|
||||
Vector3 calculate_normal(const Vector3& v1, const Vector3& v2, const Vector3& v3);
|
||||
|
||||
const float random(const float& rangeMin, const float& rangeMax);
|
||||
const float random_int(const int& rangeMin, const int& rangeMax);
|
||||
77
grid.cpp
Normal file
77
grid.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "grid.h"
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
|
||||
//#include "viewport.h"
|
||||
#include "renderer.h"
|
||||
|
||||
namespace Grid
|
||||
{
|
||||
bool visible = true;
|
||||
|
||||
void Toggle()
|
||||
{
|
||||
visible = not visible;
|
||||
}
|
||||
|
||||
void Draw(const char viewport, int size)
|
||||
{
|
||||
if (not visible) return;
|
||||
|
||||
int planeOffset = 0;
|
||||
char axis = 1; //AXIS_Y;
|
||||
/* Viewport::Viewport v = Viewport::GetViewport(viewport);
|
||||
if (v.perspective == Viewport::Perspective::Ortho) {
|
||||
if (v.yaw == 0 and v.pitch == 90) {
|
||||
planeOffset = 999;
|
||||
axis = AXIS_Y;
|
||||
} else if (v.yaw == 0 and v.pitch == -90) {
|
||||
planeOffset = -999;
|
||||
axis = AXIS_Y;
|
||||
} else if (v.yaw == 90 and v.pitch == 0) {
|
||||
planeOffset = -999;
|
||||
axis = AXIS_X;
|
||||
} else if (v.yaw == -90 and v.pitch == 0) {
|
||||
planeOffset = 999;
|
||||
axis = AXIS_X;
|
||||
} else if (v.yaw == 0 and v.pitch == 0) {
|
||||
planeOffset = 999;
|
||||
axis = AXIS_Z;
|
||||
} else if (v.yaw == 180 and v.pitch == 0) {
|
||||
planeOffset = -999;
|
||||
axis = AXIS_Z;
|
||||
}
|
||||
}
|
||||
*/
|
||||
const char axis_x = 0; //axis == AXIS_Z ? AXIS_X : axis == AXIS_X ? AXIS_Z : AXIS_X;
|
||||
const char axis_y = 1; //axis == AXIS_Z ? AXIS_Y : axis == AXIS_X ? AXIS_Y : AXIS_Z;
|
||||
|
||||
|
||||
Renderer::Push();
|
||||
Renderer::Light(OFF);
|
||||
Renderer::Depth(OFF);
|
||||
if (size == 0) size = planeOffset == 0 ? 20 : 30;
|
||||
glBegin(GL_LINES);
|
||||
for (int i = -size; i <= size; i++) {
|
||||
if (i == 0) {
|
||||
glColor4f(0.5f, 0.5f, 0.5f, 1);
|
||||
} else {
|
||||
glColor4f(0.25f, 0.25f, 0.25f, 1);
|
||||
}
|
||||
char pos[2][3] {{0,0,0}, {0,0,0}};
|
||||
pos[0][axis_x] = -size;
|
||||
pos[1][axis_x] = size;
|
||||
pos[0][axis_y] = pos[1][axis_y] = i;
|
||||
pos[0][axis] = pos[1][axis] = planeOffset;
|
||||
glVertex3f(pos[0][0], pos[0][1], pos[0][2]);
|
||||
glVertex3f(pos[1][0], pos[1][1], pos[1][2]);
|
||||
pos[0][axis_y] = -size;
|
||||
pos[1][axis_y] = size;
|
||||
pos[0][axis_x] = pos[1][axis_x] = i;
|
||||
pos[0][axis] = pos[1][axis] = planeOffset;
|
||||
glVertex3f(pos[0][0], pos[0][1], pos[0][2]);
|
||||
glVertex3f(pos[1][0], pos[1][1], pos[1][2]);
|
||||
}
|
||||
glEnd();
|
||||
Renderer::Pop();
|
||||
}
|
||||
}
|
||||
7
grid.h
Normal file
7
grid.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
namespace Grid
|
||||
{
|
||||
void Toggle();
|
||||
void Draw(const char viewport, int size = 0);
|
||||
}
|
||||
5
lagueirtofile
Normal file
5
lagueirtofile
Normal file
@@ -0,0 +1,5 @@
|
||||
libs = -lSDL2 -lGL
|
||||
cppflags = -D DEBUG -g
|
||||
executable = biomed_debug
|
||||
sourcepath = .
|
||||
buildpath = build
|
||||
156
main.cpp
Normal file
156
main.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "screen.h"
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
|
||||
#include "application.h"
|
||||
//#include "console.h"
|
||||
//#include "interpreter.h"
|
||||
//#include "worker.h"
|
||||
//#include "layout.h"
|
||||
//#include "texture.h"
|
||||
//#include "turtle.h"
|
||||
//#include "keystrokes.h"
|
||||
#include "GUI.h"
|
||||
#include "GUIMouse.h"
|
||||
#include "GUIKeyboard.h"
|
||||
#include "font.h"
|
||||
#include "GUIViewport.h"
|
||||
#include "Editor.h"
|
||||
#include "texture.h"
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
// SDL INIT
|
||||
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { puts("SDL_Init error"); return -1; }
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
|
||||
SDL_Window* gWindow = SDL_CreateWindow("BiomED", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
||||
if (gWindow == NULL) { puts("SDL_CreateWindow error"); return -1; }
|
||||
|
||||
SDL_GLContext gContext = SDL_GL_CreateContext(gWindow);
|
||||
if (gContext == NULL) { puts("SDL_GL_CreateContext error"); return -1; }
|
||||
|
||||
if (SDL_GL_SetSwapInterval(1) < 0) { puts("WARNING: no vsync!"); }
|
||||
|
||||
|
||||
// OPENGL INIT
|
||||
|
||||
glClearColor(0.12f, 0.12f, 0.12f, 1.0f);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glClearDepth(1.0f);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
glEnable(GL_NORMALIZE);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
glEnable(GL_LIGHT0);
|
||||
//static const GLfloat LightPosition[]= {0.408248f, 0.408248f, -0.816497f, 0.0f};//{ 0.5f, 0.5f, 1.0f, 0.0f }; // 5 4 2 0
|
||||
static const GLfloat LightPosition[]= {0, 0, -1.0f, 0.0f};//{ 0.5f, 0.5f, 1.0f, 0.0f }; // 5 4 2 0
|
||||
static const GLfloat LightAmbient[]= { 0.2f, 0.2f, 0.2f, 1.0f };
|
||||
static const GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
|
||||
|
||||
|
||||
// SUBSYSTEMS INIT
|
||||
|
||||
//Console::Init();
|
||||
//Worker::RegisterCommands();
|
||||
//Layout::Load("_last", SILENT);
|
||||
//Texture::texture = Texture::Create();
|
||||
//Turtle::Clear();
|
||||
|
||||
Editor::texture = Texture::Create(32, 32);
|
||||
for (int i = 0; i < 32*32*4; i++) Editor::bitmap[i] = 255;
|
||||
Texture::Update(Editor::texture, 32, 32, Editor::bitmap);
|
||||
|
||||
Font* f = new Font();
|
||||
f->Load("font");
|
||||
|
||||
viewports[1].rotation = {0,0};
|
||||
|
||||
// MAIN LOOP
|
||||
|
||||
SDL_Event e;
|
||||
while (not Application::ShouldQuit()) {
|
||||
|
||||
// SDL EVENTS
|
||||
|
||||
while (SDL_PollEvent(&e) != 0) {
|
||||
if (e.type == SDL_QUIT) {
|
||||
Application::Quit();
|
||||
} else if (e.type == SDL_WINDOWEVENT) {
|
||||
if (e.window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||
SCREEN_WIDTH = e.window.data1;
|
||||
SCREEN_HEIGHT = e.window.data2;
|
||||
//GUIElement::root->SetSize(Vector2(e.window.data1, e.window.data2));
|
||||
//} else if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
|
||||
// GUIState::NeedsRedraw();
|
||||
}
|
||||
} else if (e.type == SDL_MOUSEMOTION) {
|
||||
GUIMouse::ReceiveMouseMoveEvent(e.motion.x, e.motion.y);
|
||||
} else if (e.type == SDL_MOUSEBUTTONDOWN) {
|
||||
GUIMouse::Button b = e.button.button == 1 ? GUIMouse::Button::Left : e.button.button == 2 ? GUIMouse::Button::Middle : GUIMouse::Button::Right;
|
||||
GUIMouse::ReceiveMouseDownEvent(b);
|
||||
} else if (e.type == SDL_MOUSEBUTTONUP) {
|
||||
GUIMouse::Button b = e.button.button == 1 ? GUIMouse::Button::Left : e.button.button == 2 ? GUIMouse::Button::Middle : GUIMouse::Button::Right;
|
||||
GUIMouse::ReceiveMouseUpEvent(b);
|
||||
} else if (e.type == SDL_KEYDOWN) {
|
||||
GUIKeyboard::ReceiveKeyboardEvent(e.key.keysym.sym);
|
||||
} else if (e.type == SDL_KEYUP) {
|
||||
GUIKeyboard::ReceiveKeyboardEvent(SDLK_UNKNOWN);
|
||||
} else if (e.type == SDL_MOUSEWHEEL) {
|
||||
GUIMouse::ReceiveMouseWheelEvent(e.wheel.x, e.wheel.y);
|
||||
} else if (e.type == SDL_MULTIGESTURE) {
|
||||
printf("GESTURE: %.2f, %.2f, %i\n", e.mgesture.dTheta*100, e.mgesture.dDist*100, e.mgesture.numFingers);
|
||||
GUIMouse::ReceiveMultigestureEvent(e.mgesture.dTheta, e.mgesture.dDist, e.mgesture.numFingers);
|
||||
}
|
||||
/*if (Console::Enable(QUERY)) {
|
||||
if (e.type == SDL_TEXTINPUT) {
|
||||
Console::PutChar(toupper(e.text.text[0]));
|
||||
//printf("%c",e.text.text[0]);
|
||||
} else if (e.type == SDL_KEYDOWN) {
|
||||
if (e.key.keysym.sym == SDLK_RETURN) {
|
||||
char command[80];
|
||||
Console::Enter(command);
|
||||
Worker::ExecuteCommand(Interpreter::Do(command));
|
||||
} else if (e.key.keysym.sym == SDLK_BACKSPACE) {
|
||||
Console::DelChar();
|
||||
} else if (e.key.keysym.sym == SDLK_UP) {
|
||||
Console::PrevComm();
|
||||
} else if (e.key.keysym.sym == SDLK_DOWN) {
|
||||
Console::NextComm();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (e.type == SDL_KEYDOWN) {
|
||||
Keystrokes::KeyPressed(e.key.keysym.sym);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
// DRAW
|
||||
|
||||
if (Application::NeedsUpdate(0)) {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
//GUIState::Update();
|
||||
GUI::Draw();
|
||||
//Layout::Draw();
|
||||
//Console::Draw();
|
||||
|
||||
SDL_GL_SwapWindow(gWindow);
|
||||
glClearColor(0.12f, 0.12f, 0.12f, 1.0f);
|
||||
Application::Updated();
|
||||
GUIMouse::Reset();
|
||||
GUIKeyboard::Reset();
|
||||
}
|
||||
}
|
||||
|
||||
//Layout::Save("_last");
|
||||
}
|
||||
|
||||
171
renderer.cpp
Normal file
171
renderer.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
#include "renderer.h"
|
||||
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
State currentState {RENDER_DEPTH};
|
||||
State stackedStates[10];
|
||||
char stackPos {0};
|
||||
|
||||
void DoLightOn();
|
||||
void DoLightOff();
|
||||
void DoFillOn();
|
||||
void DoFillOff();
|
||||
void DoDepthOn();
|
||||
void DoDepthOff();
|
||||
void DoBlendOn();
|
||||
void DoBlendOff();
|
||||
void DoTextureOn();
|
||||
void DoTextureOff();
|
||||
|
||||
bool Light(const char state)
|
||||
{
|
||||
if (state == ON) {
|
||||
DoLightOn();
|
||||
} else if (state == OFF) {
|
||||
DoLightOff();
|
||||
}
|
||||
return (currentState & RENDER_LIGHT) == RENDER_LIGHT;
|
||||
}
|
||||
|
||||
bool Fill(const char state)
|
||||
{
|
||||
if (state == ON) {
|
||||
DoFillOn();
|
||||
} else if (state == OFF) {
|
||||
DoFillOff();
|
||||
}
|
||||
return (currentState & RENDER_FILL) == RENDER_FILL;
|
||||
}
|
||||
|
||||
bool Depth(const char state)
|
||||
{
|
||||
if (state == ON) {
|
||||
DoDepthOn();
|
||||
} else if (state == OFF) {
|
||||
DoDepthOff();
|
||||
}
|
||||
return (currentState & RENDER_DEPTH) == RENDER_DEPTH;
|
||||
}
|
||||
|
||||
bool Blend(const char state)
|
||||
{
|
||||
if (state == ON) {
|
||||
DoBlendOn();
|
||||
} else if (state == OFF) {
|
||||
DoBlendOff();
|
||||
}
|
||||
return (currentState & RENDER_BLEND) == RENDER_BLEND;
|
||||
}
|
||||
|
||||
bool Texture(const char state)
|
||||
{
|
||||
if (state == ON) {
|
||||
DoTextureOn();
|
||||
} else if (state == OFF) {
|
||||
DoTextureOff();
|
||||
}
|
||||
return (currentState & RENDER_TEXTURE) == RENDER_TEXTURE;
|
||||
}
|
||||
|
||||
void Push()
|
||||
{
|
||||
if (stackPos == 10) return;
|
||||
stackedStates[stackPos++] = currentState;
|
||||
}
|
||||
|
||||
void Pop()
|
||||
{
|
||||
if (stackPos == 0) return;
|
||||
SetState(stackedStates[--stackPos]);
|
||||
}
|
||||
|
||||
void SetState(const State& state)
|
||||
{
|
||||
if ((state & RENDER_LIGHT) == RENDER_LIGHT) DoLightOn(); else DoLightOff();
|
||||
if ((state & RENDER_FILL) == RENDER_FILL) DoFillOn(); else DoFillOff();
|
||||
if ((state & RENDER_BLEND) == RENDER_BLEND) DoBlendOn(); else DoBlendOff();
|
||||
if ((state & RENDER_DEPTH) == RENDER_DEPTH) DoDepthOn(); else DoDepthOff();
|
||||
if ((state & RENDER_TEXTURE) == RENDER_TEXTURE) DoTextureOn(); else DoTextureOff();
|
||||
}
|
||||
|
||||
State GetState()
|
||||
{
|
||||
return currentState;
|
||||
}
|
||||
|
||||
|
||||
void DoLightOn()
|
||||
{
|
||||
if ((currentState & RENDER_LIGHT) == RENDER_LIGHT) return;
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
currentState |= RENDER_LIGHT;
|
||||
}
|
||||
|
||||
void DoLightOff()
|
||||
{
|
||||
if ((currentState & RENDER_LIGHT) != RENDER_LIGHT) return;
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
currentState &= uint8_t(~RENDER_LIGHT);
|
||||
}
|
||||
|
||||
void DoFillOn()
|
||||
{
|
||||
if ((currentState & RENDER_FILL) == RENDER_FILL) return;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
currentState |= RENDER_FILL;
|
||||
}
|
||||
|
||||
void DoFillOff()
|
||||
{
|
||||
if ((currentState & RENDER_FILL) != RENDER_FILL) return;
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
currentState &= uint8_t(~RENDER_FILL);
|
||||
}
|
||||
|
||||
void DoDepthOn()
|
||||
{
|
||||
if ((currentState & RENDER_DEPTH) == RENDER_DEPTH) return;
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
currentState |= RENDER_DEPTH;
|
||||
}
|
||||
|
||||
void DoDepthOff()
|
||||
{
|
||||
if ((currentState & RENDER_DEPTH) != RENDER_DEPTH) return;
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
currentState &= uint8_t(~RENDER_DEPTH);
|
||||
}
|
||||
|
||||
void DoBlendOn()
|
||||
{
|
||||
if ((currentState & RENDER_BLEND) == RENDER_BLEND) return;
|
||||
glEnable(GL_BLEND);
|
||||
currentState |= RENDER_BLEND;
|
||||
}
|
||||
|
||||
void DoBlendOff()
|
||||
{
|
||||
if ((currentState & RENDER_BLEND) != RENDER_BLEND) return;
|
||||
glDisable(GL_BLEND);
|
||||
currentState &= uint8_t(~RENDER_BLEND);
|
||||
}
|
||||
|
||||
void DoTextureOn()
|
||||
{
|
||||
if ((currentState & RENDER_TEXTURE) == RENDER_TEXTURE) return;
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
currentState |= RENDER_TEXTURE;
|
||||
}
|
||||
|
||||
void DoTextureOff()
|
||||
{
|
||||
if ((currentState & RENDER_TEXTURE) != RENDER_TEXTURE) return;
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
currentState &= uint8_t(~RENDER_TEXTURE);
|
||||
}
|
||||
|
||||
}
|
||||
26
renderer.h
Normal file
26
renderer.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define RENDER_NONE 0
|
||||
#define RENDER_LIGHT 1
|
||||
#define RENDER_FILL 2
|
||||
#define RENDER_DEPTH 4
|
||||
#define RENDER_BLEND 8
|
||||
#define RENDER_TEXTURE 16
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
typedef unsigned char State;
|
||||
|
||||
bool Light(const char state = QUERY);
|
||||
bool Fill(const char state = QUERY);
|
||||
bool Depth(const char state = QUERY);
|
||||
bool Blend(const char state = QUERY);
|
||||
bool Texture(const char state = QUERY);
|
||||
|
||||
void Push();
|
||||
void Pop();
|
||||
void SetState(const State& state);
|
||||
State GetState();
|
||||
}
|
||||
17
screen.cpp
Normal file
17
screen.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "screen.h"
|
||||
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
#include "application.h"
|
||||
|
||||
float SCREEN_WIDTH = 1280;
|
||||
float SCREEN_HEIGHT = 700;
|
||||
|
||||
namespace Screen
|
||||
{
|
||||
SDL_Window* gWindow = nullptr;
|
||||
|
||||
void Beep(unsigned char r, unsigned char g, unsigned char b){
|
||||
glClearColor(float(r)/255.0f, float(g)/255.0f, float(b)/255.0f, 1.0f);
|
||||
Application::NeedsUpdate(2);
|
||||
}
|
||||
}
|
||||
12
screen.h
Normal file
12
screen.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
extern float SCREEN_WIDTH;
|
||||
extern float SCREEN_HEIGHT;
|
||||
|
||||
namespace Screen
|
||||
{
|
||||
extern SDL_Window* gWindow;
|
||||
void Beep(unsigned char r = 255, unsigned char g = 255, unsigned char b = 255);
|
||||
}
|
||||
4687
stb_image.h
Normal file
4687
stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
71
texture.cpp
Normal file
71
texture.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "texture.h"
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_NO_FAILURE_STRINGS
|
||||
#include "stb_image.h"
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
|
||||
namespace Texture
|
||||
{
|
||||
unsigned texture = 0;
|
||||
|
||||
unsigned Create(const int w, const int h)
|
||||
{
|
||||
unsigned texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
if (w != -1) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
return texture;
|
||||
}
|
||||
|
||||
const bool Load(const unsigned& texture, const char* filename)
|
||||
{
|
||||
int x,y,n;
|
||||
char name[400]; strcpy(name, filename);
|
||||
if (strrchr(filename, '.') == nullptr) strcat(name, ".png");
|
||||
unsigned char *data = stbi_load(name, &x, &y, &n, 4);
|
||||
if (data == nullptr) return false;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
stbi_image_free(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t* Load(const char* filename)
|
||||
{
|
||||
int x,y,n;
|
||||
char name[400]; strcpy(name, filename);
|
||||
if (strrchr(filename, '.') == nullptr) strcat(name, ".png");
|
||||
unsigned char *data = stbi_load(name, &x, &y, &n, 4);
|
||||
return data;
|
||||
}
|
||||
|
||||
void Update(const unsigned& texture, const int w, const int h, const uint8_t* data)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Bitmap
|
||||
{
|
||||
void PutPixel(uint8_t* data, const int x, const int y, const Color& color)
|
||||
{
|
||||
memcpy(&data[x+y*128], &color, 4);
|
||||
}
|
||||
|
||||
const Color GetPixel(uint8_t* data, const int x, const int y)
|
||||
{
|
||||
Color color;
|
||||
data += (x+y*128);
|
||||
color.r = *(data++);
|
||||
color.g = *(data++);
|
||||
color.b = *(data++);
|
||||
color.a = *(data++);
|
||||
return color;
|
||||
}
|
||||
}
|
||||
19
texture.h
Normal file
19
texture.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace Texture
|
||||
{
|
||||
extern unsigned texture;
|
||||
|
||||
unsigned Create(const int w = -1, const int h = -1);
|
||||
const bool Load(const unsigned& texture, const char* filename);
|
||||
uint8_t* Load(const char* filename);
|
||||
void Update(const unsigned& texture, const int w, const int h, const uint8_t* data);
|
||||
}
|
||||
|
||||
namespace Bitmap
|
||||
{
|
||||
void PutPixel(uint8_t* data, const int x, const int y, const Color& color);
|
||||
const Color GetPixel(uint8_t* data, const int x, const int y);
|
||||
}
|
||||
Reference in New Issue
Block a user