Newer
Older
cg / sources / poly.cpp
#include <stdio.h>
#include <math.h>

#include <GL/gl.h>
#include <GL/glu.h>

#include "poly.h"
#include <vector>
#include <string>

using namespace std;

Poly::Poly() {
	drawNormals = false;
	delta = 0.0f;
	scaleFactor = 1.0f;
	position = new Vec(0,0,0);
	center = new Vec(0,0,0);
	rotation = new Vec(0,0,0);
	material = new Material();
	normal = new Vec(0,0,0);
}

Poly::Poly(std::vector<Vec*> & _points) {  
  Poly(_points, Material());
  //TODO: this wont work. segmentation fault.
  material->ptdump("b");
}

Poly::Poly(std::vector<Vec*> & _points, Color _color) {
	delta = 0.0f;
	scaleFactor = 1.0f;
	drawNormals = false;
	position = new Vec(0,0,0);
	rotation = new Vec(0,0,0);	

	center = new Vec(0,0,0);
	normal = new Vec(0,0,0);

	material = new Material(_color);

	for (std::vector<Vec*>::size_type i = 0 ; i < _points.size(); i++ ) {
		addPoint(_points.at(i));
	}
	//setCenter(calcCenter());		
}

Poly::Poly(std::vector<Vec*> & _points, Material _material) {
	delta = 0.0f;
	scaleFactor = 1.0f;
	drawNormals = false;
	position = new Vec(0,0,0);
	rotation = new Vec(0,0,0);	
	material = _material.clone();
	center = new Vec(0,0,0);
	normal = new Vec(0,0,0);

	for (std::vector<Vec*>::size_type i = 0 ; i < _points.size(); i++ ) {
		addPoint(_points.at(i));
	}
	//setCenter(calcCenter());		
}

void Poly::calcNormal() {
	delete normal;
	/* calculate face normal */
	Vec b = *initpoints.at(0)-*initpoints.at(1);
	Vec a = *initpoints.at(2)-*initpoints.at(1);
	normal = a.cross(b).normalize().clone();
}

Poly::~Poly() {
	delete position;
	delete rotation;
	delete material;
	delete normal;
}

/*
* set the position where the (rotation-)center of
* the polygon is located
*/
void Poly::setCenter(Vec c) {
	delete center;
	center = c.clone();
}

void Poly::setCenter(Vec* c) {
	delete center;
	center = c->clone();
}

/*
* initial rotation relative to rotation center
*/
Vec Poly::getInitRotation(Vec& v) {
	return Vec(atan2(v.y(), v.z()), atan2(v.x(), v.z()), atan2(v.y(), v.x()));
}

/*
* calculate the center relative to all vertices.
*/
Vec Poly::calcCenter() {
	Vec s (0,0,0);

	if ( initpoints.size() == 0 ) {
		return s;
	}

	for ( std::vector<Vec*>::size_type i = 0; i < initpoints.size(); i++ ) {
		s = s + *(initpoints.at(i));
	}

	return s / (float)initpoints.size();
}

/*
* reset the position of all vertices (ie. translate your
* polygon to an absolute position)
*/
void Poly::setPosition(Vec newcenter) {
	delete position;
	position = newcenter.clone();
}

void Poly::setPosition(Vec* newcenter) {
	delete position;
	position = newcenter->clone();
}

void Poly::setRotation(Vec rot) {
	delete rotation;
	rotation = rot.clone();
}

void Poly::setRotation(Vec* rot) {
	delete rotation;
	rotation = rot->clone();
}

//additional rotation in arcs
void Poly::rotate(Vec rot) {
	rotation->add((Vec)rot);
}

