Skip to content

Instantly share code, notes, and snippets.

@luckyjajj
Created May 9, 2014 20:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save luckyjajj/4a62154d90d3686d9fe7 to your computer and use it in GitHub Desktop.
Save luckyjajj/4a62154d90d3686d9fe7 to your computer and use it in GitHub Desktop.
OpenGL: Banner Modeling and Animation
//
// main.cpp
// Banner Modeling and Animation
//
// Created by Lakhveer Jajj on 2013-09-25.
//
#include <iostream>
#include <string>
#include <cstdlib>
#include <math.h>
#include <GLUT/GLUT.h>
#include <OpenGL/OpenGL.h>
typedef struct Point2D
{
double x,y;
double nx,ny;
double u;
} Point2D;
#define MAXCONTROLPOINTS 30
#define PI 3.14159265
#define CHARS 20
typedef struct SubdivisionCurve
{
int numControlPoints;
Point2D controlPoints[MAXCONTROLPOINTS];
int subdivisionSteps;
int numCurvePoints;
Point2D *curvePoints;
} SubivisionCurve;
void init(void);
void display(void);
void keyboardHandler(unsigned char key, int x, int y);
Point2D cPosition (double uValue);
void computeSubdivisionCurve(SubdivisionCurve *subcurve) ;
Point2D getPoint(Point2D *currentPoints, int numCurrentPoints, int j) ;
Point2D subdivide(Point2D v1, Point2D v2, Point2D v3, Point2D v4) ;
SubdivisionCurve subcurve;
Point2D cP1;
Point2D cP2;
Point2D cP3;
GLint windowWidth = 1000;
GLint windowHeight = 700;
GLint viewportWidth = windowWidth;
GLint viewportHeight = windowHeight;
GLdouble worldLeft = -500.0;
GLdouble worldRight = 500.0;
GLdouble worldBottom= -300.0;
GLdouble worldTop = 300.0;
// Boundaries of world view (wv) window - also called the clip window
GLdouble wvLeft = -200.0, wvRight = 200.0, wvBottom = -100.0, wvTop = 100.0;
//Real coordinates from mouse clicks
GLint m_viewport[4];
GLdouble m_modelview[16];
GLdouble m_projection[16];
GLdouble rx, ry, rz;
//Text attributes
void *font = GLUT_STROKE_ROMAN;
static char message[20];
static int len = (int) strlen(message);
//Animation Variblies
bool animate = true;
Point2D finalPos;
Point2D temp[CHARS];
void init(void){
glViewport(0, 0, viewportWidth, viewportHeight);
glMatrixMode(GL_PROJECTION);
// First set it to the identity matrix
glLoadIdentity();
gluOrtho2D(wvLeft, wvRight, wvBottom, wvTop);
// Now set up the MODELVIEW matrix
glMatrixMode(GL_MODELVIEW);
int i;
for (i = 0; i <= len; i++){
temp[i] = cPosition((double)(i)/len);
printf("");
}
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
//Display moveable control points
glColor3f(0, 1, 0);
glPointSize(10.0);
glBegin(GL_POINTS);
glVertex3f(cP1.x, cP1.y,0.0);
glVertex3f(cP2.x, cP2.y,0.0);
glVertex3f(cP3.x, cP3.y,0.0);
glEnd();
//Draws curve from the controll points
glColor3f(1, 0, 0);
glBegin(GL_LINE_STRIP);
int i;
for (i=0; i < subcurve.numCurvePoints; i++){
Point2D temp = subcurve.curvePoints[i];
glVertex2f(temp.x, temp.y);
}
glEnd();
glPopMatrix();
//Draws characters to the line
for (i = 0; i <= len; i++){
glColor3f(0, 0, 1);
glPushMatrix();
glTranslatef(temp[i].x,temp[i].y+1,0.0);
double m = (temp[i].y-temp[i].ny)/ (temp[i].x-temp[i].nx);
glRotatef(atan(m)*180/PI,0.0,0.0,1.0);
glScalef(0.1,0.1,1.0);
glutStrokeCharacter(font, message[i]);
glPopMatrix();
}
glFlush();
}
Point2D cPosition (double uValue){
double totalL;
int i;
float ox = subcurve.curvePoints[0].x;
float oy = subcurve.curvePoints[0].y;
for (i=1; i < subcurve.numCurvePoints; i++){
Point2D temp = subcurve.curvePoints[i];
double total = sqrt(pow((temp.x-ox),2)+pow((temp.y-oy),2));
ox = temp.x;
oy = temp.y;
totalL = totalL +total;
}
ox = subcurve.curvePoints[0].x;
oy = subcurve.curvePoints[0].y;
double totalT=0;
double lastUVal =0;
for (i=1; i < subcurve.numCurvePoints; i++){
Point2D temp = subcurve.curvePoints[i];
double total = sqrt(pow((temp.x-ox),2)+pow((temp.y-oy),2));
totalT = totalT +total;
if (uValue >= lastUVal && uValue <= totalT/totalL ){
temp.nx = ox;
temp.ny= oy;
return temp;
}
ox = temp.x;
oy = temp.y;
lastUVal =totalT/totalL;
}
Point2D blank;
return blank;
}
void mouseHandler(int x, int y){
glGetIntegerv(GL_VIEWPORT, m_viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, m_modelview);
glGetDoublev(GL_PROJECTION_MATRIX, m_projection);
gluUnProject(x, y, 0, m_modelview, m_projection, m_viewport, &rx, &ry, &rz);
ry = ry *-1;
if (rx >= cP1.x-10 && rx <= cP1.x+10 && ry >= cP1.y-10 && ry <= cP1.y+10){
cP1.x = rx;
cP1.y = ry;
subcurve.controlPoints[0] = cP1;
computeSubdivisionCurve(&subcurve);
int i;
for (i = 0; i <= len; i++){
temp[i] = cPosition((double)(i)/len);
printf("");
}
}
else if (rx >= cP2.x-10 && rx <= cP2.x+10 && ry >= cP2.y-10 && ry <= cP2.y+10){
cP2.x = rx;
cP2.y = ry;
subcurve.controlPoints[1] = cP2;
computeSubdivisionCurve(&subcurve);
int i;
for (i = 0; i <= len; i++){
temp[i] = cPosition((double)(i)/len);
printf("");
}
}
else if (rx >= cP3.x-10 && rx <= cP3.x+10 && ry >= cP3.y-10 && ry <= cP3.y+10){
cP3.x = rx;
cP3.y = ry;
subcurve.controlPoints[2] = cP3;
computeSubdivisionCurve(&subcurve);
int i;
for (i = 0; i <= len; i++){
temp[i] = cPosition((double)(i)/len);
printf("");
}
}
glutPostRedisplay();
}
void keyboardHandler(unsigned char key, int x, int y){
switch(key)
{
case 'q':
case 'Q':
case 27:
/* Esc, q, or Q key = Quit */
exit(0);
break;
}
glutPostRedisplay();
}
int main(int argc, char ** argv){
printf("Enter in text to display: ");
char temp[20];
std::cin.getline(temp,20);
strlcpy(message,temp,20);
len = ((int) strlen(temp))-1;
cP1.x = -70;
cP1.y = 0;
cP2.x = 0;
cP2.y = 0;
cP3.x = 70;
cP3.y = 0;
subcurve.controlPoints[0] = cP1;
subcurve.controlPoints[1] = cP2;
subcurve.controlPoints[2] = cP3;
subcurve.numControlPoints = 3;
// Set desired number of subdivisionSteps
subcurve.subdivisionSteps = 5;
computeSubdivisionCurve(&subcurve);
glutInit(&argc, (char **)argv);
glutInitDisplayMode ( GLUT_SINGLE | GLUT_RGB);
//glutInitWindowPosition(100,100);
glutInitWindowSize(windowWidth,windowHeight);
glutCreateWindow ("Banner Modeling and Animation");
glutDisplayFunc(display);
glutKeyboardFunc(keyboardHandler);
glutMotionFunc(mouseHandler);
init();
glutMainLoop();
return 0;
}
#define MAXSTEPS 6
// Compute the subdivision curve
void computeSubdivisionCurve(SubdivisionCurve *subcurve)
{
Point2D *curvePoints[MAXSTEPS];
int numCurrentPoints = subcurve->numControlPoints;
int n;
Point2D *cur = subcurve->controlPoints;
Point2D *sub;
if (subcurve->subdivisionSteps > MAXSTEPS) return;
subcurve->numCurvePoints = subcurve->numControlPoints;
curvePoints[0] = subcurve->controlPoints;
for (int i=1; i <= subcurve->subdivisionSteps; i++)
{
subcurve->numCurvePoints += subcurve->numCurvePoints - 1;
curvePoints[i] = (Point2D *) malloc(subcurve->numCurvePoints * sizeof(Point2D));
}
sub = curvePoints[1];
for (int i=0; i < subcurve->subdivisionSteps; i++)
{
n = numCurrentPoints-1;
for (int j=0; j<n; j++)
{
sub[2*j] = cur[j];
sub[2*j+1] = subdivide(getPoint(cur,numCurrentPoints,j-1),
getPoint(cur,numCurrentPoints,j),
getPoint(cur,numCurrentPoints,j+1),
getPoint(cur,numCurrentPoints,j+2));
}
sub[2*n]=cur[n];
cur = sub;
sub = curvePoints[i+2];
numCurrentPoints += n;
}
subcurve->curvePoints = curvePoints[subcurve->subdivisionSteps];
}
Point2D getPoint(Point2D *currentPoints, int numCurrentPoints, int j)
{
int n= numCurrentPoints;
if (j>=0 && j<n) return currentPoints[j];
Point2D p0, p1;
// boundary cases
if (j==-1)
{
p0 = currentPoints[0];
p1 = currentPoints[1];
}
if (j==n)
{
p1 = currentPoints[n-2];
p0 = currentPoints[n-1];
}
Point2D linearCombo;
linearCombo.x = 2*p0.x + -1 * p1.x;
linearCombo.y = 2*p0.y + -1 * p1.y;
return linearCombo;
}
Point2D subdivide(Point2D v1, Point2D v2, Point2D v3, Point2D v4)
{
Point2D result;
result.x = (9.0*(v2.x+v3.x)-v1.x-v4.x)/16.0;
result.y = (9.0*(v2.y+v3.y)-v1.y-v4.y)/16.0;
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment