Newer
Older
cg / sources / poly.cpp
@glproj03 glproj03 on 20 Jan 2006 4 KB compact code
#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() {
	position = new Vec(0,0,0);
	rotation = new Vec(0,0,0);
	color = new Color(1,0,0);
	setCenter(Vec(0,0,0));
}

Poly::Poly(std::vector<Vec*> & _points) {
	Poly(_points, Color(1,0,0));
}

Poly::Poly(std::vector<Vec*> & _points, Color _color) {
	position = new Vec(0,0,0);
	rotation = new Vec(0,0,0);
	color = _color.clone();

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

	setCenter(calcCenter());
}

Poly::~Poly() {
	delete position;
	delete rotation;
	delete color;
}

/*
* set the position where the (rotation-)center of
* the polygon is located
*/
void Poly::setCenter(Vec c) {
  position = 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) {
	Vec diff = newcenter - (*position);
	delete position;
	position = newcenter.clone();

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

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

Vec Poly::rotate_x(Vec& c) {
	Vec initrot = getInitRotation(c);
	Vec rot = initrot + *rotation;
	float r = Vec(0, c.y(), c.z()).length();
	return Vec (c.x(), r*cos(rot.x()), r*sin(rot.x()));
}

Vec Poly::rotate_y(Vec& c) {
	Vec initrot = getInitRotation(c);
	Vec rot = initrot + *rotation;
	float r = Vec(c.x(), 0, c.z()).length();
	return Vec (r*sin(rot.y()), c.y(), r*cos(rot.y()));
}

Vec Poly::rotate_z(Vec& c) {
	Vec initrot = getInitRotation(c);
	Vec rot = initrot + *rotation;
	float r = Vec(c.x(), c.y(), 0).length();
	return Vec (r*cos(rot.z()), r*sin(rot.z()), c.z());
}

Vec Poly::rotate_xyz(Vec out) {
  Vec ret = rotate_x(out);
  ret = rotate_y(ret);
  ret = rotate_z(ret);
  return ret;
}

void Poly::draw() {
  unsigned int vcount = initpoints.size();

  //draw Poly
  glBegin (GL_POLYGON);
	for ( std::vector<Vec*>::size_type i = 0; i < vcount; i++ ) {
	  Vec cur =  rotate_xyz(*initpoints.at(i) - *position);
	  //normal
	  Vec prev = rotate_xyz(*initpoints.at((i-1+vcount)%vcount) - *position);
	  Vec next = rotate_xyz(*initpoints.at((i+1) % vcount) - *position);
	  prev = prev - cur; 
	  next = next - cur; 
	  glNormal3fv(prev.cross(next).normalize().c);

	  color->drawColor();
	  glVertex3fv((*position + cur).c);
	}
  glEnd();

  //draw Normals
/*  for ( std::vector<Vec*>::size_type i = 0; i < vcount; i++ ) {	
	Vec cur =  rotate_xyz(*initpoints.at(i) - *position);	
	//previous and next Vector of current Vector to calculate normal
	Vec prev = rotate_xyz(*initpoints.at((i-1+vcount)%vcount) - *position);
	Vec next = rotate_xyz(*initpoints.at((i+1) % vcount) - *position);	
	prev = prev - cur; 
	next = next - cur; 
	
	glBegin (GL_LINES); 
	glVertex3fv((cur + *position).c);
	glVertex3fv((cur + prev.cross(next).normalize() + *position).c);
	glEnd();
  }*/
}

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], color: [%f, %f, %f])\n",
		 whitespace.c_str(), initpoints.size(), 
		 position->x(), position->y(), position->z(),
		 rotation->x(), rotation->y(), rotation->z(), 
		 color->r, color->g, color->b);

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

void Poly::addPoint(Vec* p) {
	initpoints.push_back(p);
}

void Poly::setColor(Color c) {
	color = c.clone();
}

Color* Poly::getColor() {
	return color;
}