#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);
Color c2 = Color(0,0,0);
material = new Material(_color, c2);
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->drawMaterial();
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() {
printf("got material %f", material);
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) {
printf("scale: %f\n", f);
scaleFactor *= f;
}