616 lines
16 KiB
C++
616 lines
16 KiB
C++
#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]);
|
|
}
|