I am trying to call a function, only when "spacebar" is pressed. Its key code is 32.
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <cmath>
#include <iostream>
#include <string.h>
using namespace std;
GLuint window, View1;
void Display_Mid_Ellipse()
{
double xc=0.0, yc=0.0, rx=140.0, ry=200.0;
double rxSq = rx * rx;
double rySq = ry * ry;
double x = 0, y = ry, p;
double px = 0, py = 2 * rxSq * y;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f( 1 ,0, 0);
glBegin(GL_POINTS);
glVertex2d(xc+x,yc-y);
glVertex2d(xc-x,yc-y);
glVertex2d(xc-x,yc+y);
glEnd();
p = rySq - (rxSq * ry) + (0.25 * rxSq);
while (px < py)
{
x++;
px = px + 2 * rySq;
if (p < 0)
p = p + rySq + px;
else
{
y--;
py = py - 2 * rxSq;
p = p + rySq + px - py;
}
glBegin(GL_POINTS);
glVertex2d(xc+x,yc+y);
glVertex2d(xc+x,yc-y);
glVertex2d(xc-x,yc-y);
glVertex2d(xc-x,yc+y);
glEnd();
}
p = rySq*(x+0.5)*(x+0.5) + rxSq*(y-1)*(y-1) - rxSq*rySq;
while (y > 0)
{
y--;
py = py - 2 * rxSq;
if (p > 0)
p = p + rxSq - py;
else
{
x++;
px = px + 2 * rySq;
p = p + rxSq - py + px;
}
glBegin(GL_POINTS);
glVertex2d(xc+x,yc+y);
glVertex2d(xc+x,yc-y);
glVertex2d(xc-x,yc-y);
glVertex2d(xc-x,yc+y);
glEnd();
glFlush();
}
} //end_MIDPOINT_ELLIPSE
void init () {
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.3,0.3,0.3,0.7);
gluOrtho2D(-500.0,500.0,-500.0,500.0);
}
void View1Display()
{
glutSetWindow(View1);
gluOrtho2D(-500.0,500.0,-500.0,500.0);
Display_Mid_Ellipse();
}
void Display()
{
glutSetWindow(window);
glClear(GL_COLOR_BUFFER_BIT);
//View1Display();
}
void keyFunc(unsigned char ch, int x, int y){
if(ch==32){
View1Display();
}
}
int main (int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(750, 750);
glutInitWindowPosition(0, 0);
window=glutCreateWindow("Circle and ellipse");
init();
View1 = glutCreateSubWindow(window,20,40, 340,340);
glutDisplayFunc(Display);
glutKeyboardFunc(keyFunc);
glutMainLoop();
return 0;
}
When i call the same View1Display from the Display() function, it works well.
I'm confused. I have tried the alternatives I could but could not find a solution. Please help.
Thanks
Callbacks are registered for the active window (creating a window implicitly activates it) so you can register separate display callbacks for the toplevel window and your subwindow.
Don't call your subwindow display function from the keyboard callback. Toggle a shared variable & use glutPostWindowRedisplay() to force a redraw instead.
If you're going to use GLUT_SINGLE make sure to glFlush() to force updates out to the framebuffer.
All together:
#include <GL/glut.h>
#include <cmath>
using namespace std;
void Display_Mid_Ellipse()
{
double xc = 0.0, yc = 0.0, rx = 140.0, ry = 200.0;
double rxSq = rx * rx;
double rySq = ry * ry;
double x = 0, y = ry, p;
double px = 0, py = 2 * rxSq * y;
glClear( GL_COLOR_BUFFER_BIT );
glColor3f( 1, 0, 0 );
glBegin( GL_POINTS );
glVertex2d( xc + x, yc - y );
glVertex2d( xc - x, yc - y );
glVertex2d( xc - x, yc + y );
glEnd();
p = rySq - ( rxSq * ry ) + ( 0.25 * rxSq );
while( px < py )
{
x++;
px = px + 2 * rySq;
if( p < 0 )
p = p + rySq + px;
else
{
y--;
py = py - 2 * rxSq;
p = p + rySq + px - py;
}
glBegin( GL_POINTS );
glVertex2d( xc + x, yc + y );
glVertex2d( xc + x, yc - y );
glVertex2d( xc - x, yc - y );
glVertex2d( xc - x, yc + y );
glEnd();
}
p = rySq*( x + 0.5 )*( x + 0.5 ) + rxSq*( y - 1 )*( y - 1 ) - rxSq*rySq;
while( y > 0 )
{
y--;
py = py - 2 * rxSq;
if( p > 0 )
p = p + rxSq - py;
else
{
x++;
px = px + 2 * rySq;
p = p + rxSq - py + px;
}
glBegin( GL_POINTS );
glVertex2d( xc + x, yc + y );
glVertex2d( xc + x, yc - y );
glVertex2d( xc - x, yc - y );
glVertex2d( xc - x, yc + y );
glEnd();
glFlush();
}
} //end_MIDPOINT_ELLIPSE
bool displayEllipse = false;
void View1Display()
{
glClearColor( 0.3, 0.3, 0.3, 0.7 );
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D( -500.0, 500.0, -500.0, 500.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
if( displayEllipse )
Display_Mid_Ellipse();
glFlush();
}
void Display()
{
glClearColor( 0.0, 0.0, 0.0, 1.0 );
glClear( GL_COLOR_BUFFER_BIT );
glFlush();
}
GLuint window;
GLuint View1;
void keyFunc( unsigned char ch, int x, int y )
{
if( ch == 32 )
{
displayEllipse = !displayEllipse;
glutPostWindowRedisplay( View1 );
}
}
int main( int argc, char *argv[] )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
glutInitWindowSize( 750, 750 );
glutInitWindowPosition( 0, 0 );
window = glutCreateWindow( "Circle and ellipse" );
glutDisplayFunc( Display );
glutKeyboardFunc( keyFunc );
View1 = glutCreateSubWindow( window, 20, 40, 340, 340 );
glutDisplayFunc( View1Display );
glutMainLoop();
return 0;
}
Related
I have just tried to run the Bresenham function which draws a line from 2 vertexes, but only the white screen of GLUT appear, there is no line at all. Here is my source code, can anybody help me?
#include <math.h>
#include <windows.h>
#include <GL/glut.h>
#include <GL/gl.h>
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 500.0, 0.0, 500.0);
}
void Bresenham(int x1, int y1, int x2, int y2) {
int Dx = abs(x2 - x1);
int Dy = abs(y2 - y1);
int p = 2 * Dy - Dx;
int c1 = 2 * Dy;
int c2 = 2 * (Dy - Dx);
int x = x1;
int y = y1;
int x_unit = 1, y_unit = 1;
glVertex2d(x, y);
while (x != x2) {
if (p<0) p += c1;
else {
p += c2;
y += y_unit;
}
x += x_unit;
glVertex2d(x, y);
}
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
Bresenham(50, 150, 300, 200);
glEnd();
glFlush();
}
int main(int iArgc, char** cppArgv) {
glutInit(&iArgc, cppArgv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(600, 600);
glutInitWindowPosition(50, 50);
glutCreateWindow("Line");
init();
int x1=50, y1=150, x2=300, y2=200;
glutDisplayFunc(display);
glutMainLoop();
return EXIT_SUCCESS;
}
Make sure your background color doesn't match your drawing color. Kinda hard to see white-on-white :)
Drawing the line in red works on my machine:
#include <GL/glut.h>
void Bresenham(int x1, int y1, int x2, int y2)
{
int Dx = abs(x2 - x1);
int Dy = abs(y2 - y1);
int p = 2 * Dy - Dx;
int c1 = 2 * Dy;
int c2 = 2 * (Dy - Dx);
int x = x1;
int y = y1;
int x_unit = 1, y_unit = 1;
glVertex2d(x, y);
while (x != x2)
{
if (p<0)
p += c1;
else
{
p += c2;
y += y_unit;
}
x += x_unit;
glVertex2d(x, y);
}
}
void display(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 500.0, 0.0, 500.0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_POLYGON);
glColor3ub( 255, 0, 0 );
Bresenham(50, 150, 300, 200);
glEnd();
glutSwapBuffers();
}
int main(int argc, char** argv )
{
glutInit( &argc, argv );
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(600, 600);
glutCreateWindow("Line");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
This question already has an answer here:
Compilation error with bresenham line algorithm?
(1 answer)
Closed 6 years ago.
Errors while compiling:
redefinition of 'y1' as different kind of symbol float x1 = 0, y1 = 0, x2 = 0, y2 = 0;
non-object type 'double (double)' is not assignable
y1 = 240-y;
no matching function for call to 'drawPixel'
drawPixel( x1, y1 );
no matching function for call to 'dda'
dda( x1, y1, x2, y2 );
Code:
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <iostream>
using namespace std;
#include <cstdlib>
#include <cmath>
//defining constants
#define MAX_WIDTH 640
#define MAX_HEIGHT 480
int flag = 1;
float x1 = 0, y1 = 0, x2 = 0, y2 = 0;
//method for drawing the pixel
void drawPixel( int x, int y ){
glBegin( GL_POINTS );
//setting the pointer color
glColor3f( 1.0, 1.0, 1.0 );
glVertex2i( x, y );
glEnd();
glFlush();
}
//display callback function
void display(){
glClear( GL_COLOR_BUFFER_BIT );
gluLookAt( 0.0, 0.0, 0.0, 0.0, 0.0, 5.0, 0.0, 1.0, 0.0 );
/*
glBegin( GL_POINTS );
//setting the pointer color
glColor3f( 1.0, 1.0, 1.0 );
glVertex2i( 0, 0 );
glVertex2i( 10, 0 );
glEnd();
*/
glFlush();
}
//catching keyboard events
void keyboardEvent( unsigned char c, int x, int y ){
if( c == 27 ){
exit(0);
}
}
//dda implementation
void dda( float m1 , float n1 , float m2 , float n2 ){
float slope , Dx , Dy;
float dx , dy , length;
int i = 1;
dx = dy = length = 0.0;
slope = Dx = Dy = 0.0;
dx = m2 - m1;
dy = n2 - n1;
slope = dy/dx; //slope
cout << m1 << "\t" << n1 << "\t" << m2 << "\t" << n2 << endl;
length = (dx >= dy)?dx:dy ;
cout << length<< endl;
Dx = dx/length;
Dy = dy/length;
drawPixel( round(m1), round(n1) );
cout << m1 << m2 << endl;
for( ; i <= length ; i++ ){
m1 = m1 + Dx;
n1 = n1 + Dy;
drawPixel( round(m1), round(n1) );
cout << m1 << m2 << endl;
}
}
//catching mouse click events
void mouseEvent( int button, int state, int x, int y ){
//checking if the mouse button is clicked or not using state para.
if( state == GLUT_DOWN ){
if( button == GLUT_LEFT_BUTTON && flag == 1 ){
x1 = 320-x;
y1 = 240-y;
drawPixel( x1, y1 );
flag++;
}
else if( button == GLUT_LEFT_BUTTON && flag == 2 ){
x2 = 320-x;
y2 = 240-y;
drawPixel( x2, y2 );
flag++;
}
else if( button == GLUT_RIGHT_BUTTON && flag > 2 ){
drawPixel( 320-x, 240-y );
cout << x1 << "\t" << y1 << "\t" << x2 << "\t" << y2 << endl;
dda( x1, y1, x2, y2 );
}
}
}
//adjusting window when it is moved or resized
void reshape( int w, int h ){
glViewport( 0, 0, w, h );
}
//initialising the window at startup
void initialise(){
glClearColor( 0.0, 0.0, 0.0, 1.0 );
glPointSize( 5 );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D( -320, 320, -240, 240 );
}
int main( int argc, char **argv ){
//initialising the glut library
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
glutInitWindowSize( MAX_WIDTH, MAX_HEIGHT );
glutInitWindowPosition( 100, 100 );
glutCreateWindow("DDA Assignment");
//calling normal functions
initialise();
//registering callback functions
glutDisplayFunc( display );
glutKeyboardFunc( keyboardEvent );
glutMouseFunc( mouseEvent );
glutReshapeFunc( reshape );
glutMainLoop();
return 0;
}
If you compile this on POSIX, you will end up with <math.h> (and cmath) declaring functions with the name y0, y1 and yn, which will totally conflict with any global variable of the same name.
Since you explicitely tagged this question as c++14, you should also tell your compile to use that standard by using
g++ -std=c++14
(or any other appropriate version of the standard), which will also prevent the libc headers from declaring functions which are not in that standard.
I've got some code but the matrix orientation does not appeal to my purposes, can someone teach me how to convert it's orientation, it's currently set up as X Z Y, but i would like it to reflect X Y Z, can someone please highlight what must be done?
when i do vertex3f(100, 100, 10); forexample, the 10 value should reflect the Z value on my grid.
Here is my code:
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <Windows.h>
#include <glut.h>
#include <iostream>
using namespace std;
const float sensitivity = 0.005;
const float walk_speed = 0.5;
float cam_pos[3] = { 100.5, 10.0f, 50 };
float cam_view[3] = { -1.0f, 0.0f, 1.0f };
static int old_x, old_y, half_width, half_height;
int width = 1024, height = 768;
void updateKeys()
{
if (GetAsyncKeyState('W')){
cam_pos[0] += cam_view[0] * walk_speed;
cam_pos[1] += cam_view[1] * walk_speed;
cam_pos[2] += cam_view[2] * walk_speed;
}
if (GetAsyncKeyState('S')){
cam_pos[0] -= cam_view[0] * walk_speed;
cam_pos[1] -= cam_view[1] * walk_speed;
cam_pos[2] -= cam_view[2] * walk_speed;
}
if (GetAsyncKeyState('A')){
cam_pos[0] += cam_view[2] * walk_speed;
cam_pos[2] -= cam_view[0] * walk_speed;
}
if (GetAsyncKeyState('D')){
cam_pos[0] -= cam_view[2] * walk_speed;
cam_pos[2] += cam_view[0] * walk_speed;
}
if (GetAsyncKeyState(VK_SPACE)){
cam_pos[1] += walk_speed;
}
}
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//3d camera
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
cam_pos[0], cam_pos[1], cam_pos[2],
cam_pos[0] + cam_view[0], cam_pos[1] + cam_view[1], cam_pos[2] + cam_view[2],
0.0f, 1.0f, 0.0f);
//render grid
glBegin(GL_LINES);
for (int i = 0; i <= 100; i++) {
if (i == 0) { glColor3f(.6, .3, .3); }
else { glColor3f(.25, .25, .25); };
glVertex3f(i, 0, 0);
glVertex3f(i, 0, 100);
if (i == 0) { glColor3f(.3, .3, .6); }
else { glColor3f(.25, .25, .25); };
glVertex3f(0, 0, i);
glVertex3f(100, 0, i);
};
glEnd();
glEnable(GL_POINT_SMOOTH);
glPointSize(50.0f);
glColor3f(1, 0, 0);
glBegin(GL_POINTS);
glVertex3f(0, 0, 0);
//X, Z, Y
glVertex3f(10, -10, 10);
glEnd();
updateKeys();
glutSwapBuffers();
}
void normalize(float *v)
{
float magnitude = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] /= magnitude;
v[1] /= magnitude;
v[2] /= magnitude;
}
void rotate_view(float *view, float angle, float x, float y, float z)
{
float new_x;
float new_y;
float new_z;
float c = cos(angle);
float s = sin(angle);
new_x = (x*x*(1 - c) + c) * view[0];
new_x += (x*y*(1 - c) - z*s) * view[1];
new_x += (x*z*(1 - c) + y*s) * view[2];
new_y = (y*x*(1 - c) + z*s) * view[0];
new_y += (y*y*(1 - c) + c) * view[1];
new_y += (y*z*(1 - c) - x*s) * view[2];
new_z = (x*z*(1 - c) - y*s) * view[0];
new_z += (y*z*(1 - c) + x*s) * view[1];
new_z += (z*z*(1 - c) + c) * view[2];
view[0] = new_x;
view[1] = new_y;
view[2] = new_z;
normalize(view);
}
void motion(int x, int y)
{
float rot_x, rot_y;
float rot_axis[3];
x -= half_width;
y -= half_height;
rot_x = -(float)(x - old_x) * sensitivity;
rot_y = -(float)(y - old_y) * sensitivity;
old_x = x;
old_y = y;
rotate_view(cam_view, rot_x, 0.0f, 1.0f, 0.0f);
rot_axis[0] = -cam_view[2];
rot_axis[1] = 0.0f;
rot_axis[2] = cam_view[0];
normalize(rot_axis);
rotate_view(cam_view, rot_y, rot_axis[0], rot_axis[1], rot_axis[2]);
}
void mouse(int button, int state, int x, int y)
{
old_x = x - half_width;
old_y = y - half_height;
glutPostRedisplay();
}
void idle()
{
glutPostRedisplay();
}
void keys(unsigned char c, int x, int y)
{
glutPostRedisplay();
cout << "camera view: :" << cam_view[0] << "," << cam_view[1] << "," << cam_view[2] << endl;
}
void reshape(int w, int h)
{
width = w;
height = h;
half_height = w / 2;
half_width = h / 2;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 10000.0);
glViewport(0, 0, w, h);
}
//----------------------------------------------------------------------
// Main program
//----------------------------------------------------------------------
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(width, height);
glutCreateWindow("OpenGL");
glutDisplayFunc(renderScene);
glutKeyboardFunc(keys);
glutReshapeFunc(reshape);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutIdleFunc(idle);
// OpenGL init
glEnable(GL_DEPTH_TEST);
// enter GLUT event processing cycle
glutMainLoop();
return 0; // this is just to keep the compiler happy
}
Use a transformation matrix that "remaps" the values. You can push that matrix on your modelview as usual.
The identity matrix is:
(1, 0, 0; 0, 1, 0; 0, 0, 1)
Your matrix would be:
(1, 0, 0; 0, 0, 1; 0, 1, 0)
I guess you can spot the difference. You can extend to a 4D matrix for homogeneous coordinates accordingly.
I try in 3D but i am a beginner, so i try do with 2D first and value of z = 0. I have an array of points with values random in array points[] using std::vector. I have functions Distance(...) and CaculateF(...) to caculate new value for points[] and store in array pnew[]. I need draw points[] and move them to the value of pnew[], but i only know drawing random points in array points[] first, i can't move them exactly to values in pnew[]. Can anybody help me?!
#include<stdlib.h>
#include<glut.h>
#include<iostream>
#include<conio.h>
#include<math.h>
#include<omp.h>
#include<time.h>
#include<Windows.h>
#include<vector>
using namespace std;
struct Point
{
float x, y , z;
float vx, vy, vz;
unsigned long m;
unsigned char r, g, b, a;
};
vector< Point > points, pnew;
void animation_points( int value )
{
// move all points left each frame
for( size_t i = 0; i < points.size(); ++i )
{
points[i].x -= 1;
// wrap point around if it's moved off
// the edge of our 100x100 area
if( points[i].x < -50 )
{
points[i].x = 100 + points[i].x;
}
}
glutPostRedisplay();
glutTimerFunc(30, animation_points, 1);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-50, 50, -50, 50, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw
glColor3ub( 255, 255, 255 );
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
glVertexPointer( 2, GL_FLOAT, sizeof(Point), &points[0].x );
glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(Point), &points[0].r );
glPointSize( 3.0 );
glDrawArrays( GL_POINTS, 0, points.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glFlush();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
}
//Distance between i and j
float Distance(float x1,float y1, float z1, float x2, float y2, float z2)
{
return (sqrt(pow(x1-x2,2) + pow(y1-y2,2) + pow(z1-z2,2)));
}
//Value of F on Ox, Oy, Oz
Point CalculateF(double d, Point a, Point b, int dt)
{
Point F;
float vnewx, vnewy, vnewz, xnew , ynew, znew;
float G = 6.6742*pow(10,-11);
float Fx = (G*a.m*b.m/pow(d,2)*(a.x-b.x)/d);
float Fy = (G*a.m*b.m/pow(d,2)*(a.y-b.y)/d);
float Fz = (G*a.m*b.m/pow(d,2)*(a.z-b.z)/d);
vnewx = a.vx + Fx*dt/a.m;
vnewy = a.vy + Fy*dt/a.m;
vnewz = a.vz + Fz*dt/a.m;
xnew = a.x + a.x*dt;
ynew = a.y + a.y*dt;
znew = a.z + a.z*dt;
F.x = xnew;
F.y = ynew;
F.z = znew;
F.vx = vnewx;
F.vy = vnewy;
F.vz = vnewz;
F.m = a.m;
return F;
}
int main(int argc, char **argv)
{
// begin
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(640,480);
glutCreateWindow("N - body");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
// animation points
//glutTimerFunc(30, animation_points, 1);
////
int n, t;
cout<<"\n Number of body: ";
cin>>n;
// move after time t
cout<<"\n\n Time: ";
cin>>t;
t *= 3600;
// random points
for( int i = 0; i < n; ++i )
{
Point pt;
pt.x = -50 + (rand() % 100);
pt.y = -50 + (rand() % 100);
pt.z = 0;
pt.r = rand() % 255;
pt.g = rand() % 255;
pt.b = rand() % 255;
pt.a = 255;
points.push_back(pt);
}
glutMainLoop();
float d;
//#pragma omp parallel default(shared) private(i,j)
for (int i = 0 ; i < n ; i++)
{
//#pragma omp for schedule(static)
for (int j = 0 ; j < n ; j++)
{
d = Distance(points[i].x, points[i].y,points[i].z, points[j].x, points[j].y, points[j].z);
if (d!=0)
points[i] = CalculateF(d,points[i], points[j], t);
}
pnew.push_back(points[i]);
}
return 0;
}
You need to store the initial and the target positions of your points in arrays, then interpolate between them in the rendering code. To do that, you determine how much time has passed, compute a double lambda in the range 0.0 to 1.0 from the time, then draw the points at the position p_start + lambda * (p_target - p_start).
below is the code so far, my problem lies in dragging the graph around the window ? i can't seem to do it ? any tips for me guys ?? What i want is when you click and hold down the left mouse button you should be able to drag the graph around the window ?
#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>
#if !defined(GLUT_WHEEL_UP)
# define GLUT_WHEEL_UP
# define GLUT_WHEEL_DOWN 4
#endif
/* Set initial size of the display window. */
GLsizei winWidth = 600, winHeight = 600;
/* Set size of world-coordinate clipping window. */
GLfloat xwcMin = -50.0, xwcMax = 50.0;
GLfloat ywcMin = -50.0, ywcMax = 50.0;
bool leftButton;
int downX, downY;
class wcPt3D {
public:
GLfloat x, y, z;
};
void init (void) {
/* Set color of display window to white. */
glClearColor (1.0, 1.0, 1.0, 0.0);
}
void plotPoint (wcPt3D bezCurvePt) {
glBegin (GL_POINTS);
glVertex2f (bezCurvePt.x, bezCurvePt.y);
glEnd ( );
}
/* Compute binomial coefficients C for given value of n. */
void binomialCoeffs (GLint n, GLint * C) {
GLint k, j;
for (k = 0; k <= n; k++) {
/* Compute n!/(k!(n - k)!). */
C [k] = 1;
for (j = n; j >= k + 1; j--)
C [k] *= j;
for (j = n - k; j >= 2; j--)
C [k] /= j;
}
}
void computeBezPt (GLfloat t, wcPt3D * bezPt, GLint nCtrlPts,
wcPt3D * ctrlPts, GLint * C) {
GLint k, n = nCtrlPts - 1;
GLfloat bezBlendFcn;
bezPt->x = bezPt->y = bezPt->z = 0.0;
/* Compute blending functions and blend control points. */
for (k = 0; k < nCtrlPts; k++) {
bezBlendFcn = C [k] * pow (t, k) * pow (1 - t, n - k);
bezPt->x += ctrlPts [k].x * bezBlendFcn;
bezPt->y += ctrlPts [k].y * bezBlendFcn;
bezPt->z += ctrlPts [k].z * bezBlendFcn;
}
}
void bezier (wcPt3D * ctrlPts, GLint nCtrlPts, GLint nBezCurvePts) {
wcPt3D bezCurvePt;
GLfloat t;
GLint *C;
/* Allocate space for binomial coefficients */
C = new GLint [nCtrlPts];
binomialCoeffs (nCtrlPts - 1, C);
for (int i = 0; i <= nBezCurvePts; i++) {
t = GLfloat (i) / GLfloat (nBezCurvePts);
computeBezPt (t, &bezCurvePt, nCtrlPts, ctrlPts, C);
plotPoint (bezCurvePt);
}
delete [ ] C;
}
void displayFcn (void) {
glClear (GL_COLOR_BUFFER_BIT); // Clear display window.
/* Set example number of control points and number of
* curve positions to be plotted along the Bezier curve.
*/ GLint nCtrlPts = 4, nBezCurvePts = 1000;
wcPt3D ctrlPts [4] = { {-40.0, -40.0, 0.0}, {-10.0, 200.0, 0.0},
{10.0, -200.0, 0.0}, {40.0, 40.0, 0.0} };
glPointSize (4);
glColor3f (1.0, 0.0, 0.0); // Set point color to red.
bezier (ctrlPts, nCtrlPts, nBezCurvePts);
glutSwapBuffers();
}
void winReshapeFcn (GLint newWidth, GLint newHeight) {
/* Maintain an aspect ratio of 1.0. */
glViewport (0, 0, xwcMin, ywcMin);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ( );
gluOrtho2D (xwcMin, xwcMax, ywcMin, ywcMax);
glutPostRedisplay();
}
void MouseCallback(int button, int state, int x, int y) {
downX = x;
downY = y;
leftButton = ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN));
glutPostRedisplay();
}
void MotionCallback(int x, int y) {
if (leftButton){
downX=downX+x;
downY=downY+y;
gluOrtho2D (xwcMin, xwcMax, ywcMin, ywcMax);
}
downX = x;
downY = y;
glutPostRedisplay();
}
/*
void MouseCallback(int button, int state, int x, int y) {
if (button == GLUT_WHEEL_UP && glutGetModifiers()==GLUT_ACTIVE_CTRL) {
}else if (button == GLUT_WHEEL_DOWN)
glutPostRedisplay();
}
*/
int main (int argc, char** argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition (50, 50);
glutInitWindowSize (winWidth, winHeight);
glutCreateWindow ("Bezier Curve");
init ( );
glutDisplayFunc (displayFcn);
glutReshapeFunc (winReshapeFcn);
glutMouseFunc(MouseCallback);
glutMotionFunc(MotionCallback);
glutMainLoop ( );
}
Try this:
#include <GL/glut.h>
#include <cmath>
// Compute binomial coefficients C for given value of n.
void binomialCoeffs
(
GLint n,
GLint* C
)
{
for (GLint k = 0; k <= n; k++)
{
// Compute n!/(k!(n - k)!).
C [k] = 1;
for (GLint j = n; j >= k + 1; j--)
C [k] *= j;
for (GLint j = n - k; j >= 2; j--)
C [k] /= j;
}
}
struct wcPt3D
{
GLfloat x, y, z;
};
void computeBezPt
(
GLfloat t,
wcPt3D* bezPt,
GLint nCtrlPts,
wcPt3D* ctrlPts,
GLint* C
)
{
GLint n = nCtrlPts - 1;
GLfloat bezBlendFcn;
bezPt->x = bezPt->y = bezPt->z = 0.0;
// Compute blending functions and blend control points.
for (GLint k = 0; k < nCtrlPts; k++)
{
bezBlendFcn = C [k] * pow (t, k) * pow (1 - t, n - k);
bezPt->x += ctrlPts [k].x * bezBlendFcn;
bezPt->y += ctrlPts [k].y * bezBlendFcn;
bezPt->z += ctrlPts [k].z * bezBlendFcn;
}
}
void bezier
(
wcPt3D* ctrlPts,
GLint nCtrlPts,
GLint nBezCurvePts
)
{
// Allocate space for binomial coefficients
GLint* C = new GLint [nCtrlPts];
binomialCoeffs (nCtrlPts - 1, C);
glBegin (GL_POINTS);
for (int i = 0; i <= nBezCurvePts; i++)
{
GLfloat t = GLfloat (i) / GLfloat (nBezCurvePts);
wcPt3D bezCurvePt;
computeBezPt (t, &bezCurvePt, nCtrlPts, ctrlPts, C);
glVertex2f (bezCurvePt.x, bezCurvePt.y);
}
glEnd();
delete [ ] C;
}
int btn;
int startMouseX = 0;
int startMouseY = 0;
int startTransX = 0;
int startTransY = 0;
int curTransX = 0;
int curTransY = 0;
void MouseCallback(int button, int state, int x, int y)
{
btn = button;
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
{
startMouseX = x;
startMouseY = glutGet( GLUT_WINDOW_HEIGHT ) - y;
startTransX = curTransX;
startTransY = curTransY;
}
glutPostRedisplay();
}
void MotionCallback(int x, int y)
{
int curMouseX = x;
int curMouseY = glutGet( GLUT_WINDOW_HEIGHT ) - y;
if ( btn == GLUT_LEFT_BUTTON )
{
curTransX = startTransX + ( curMouseX - startMouseX );
curTransY = startTransY + ( curMouseY - startMouseY );
}
glutPostRedisplay();
}
// Set size of world-coordinate clipping window.
GLfloat xwcMin = -50.0, xwcMax = 50.0;
GLfloat ywcMin = -50.0, ywcMax = 50.0;
void displayFcn ()
{
// Clear display window.
glClearColor (1.0, 1.0, 1.0, 0.0);
glClear (GL_COLOR_BUFFER_BIT);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ( );
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glTranslatef( curTransX / w * 2, curTransY / h * 2, 0 );
gluOrtho2D (xwcMin, xwcMax, ywcMin, ywcMax);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
// Set example number of control points and number of
// curve positions to be plotted along the Bezier curve.
GLint nCtrlPts = 4, nBezCurvePts = 1000;
wcPt3D ctrlPts [4] =
{
{-40.0, -40.0, 0.0},
{-10.0, 200.0, 0.0},
{10.0, -200.0, 0.0},
{40.0, 40.0, 0.0}
};
// Set point color to red.
glPointSize (4);
glColor3f (1.0, 0.0, 0.0);
bezier (ctrlPts, nCtrlPts, nBezCurvePts);
glutSwapBuffers();
}
int main (int argc, char** argv)
{
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition (50, 50);
glutInitWindowSize (600, 600);
glutCreateWindow ("Bezier Curve");
glutDisplayFunc (displayFcn);
glutMouseFunc(MouseCallback);
glutMotionFunc(MotionCallback);
glutMainLoop ( );
}
Adapted from my answer here.
EDIT: Minimal(-ish) difference version:
#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>
#if !defined(GLUT_WHEEL_UP)
# define GLUT_WHEEL_UP
# define GLUT_WHEEL_DOWN 4
#endif
/* Set initial size of the display window. */
GLsizei winWidth = 600, winHeight = 600;
/* Set size of world-coordinate clipping window. */
GLfloat xwcMin = -50.0, xwcMax = 50.0;
GLfloat ywcMin = -50.0, ywcMax = 50.0;
class wcPt3D {
public:
GLfloat x, y, z;
};
void init (void) {
/* Set color of display window to white. */
glClearColor (1.0, 1.0, 1.0, 0.0);
}
void plotPoint (wcPt3D bezCurvePt) {
glBegin (GL_POINTS);
glVertex2f (bezCurvePt.x, bezCurvePt.y);
glEnd ( );
}
/* Compute binomial coefficients C for given value of n. */
void binomialCoeffs (GLint n, GLint * C) {
GLint k, j;
for (k = 0; k <= n; k++) {
/* Compute n!/(k!(n - k)!). */
C [k] = 1;
for (j = n; j >= k + 1; j--)
C [k] *= j;
for (j = n - k; j >= 2; j--)
C [k] /= j;
}
}
void computeBezPt (GLfloat t, wcPt3D * bezPt, GLint nCtrlPts,
wcPt3D * ctrlPts, GLint * C) {
GLint k, n = nCtrlPts - 1;
GLfloat bezBlendFcn;
bezPt->x = bezPt->y = bezPt->z = 0.0;
/* Compute blending functions and blend control points. */
for (k = 0; k < nCtrlPts; k++) {
bezBlendFcn = C [k] * pow (t, k) * pow (1 - t, n - k);
bezPt->x += ctrlPts [k].x * bezBlendFcn;
bezPt->y += ctrlPts [k].y * bezBlendFcn;
bezPt->z += ctrlPts [k].z * bezBlendFcn;
}
}
void bezier (wcPt3D * ctrlPts, GLint nCtrlPts, GLint nBezCurvePts) {
wcPt3D bezCurvePt;
GLfloat t;
GLint *C;
/* Allocate space for binomial coefficients */
C = new GLint [nCtrlPts];
binomialCoeffs (nCtrlPts - 1, C);
for (int i = 0; i <= nBezCurvePts; i++) {
t = GLfloat (i) / GLfloat (nBezCurvePts);
computeBezPt (t, &bezCurvePt, nCtrlPts, ctrlPts, C);
plotPoint (bezCurvePt);
}
delete [ ] C;
}
int curTransX = 0;
int curTransY = 0;
void displayFcn (void) {
glClear (GL_COLOR_BUFFER_BIT); // Clear display window.
glMatrixMode (GL_PROJECTION);
glLoadIdentity ( );
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
glTranslatef( curTransX / w * 2, curTransY / h * 2, 0 );
gluOrtho2D (xwcMin, xwcMax, ywcMin, ywcMax);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
/* Set example number of control points and number of
* curve positions to be plotted along the Bezier curve.
*/ GLint nCtrlPts = 4, nBezCurvePts = 1000;
wcPt3D ctrlPts [4] = { {-40.0, -40.0, 0.0}, {-10.0, 200.0, 0.0},
{10.0, -200.0, 0.0}, {40.0, 40.0, 0.0} };
glPointSize (4);
glColor3f (1.0, 0.0, 0.0); // Set point color to red.
bezier (ctrlPts, nCtrlPts, nBezCurvePts);
glutSwapBuffers();
}
int btn;
int startMouseX = 0;
int startMouseY = 0;
int startTransX = 0;
int startTransY = 0;
void MouseCallback(int button, int state, int x, int y) {
btn = button;
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
{
startMouseX = x;
startMouseY = glutGet( GLUT_WINDOW_HEIGHT ) - y;
startTransX = curTransX;
startTransY = curTransY;
}
glutPostRedisplay();
}
void MotionCallback(int x, int y) {
int curMouseX = x;
int curMouseY = glutGet( GLUT_WINDOW_HEIGHT ) - y;
if ( btn == GLUT_LEFT_BUTTON )
{
curTransX = startTransX + ( curMouseX - startMouseX );
curTransY = startTransY + ( curMouseY - startMouseY );
}
glutPostRedisplay();
}
/*
void MouseCallback(int button, int state, int x, int y) {
if (button == GLUT_WHEEL_UP && glutGetModifiers()==GLUT_ACTIVE_CTRL) {
}else if (button == GLUT_WHEEL_DOWN)
glutPostRedisplay();
}
*/
int main (int argc, char** argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition (50, 50);
glutInitWindowSize (winWidth, winHeight);
glutCreateWindow ("Bezier Curve");
init ( );
glutDisplayFunc (displayFcn);
glutMouseFunc(MouseCallback);
glutMotionFunc(MotionCallback);
glutMainLoop ( );
}