Sie sind auf Seite 1von 8

//**************************************

// Name: OpenGL Spine drawing app


// Description:It's a Spline Drawing Application that uses the OpenGL
Libraries. I used the GLUT event handler interface to control Mouse
functions.You will Need:
OpenGL
Glut
and a C++ compiler
Found at: http://modzer0.cs.uaf.edu/~hartsock/C_Cpp/OpenGL/Splines.html
// By: Found on the World Wide Web
//**************************************
/************************************************************************\
|
|
Shawn R. Hartsock
|
CS 381
|
Prof: Hartman
|
due: 11/4/1998
|
|
Splines.c
|
Draws Splines!
|
Menus: Spline Type, Tension, Reset, Quit
|
Keys : z,x,i,j,k,l,1,2,3
|Point: Drag to move spline points
|Rainbows free of charge.
| The color (rainbow) allows you to observe the "speed" at which
| the points are moving along the line toward the end point.
| Negative tension causes the control points to be weighted heavier...
| Positive tension up to 1.0 causes the control points to be weighted
| less, and a tension of 1.0 means that the control points are ignored.
| A tension of MORE than 1.0 means that the control points "push" the
| line rather than "pull" it, or vice versa (cardinal spline)... a
| Positive value greater than 1.0 makes the control points weighted
| NEGATIVELY.
\************************************************************************/
# include <math.h>
# include <GL/glut.h>
# define NUMSTEPS 0.01 /* <-- for win32 compatability */
/*****************************************************************\
* Zoom and View Variables
* These Variables have all been set for optimum viewing of
* the default spline... it was easier to transform the view than
* to figure out new points!
**/
/* bool refresh = false; */
int refresh = 0;
double scale = 0.50;
double T_Y = 275.0000, T_X = 200.0000;

/* double M_PI = 3.14159265359; <- for win32 compatablility */


