#include "glumodel.h"
#include <string>
#include <GL/gl.h> // This file import the OpenGL interface
#include <GL/glu.h> // This file offers some OpenGL-related utilities
#include <math.h>
GenericModel::GenericModel() {
init(Vec(0,0,0), Material());
}
GenericModel::GenericModel(Vec _pos, Material _mat) {
init(_pos, _mat);
}
void GenericModel::init(Vec _pos, Material _mat) {
pos = _pos.clone();
rot = new Vec(0,0,0);
scalefactor = 1;
mat = _mat.clone();
pt = gluNewQuadric();
visible = true;
}
void GenericModel::hide ( ) {
visible = false;
}
void GenericModel::show ( ) {
visible = true;
}
void GenericModel::scale ( float s ) {
scalefactor = scalefactor * s;
}
void GenericModel::setColor(Color* c) {
Color sp = *(mat->specular->clone());
delete mat;
mat = new Material(*(c->clone()), sp);
}
void GenericModel::translate ( Vec d ) {
pos->add((Vec)d);
}
void GenericModel::rotate ( Vec r ) {
rot->add((Vec)r);
}
GluSphere::GluSphere() {
init(Vec(0,0,0), Material(Color(1,0,1)), 10);
}
GluSphere::GluSphere(Vec _pos, Material _mat, float _rad) {
init(_pos, _mat, _rad);
}
void GluSphere::init(Vec _pos, Material _mat, float _rad) {
GenericModel::init(_pos, _mat);
rad = _rad;
}
void GluSphere::draw() {
if ( visible ) {
glPushMatrix();
glRotatef(rot->x(), 1.0f, 0.0f, 0.0f);
glRotatef(rot->y(), 0.0f, 1.0f, 0.0f);
glRotatef(rot->z(), 0.0f, 0.0f, 1.0f);
glTranslatef(pos->x(), pos->y(), pos->z());
mat->draw();
gluSphere(gluNewQuadric(), rad, 300, 300);
glPopMatrix();
}
}
Fractal::Fractal() {
init(Vec(0,0,0), Material(), 4, 30);
}
void Fractal::init(Vec _pos, Material _m, int _iters, float _len) {
GenericModel::init(_pos, _m);
iters = _iters;
pos = _pos.clone();
len = _len;
}
void Fractal::setIterations(int _iters) {
iters = _iters;
}
SierpinskiPyramid::SierpinskiPyramid(Vec _pos, int _iters, float _len) {
Fractal::init(_pos, Material(), _iters, _len);
rot = new Vec(0,0,0);
buildList();
}
void SierpinskiPyramid::buildList() {
list = glGenLists(1);
glNewList(list, GL_COMPILE);
drawPyramid();
glEndList();
}
void SierpinskiPyramid::construct(int n) {
if ( n > 0 ) {
n--;
glPushMatrix();
glScalef(0.5, 0.5, 0.5);
construct(n);
glPopMatrix();
glPushMatrix();
glScalef(0.5, 0.5, 0.5);
glTranslatef(1, 0, 0.5);
construct(n);
glPopMatrix();
glPushMatrix();
glScalef(0.5, 0.5, 0.5);
glTranslatef(0, 0, 1);
construct(n);
glPopMatrix();
glPushMatrix();
glScalef(0.5, 0.5, 0.5);
glTranslatef(0.5, 1, 0.5);
construct(n);
glPopMatrix();
} else {
/* if available, use OpenGL lists to accelerate drawing */
if ( list == 0 ) {
drawPyramid();
} else {
glCallList(list);
}
}
}
void SierpinskiPyramid::drawPyramid() {
Vec a;
Vec b;
Vec p0 = Vec(0,0,0);
Vec p1 = Vec(1,0,0.5);
Vec p2 = Vec(0,0,1);
Vec p3 = Vec(0.5,1,0.5);
glBegin(GL_TRIANGLES);
a = (p0)-(p1);
b = (p2)-(p1);
glNormal3fv((a.cross(b)).c);
glVertex3fv(p0.c);
glVertex3fv(p1.c);
glVertex3fv(p2.c);
a = (p3)-(p1);
b = (p0)-(p1);
glNormal3fv((a.cross(b)).c);
glVertex3fv(p3.c);
glVertex3fv(p1.c);
glVertex3fv(p0.c);
a = (p0)-(p2);
b = (p3)-(p2);
glNormal3fv((a.cross(b)).c);
glVertex3fv(p0.c);
glVertex3fv(p2.c);
glVertex3fv(p3.c);
a = (p2)-(p1);
b = (p3)-(p1);
glNormal3fv((a.cross(b)).c);
glVertex3fv(p2.c);
glVertex3fv(p1.c);
glVertex3fv(p3.c);
glEnd();
}
void SierpinskiPyramid::draw() {
if ( visible ) {
glPushMatrix();
/* rotate SierpinskiPyramid */
glRotatef(rot->x(), 1.0f, 0.0f, 0.0f);
glRotatef(rot->y(), 0.0f, 1.0f, 0.0f);
glRotatef(rot->z(), 0.0f, 0.0f, 1.0f);
/* move it to the desired position */
glTranslatef(pos->x(), pos->y(), pos->z());
/* scale it to the desired length, width and height */
glScalef(len, len, len);
glScalef(scalefactor, scalefactor, scalefactor);
/* draw material */
mat->draw();
/* draw it */
construct(iters);
glPopMatrix();
}
}
SierpinskiPyramid::~SierpinskiPyramid ( ) { }
KochFractal::KochFractal(Vec _pos, int _iters, float _len) {
Fractal::init(_pos, Material(), _iters, _len);
setIterations(_iters);
multiplicity = 6;
mult_angle = 60;
}
void KochFractal::setIterations(int _iters) {
Fractal::setIterations(_iters) ;
mylen = len / pow(3, iters);
}
void KochFractal::draw() {
if ( visible ) {
//TODO: move draw function to Fractal class, it's common for all
//inheriting fractals....
glPushMatrix();
/* rotate */
glRotatef(rot->x(), 1.0f, 0.0f, 0.0f);
glRotatef(rot->y(), 0.0f, 1.0f, 0.0f);
glRotatef(rot->z(), 0.0f, 0.0f, 1.0f);
/* move it to the desired position */
glTranslatef(pos->x(), pos->y(), pos->z());
glScalef(scalefactor, scalefactor, scalefactor);
for (int i = 0; i < multiplicity; i++) {
iter(iters);
glRotatef(mult_angle, 1,0,0);
}
glPopMatrix();
}
}
void KochFractal::iter(float nbit) {
float n = nbit - 1;
if (n >= 0) {
iter(n);
glRotatef(60,1,0,0);
iter(n);
glRotatef(-120,1,0,0);
iter(n);
glRotatef(60,1,0,0);
iter(n);
} else {
glBegin(GL_LINES);
glVertex3f(0,0,0);
glVertex3f(0,mylen,0);
glEnd();
glTranslatef(0,mylen,0);
}
}