Newer
Older
cg / sources / glumodel.cpp
@glproj03 glproj03 on 9 Feb 2006 4 KB fractal iterations changeable
#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);
	scale = 1;
	mat = _mat.clone();
	pt = gluNewQuadric();
	visible = true;
}

void GenericModel::hide ( ) {
	visible = false;
}

void GenericModel::show ( ) {
	visible = true;
}

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);

		/* 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());

		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);
	}
}