Michaël Lemaire
bf1f9192e5
* Added body rotation using hit button * Added rotating decapitation camera * Added slow motion on death * Improved camera tracking * Added motion blur * Fixed several bugs
475 lines
12 KiB
C++
475 lines
12 KiB
C++
#include "main.h"
|
|
|
|
#include <math.h>
|
|
|
|
#include "legoblocks.h"
|
|
#include "utils.h"
|
|
#include "3dutils.h"
|
|
#include "objectfactory.h"
|
|
#include "vector.h"
|
|
#include "glapi.h"
|
|
|
|
BasicBlock::BasicBlock(int width, int height, int depth)
|
|
: MeshObject(
|
|
createBox(-width / 2.0, width / 2.0, -height / 2.0 * BLOCKHEIGHT,
|
|
BLOCKHEIGHT * height / 2.0, -depth / 2.0, depth / 2.0)) {
|
|
appearance = new BasicBlockAppearance(width, height, depth);
|
|
// geometry = new MeshShape(this);
|
|
}
|
|
|
|
void BasicBlock::setColor(float red, float green, float blue) {
|
|
appearance->getMaterial()->setColor(red, green, blue, 1);
|
|
}
|
|
|
|
BasicBlockAppearance::BasicBlockAppearance(int width, int height, int depth) {
|
|
this->width = width;
|
|
this->height = height;
|
|
this->depth = depth;
|
|
vectorSet(displacement, 0, 0, 0);
|
|
gllist = glGenLists(1);
|
|
usematerial = true;
|
|
}
|
|
|
|
void BasicBlockAppearance::prepare() {
|
|
glNewList(gllist, GL_COMPILE);
|
|
|
|
float width = this->width;
|
|
float height = this->height * BLOCKHEIGHT;
|
|
|
|
if (usematerial)
|
|
material.enable();
|
|
{ // Block
|
|
// Front Face
|
|
glPushMatrix();
|
|
glTranslatef(-width / 2.0, -height / 2.0, depth / 2.0);
|
|
drawDetailRectangle(width, height);
|
|
glPopMatrix();
|
|
|
|
// Back Face
|
|
glPushMatrix();
|
|
glTranslatef(width / 2.0, -height / 2.0, -depth / 2.0);
|
|
glRotatef(180, 0, 1, 0);
|
|
drawDetailRectangle(width, height);
|
|
glPopMatrix();
|
|
|
|
// Top Face
|
|
glPushMatrix();
|
|
glTranslatef(-width / 2.0, height / 2.0, depth / 2.0);
|
|
glRotatef(-90, 1, 0, 0);
|
|
drawDetailRectangle(width, depth);
|
|
glPopMatrix();
|
|
|
|
// Bottom Face
|
|
glPushMatrix();
|
|
glTranslatef(-width / 2.0, -height / 2.0, -depth / 2.0);
|
|
glRotatef(90, 1, 0, 0);
|
|
drawDetailRectangle(width, depth);
|
|
glPopMatrix();
|
|
|
|
// Right face
|
|
glPushMatrix();
|
|
glTranslatef(width / 2.0, -height / 2.0, depth / 2.0);
|
|
glRotatef(90, 0, 1, 0);
|
|
drawDetailRectangle(depth, height);
|
|
glPopMatrix();
|
|
|
|
// Left Face
|
|
glPushMatrix();
|
|
glTranslatef(-width / 2.0, -height / 2.0, -depth / 2.0);
|
|
glRotatef(-90, 0, 1, 0);
|
|
drawDetailRectangle(depth, height);
|
|
glPopMatrix();
|
|
}
|
|
|
|
glPushMatrix();
|
|
glTranslatef(0.5 - width / 2.0, height - height / 2.0, 0.5 - depth / 2.0);
|
|
int x, z;
|
|
for (x = 0; x < width; x++) {
|
|
// glPushMatrix();
|
|
for (z = 0; z < depth; z++) {
|
|
createKnob();
|
|
glTranslatef(0, 0, 1);
|
|
}
|
|
glTranslatef(1, 0, -depth);
|
|
// glPopMatrix();
|
|
}
|
|
glPopMatrix();
|
|
|
|
if (usematerial)
|
|
material.disable();
|
|
glEndList();
|
|
}
|
|
|
|
void BasicBlockAppearance::draw() {
|
|
glPushMatrix();
|
|
glTranslatef(displacement[0], displacement[1], displacement[2]);
|
|
glCallList(gllist);
|
|
glPopMatrix();
|
|
// prepare();
|
|
}
|
|
|
|
#define BLOCKDETAILGRID 1
|
|
|
|
void drawDetailRectangle(float width, float height) {
|
|
glBegin(GL_QUADS);
|
|
float x, y, x2, y2;
|
|
glNormal3f(0, 0, 1);
|
|
|
|
for (y = 0; y < height; y += BLOCKDETAILGRID) {
|
|
y2 = y + BLOCKDETAILGRID;
|
|
if (y2 > height)
|
|
y2 = height;
|
|
for (x = 0; x < width; x += BLOCKDETAILGRID) {
|
|
x2 = x + BLOCKDETAILGRID;
|
|
if (x2 > width)
|
|
x2 = width;
|
|
|
|
glTexCoord2f(x / width, y / height);
|
|
glVertex3f(x, y, 0);
|
|
|
|
glTexCoord2f(x2 / width, y / height);
|
|
glVertex3f(x2, y, 0);
|
|
|
|
glTexCoord2f(x2 / width, y2 / height);
|
|
glVertex3f(x2, y2, 0);
|
|
|
|
glTexCoord2f(x / width, y2 / height);
|
|
glVertex3f(x, y2, 0);
|
|
}
|
|
}
|
|
glEnd();
|
|
}
|
|
|
|
#define KNOBROUNDNESS 0.03
|
|
|
|
int knobgllist;
|
|
int knobdetail;
|
|
|
|
void renderKnob(int knobsegments) {
|
|
point2d knobpoints[4];
|
|
knobpoints[0].x = 0.3;
|
|
knobpoints[0].y = 0;
|
|
knobpoints[1].x = 0.3;
|
|
knobpoints[1].y = BLOCKHEIGHT * 0.5 - KNOBROUNDNESS;
|
|
knobpoints[2].x = 0.3 - KNOBROUNDNESS;
|
|
knobpoints[2].y = BLOCKHEIGHT * 0.5;
|
|
knobpoints[3].x = 0;
|
|
knobpoints[3].y = BLOCKHEIGHT * 0.5;
|
|
|
|
point2d knobderivates[4];
|
|
knobderivates[0].x = 0;
|
|
knobderivates[0].y = knobpoints[1].y - knobpoints[0].y;
|
|
knobderivates[1].x = 0;
|
|
knobderivates[1].y = knobpoints[2].y - knobpoints[1].y;
|
|
knobderivates[2].x = knobpoints[2].x - knobpoints[1].x;
|
|
knobderivates[2].y = 0;
|
|
knobderivates[3].x = knobpoints[3].x - knobpoints[2].x;
|
|
knobderivates[3].y = 0;
|
|
|
|
createLathedSurface(knobpoints, knobderivates, 4, knobsegments, 4);
|
|
}
|
|
|
|
void initKnob(void) {
|
|
glNewList(knobgllist, GL_COMPILE);
|
|
|
|
renderKnob(knobdetail);
|
|
|
|
glEndList();
|
|
}
|
|
|
|
void createKnob(int knobsegments) {
|
|
if (knobsegments != -1) {
|
|
renderKnob(knobsegments);
|
|
return;
|
|
}
|
|
glCallList(knobgllist);
|
|
}
|
|
|
|
float knobroundness = 0.05;
|
|
float pillarroundness = 0.03;
|
|
|
|
HeadAppearance::HeadAppearance(void) { gllist = glGenLists(1); }
|
|
|
|
void HeadAppearance::prepare(void) {
|
|
glNewList(gllist, GL_COMPILE);
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(0, -0.5, 0);
|
|
|
|
point2d headpoints[14];
|
|
|
|
headpoints[0].x = 0.0;
|
|
headpoints[0].y = BLOCKHEIGHT * (0);
|
|
headpoints[1].x = 0.4;
|
|
headpoints[1].y = BLOCKHEIGHT * (0);
|
|
headpoints[2].x = 0.45;
|
|
headpoints[2].y = BLOCKHEIGHT * (0.35);
|
|
headpoints[3].x = 0.55;
|
|
headpoints[3].y = BLOCKHEIGHT * (0.5);
|
|
headpoints[4].x = 0.62 * 1.0;
|
|
headpoints[4].y = BLOCKHEIGHT * (0.65);
|
|
headpoints[5].x = 0.65 * 1.0;
|
|
headpoints[5].y = BLOCKHEIGHT * (1);
|
|
headpoints[6].x = 0.65 * 1.0;
|
|
headpoints[6].y = BLOCKHEIGHT * (1.75);
|
|
headpoints[7].x = 0.65 * 1.0;
|
|
headpoints[7].y = BLOCKHEIGHT * (2.35);
|
|
headpoints[8].x = 0.62 * 1.0;
|
|
headpoints[8].y = BLOCKHEIGHT * (2.60);
|
|
headpoints[9].x = 0.55 * 1.0;
|
|
headpoints[9].y = BLOCKHEIGHT * (2.80);
|
|
headpoints[10].x = 0.4;
|
|
headpoints[10].y = BLOCKHEIGHT * (2.95);
|
|
headpoints[11].x = 0.3;
|
|
headpoints[11].y = BLOCKHEIGHT * 3.5 - pillarroundness;
|
|
headpoints[12].x = 0.3 - pillarroundness;
|
|
headpoints[12].y = BLOCKHEIGHT * 3.5;
|
|
headpoints[13].x = 0;
|
|
headpoints[13].y = BLOCKHEIGHT * 3.5;
|
|
headpoints[11].x = 0;
|
|
headpoints[11].y = BLOCKHEIGHT * 3.0;
|
|
|
|
glColor4f(0.8, 0.8, 0.0, 1.0);
|
|
|
|
faceTexture->enable();
|
|
glBlendFunc(GL_ONE, GL_SRC_ALPHA);
|
|
createLathedSurface(headpoints, NULL, 12, 16, 24);
|
|
faceTexture->disable();
|
|
|
|
glTranslatef(0, BLOCKHEIGHT * 3 - 0.05, 0);
|
|
|
|
createKnob(16);
|
|
|
|
glPopMatrix();
|
|
|
|
glEndList();
|
|
}
|
|
|
|
void HeadAppearance::draw(void) { glCallList(gllist); }
|
|
|
|
FlowerAppearance::FlowerAppearance(int color1, int color2, int color3) {
|
|
gllist = glGenLists(1);
|
|
this->color1 = color1;
|
|
this->color2 = color2;
|
|
this->color3 = color3;
|
|
}
|
|
|
|
void FlowerAppearance::prepare(void) {
|
|
glNewList(gllist, GL_COMPILE);
|
|
|
|
glPushMatrix();
|
|
|
|
int colors[] = {color1, color2, color3};
|
|
|
|
glColor3f(0.0, 0.6, 0.0);
|
|
|
|
point2d basepoints[8];
|
|
basepoints[0].x = 0.4;
|
|
basepoints[0].y = 0;
|
|
basepoints[1].x = 0.4;
|
|
basepoints[1].y = BLOCKHEIGHT * 1.5 - pillarroundness;
|
|
basepoints[2].x = 0.4 - pillarroundness;
|
|
basepoints[2].y = BLOCKHEIGHT * 1.5;
|
|
basepoints[3].x = 0.3 + pillarroundness;
|
|
basepoints[3].y = BLOCKHEIGHT * 1.5;
|
|
basepoints[4].x = 0.3;
|
|
basepoints[4].y = BLOCKHEIGHT * 1.5 + pillarroundness;
|
|
basepoints[5].x = 0.3;
|
|
basepoints[5].y = BLOCKHEIGHT * 2.0 - pillarroundness;
|
|
basepoints[6].x = 0.3 - pillarroundness;
|
|
basepoints[6].y = BLOCKHEIGHT * 2.0;
|
|
basepoints[7].x = 0;
|
|
basepoints[7].y = BLOCKHEIGHT * 2.0;
|
|
|
|
point2d basederivates[8];
|
|
basederivates[0].x = 0;
|
|
basederivates[0].y = basepoints[1].y - basepoints[0].y;
|
|
basederivates[1].x = 0;
|
|
basederivates[1].y = basepoints[2].y - basepoints[1].y;
|
|
basederivates[2].x = basepoints[2].x - basepoints[1].x;
|
|
basederivates[2].y = 0;
|
|
basederivates[3].x = basepoints[4].x - basepoints[3].x;
|
|
basederivates[3].y = 0;
|
|
basederivates[4].x = 0;
|
|
basederivates[4].y = basepoints[4].y - basepoints[3].y;
|
|
basederivates[5].x = 0;
|
|
basederivates[5].y = basepoints[6].y - basepoints[5].y;
|
|
basederivates[6].x = basepoints[6].x - basepoints[5].x;
|
|
basederivates[6].y = 0;
|
|
basederivates[7].x = basepoints[7].x - basepoints[6].x;
|
|
basederivates[7].y = 0;
|
|
|
|
createLathedSurface(basepoints, basederivates, 8, 8, 8);
|
|
|
|
int i, j;
|
|
for (i = 0; i < 3; i++) {
|
|
glColor3f(0.0, 0.6, 0.0);
|
|
glPushMatrix();
|
|
glTranslatef(0, BLOCKHEIGHT, 0.4);
|
|
glRotatef(20 - 90, 1, 0, 0);
|
|
gluCylinder(gluNewQuadric(), 0.1, 0.1, BLOCKHEIGHT * (3 + i * 0.7), 4, 1);
|
|
glRotatef(90, 1, 0, 0);
|
|
glTranslatef(0, BLOCKHEIGHT * (3 + i * 0.7), 0);
|
|
|
|
float r = 0.0, g = 0.0, b = 0.0;
|
|
switch (colors[i]) {
|
|
case FLOWER_RED:
|
|
r = 1.0;
|
|
g = 0.0;
|
|
b = 0.0;
|
|
break;
|
|
case FLOWER_YELLOW:
|
|
r = 1.0;
|
|
g = 1.0;
|
|
b = 0.0;
|
|
break;
|
|
case FLOWER_WHITE:
|
|
r = 1.0;
|
|
g = 1.0;
|
|
b = 1.0;
|
|
break;
|
|
}
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
glColor3f(r, g, b);
|
|
createKnob();
|
|
|
|
/* Terälehdet tehdään triangle-fanilla */
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
glNormal3f(0.0, 1.0, 0.0);
|
|
glVertex3f(0.0, 0.0, 0.0);
|
|
float x, z;
|
|
for (j = 0; j < 24; j += 4) {
|
|
x = sin((j + 0) * 2 * PI / 24) * 0.4;
|
|
z = cos((j + 0) * 2 * PI / 24) * 0.4;
|
|
glVertex3f(x, 0.0, z);
|
|
x = sin((j + 1) * 2 * PI / 24) * 0.55;
|
|
z = cos((j + 1) * 2 * PI / 24) * 0.55;
|
|
glVertex3f(x, 0.0, z);
|
|
x = sin((j + 2) * 2 * PI / 24) * 0.6;
|
|
z = cos((j + 2) * 2 * PI / 24) * 0.6;
|
|
glVertex3f(x, 0.0, z);
|
|
x = sin((j + 3) * 2 * PI / 24) * 0.55;
|
|
z = cos((j + 3) * 2 * PI / 24) * 0.55;
|
|
glVertex3f(x, 0.0, z);
|
|
}
|
|
glVertex3f(0, 0.0, 0.4);
|
|
glEnd();
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
glPopMatrix();
|
|
|
|
glRotatef(120, 0, 1, 0);
|
|
}
|
|
|
|
glPopMatrix();
|
|
|
|
glEndList();
|
|
}
|
|
|
|
void FlowerAppearance::draw(void) { glCallList(gllist); }
|
|
|
|
LampAppearance::LampAppearance(void) { gllist = glGenLists(1); }
|
|
|
|
void LampAppearance::prepare(void) {
|
|
glNewList(gllist, GL_COMPILE);
|
|
|
|
glPushMatrix();
|
|
|
|
// glTranslatef(0, -1, 0);
|
|
|
|
// glRotatef(180, 1, 0, 0);
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
point2d lightpoints[11];
|
|
lightpoints[0].x = 0.4;
|
|
lightpoints[0].y = BLOCKHEIGHT * (0);
|
|
lightpoints[1].x = 0.55;
|
|
lightpoints[1].y = BLOCKHEIGHT * (0);
|
|
lightpoints[2].x = 0.62;
|
|
lightpoints[2].y = BLOCKHEIGHT * (0 + 0.15);
|
|
lightpoints[3].x = 0.65;
|
|
lightpoints[3].y = BLOCKHEIGHT * (0 + 0.5);
|
|
lightpoints[4].x = 0.68;
|
|
lightpoints[4].y = BLOCKHEIGHT * (0 + 1.25);
|
|
lightpoints[5].x = 0.65;
|
|
lightpoints[5].y = BLOCKHEIGHT * (0 + 2);
|
|
lightpoints[6].x = 0.62;
|
|
lightpoints[6].y = BLOCKHEIGHT * (0 + 2.35);
|
|
lightpoints[7].x = 0.55;
|
|
lightpoints[7].y = BLOCKHEIGHT * (0 + 2.5);
|
|
lightpoints[8].x = 0.4;
|
|
lightpoints[8].y = BLOCKHEIGHT * (0 + 2.5);
|
|
lightpoints[9].x = 0.4;
|
|
lightpoints[9].y = BLOCKHEIGHT * (0 + 3);
|
|
lightpoints[10].x = 0.0;
|
|
lightpoints[10].y = BLOCKHEIGHT * (0 + 3);
|
|
glColor4f(0.8, 0.8, 0.8, 0.5);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
createLathedSurface(lightpoints, NULL, 11, 8, 11);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
/*glColor3f(0.5, 0.5, 0.5);
|
|
|
|
glBegin(GL_LINES);
|
|
glVertex3f(0, 1, 0);
|
|
glVertex3f(0, -100, 0);
|
|
glEnd();*/
|
|
|
|
/*float screencoords[3]
|
|
getPointCoordinates(0,lighty,0);
|
|
|
|
glLoadIdentity();
|
|
glTranslatef(screencoords.x,screencoords.y,0);
|
|
glDisable(GL_DEPTH_TEST);
|
|
glEnable(GL_CULL_FACE);
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_ONE,GL_ONE);
|
|
glEnable(GL_TEXTURE_2D);
|
|
glBindTexture(GL_TEXTURE_2D,*flaretexture);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
float sizey=8.0/distance*staticlightflarebrightnesses[lightnumber];
|
|
float sizex=sizey*height/width;
|
|
|
|
if (distance>0.5){
|
|
glBegin(GL_QUADS);
|
|
glColor3f(staticlightflarebrightnesses[lightnumber],staticlightflarebrightnesses[lightnumber],staticlightflarebrightnesses[lightnumber]);
|
|
|
|
glTexCoord2f(0.0, 0.0);
|
|
glVertex2f(-sizex,sizey);
|
|
|
|
glTexCoord2f(0.0, 1.0);
|
|
glVertex2f(-sizex,-sizey);
|
|
|
|
glTexCoord2f(1.0, 1.0);
|
|
glVertex2f( sizex,-sizey);
|
|
|
|
glTexCoord2f(1.0, 0.0);
|
|
glVertex2f( sizex,sizey);
|
|
glEnd();
|
|
}
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();*/
|
|
|
|
glPopMatrix();
|
|
|
|
glEndList();
|
|
}
|
|
|
|
void LampAppearance::draw(void) { glCallList(gllist); }
|