/**************************************************
* File: CGWorld.cpp
* Author: Dr. Dalton R. Hunkins
* Date: February 2009
**************************************************/
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/Utils/MathFunctions.h>
#include "CGWorld.h"
#include <cmath>
using std::abs;
using std::pow;
using std::cos;
using std::sin;
CGWorld::CGWorld() {
}
void CGWorld::createSubWindow(int parentHandle,
int parentWidth, int parentHeight,
int startX, int startY,
int width, int height) {
windowHandle = glutCreateSubWindow(parentHandle,
startX*parentWidth/100, startY*parentHeight/100,
width*parentWidth/100, height*parentHeight/100);
CGWorld::cornerX = startX;
CGWorld::cornerY = startY;
CGWorld::width = width;
CGWorld::height = height;
}
void CGWorld::init(float clearColor[]) {
glClearColor(clearColor[0], clearColor[1], clearColor[2], 1.0);
lightColor[0] = lightColor[1] = lightColor[2] = 1.0;
geometryColor[0] = 1.0;
geometryColor[1] = 1.0;
geometryColor[2] = 0.0;
geometryColor[3] = 1.0;
hsvSquare[0].setHSV(25.0, 1.0, 0.85);
hsvSquare[1].setHSV(25.0, 0.6, 0.85);
hsvSquare[2].setHSV(25.0, 0.4, 0.85);
coordinates[0].setXYZ( 0.16, 0.35, 0.0);
coordinates[1].setXYZ(-0.04, 0.24, 0.0);
coordinates[2].setXYZ( 0.09, 0.07, 0.0);
coordinates[3].setXYZ( 0.40, 0.06, 0.0);
coordinates[4].setXYZ( 0.30, -0.11, 0.0);
coordinates[5].setXYZ( 0.23, -0.27, 0.0);
coordinates[6].setXYZ( 0.12, -0.33, 0.0);
coordinates[7].setXYZ( 0.00, -0.31, 0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 2.0, 2.0, // eyePoint
0.0, 0.0, 0.0, // lookAtPoint
0.0, 1.0, 0.0); // upVector
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, 1.0, 0.1, 100.0);
lightColor[0] = lightColor[1] = lightColor[2] = 1.0;
setLighting();
}
void CGWorld::display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glDisable(GL_LIGHTING);
glBlendFunc(GL_ONE, GL_ZERO);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(-1.0, -0.5, -1.0);
drawBoard();
glPopMatrix();
glEnable(GL_LIGHTING);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPushMatrix();
glScalef(2.0, 1.5, 2.0);
drawSurfaceOfRevolution();
glPopMatrix();
glutSwapBuffers();
glDisable(GL_DEPTH_TEST);
}
void CGWorld::setLighting() {
float directionalPosition[] = { 0.0, 0.0, 3.0, 0.0};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, darkGray);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightColor);
glLightfv(GL_LIGHT1, GL_POSITION, directionalPosition);
glEnable(GL_LIGHT1);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
}
void CGWorld::setAlpha(float value) {
geometryColor[3] = value;
glutSetWindow(windowHandle);
glutPostRedisplay();
}
void CGWorld::xzSquare(int which) {
if (which == 1) {
glBegin(GL_TRIANGLE_FAN);
glColor3fv(hsvSquare[0].getRGB());
glVertex3d(0.5, 0.0, 0.5);
glColor3fv(hsvSquare[1].getRGB());
glVertex3d(0.0, 0.0, 0.0);
glColor3fv(hsvSquare[2].getRGB());
glVertex3d(1.0, 0.0, 0.0);
glColor3fv(hsvSquare[1].getRGB());
glVertex3d(1.0, 0.0, 1.0);
glColor3fv(hsvSquare[2].getRGB());
glVertex3d(0.0, 0.0, 1.0);
glColor3fv(hsvSquare[1].getRGB());
glVertex3d(0.0, 0.0, 0.0);
glEnd();
}
else {
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.8, 0.8, 0.8);
glVertex3d(0.5,0.0, 0.5);
glColor3f(0.4, 0.4, 0.4);
glVertex3d(0.0, 0.0, 0.0);
glColor3f(0.6, 0.6, 0.6);
glVertex3d(1.0, 0.0, 0.0);
glColor3f(0.4, 0.4, 0.4);
glVertex3d(1.0, 0.0, 1.0);
glColor3f(0.6, 0.6, 0.6);
glVertex3d(0.0, 0.0, 1.0);
glColor3f(0.4, 0.4, 0.4);
glVertex3d(0.0, 0.0, 0.0);
glEnd();
}
}
void CGWorld::xzRow(int first, int second) {
for (int i=0; i<numberOfSquares; i+=2) {
glPushMatrix();
glTranslated(i*sizeOfSquare, 0.0, 0.0);
glScaled(sizeOfSquare, 1.0, sizeOfSquare);
xzSquare(first);
glPopMatrix();
}
for (int i=1; i<numberOfSquares; i+=2) {
glPushMatrix();
glTranslated(i*sizeOfSquare, 0.0, 0.0);
glScaled(sizeOfSquare, 1.0, sizeOfSquare);
xzSquare(second);
glPopMatrix();
}
}
void CGWorld::drawBoard() {
glMatrixMode(GL_MODELVIEW);
for (int i = 0; i<numberOfSquares; i+=2) {
glPushMatrix();
glTranslated(0.0, 0.0, i*sizeOfSquare);
xzRow(2, 1);
glTranslated(0.0, 0.0, sizeOfSquare);
xzRow(1, 2);
glPopMatrix();
}
}
void CGWorld::drawSurfaceOfRevolution() {
const double angleIncrement = 10.0;
const double angleOfRevolution = 360.0;
const int numberOfDivisions = 32;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, geometryColor);
glEnable(GL_NORMALIZE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
double point[3];
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glScaled(0.7, 1.2, 0.7);
double angle = 0.0;
while (angle < angleOfRevolution) {
glBegin(GL_QUAD_STRIP);
for (int i=1; i<=numberOfDivisions; i++) {
getPointOnCurve(i/ (double) numberOfDivisions, point);
glNormal3d(cos(angle*PI/180.0)*abs(point[0]), 0.0,
sin(angle*PI/180.0)*abs(point[0]));
glVertex3d(cos(angle*PI/180.0)*abs(point[0]), point[1],
sin(angle*PI/180.0)*abs(point[0]));
glNormal3d(cos((angle+angleIncrement)*PI/180.0)*abs(point[0]), 0.0,
sin((angle+angleIncrement)*PI/180.0)*abs(point[0]));
glVertex3d(cos((angle+angleIncrement)*PI/180.0)*abs(point[0]), point[1],
sin((angle+angleIncrement)*PI/180.0)*abs(point[0]));
}
glEnd();
angle += angleIncrement;
}
glPopMatrix();
}
void CGWorld::getPointOnCurve(double U, double pointOnCurve[3]) {
int numberOfControlPoints = 8;
double sumX = 0.0;
double sumY = 0.0;
double sumZ = 0.0;
if (U > 0.99) {
pointOnCurve[0] = coordinates[7].getX();
pointOnCurve[1] = coordinates[7].getY();
pointOnCurve[2] = coordinates[7].getZ();
}
else if (U < 0.01) {
pointOnCurve[0] = coordinates[0].getX();
pointOnCurve[1] = coordinates[0].getY();
pointOnCurve[2] = coordinates[0].getZ();
}
else {
for (int k = 0; k < numberOfControlPoints; k++) {
double factor = combinations(numberOfControlPoints, k) * pow(U, k)
* pow(1 - U, numberOfControlPoints - k);
sumX += factor*coordinates[k].getX();
sumY += factor*coordinates[k].getY();
sumZ += factor*coordinates[k].getZ();
}
double factor = combinations(numberOfControlPoints,
numberOfControlPoints) * pow(U, numberOfControlPoints) * pow(1- U, 0);
sumX += factor*coordinates[7].getX();
sumY += factor*coordinates[7].getY();
sumZ += factor*coordinates[7].getZ();
pointOnCurve[0] = sumX;
pointOnCurve[1] = sumY;
pointOnCurve[2] = sumZ;
}
}
int CGWorld::combinations(int n, int i) {
int returnValue = 0;
int denominator = 1;
int numerator = 1;
if (i == 0)
returnValue = 1;
else if (i <= n) {
for (int k=1; k<=i; k++)
denominator *= k;
for (int k=n; k>=(n-i+1); k--)
numerator *= k;
returnValue = numerator/denominator;
}
return returnValue;
}
int CGWorld::getWindowHandle() {
return windowHandle;
}
int CGWorld::getCornerX() {
return cornerX;
}
int CGWorld::getCornerY() {
return cornerY;
}
int CGWorld::getWidth() {
return width;
}
int CGWorld::getHeight() {
return height;
}