Blame onefile/cube.c

261920
261920
#include <math.h></math.h>
261920
#include <gl gl.h=""></gl>
261920
#include <helianthus.h></helianthus.h>
261920
261920
261920
#include "matrix.inc.h"
261920
261920
261920
typedef struct {
261920
  int colors[6];
261920
  Matrix position;
261920
  Vector3 mousePos[6];
261920
} Cube;
261920
261920
261920
const double colors[7][4] = {
261920
  { 0.25, 0.25, 0.25, 1 }, // gray
261920
  { 1   , 1   , 1   , 1 }, // white
261920
  { 0   , 0.5 , 0   , 1 }, // green
261920
  { 1   , 0.5 , 0   , 1 }, // orange
261920
  { 1   , 1   , 0   , 1 }, // yellow
261920
  { 0   , 0   , 1   , 1 }, // blue
261920
  { 1   , 0   , 0   , 1 }, // red
261920
};
261920
261920
Cube cubes[27];
261920
261920
Matrix position;
261920
double mx, my;
261920
261920
int turning;
261920
Vector3 turnAxis;
261920
double turnLayer;
261920
double turnAngle;
261920
261920
261920
void randomTurn() {
261920
  vector3Set(&turnAxis, 0, 0, 0);
261920
  turnAxis.a[randomNumber(0, 2)] = randomNumber(0, 1)*2 - 1;
261920
  turnLayer = randomNumber(-1, 1);
261920
  turnAngle = 0;
261920
  turning = TRUE;
261920
}
261920
261920
261920
void captureMouse(Vector3 *position, double z) {
261920
  vector3Set(position, 0, 0, 100);
261920
261920
  double mx = mouseX();
261920
  double my = mouseY();
261920
  double w = windowGetWidth();
261920
  double h = windowGetHeight();
261920
261920
  mx = mx/w*2 - 1;
261920
  my = 1 - my/h*2;
261920
  Vector4 p0, p1;
261920
  vector4Set(&p0, mx, my, -1, 1);
261920
  vector4Set(&p1, mx, my,  1, 1);
261920
261920
  Matrix back, transform, projection, modelview;
261920
  glGetDoublev(GL_PROJECTION_MATRIX, projection.a);
261920
  glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a);
261920
  matrixMultMatrix(&transform, &modelview, &projection);
261920
  matrixInvert(&back, &transform);
261920
261920
  vector4MultMatrix(&p0, &p0, &back);
261920
  vector4MultMatrix(&p1, &p1, &back);
261920
  if (fabs(p0.w) <= 1e-6 || fabs(p1.w) <= 1e-6)
261920
    return;
261920
  vector4PespectiveDivide(&p0, &p0);
261920
  vector4PespectiveDivide(&p1, &p1);
261920
261920
  double dz = p1.z - p0.z;
261920
  if (fabs(dz) <= 1e-6)
261920
    return;
261920
261920
  double l = (z - p0.z)/dz;
261920
  double x = (p1.x - p0.x)*l + p0.x;
261920
  double y = (p1.y - p0.y)*l + p0.y;
261920
261920
  vector4Set(&p0, x, y, z, 1);
261920
  vector4MultMatrix(&p0, &p0, &transform);
261920
  if (fabs(p0.w) <= 1e-6)
261920
    return;
261920
  vector4PespectiveDivide(&p0, &p0);
261920
  vector3Set(position, x, y, p0.z);