/* Spline Variables */
int which=0,move; /*Which controls which spline to draw, move is the point*/
double P[4][2] = {{0,0}, {50,250}, {300,300}, {350,550}};
double tension = 0.0;
/******************************/
/* Application Specific Code: */
void draw_points(){
int ii;
glPointSize(3);
glBegin(GL_POINTS);
glColor3d(0.9,0.1,0.1);
for(ii=0; ii<4; ii++) glVertex2i(P[ii][0],P[ii][1]);
glColor3d(1.0,1.0,1.0);
glEnd();
glPointSize(1.0);
}
void arrow(double w1[2],double w2[2]) {
#define DIST(a,b) fsqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]b[1]))
glPushMatrix();
glTranslated(w1[0],w1[1],0);
glRotated(atan2(w2[1]-w1[1],w2[0]-w1[0])*180/M_PI,0,0,1);
glScaled(DIST(w1,w2),DIST(w1,w2),1);
/* The portion of the code up to here may be useful in subsequent
programs. We have transformed coordinate space so that w1 has been
mapped to (0,0) and w2 has been mapped to (1,0). */
glBegin(GL_LINES);
glColor3d(0.9,0.9,0.2);
glVertex2d(0.0,0.0); glVertex2d(1.0,0.0);
glVertex2d(0.9,0.02); glVertex2d(1.0,0.0);
glVertex2d(0.9,-0.02); glVertex2d(1.0,0.0);
glColor3d(1.0,1.0,1.0);
glEnd();
glPopMatrix();
}
/*****************************************************************\
Spline Drawing formulae:
\**********************/
double StartPt(int ii){
/*Points of array are zero based so
point 1 is 0, 2 is 1, 3 is 2, and 4 is 3
NOTE:
which 0== Hermite, 1== Bezier, 2== Cardinal
*/
if(which == 2) return P[1][ii]; /*P2*/
elsereturn P[0][ii]; /*P1*/

}
double EndPt(int ii){
if(which == 1) return P[3][ii]; /*P4*/
else
return P[2][ii]; /*P3*/
}
double StartTan(int ii){
if(which == 0){
return((1-tension)*(P[1][ii] - P[0][ii]) ); }
if(which == 1){
return( 3*(1-tension)*(P[1][ii] - P[0][ii]) );
}
if(which == 2){
return((1-tension)*(P[2][ii] - P[0][ii]) /2 );
}
else return 0.0;
}
double EndTan(int ii){
if(which == 0){
return((1-tension)*(P[3][ii] - P[2][ii]) ); }
if(which == 1){
return( 3*(1-tension)*(P[3][ii] - P[2][ii]) );
}
if(which == 2){
return((1-tension)*(P[3][ii] - P[1][ii])/2 ); }
else return 0.0;
}
/*****************************************************************\
Spline Drawing routine:
Calls formulae for input.
\**********************/
void Spline(){
int ii;
double R,G,B,t, vv[2];
double inc;
inc = NUMSTEPS;
R = 1.0; G = 0.7; B = 0.0;
for(t=0; t<=1; t+=inc){
for(ii=0;ii<2;ii++){
vv[ii] = ((2*t*t*t)-(3*t*t)+1)*StartPt(ii)
+ ((-2*t*t*t)+(3*t*t))*EndPt(ii)
+ ((t*t*t)-(2*t*t)+t)*StartTan(ii)
+ ((t*t*t)-(t*t))*EndTan(ii);
}
R -= t * 0.08;
B += t * 0.08;
glColor3d(R,G,B);
glVertex2dv(vv);
}
}
/*****************************************************************\
draw_splines():encloses point generation routines.
\**********************/
void draw_splines(){
glBegin(GL_LINE_STRIP);

Spline();
glEnd();
}
/***************************/
/* General Glut Functions: */
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslated((200),(200),0);
glScaled(scale,scale,1);/* Zoom */
glTranslated((-T_X),(-T_Y),0); /* move */
/* Draw Here */
if(which == 0){ arrow(P[0],P[1]); arrow(P[2],P[3]); }
draw_splines();
draw_points();
glPopMatrix();
glutSwapBuffers();
}
void init (void) {
/*General Init: */
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,400,400,0);
glMatrixMode(GL_MODELVIEW);
/* Call specific Init: */
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
}
void idle (void){
/* General: */
if(refresh){
refresh = !refresh;
glutPostRedisplay();
}
}
void keyboard(unsigned char dakey, int x, int y) {
switch (dakey) {
case '1':
which = 0;
glutPostRedisplay();
break;
case '2':
which = 1;
glutPostRedisplay();
break;
case '3':

which = 2;
glutPostRedisplay();
break;
/***************************/
/* Zoom and View Controls: */
case 'i':
refresh = !refresh; T_Y -= 25;
case 'k':
refresh = !refresh; T_Y += 25;
case 'l':
refresh = !refresh; T_X += 25;
case 'j':
refresh = !refresh; T_X -= 25;
case 'x': case '.' :
refresh = !refresh;
scale += 0.10; break;
case 'z': case ',' :
refresh = !refresh;
scale -= 0.10; break;
default: break;

glutPostRedisplay(); break;
glutPostRedisplay(); break;
glutPostRedisplay(); break;
glutPostRedisplay(); break;

}
}
void menu(int value) {
switch(value) {
case 3:
P[0][0] = 0;P[0][1] = 0;P[1][0] = 50; P[1][1] = 250;
P[2][0] = 300; P[2][1] = 300; P[3][0] = 350; P[3][1] = 550;
T_Y = 275.0000; T_X = 200.0000;
scale = 0.5;
tension = 0.0;
which = 0;
glutPostRedisplay();
break;
case 4: exit(0); break;
}
}
void TensionMenu(int value) {
switch(value) {
case 101: tension = -2.0; glutPostRedisplay(); break;
case 102: tension = -1.0; glutPostRedisplay(); break;
case 103: tension = -0.5; glutPostRedisplay(); break;
case 104: tension = 0.0; glutPostRedisplay(); break;
case 105: tension = 0.2; glutPostRedisplay(); break;
case 106: tension = 0.4; glutPostRedisplay(); break;
case 107: tension = 0.6; glutPostRedisplay(); break;
case 108: tension = 0.8; glutPostRedisplay(); break;
case 109: tension = 1.0; glutPostRedisplay(); break;
case 110: tension = 2.0; glutPostRedisplay(); break;

case 111: tension = 4.0; glutPostRedisplay(); break;


default : tension = 0.0; glutPostRedisplay(); break;
}
}
void SplineMenu(int value) {
switch(value) {
case 10:
which = 0; glutPostRedisplay();
break;
case 20:
which = 1; glutPostRedisplay();
break;
case 30:
which = 2; glutPostRedisplay();
break;
default: which = 0; glutPostRedisplay(); break;
}
}
void MakeMenu(){
int SpM,TnM;
SpM = glutCreateMenu(SplineMenu);
glutAddMenuEntry("Hermite" ,10);
glutAddMenuEntry("Bezier" ,20);
glutAddMenuEntry("Cardinal",30);
TnM = glutCreateMenu(TensionMenu);
glutAddMenuEntry("-2.0",101);
glutAddMenuEntry("-1.0",102);
glutAddMenuEntry("-0.5",103);
glutAddMenuEntry("0.0" ,104);
glutAddMenuEntry("0.2" ,105);
glutAddMenuEntry("0.4" ,106);
glutAddMenuEntry("0.6" ,107);
glutAddMenuEntry("0.8" ,108);
glutAddMenuEntry("1.0" ,109);
glutAddMenuEntry("2.0" ,110);
glutAddMenuEntry("4.0" ,111);
glutCreateMenu(menu);
glutAddSubMenu("Spline", SpM);
glutAddSubMenu("Tension",TnM);
glutAddMenuEntry("Reset Image",3);
glutAddMenuEntry("Quit",4);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
/*****************************************************************\
Mouse functions! Transforms Mouse Points to relative GL
coordinates... by far the hardest part!
\**********************/
void mouse(int button, int state, int Mx, int My) {

int ii;
switch(button){
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN){
for(ii=0; ii<4; ii++) {
if ( (( ( ((Mx-200) / scale) + T_X)) >
(P[ii][0]-10) )&&
(( ( ((Mx-200) / scale) + T_X))
< (P[ii][0]+10) )&&
(( ( ((My-200) / scale) + T_Y))
> (P[ii][1]-10) )&&
(( ( ((My-200) / scale)
+ T_Y)) < (P[ii][1]+10)) ){
move = ii;
break;
}
else move = 4;
/*
Nifty and extremely complex
scaling tests...
means you can zoom in and still control
the points
and the mouse motion will match the
point's motion
took me two hours to work this out...
Make that FOUR...
((It's((a((Paren(thet(ic(al((Ni(g(h)T)m)a)r)e)).).).) )!)!)!)
*/
} /* for */
} /* if */
break;
}
}
void MouseMove(int newx, int newy){
if(move != 4){
P[move][0] = ((newx-200) / scale) + T_X;
P[move][1] = ((newy-200) / scale) + T_Y;
refresh = !refresh;
}
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (400, 400);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Splines");
init();
glutDisplayFunc(display);

glutIdleFunc(idle);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(MouseMove);
MakeMenu();
glutMainLoop();
return 0;/* ANSI C requires main to return int. */
}

Das könnte Ihnen auch gefallen