void Poly::draw() {
	Vec n = Vec(0.0f, 0.0f, 0.0f);
	Color nc = Color(1.0f, 0.0f, 1.0f);

	std::vector<Vec*>::size_type vcount = initpoints.size();

	//save camera position
	glPushMatrix();

	//center on origin
	//glTranslatef(-center->x(), -center->y(), -center->z());
	glTranslatef(center->x(), center->y(), center->z());

	//move to origin
	glTranslatef(-position->x(), -position->y(), -position->z());

	//rotate poly
	glRotatef(rotation->x(), 1.0f, 0.0f, 0.0f);
	glRotatef(rotation->y(), 0.0f, 1.0f, 0.0f);
	glRotatef(rotation->z(), 0.0f, 0.0f, 1.0f);

	//move to origin
	//glTranslatef(position->x(), position->y(), position->z());

	//center on origin
	glTranslatef(center->x(), center->y(), center->z());

	//scale
	glScalef(scaleFactor, scaleFactor, scaleFactor);

	if ( drawNormals ) {
		/* draw face normal */
		glBegin(GL_LINES);
			nc.drawColor();
			glVertex3fv(calcCenter().c);
			glVertex3fv((calcCenter()+(*normal * 3.0f)).c);
		glEnd();

		/* draw vertex normals */
		for ( std::vector<Vec*>::size_type i = 0; i < vcount; i++ ) {
			if ( delta <= 0.0f ) {
				/* face normal */
				glBegin(GL_LINES);
					nc.drawColor();
					glVertex3fv((*initpoints.at(i)).c);
					glVertex3fv((*initpoints.at(i)+(*normal * 1.5f)).c);
				glEnd();
			} else {
				/* vertex normal (delta) */
				n.c[0] = 0.0f;
				n.c[1] = 0.0f;
				n.c[2] = 0.0f;

				n = n+*normal;

				for ( std::vector<SPoly*>::size_type j = 0; j < initpoints.at(i)->faces.size(); j++ ) {
					if ( ((Poly*)initpoints.at(i)->faces.at(j))->normal->angle(*normal) < delta ) {
						n = n+*(((Poly*)initpoints.at(i)->faces.at(j))->normal);
					}
				}

				n = n.normalize();

				glBegin(GL_LINES);
					nc.drawColor();
					glVertex3fv((*initpoints.at(i)).c);
					glVertex3fv((*initpoints.at(i)+(n * 1.5f)).c);
				glEnd();
			}
		}
	}

	glBegin (GL_POLYGON);

	for ( std::vector<Vec*>::size_type i = 0; i < vcount; i++ ) {

		if ( delta <= 0.0f ) {
			/* face normal */
		  glNormal3fv((*normal).c);
		} else {
			/* vertex normal (delta) */
			n.c[0] = 0.0f;
			n.c[1] = 0.0f;
			n.c[2] = 0.0f;

			n = n+*normal;

			for ( std::vector<SPoly*>::size_type j = 0; j < initpoints.at(i)->faces.size(); j++ ) {
				if ( ((Poly*)initpoints.at(i)->faces.at(j))->normal->angle(*normal) < delta ) {
					n = n+*(((Poly*)initpoints.at(i)->faces.at(j))->normal);
				}
			}

			n = n.normalize();

			glNormal3fv(n.c);
		}

		material->draw();
		glVertex3fv((*initpoints.at(i)).c);
	}

	glEnd();

	//restore camera position
	glPopMatrix();
}

int Poly::numPoints() {
	return (int)initpoints.size();
}

void Poly::vardump(std::string whitespace) {
	printf("%sPoly(%d points, center: [%f, %f, %f], rotation: [%f, %f, %f]\n",
		whitespace.c_str(), initpoints.size(), 
		position->x(), position->y(), position->z(),
		rotation->x(), rotation->y(), rotation->z()
	);

	for (std::vector<Vec*>::size_type i = 0 ; i < initpoints.size(); i++ ) {
		initpoints.at(i)->vardump(whitespace+"	");
	}
}

void Poly::addPoint(Vec* p) {
	p->registerFace(this);
	initpoints.push_back(p);

	if ( initpoints.size() > 2 ) {
		this->calcNormal();
	}
}

void Poly::setColor(Color c) {
  delete material;
  material = new Material(c, Color(0,0,0));
}

void Poly::setColor(Color* c) {
  delete material;
  Color sc = *c;
  material = new Material(sc, Color(0,0,0));
}

Material* Poly::getMaterial() {
  return material;
}

void Poly::setMaterial(Material *m){
  delete material;
  material = m->clone();
}

void Poly::setMaterial(Material m){
  delete material;
  material = m.clone();
}


void Poly::setDelta(float d) {
	delta = d;
}

void Poly::showNormals() {
	drawNormals = true;
}

void Poly::hideNormals() {
	drawNormals = false;
}

Poly* Poly::clone() {
	Poly* np = new Poly();

	for (std::vector<Vec*>::size_type i = 0 ; i < initpoints.size(); i++ ) {
		np->addPoint(initpoints.at(i)->clone());
	}

	if ( drawNormals ) {
		np->showNormals();
	} else {
		np->hideNormals();
	}

	np->setDelta(delta);
	np->setMaterial(material);
	np->setPosition(position);
	np->setCenter(center);
	np->setRotation(rotation);
	np->scale(scaleFactor);
	return np;
}

void Poly::translate(Vec d) {
	position->add((Vec)d);
}

void Poly::scale(float f) {
	scaleFactor *= f;
}