261920
}
261920
261920
261920
void drawCube(Cube *cube) {
261920
  const double s = 0.5;
261920
  const double ss = 0.8*s;
261920
  const double sq2 = sqrt(2);
261920
  const double sq3 = sqrt(3);
261920
261920
  glPushMatrix();
261920
  if (turning && fabs(vector3Dot(&cube->position.ow.xyz, &turnAxis) - turnLayer) < 0.5)
261920
    glRotated(turnAngle, turnAxis.x, turnAxis.y, turnAxis.z);
261920
  glMultMatrixd(cube->position.a);
261920
261920
  for(int i = 0; i < 6; ++i) {
261920
    glColor4dv(colors[cube->colors[i]]);
261920
    glBegin(GL_QUADS);
261920
    glNormal3d(0, 0, -1);
261920
    glVertex3d(-ss, -ss, -s);
261920
    glVertex3d(-ss,  ss, -s);
261920
    glVertex3d( ss,  ss, -s);
261920
    glVertex3d( ss, -ss, -s);
261920
    glEnd();
261920
261920
    glColor4dv(colors[0]);
261920
    glBegin(GL_QUADS);
261920
    glNormal3d(-sq2, 0, -sq2);
261920
    glVertex3d(-s,  -ss, -ss);
261920
    glVertex3d(-s,   ss, -ss);
261920
    glVertex3d(-ss,  ss,  -s);
261920
    glVertex3d(-ss, -ss,  -s);
261920
    glNormal3d(0, -sq2, -sq2);
261920
    glVertex3d(-ss,  -s, -ss);
261920
    glVertex3d(-ss, -ss,  -s);
261920
    glVertex3d( ss, -ss,  -s);
261920
    glVertex3d( ss,  -s, -ss);
261920
    glEnd();
261920
261920
    glBegin(GL_TRIANGLES);
261920
    glNormal3d(-sq3, -sq3, -sq3);
261920
    glVertex3d(-ss, -ss, -s);
261920
    glVertex3d(-ss, -s, -ss);
261920
    glVertex3d(-s, -ss, -ss);
261920
    glEnd();
261920
    if (i == 0) {
261920
      glBegin(GL_TRIANGLES);
261920
      glNormal3d(-sq3, sq3, -sq3);
261920
      glVertex3d(-s, ss, -ss);
261920
      glVertex3d(-ss, s, -ss);
261920
      glVertex3d(-ss, ss, -s);
261920
      glEnd();
261920
    }
261920
    if (i == 1) {
261920
      glBegin(GL_TRIANGLES);
261920
      glNormal3d(sq3, -sq3, -sq3);
261920
      glVertex3d(s, -ss, -ss);
261920
      glVertex3d(ss, -s, -ss);
261920
      glVertex3d(ss, -ss, -s);
261920
      glEnd();
261920
    }
261920
261920
    glRotated(90, i%2, -((i+1)%2), 0);
261920
  }
261920
  glPopMatrix();
261920
}
261920
261920
261920
void init() {
261920
  background(colorByName("black"));
261920
261920
  Cube *c = cubes;
261920
  for(int ix = -1; ix <= 1; ++ix)
261920
  for(int iy = -1; iy <= 1; ++iy)
261920
  for(int iz = -1; iz <= 1; ++iz, ++c) {
261920
    if (iz < 0) c->colors[0] = 0+1;
261920
    if (ix > 0) c->colors[1] = 1+1;
261920
    if (iy > 0) c->colors[2] = 2+1;
261920
    if (iz > 0) c->colors[3] = 3+1;
261920
    if (ix < 0) c->colors[4] = 4+1;
261920
    if (iy < 0) c->colors[5] = 5+1;
261920
    c->position.ox.x = c->position.oy.y = c->position.oz.z = c->position.ow.w = 1;
261920
    c->position.ow.x = ix;
261920
    c->position.ow.y = iy;
261920
    c->position.ow.z = iz;
261920
  }
261920
261920
  matrixSetIdentity(&position);
261920
  randomTurn();
261920
}
261920
261920
261920
void draw() {
261920
  saveState();
261920
261920
  if (mouseDown("right")) {
261920
    double ay = mouseX() - mx;
261920
    double ax = mouseY() - my;
261920
    Matrix rotation;
261920
    matrixSetRotation(&rotation, ax, 1, 0, 0);
261920
    matrixMultMatrix(&position, &position, &rotation);
261920
    matrixSetRotation(&rotation, ay, 0, 1, 0);
261920
    matrixMultMatrix(&position, &position, &rotation);
261920
  }
261920
  if (mouseDown("middle")) {
261920
    double az = mouseX() - mx;
261920
    Matrix rotation;
261920
    matrixSetRotation(&rotation, az, 0, 0, 1);
261920
    matrixMultMatrix(&position, &position, &rotation);
261920
  }
261920
  mx = mouseX(); my = mouseY();
261920
261920
  if (turning) {
261920
    turnAngle += windowGetFrameTime()*90;
261920
    if (turnAngle > 90) {
261920
      turnAngle = 90;
261920
      Matrix turningMatrix;
261920
      matrixSetRotation(&turningMatrix, turnAngle, turnAxis.x, turnAxis.y, turnAxis.z);
261920
      for(int i = 0; i < 27; ++i) {
261920
        if (fabs(vector3Dot(&cubes[i].position.ow.xyz, &turnAxis) - turnLayer) < 0.5)
261920
          matrixMultMatrix(&cubes[i].position, &cubes[i].position, &turningMatrix);
261920
      }
261920
      turning = FALSE;
261920
      randomTurn();
261920
    }
261920
  }
261920
261920
  glClear(GL_DEPTH_BUFFER_BIT);
261920
  glEnable(GL_DEPTH_TEST);
261920
  glEnable(GL_CULL_FACE);
261920
  glEnable(GL_COLOR_MATERIAL);
261920
  glEnable(GL_LIGHTING);
261920
  glEnable(GL_LIGHT0);
261920
261920
  Matrix perspective;
261920
  matrixSetPerspective(&perspective, 100.0, windowGetWidth()/(double)windowGetHeight(), 0.01, 100);
261920
  glMatrixMode(GL_PROJECTION);
261920
  glLoadMatrixd(perspective.a);
261920
  glMatrixMode(GL_MODELVIEW);
261920
  glLoadIdentity();
261920
  glTranslated(0, 0, -5);
261920
  glMultMatrixd(position.a);
261920
261920
  for(int i = 0; i < 27; ++i)
261920
    drawCube(&cubes[i]);
261920
261920
  glDisable(GL_DEPTH_TEST);
261920
  restoreState();
261920
}
261920
261920
261920
int main() {
261920
  windowSetVariableFrameRate();
261920
  windowSetResizable(TRUE);
261920
  windowSetInit(&init);
261920
  windowSetDraw(&draw);
261920
  windowRun();
261920
}
261920