Newer
Older
cg / sources / glumodel.cpp
#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

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();
  enabled = true;
}

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

  if (enabled) {
	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;
}

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 {
		//TODO: make this parametrable
		float c[] = {1.0, 0, 0};
		glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c);

		/* 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() {
	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 it */
	construct(iters);

	glPopMatrix();
}

SierpinskiPyramid::~SierpinskiPyramid ( ) { }

KochFractal::KochFractal(Vec _pos, int _iters, float _len) {
  Fractal::init(_pos, Material(), _iters, _len / (_iters*_iters*_iters));
  multiplicity = 6;
  mult_angle = 60;
}

void KochFractal::draw() {
	//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,len,0);
	glEnd();
	glTranslatef(0,len,0);
  }
}