Draw A Sphere With Opengl - opengl

I draw the sphere by OpenGL.
This program can draw sphere when "SLIED = STACK".
But It's doesn't work when "SLIED not equal STACK".
I may be mistake "index array".
I want to use VBO and DMA(Dynamic memory allocate.use flat array).
But If You have another good idea, teach me.
//#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib,"glew32.lib")
#include <gl/glew.h>
#include <math.h>
#include <GL/freeglut/freeglut.h>
#define WIDTH 640
#define HEIGHT 480
#define M_PI 3.14159265358979323846
float angle=0.0f;
//functions----------------------------------------------//
void Shere_dma(double radius, int nSlice, int nStack);
void setSphereData(double radius, int nSlice, int nStack);
void DrawSphereVBO(void);
//-------------------------------------------------------//
//variabless---------------------------------------------//
int SLICE=0;
int STACK=0;
GLuint SVboId[3];
GLfloat* Svertex;//Vertex
GLfloat* Snormal;//Normal
GLfloat* Scolor; //Color
GLuint* indices_top; //TOP indices
GLuint* indices_bottom; //BOTTOM indies
GLuint* indices_side; //SIDE indices
//-------------------------------------------------------//
//Memory Allocate
void Shere_dma(double radius, int nSlice, int nStack){
Svertex = new GLfloat[(nSlice+1)*(nStack+1)*3];
Snormal = new GLfloat[(nSlice+1)*(nStack+1)*3];
Scolor = new GLfloat[(nSlice+1)*(nStack+1)*3];
indices_top = new GLuint[(nSlice+1)*(nStack+1)*3];
indices_bottom = new GLuint[(nSlice+1)*(nStack+1)*3];
indices_side = new GLuint[(nSlice+1)*(nStack+1)*4];
}
//inputData
void setSphereData(double radius, int nSlice, int nStack){
double phi; //Azimuth
double theta; //long
int coordinates=0;
int Slice_current_point_no=0;
int Slice_next_point_no=0;
const int x = 0;
const int y = 1;
const int z = 2;
const int p1 = 0;
const int p2 = 1;
const int p3 = 2;
const int p4 = 3;
//Vertex
for(int i = 0;i <= nSlice;i++)
{
phi = 2.0 * M_PI * (double)i / (double)nSlice;
for(int j = 0;j <= nStack;j++)
{
theta = M_PI * (double)j / (double)nStack;
Svertex[coordinates+x] = (float)(radius * sin(theta) * cos(phi)); //x
Svertex[coordinates+y] = (float)(radius * sin(theta) * sin(phi)); //y
Svertex[coordinates+z] = (float)(radius * cos(theta)); //z
Snormal[coordinates+x] = (float)(radius * sin(theta) * cos(phi)); //x
Snormal[coordinates+y] = (float)(radius * sin(theta) * sin(phi)); //y
Snormal[coordinates+z] = (float)(radius * cos(theta)); //z
Scolor[coordinates+x] = 1.0; //x
Scolor[coordinates+y] = 0.0; //y
Scolor[coordinates+z] = 0.0; //z
coordinates += 3;
}
}
//TOP
coordinates = 0;
Slice_current_point_no = 0;
Slice_next_point_no = nSlice;
for(int i = 0; i < nSlice; i++){
indices_top[coordinates+p1] = Slice_current_point_no;
indices_top[coordinates+p2] = indices_top[coordinates]+1;
indices_top[coordinates+p3] = Slice_next_point_no+2;
coordinates+=3;
Slice_current_point_no += nSlice+1;
Slice_next_point_no += nSlice+1;
}
//BOTTOM
coordinates =0;
Slice_current_point_no = 0;
Slice_next_point_no = nSlice;
for(int i = 0; i < nSlice; i++){
indices_bottom[coordinates+p1] = Slice_current_point_no+(nStack-1);
indices_bottom[coordinates+p2] = indices_bottom[coordinates]+1;
indices_bottom[coordinates+p3] = Slice_next_point_no+(nStack);
coordinates+=3;
Slice_current_point_no += nSlice+1;
Slice_next_point_no += nSlice+1;
}
//↓May be wrong ********************************************************************************//
//SIDE
coordinates=0;
Slice_current_point_no = 0;
Slice_next_point_no = nSlice+1;
for(int i=0; i < nSlice;i++){
for(int j=1; j < nStack-1; j++){
indices_side[coordinates+p1] = Slice_current_point_no+j;
indices_side[coordinates+p2] = indices_side[coordinates]+1;
indices_side[coordinates+p3] = Slice_next_point_no+(j+1);
indices_side[coordinates+p4] = Slice_next_point_no+j;
coordinates+=4;
}
Slice_current_point_no += nSlice+1;
Slice_next_point_no += nSlice+1;
}
//↑May be wrong ********************************************************************************//
glGenBuffers(3,&SVboId[0]);
//Vertex
glBindBuffer(GL_ARRAY_BUFFER,SVboId[0]);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(nSlice+1)*(nStack+1)*3,
Svertex,GL_DYNAMIC_DRAW);
//Normal
glBindBuffer(GL_ARRAY_BUFFER,SVboId[1]);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(nSlice+1)*(nStack+1)*3,
Snormal,GL_DYNAMIC_DRAW);
//Color
glBindBuffer(GL_ARRAY_BUFFER,SVboId[2]);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*(nSlice+1)*(nStack+1)*3,
Scolor,GL_STREAM_DRAW);
}
//Draw
void DrawSphereVBO(void)
{
int point=0;
//Enable
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
//Vertex
glBindBuffer(GL_ARRAY_BUFFER,SVboId[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
//Normal
glBindBuffer(GL_ARRAY_BUFFER,SVboId[1]);
glNormalPointer(GL_FLOAT, 0, 0);
//Color
glBindBuffer(GL_ARRAY_BUFFER,SVboId[2]);
glColorPointer(3,GL_FLOAT, 0, 0);
//---------------------------------Draw---------------------------------------------------//
//TOP
for(int i=0; i<SLICE;i++){
glDrawRangeElements(GL_TRIANGLES, point, point+2, 3, GL_UNSIGNED_INT, indices_top+i*3);
point+=3;
}
//BOTTOM
point=0;
for(int i=0; i<SLICE;i++){
glDrawRangeElements(GL_TRIANGLES, point, point+2, 3, GL_UNSIGNED_INT, indices_bottom+i*3);
point+=3;
}
//↓May be wrong ********************************************************************************//
//SIDE
point=0;
for(int i=0; i< (SLICE*(STACK-2));i++){
glDrawRangeElements(GL_QUADS, point, point+3, 4, GL_UNSIGNED_INT, indices_side+i*4);
point+=4;
}
//↑May be wrong ********************************************************************************//
//---------------------------------Draw---------------------------------------------------//
//Disable
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0,0,WIDTH,HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(5.0, 5.0,5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glRotatef(angle,0.0f,1.0f,0.0f);
DrawSphereVBO();
glutSwapBuffers();
}
void idle(void)
{
glutPostRedisplay();
angle+=0.2f;
}
void Init(){
glewInit();
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);
SLICE = 5;
STACK = 5;
Shere_dma(1,SLICE,STACK); //MemoryAllocate
setSphereData(1,SLICE,STACK); //InputData
}
int main(int argc, char *argv[])
{
glutInitWindowPosition(100, 100);
glutInitWindowSize(WIDTH, HEIGHT);
glutInit(&argc, argv);
glutCreateWindow("VBO");
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutDisplayFunc(display);
glutIdleFunc(idle);
Init();
glutMainLoop();
return 0;
}
I refer to this code.
void drawSphere(double radius, int nSlice, int nStack)
{
int i, j;
double phi; //
double theta; //long
float p[31][31][3]; //Vertex
float *p1,*p2,*p3,*p4;
if(nSlice > 30) nSlice = 30;
if(nStack > 30) nStack = 30;
//Vertex
for(i = 0;i <= nSlice;i++)
{
phi = 2.0 * M_PI * (double)i / (double)nSlice;
for(j = 0;j <= nStack;j++)
{
theta = M_PI * (double)j / (double)nStack;
p[i][j][0] = (float)(radius * sin(theta) * cos(phi));//x
p[i][j][1] = (float)(radius * sin(theta) * sin(phi));//y
p[i][j][2] = (float)(radius * cos(theta)); //z
}
}
//Top(j=0)
for(i = 0;i < nSlice; i++)
{
p1 = p[i][0]; p2 = p[i][1];
p3 = p[i+1][1];
glBegin(GL_TRIANGLES);
glNormal3fv(p1); glVertex3fv(p1);
glNormal3fv(p2); glVertex3fv(p2);
glNormal3fv(p3); glVertex3fv(p3);
glEnd();
}
//Bottom
j=nStack-1;
for(i = 0;i < nSlice; i++)
{
p1 = p[i][j]; p2 = p[i][j+1];
p3 = p[i+1][j];
glBegin(GL_TRIANGLES);
glNormal3fv(p1); glVertex3fv(p1);
glNormal3fv(p2); glVertex3fv(p2);
glNormal3fv(p3); glVertex3fv(p3);
glEnd();
}
for(i = 0;i < nSlice;i++){
for(j = 1;j < nStack-1; j++)
{
p1 = p[i][j]; p2 = p[i][j+1];
p3 = p[i+1][j+1]; p4 = p[i+1][j];
glBegin(GL_QUADS);
glNormal3fv(p1); glVertex3fv(p1);
glNormal3fv(p2); glVertex3fv(p2);
glNormal3fv(p3); glVertex3fv(p3);
glNormal3fv(p4); glVertex3fv(p4);
glEnd();
}
}
}

I've written a tutorial on generating sphere meshes - it doesn't come with source code, but describes the process and walks you through the issues you'll encounter. You can find the tutorial at: http://sol.gfxile.net/sphere/index.html

I would recommend using spherical coordinates using two angles phi (elevation) and theta (around) or by using the equation of the sphere: x2 + y2 + z2 = r2
were you keep one of the values constant and increment later as you replace values in the 2nd to find the 3rd value.

Related

OpenGL Output Not Displaying Correctly using Image for Texture

so I got an image as a texture for a square, but the problem is that whenever I run the code I get this:
But when I take this line out:
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
Then I get this output (the white space is where I want to put the image as a texture):
Or if I change the third parameter to 5, then I get this output. But I know that the texture does display correctly when I run the code below, but the output is still like the first image at the top. How would I go about fixing the output so that it looks like the second image with the texture showing? Note that the texture DOES display fine with my code, you just cant see it becuase it's hidden becuase the whole output wont display properly.
#include <GL/glut.h>
#include <iostream>
#include <unistd.h>
#include <math.h>
#include <GL/gl.h>
#include <opencv2/opencv.hpp> //for OpenCV 3.x
#include <opencv/highgui.h> //for OpenCV 3.x
#include <cstdio>
#include <stdlib.h>
#include <string.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdio.h>
#include <math.h>
#define UpperBD 80
#define PI 3.1415926
#define Num_pts 10
using namespace std;
float Xe = 200.0f;//100
float Ye = 300.0f;
float Ze = 450.0f;
float Rho = sqrt(pow(Xe,2) + pow(Ye,2) + pow(Ze,2));
float D_focal = 100.0f;
GLuint texture[2];
struct Image {
unsigned long sizeX;
unsigned long sizeY;
char *data;
};
typedef struct Image Image;
#define checkImageWidth 64
#define checkImageHeight 64
GLubyte checkImage[checkImageWidth][checkImageHeight][3];
void makeCheckImage(void){
int i, j, c;
for (i = 0; i < checkImageWidth; i++) {
for (j = 0; j < checkImageHeight; j++) {
c = ((((i&0x8)==0)^((j&0x8)==0)))*255;
checkImage[i][j][0] = (GLubyte) c;
checkImage[i][j][1] = (GLubyte) c;
checkImage[i][j][2] = (GLubyte) c;
}
}
}
int ImageLoad(char *filename, Image *image) {
FILE *file;
unsigned long size; // size of the image in bytes.
unsigned long i; // standard counter.
unsigned short int planes; // number of planes in image (must be 1)
unsigned short int bpp; // number of bits per pixel (must be 24)
char temp; // temporary color storage for bgr-rgb conversion.
// make sure the file is there.
if ((file = fopen(filename, "rb"))==NULL){
printf("File Not Found : %s\n",filename);
return 0;
}
// seek through the bmp header, up to the width/height:
fseek(file, 18, SEEK_CUR);
// read the width
if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
printf("Error reading width from %s.\n", filename);
return 0;
}
if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
printf("Error reading height from %s.\n", filename);
return 0;
}
size = image->sizeX * image->sizeY * 3;
// read the planes
if ((fread(&planes, 2, 1, file)) != 1) {
printf("Error reading planes from %s.\n", filename);
return 0;
}
if (planes != 1) {
printf("Planes from %s is not 1: %u\n", filename, planes);
return 0;
}
// read the bitsperpixel
if ((i = fread(&bpp, 2, 1, file)) != 1) {
printf("Error reading bpp from %s.\n", filename);
return 0;
}
if (bpp != 24) {
printf("Bpp from %s is not 24: %u\n", filename, bpp);
return 0;
}
// seek past the rest of the bitmap header.
fseek(file, 24, SEEK_CUR);
// read the data.
image->data = (char *) malloc(size);
if (image->data == NULL) {
printf("Error allocating memory for color-corrected image data");
return 0;
}
if ((i = fread(image->data, size, 1, file)) != 1) {
printf("Error reading image data from %s.\n", filename);
return 0;
}
for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}
// we're done.
return 1;
}
Image * loadTexture(){
Image *image1;
// allocate space for texture
image1 = (Image *) malloc(sizeof(Image));
if (image1 == NULL) {
printf("Error allocating space for image");
exit(0);
}
if (!ImageLoad("g.bmp", image1)) {
exit(1);
}
return image1;
}
void myinit(void)
//something in this function is making it not appear properly
{
// glClearColor (0.5, 0.5, 0.5, 0.0);
// glEnable(GL_DEPTH_TEST);
// glDepthFunc(GL_LESS);
Image *image1 = loadTexture();
// makeCheckImage();
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Create Texture
glGenTextures(2, texture);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //scale linearly when image smalled than texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
//above line causing problem
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, texture[1]);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
// glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,&checkImage[0][0][0]);
glEnable(GL_TEXTURE_2D);
// glShadeModel(GL_FLAT);
}
typedef struct {
float X[UpperBD];
float Y[UpperBD];
float Z[UpperBD];
} pworld;
typedef struct {
float X[UpperBD];
float Y[UpperBD];
float Z[UpperBD];
} pviewer;
typedef struct{
float X[UpperBD];
float Y[UpperBD];
} pperspective;
typedef struct{
float X[UpperBD];
float Y[UpperBD];
} pattern2DL;
typedef struct{
float X[UpperBD];
float Y[UpperBD];
} arrowpoint;
typedef struct {
float r[UpperBD], g[UpperBD], b[UpperBD];
} pt_diffuse;
void mydisplay()
{
// define x-y coordinate
float p1x=-1.0f, p1y= 0.0f;
float p2x= 1.0f, p2y= 0.0f;
float p3x= 0.0f, p3y= 1.0f;
float p4x= 0.0f, p4y=-1.0f;
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
pworld world;
pviewer viewer;
pperspective perspective;
pattern2DL letterL;
arrowpoint arrow;
//define the x-y-z world coordinate
world.X[0] = 0.0; world.Y[0] = 0.0; world.Z[0] = 0.0; // origin
world.X[1] = 50.0; world.Y[1] = 0.0; world.Z[1] = 0.0; // x-axis
world.X[2] = 0.0; world.Y[2] = 50.0; world.Z[2] = 0.0; // y-axis
world.X[3] = 0.0; world.Y[3] = 0.0; world.Z[3] = 50.0; // y-axis
//define projection plane world coordinate , THIS IS THE SQUARE AROUND THE LETTERS
world.X[4] = 60.0; world.Y[4] = -50.0; world.Z[4] = 0.0;
world.X[5] = 60.0; world.Y[5] = 50.0; world.Z[5] = 0.0; // base line
world.X[7] = 60.0; world.Y[7] = -50.0; world.Z[7] = 100.0; // side bar
world.X[6] = 60.0; world.Y[6] = 50.0; world.Z[6] = 100.0; // side bar
//define 2D pattern letter A
letterL.X[0] = -10.0; letterL.Y[0] = 10.0;
letterL.X[1] = -15.0; letterL.Y[1] = 10.0;
letterL.X[2] = -20.0; letterL.Y[2] = 30.0;
letterL.X[3] = -40.0; letterL.Y[3] = 30.0;
letterL.X[4] = -45.0; letterL.Y[4] = 10.0;
letterL.X[5] = -50.0; letterL.Y[5] = 10.0;
letterL.X[6] = -37.0; letterL.Y[6] = 70.0;
letterL.X[7] = -23.0; letterL.Y[7] = 70.0;
letterL.X[8] = -25.0; letterL.Y[8] = 40.0;
letterL.X[9] = -35.0; letterL.Y[9] = 40.0;
letterL.X[10] = -30.0; letterL.Y[10] = 60.0;
//letter B
letterL.X[11] = 10.0; letterL.Y[11] = 10.0;
letterL.X[12] = 10.0; letterL.Y[12] = 70.0;
letterL.X[13] = 20.0; letterL.Y[13] = 10.0;
letterL.X[14] = 20.0; letterL.Y[14] = 70.0;
letterL.X[15] = 20.0; letterL.Y[15] = 60.0;
letterL.X[16] = 20.0; letterL.Y[16] = 45.0;
letterL.X[17] = 20.0; letterL.Y[17] = 35.0;
letterL.X[18] = 20.0; letterL.Y[18] = 20.0;
letterL.X[19] = 25.0; letterL.Y[19] = 58.0;
letterL.X[20] = 27.0; letterL.Y[20] = 56.0;
letterL.X[21] = 28.0; letterL.Y[21] = 52.0;
letterL.X[22] = 27.0; letterL.Y[22] = 49.0;
letterL.X[23] = 25.0; letterL.Y[23] = 47.0;
letterL.X[24] = 25.0; letterL.Y[24] = 33.0;
letterL.X[25] = 27.0; letterL.Y[25] = 31.0;
letterL.X[26] = 28.0; letterL.Y[26] = 27.0;
letterL.X[27] = 27.0; letterL.Y[27] = 24.0;
letterL.X[28] = 25.0; letterL.Y[28] = 22.0;
letterL.X[29] = 30.0; letterL.Y[29] = 65.0;
letterL.X[30] = 34.0; letterL.Y[30] = 60.0;
letterL.X[31] = 34.0; letterL.Y[31] = 50.0;
letterL.X[32] = 30.0; letterL.Y[32] = 45.0;
letterL.X[33] = 25.0; letterL.Y[33] = 40.0;
letterL.X[34] = 30.0; letterL.Y[34] = 38.0;
letterL.X[35] = 34.0; letterL.Y[35] = 30.0;
letterL.X[36] = 34.0; letterL.Y[36] = 20.0;
letterL.X[37] = 30.0; letterL.Y[37] = 15.0;
arrow.X[0] = 0.0; arrow.Y[0] = 25.0;
arrow.X[1] = 0.0; arrow.Y[1] = 75.0;
arrow.X[2] = 60.0; arrow.Y[2] = 75.0;
arrow.X[3] = 60.0; arrow.Y[3] = 85.0;
arrow.X[4] = 90.0; arrow.Y[4] = 50.0;
arrow.X[5] = 60.0; arrow.Y[5] = 15.0;
arrow.X[6] = 60.0; arrow.Y[6] = 25.0;
arrow.X[7] = 0.0; arrow.Y[7] = 25.0;
arrow.X[8] = 0.0; arrow.Y[8] = 75.0;
arrow.X[9] = 60.0; arrow.Y[9] = 75.0;
arrow.X[10] = 60.0; arrow.Y[10] = 85.0;
arrow.X[11] = 90.0; arrow.Y[11] = 50.0;
arrow.X[12] = 60.0; arrow.Y[12] = 15.0;
arrow.X[13] = 60.0; arrow.Y[13] = 25.0;
//decoration
for(int i = 0; i <= 37; i++)
{
world.X[8+i] = 60.0;
world.Y[8+i] = letterL.X[i];
world.Z[8+i] = letterL.Y[i];
}
//arrow
for(int j = 0; j <= 6; j++)
{
world.X[46+j] = arrow.X[j]-50;//-50
world.Y[46+j] = arrow.Y[j];
world.Z[46+j] = 100.0;//CHANGE TO 150?
}
for(int k = 0; k <= 6; k++)
{
world.X[53+k] = arrow.X[k]-50;
world.Y[53+k] = arrow.Y[k];
world.Z[53+k] = 110.0;//CHANGE TO 150?
}
float sPheta = Ye / sqrt(pow(Xe,2) + pow(Ye,2));
float cPheta = Xe / sqrt(pow(Xe,2) + pow(Ye,2));
float sPhi = sqrt(pow(Xe,2) + pow(Ye,2)) / Rho;
float cPhi = Ze / Rho;
float xMin = 1000.0, xMax = -1000.0;
float yMin = 1000.0, yMax = -1000.0;
//47 is normal vector 46 is a, 45 is ps, 7 is top left box vertex
//COMUTER SHADE OF FLOATING ARROW DUE NEXT WEEK
world.X[60] = -200.0; world.Y[60]=50.0; world.Z[60]=200.0;//ps
world.X[61] = 0.0; world.Y[61]=0.0; world.Z[61]=0.0;//vector a
world.X[62] = 0.0; world.Y[62]=0.0; world.Z[62]=1.0;//VECTOR N
float tmp = (world.X[62]*(world.X[61]-world.X[60]))
+(world.Y[62]*(world.Y[61]-world.Y[60]))
+(world.Z[62]*(world.Z[61]-world.Z[60]));
cout << tmp;
float lambda = tmp/((world.X[62]*(world.X[60]-world.X[7]))
+(world.Y[62]*(world.Y[60]-world.Y[7]))
+(world.Z[62]*(world.Z[60]-world.Z[7])));
cout << lambda;
float lambda_2 = tmp/((world.X[62]*(world.X[60]-world.X[6]))//MAKE ARROW HIGHER, ABOVE PROJECTION PLANE SQUARE
+(world.Y[62]*(world.Y[60]-world.Y[6]))
+(world.Z[62]*(world.Z[60]-world.Z[6])));
cout << lambda_2;
world.X[63] = world.X[60]+lambda*(world.X[60]-world.X[7]);//interseciton point for p7, X COMP
world.Y[63] = world.Y[60]+lambda*(world.Y[60]-world.Y[7]);//Y COMP
world.Z[63] = 0.0;
world.X[64] = world.X[60]+lambda_2*(world.X[60]-world.X[6]);//interseciton point for p7, X COMP
world.Y[64] = world.Y[60]+lambda_2*(world.Y[60]-world.Y[6]);//Y COMP
world.Z[64] = 0.0;
//for arrow's shade, 46-52
float lambda_arrow1 = tmp/((world.X[62]*(world.X[60]-world.X[46]))
+(world.Y[62]*(world.Y[60]-world.Y[46]))
+(world.Z[62]*(world.Z[60]-world.Z[46])));
float lambda_arrow2 = tmp/((world.X[62]*(world.X[60]-world.X[47]))//MAKE ARROW HIGHER, ABOVE PROJECTION PLANE SQUARE
+(world.Y[62]*(world.Y[60]-world.Y[47]))
+(world.Z[62]*(world.Z[60]-world.Z[47])));
float lambda_arrow3 = tmp/((world.X[62]*(world.X[60]-world.X[48]))
+(world.Y[62]*(world.Y[60]-world.Y[48]))
+(world.Z[62]*(world.Z[60]-world.Z[48])));
float lambda_arrow4 = tmp/((world.X[62]*(world.X[60]-world.X[49]))
+(world.Y[62]*(world.Y[60]-world.Y[49]))
+(world.Z[62]*(world.Z[60]-world.Z[49])));
float lambda_arrow5 = tmp/((world.X[62]*(world.X[60]-world.X[50]))
+(world.Y[62]*(world.Y[60]-world.Y[50]))
+(world.Z[62]*(world.Z[60]-world.Z[50])));
float lambda_arrow6 = tmp/((world.X[62]*(world.X[60]-world.X[51]))
+(world.Y[62]*(world.Y[60]-world.Y[51]))
+(world.Z[62]*(world.Z[60]-world.Z[51])));
float lambda_arrow7 = tmp/((world.X[62]*(world.X[60]-world.X[52]))
+(world.Y[62]*(world.Y[60]-world.Y[52]))
+(world.Z[62]*(world.Z[60]-world.Z[52])));
world.X[65] = world.X[60]+lambda_arrow1*(world.X[60]-world.X[46]);//interseciton point for p7, X COMP
world.Y[65] = world.Y[60]+lambda_arrow1*(world.Y[60]-world.Y[46]);//Y COMP
world.Z[65] = 0.0;
world.X[66] = world.X[60]+lambda_arrow2*(world.X[60]-world.X[47]);//interseciton point for p7, X COMP
world.Y[66] = world.Y[60]+lambda_arrow2*(world.Y[60]-world.Y[47]);//Y COMP
world.Z[66] = 0.0;
world.X[67] = world.X[60]+lambda_arrow3*(world.X[60]-world.X[48]);//interseciton point for p7, X COMP
world.Y[67] = world.Y[60]+lambda_arrow3*(world.Y[60]-world.Y[48]);//Y COMP
world.Z[67] = 0.0;
world.X[68] = world.X[60]+lambda_arrow4*(world.X[60]-world.X[49]);//interseciton point for p7, X COMP
world.Y[68] = world.Y[60]+lambda_arrow4*(world.Y[60]-world.Y[49]);//Y COMP
world.Z[68] = 0.0;
world.X[69] = world.X[60]+lambda_arrow5*(world.X[60]-world.X[50]);//interseciton point for p7, X COMP
world.Y[69] = world.Y[60]+lambda_arrow5*(world.Y[60]-world.Y[50]);//Y COMP
world.Z[69] = 0.0;
world.X[70] = world.X[60]+lambda_arrow6*(world.X[60]-world.X[51]);//interseciton point for p7, X COMP
world.Y[70] = world.Y[60]+lambda_arrow6*(world.Y[60]-world.Y[51]);//Y COMP
world.Z[70] = 0.0;
world.X[71] = world.X[60]+lambda_arrow7*(world.X[60]-world.X[52]);//interseciton point for p7, X COMP
world.Y[71] = world.Y[60]+lambda_arrow7*(world.Y[60]-world.Y[52]);//Y COMP
world.Z[71] = 0.0;
// -----------diffuse reflection-----------*
pt_diffuse diffuse; //diffuse.r[3]
//-------reflectivity coefficient-----------*
#define Kdr 0.8
#define Kdg 0.0
#define Kdb 0.0
// define additional pts to find diffuse reflection
//world.X[49] = world.X[45] + lambda_2*(world.X[45] - world.X[6]);
//--------compute distance------------------*//change 45 to 60!!!!!!
float distance[UpperBD];
for (int i=63; i<=71; i++) {
distance[i] = sqrt(pow((world.X[i]-world.X[60]),2)+ //intersect pt p7
pow((world.Y[i]-world.Y[60]),2)+
pow((world.X[i]-world.X[60]),2) );
//std::cout << "distance[i] " << distance[i] << std::endl;
}
// for (int i=4; i<=5; i++){
// distance[i] = sqrt(pow((world.X[i]-world.X[60]),2)+ //pt p4 of projection plane
// pow((world.Y[i]-world.Y[60]),2)+
// pow((world.X[i]-world.X[60]),2) );
// //std::cout << "distance[i] " << distance[i] << std::endl;
// }
//--------compute angle---------------------*
float angle[UpperBD], tmp_dotProd[UpperBD], tmp_mag_dotProd[UpperBD];
for (int i=63; i<=71; i++){
tmp_dotProd[i] = world.Z[i]-world.X[60];
std::cout << " tmp_dotProd[i] " << tmp_dotProd[i] << std::endl;
tmp_mag_dotProd[i] = sqrt(pow((world.X[i]-world.X[60]),2)+ //[45] pt light source
pow((world.Y[i]-world.Y[60]),2)+
pow((world.Z[i]-world.Z[60]),2) );
std::cout << " tmp_mag_dotProd[i] 1 " << tmp_mag_dotProd[i] << std::endl;
angle[i] = tmp_dotProd[i]/ tmp_mag_dotProd[i];
std::cout << "angle[i] " << angle[i] << std::endl;
//compute color intensity
diffuse.r[i] = Kdr * angle[i] / pow(distance[i],2) ;
diffuse.g[i] = Kdg * angle[i] / pow(distance[i],2) ;
diffuse.b[i] = Kdb * angle[i] / pow(distance[i],2) ;
}
// for (int i=4; i<=5; i++){
//
// tmp_dotProd[i] = world.Z[i]-world.X[45];
// std::cout << " tmp_dotProd[i] " << tmp_dotProd[i] << std::endl;
//
// tmp_mag_dotProd[i] = sqrt(pow((world.X[i]-world.X[45]),2)+ //[45] pt light source
// pow((world.Y[i]-world.Y[45]),2)+
// pow((world.Z[i]-world.Z[45]),2) );
// std::cout << " tmp_mag_dotProd[i] 1 " << tmp_mag_dotProd[i] << std::endl;
//
// angle[i] = tmp_dotProd[i]/ tmp_mag_dotProd[i];
// std::cout << "angle[i] " << angle[i] << std::endl;
//
// //compute color intensity
// diffuse.r[i] = Kdr * angle[i] / pow(distance[i],2) ;
// diffuse.g[i] = Kdg * angle[i] / pow(distance[i],2) ;
// diffuse.b[i] = Kdb * angle[i] / pow(distance[i],2) ;
//
// //std::cout << "diffuse.r[i] " << diffuse.r[i] << std::endl;
// //std::cout << "diffuse.g[i] " << diffuse.g[i] << std::endl;
// }
//
for(int i = 0; i < UpperBD; i++)
{
viewer.X[i] = -sPheta * world.X[i] + cPheta * world.Y[i];
viewer.Y[i] = -cPheta * cPhi * world.X[i]
- cPhi * sPheta * world.Y[i]
+ sPhi * world.Z[i];
viewer.Z[i] = -sPhi * cPheta * world.X[i]
- sPhi * cPheta * world.Y[i]
-cPheta * world.Z[i] + Rho;
// cout << i;
}
for(int i = 0; i <= UpperBD; i++)
{
perspective.X[i] = D_focal * viewer.X[i] / viewer.Z[i] ;
perspective.Y[i] = D_focal * viewer.Y[i] / viewer.Z[i] ;
if (perspective.X[i] > xMax) xMax = perspective.X[i];
if (perspective.X[i] < xMin) xMin = perspective.X[i];
if (perspective.Y[i] > yMax) yMax = perspective.Y[i];
if (perspective.Y[i] < yMin) yMin = perspective.Y[i];
/////*
//std::cout << "xMin " << xMin << std::endl;
// std::cout << "xMax " << xMax << std::endl;
// std::cout << "yMin " << yMin << std::endl;
// std::cout << "yMax " << yMax << std::endl;
//*/
}
for(int i = 0; i <= UpperBD; i++)
{
if ((xMax-xMin) != 0) perspective.X[i] = perspective.X[i]/(xMax-xMin);
if ((yMax-yMin) != 0) perspective.Y[i] = perspective.Y[i]/(yMax-yMin);
std::cout << i << perspective.X[i] << perspective.Y[i] << std::endl;
}
glViewport(0,0,1550,1250);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glBegin(GL_LINES);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(perspective.X[0],perspective.Y[0]);
glVertex2f(perspective.X[1],perspective.Y[1]);
glColor3f(0.0, 1.0, 0.0);
glVertex2f(perspective.X[0],perspective.Y[0]);
glVertex2f(perspective.X[2],perspective.Y[2]);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(perspective.X[0],perspective.Y[0]);
glVertex2f(perspective.X[3],perspective.Y[3]);
glColor3f(1.0, 1.0, 0.0); // projection plane , square
glVertex2f(perspective.X[4],perspective.Y[4]);
glVertex2f(perspective.X[5],perspective.Y[5]);
glVertex2f(perspective.X[4],perspective.Y[4]);
glVertex2f(perspective.X[7],perspective.Y[7]);
glVertex2f(perspective.X[5],perspective.Y[5]);
glVertex2f(perspective.X[6],perspective.Y[6]);
glVertex2f(perspective.X[6],perspective.Y[6]);
glVertex2f(perspective.X[7],perspective.Y[7]);
glEnd();
glColor3f(0.0, 1.0, 0.0); // LETTER A STARTS HERE
glBegin(GL_POLYGON);
glVertex2f(perspective.X[13],perspective.Y[13]);
glVertex2f(perspective.X[12],perspective.Y[12]);
glVertex2f(perspective.X[11],perspective.Y[11]);
glVertex2f(perspective.X[12],perspective.Y[12]);
glVertex2f(perspective.X[14],perspective.Y[14]);
glVertex2f(perspective.X[13],perspective.Y[13]);
glVertex2f(perspective.X[18],perspective.Y[18]);
glVertex2f(perspective.X[17],perspective.Y[17]);
glVertex2f(perspective.X[11],perspective.Y[11]);
glVertex2f(perspective.X[17],perspective.Y[17]);
glVertex2f(perspective.X[18],perspective.Y[18]);
glVertex2f(perspective.X[14],perspective.Y[14]);
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(perspective.X[8],perspective.Y[8]);
glVertex2f(perspective.X[15],perspective.Y[15]);
glVertex2f(perspective.X[14],perspective.Y[14]);
glVertex2f(perspective.X[15],perspective.Y[15]);
glVertex2f(perspective.X[14],perspective.Y[14]);
glVertex2f(perspective.X[18],perspective.Y[18]);
glVertex2f(perspective.X[16],perspective.Y[16]);
glVertex2f(perspective.X[18],perspective.Y[18]);
glVertex2f(perspective.X[16],perspective.Y[16]);
glVertex2f(perspective.X[10],perspective.Y[10]);
glVertex2f(perspective.X[9],perspective.Y[9]);
glVertex2f(perspective.X[10],perspective.Y[10]);
glVertex2f(perspective.X[8],perspective.Y[8]);
glVertex2f(perspective.X[9],perspective.Y[9]);
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(perspective.X[16],perspective.Y[16]);
glVertex2f(perspective.X[17],perspective.Y[17]);
//etc...
glEnd();
glColor3f(0.0, 1.0, 0.0); //LETTER B STARTS HERE
glBegin(GL_POLYGON);
glVertex2f(perspective.X[19],perspective.Y[19]);
glVertex2f(perspective.X[20],perspective.Y[20]);
//etc...
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINES);
//
glVertex2f(perspective.X[23],perspective.Y[23]);
glVertex2f(perspective.X[24],perspective.Y[24]);
glVertex2f(perspective.X[25],perspective.Y[25]);
glVertex2f(perspective.X[26],perspective.Y[26]);
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(perspective.X[27],perspective.Y[27]);
glVertex2f(perspective.X[28],perspective.Y[28]);
//etc...
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(perspective.X[29],perspective.Y[29]);
glVertex2f(perspective.X[30],perspective.Y[30]);
//etc...
glEnd();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(perspective.X[24],perspective.Y[24]);
glVertex2f(perspective.X[41],perspective.Y[41]);
//etc...
glEnd();
glColor3f(0.0, 1.0, 0.0);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);//3D arrow starts here
glVertex2f(perspective.X[46],perspective.Y[46]);
glVertex2f(perspective.X[47],perspective.Y[47]);
//etc...
glEnd(); //end arrow
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_LINES);
glVertex2f(perspective.X[63],perspective.Y[63]);
glVertex2f(perspective.X[64],perspective.Y[64]);
//etc...
glEnd(); //end arrow
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_LINES);
//arrow shadow
glVertex2f(perspective.X[65],perspective.Y[65]);
glVertex2f(perspective.X[66],perspective.Y[66]);
//etc...
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[1]);
// glutSolidTeapot(0.1);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glEnable( GL_TEXTURE_2D );
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
glBegin(GL_QUADS);
glVertex2f(perspective.X[4],perspective.Y[4]);
glTexCoord2f(0.0, 0.0);
glVertex2f(perspective.X[5],perspective.Y[5]);
glTexCoord2f(0.1, 0.0);
glVertex2f(perspective.X[4],perspective.Y[4]);
glTexCoord2f(0.1, 0.1);
glVertex2f(perspective.X[7],perspective.Y[7]);
glTexCoord2f(0.0, 0.1);
glVertex2f(perspective.X[5],perspective.Y[5]);
glVertex2f(perspective.X[6],perspective.Y[6]);
glVertex2f(perspective.X[6],perspective.Y[6]);
glVertex2f(perspective.X[7],perspective.Y[7]);
glEnd();
glDisable( GL_TEXTURE_2D );
//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
#define display_scaling 200000.0
#define display_shifting 0.2
for (int i=63; i<=71; i++) {
float r, g, b;
r = display_scaling*diffuse.r[i]+display_shifting;
//r = display_scaling*diffuse.r[i];
g = diffuse.g[i]; b = diffuse.b[i] ;
glColor3f(r, g, b);
std::cout << "display_scaling*diffuse.r[i] " << r << std::endl;
glBegin(GL_POLYGON);
glVertex2f(perspective.X[i],perspective.Y[i]);
glVertex2f(perspective.X[i]+0.1,perspective.Y[i]);
glVertex2f(perspective.X[i]+0.1,perspective.Y[i]+0.1);
glVertex2f(perspective.X[i],perspective.Y[i]+0.1);
glEnd();
}
gluPerspective(45.0,0.5,1.0,60.0);
gluOrtho2D(5, 10, 0.0, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutSwapBuffers();
glFlush();
//sleep(5);
}
int main(int argc, char** argv)
{
cv::Mat image = cv::imread("b.jpg", CV_LOAD_IMAGE_COLOR);
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB );
glutInitWindowSize(900, 1000);
glutCreateWindow("lab");
//imshow( "lab", image );
glutDisplayFunc(mydisplay);
myinit();
glutMainLoop();
}
glEnable(GL_TEXTURE_2D) has to be removed from myinit, because it is done immediately before the object with the texture is drawn.
Further use the STB library, which can be found at GitHub - nothings/stb to load the bitmap:
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
void myinit(void)
{
glGenTextures(2, texture);
int cx, cy, ch;
stbi_uc *img = stbi_load("g.bmp", &cx, &cy, &ch, 3);
if (!img)
return;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, cx, cy, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
stbi_image_free( img );
// ....
}
The number of vertex coordinates is UpperBD, so the maximum index is UpperBD-1 or < UpperBD, but not <= UpperBD.
Change (2 times):
for(int i = 0; i <= UpperBD; i++)
for(int i = 0; i < UpperBD; i++)
gluPerspective and gluOrtho2D at once makes no sense at all.
Init the projection matrix and the model view matrix at the begin of each frame in mydisplay:
void mydisplay()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,0.5,1.0,60.0);
//gluOrtho2D(5, 10, 0.0, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
.....
}
When the vertex coordinate is set by glVertex the current texture coordinates, and is associated with the vertex coordinate. This means glTexCoord has to be dine before glVertex. A GL_QUAD primitive consitis of 4 vertices and each vertex coordinate needs its own texture coordinate:
glBindTexture(GL_TEXTURE_2D, texture[0]);
glEnable( GL_TEXTURE_2D );
glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex2f(perspective.X[4],perspective.Y[4]);
glTexCoord2f(1.0, 0.0);
glVertex2f(perspective.X[5],perspective.Y[5]);
glTexCoord2f(1.0, 1.0);
glVertex2f(perspective.X[6],perspective.Y[6]);
glTexCoord2f(0.0, 1.0);
glVertex2f(perspective.X[7],perspective.Y[7]);
glEnd();

Flickering with Particles in OpenGL C++

I am having trouble with this code. I want it to fire fireworks that explode and fall in front of a static background. Right now the fireworks and background work, but together they cause a flickering and the fireworks don't fall at a regular rate. How do I prevent this flickering and achieve a regular rate of firework's fall?
#include <GL/freeglut.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <iomanip>
#include "Header.h"
using namespace std;
#define M_PI (3.1415926535897932384626433832795)
GLfloat randomNum()
{
return (rand() % 10000) / 10000.0;
}
GLfloat nx = 0;
GLfloat ny = .8;
#define MAX_POINTS 750
GLfloat numPoints;
GLfloat curx, cury;
GLfloat x[MAX_POINTS], y[MAX_POINTS];
GLfloat xacc[MAX_POINTS], yacc[MAX_POINTS];
GLfloat red, green, blue;
int step; int length;
GLfloat newRed = 0;
GLfloat newGreen = 0;
GLfloat newBlue = 0;
GLint totPor = 0;
GLint strontiumPor = 0;
GLfloat bariumPor = 0;
GLfloat copperPor = 0;
GLfloat sodiumPor = 0;
GLfloat phosPor = 0;
GLfloat red2;
GLfloat green2;
GLfloat green3;
GLfloat blue2;
void initialize()
{
int j; double temp, temp2;
numPoints = randomNum()*(MAX_POINTS - 1);
curx = nx;
cury = ny;
//Color Mixing
if (totPor != 0)
{
red = newRed * strontiumPor / (totPor - strontiumPor); //s red
green = newGreen * bariumPor / (totPor - bariumPor); //b green
blue = newBlue * copperPor / (totPor - copperPor); //c blue
red2 = newRed * sodiumPor / (totPor - sodiumPor); //d yellow
green2 = newGreen * sodiumPor / (totPor - sodiumPor);
green3 = newGreen * phosPor / (totPor - phosPor); //p blue green
blue2 = newBlue * phosPor / (totPor - phosPor);
red = red + red2;
green = green + green2 + green3;
blue = blue + blue2;
}
else
{
red = newRed;
green = newGreen;
blue = newBlue;
}
glPointSize(1.7);
step = 0;
length = 500 + 300 * randomNum();
/* initialize the blast */
for (j = 0; j<numPoints; j++) {
x[j] = curx;
y[j] = cury;
temp = randomNum();
temp2 = randomNum()*2.0*M_PI;
xacc[j] = (cos(temp2) * temp) / length;
yacc[j] = (sin(temp2) * temp) / length;
}
}
void draw_fireworks(void)
{
int i;
double glow = (length - (step)) / (double)length;
glColor3f(red*glow, green*glow, blue*glow); //glow
glBegin(GL_POINTS);
for (i = 0; i<numPoints; i++) {
x[i] += xacc[i];
y[i] += yacc[i];
glVertex2f(x[i], y[i]);
}
glEnd();
glFlush();
glutSwapBuffers();
}
void display(void)
{
int i;
glClear(GL_COLOR_BUFFER_BIT);
if (step < 0.9*length) {
for (i = 0; i<numPoints; i++)
yacc[i] -= 0.02 / length; // gravity
draw_fireworks();
}
step++;
if (step > length) initialize();
DrawScene();
glutSwapBuffers();
}
int t = 0;
void idle(void)
{
if (t == 45000)
{
glutPostRedisplay();
t = 0;
}
t++;
}
void SpecialKey(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_LEFT:
/* Move fireworks left or right, up or down */
nx = nx + -.025;
break;
case GLUT_KEY_RIGHT:
nx = nx + .025;
break;
case GLUT_KEY_UP:
ny = ny + .025;
break;
case GLUT_KEY_DOWN:
ny = ny + -.025;
break;
}
glutPostRedisplay();
}
void Keyboard(unsigned char key, int x, int y)
{
//Select Chemicals
switch (key)
{
case 's':
newRed = 1;
strontiumPor = strontiumPor + 1;
totPor = totPor + 1;
break;
case 'b':
newGreen = 1;
bariumPor = bariumPor + 1;
totPor = totPor + 1;
break;
case 'c':
newBlue = 1;
copperPor = copperPor + 1;
totPor = totPor + 1;
break;
case 'd':
newRed = 1;
newGreen = 1;
sodiumPor = sodiumPor + 1;
totPor = totPor + 1;
break;
case 'p':
newBlue = 1;
newGreen = 1;
phosPor = phosPor + 1;
totPor = totPor + 1;
break;
case 'R': newRed = newRed + .1;
break;
case 'G': newGreen = newGreen + .1;
break;
case 'B': newBlue = newBlue + .1;
break;
case ' ': //Space bar is Reset or start
newRed = 1;
newGreen = 1;
newBlue = 1;
totPor = 0;
strontiumPor = 0;
bariumPor = 0;
copperPor = 0;
sodiumPor = 0;
phosPor = 0;
break;
case 'm': nx = 0; ny = 0.8; //M resets target to default
break;
case 'q': exit(0); //Q is quit
}
glutPostRedisplay();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-1.0, 1.0,
-1.0*(GLfloat)h / (GLfloat)w, 1.0*(GLfloat)h / (GLfloat)w,
-1.0, 1.0);
else
glOrtho(-1.0*(GLfloat)w / (GLfloat)h, 1.0*(GLfloat)w / (GLfloat)h,
-1.0, 1.0,
-1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(700, 700);
glutInitWindowPosition(0, 0);
glutCreateWindow("Fireworks Display");
glClearColor(0.0, 0.0, 0.0, 0.0);
initialize();
initText();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glutKeyboardFunc(Keyboard);
glutSpecialFunc(SpecialKey);
glutMainLoop();
return 0;
}
And then also this:
#include <GL/freeglut.h>
#include "Soil.h"
GLuint tex_ID;
void LoadTextureMap()
{
int width, height, channels;
unsigned char* image = SOIL_load_image("washington.png", &width, &height, &channels, SOIL_LOAD_AUTO);
glGenTextures(1, &tex_ID);
glBindTexture(GL_TEXTURE_2D, tex_ID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, channels, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
}
void Tree(GLfloat x, GLfloat y, GLfloat z)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex_ID);
glPushMatrix();
glRotatef(180, 0.0f, 0.0f, 1.0f);
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0 + x, -1.0 + y, 1.0 + z);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0 + x, 1.0 + y, 1.0 + z);
glTexCoord2f(1.0, 1.0); glVertex3f(1 + x, 1.0 + y, 1.0 + z);
glTexCoord2f(1.0, 0.0); glVertex3f(1 + x, -1.0 + y, 1.0 + z);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
void DrawScene()
{
Tree(0, 0, 0);
}
void initText()
{
LoadTextureMap();
}
You're calling glutSwapBuffers() in draw_fireworks() and also in display(). You should call it only once per frame.
Btw, if you want to learn OpenGL don't waste your time with this legacy fixed function pipeline stuff. Go with shaders instead.

How to draw sphere from polygons taken dynamically from user

I am trying to create a sphere by code using number of polygons which may very dynamically from 100 to 1000 from user by up and down keys . And those selected number of polygons must be shown on the screen.
What i have seen on google search is creating triangle manually (not dynamically) like this code but still it couldn't help me, Could some one please give me idea:
#include <cmath>
#include <vector>
#include <gl/glut.h>
const float PI = 3.14159265358979323846f;
#pragma pack(1)
template <typename TYPE>
class GeometryVector
{
public:
GeometryVector(const TYPE x_ = TYPE(), const TYPE y_ = TYPE(), const TYPE z_ = TYPE());
const TYPE x;
const TYPE y;
const TYPE z;
};
#pragma pack()
template <typename TYPE>
GeometryVector<TYPE>::GeometryVector(const TYPE x_, const TYPE y_, const TYPE z_)
:
x(x_),
y(y_),
z(z_)
{
}
class StackedSphere
{
public:
StackedSphere(const float radius = 1.0f, const unsigned int stacks = 8, const unsigned int slices = 16);
void render() const;
private:
std::vector<GeometryVector<float> > geometryData_;
std::vector<unsigned short> indexData_;
};
StackedSphere::StackedSphere(const float radius, const unsigned int stacks, const unsigned int slices)
{
for (unsigned int stackNumber = 0; stackNumber <= stacks; ++stackNumber)
{
for (unsigned int sliceNumber = 0; sliceNumber < slices; ++sliceNumber)
{
float theta = stackNumber * PI / stacks;
float phi = sliceNumber * 2 * PI / slices;
float sinTheta = std::sin(theta);
float sinPhi = std::sin(phi);
float cosTheta = std::cos(theta);
float cosPhi = std::cos(phi);
geometryData_.push_back(GeometryVector<float>(radius * cosPhi * sinTheta, radius * sinPhi * sinTheta, radius * cosTheta));
}
}
for (unsigned int stackNumber = 0; stackNumber < stacks; ++stackNumber)
{
for (unsigned int sliceNumber = 0; sliceNumber <= slices; ++sliceNumber)
{
indexData_.push_back((stackNumber * slices) + (sliceNumber % slices));
indexData_.push_back(((stackNumber + 1) * slices) + (sliceNumber % slices));
}
}
}
void StackedSphere::render() const
{
glVertexPointer(3, GL_FLOAT, 0, &geometryData_[0]);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawElements(GL_TRIANGLE_STRIP, indexData_.size(), GL_UNSIGNED_SHORT, &indexData_[0]);
}
class SpiralSphere
{
public:
SpiralSphere(const float radius = 1.0f, const unsigned int loops = 8, const unsigned int segmentsPerLoop = 16);
void render() const;
private:
std::vector<GeometryVector<float> > geometryData_;
std::vector<unsigned short> indexData_;
};
SpiralSphere::SpiralSphere(const float radius, const unsigned int loops, const unsigned int segmentsPerLoop)
{
for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
{
float theta = 0;
float phi = loopSegmentNumber * 2 * PI / segmentsPerLoop;
float sinTheta = std::sin(theta);
float sinPhi = std::sin(phi);
float cosTheta = std::cos(theta);
float cosPhi = std::cos(phi);
geometryData_.push_back(GeometryVector<float>(radius * cosPhi * sinTheta, radius * sinPhi * sinTheta, radius * cosTheta));
}
for (unsigned int loopNumber = 0; loopNumber <= loops; ++loopNumber)
{
for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
{
float theta = (loopNumber * PI / loops) + ((PI * loopSegmentNumber) / (segmentsPerLoop * loops));
if (loopNumber == loops)
{
theta = PI;
}
float phi = loopSegmentNumber * 2 * PI / segmentsPerLoop;
float sinTheta = std::sin(theta);
float sinPhi = std::sin(phi);
float cosTheta = std::cos(theta);
float cosPhi = std::cos(phi);
geometryData_.push_back(GeometryVector<float>(radius * cosPhi * sinTheta, radius * sinPhi * sinTheta, radius * cosTheta));
}
}
for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
{
indexData_.push_back(loopSegmentNumber);
indexData_.push_back(segmentsPerLoop + loopSegmentNumber);
}
for (unsigned int loopNumber = 0; loopNumber < loops; ++loopNumber)
{
for (unsigned int loopSegmentNumber = 0; loopSegmentNumber < segmentsPerLoop; ++loopSegmentNumber)
{
indexData_.push_back(((loopNumber + 1) * segmentsPerLoop) + loopSegmentNumber);
indexData_.push_back(((loopNumber + 2) * segmentsPerLoop) + loopSegmentNumber);
}
}
}
void SpiralSphere::render() const
{
glVertexPointer(3, GL_FLOAT, 0, &geometryData_[0]);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawElements(GL_TRIANGLE_STRIP, indexData_.size(), GL_UNSIGNED_SHORT, &indexData_[0]);
}
StackedSphere sphere1(4, 8, 16);
SpiralSphere sphere2(4, 8, 16);
int r = 0;
void reshape(int width, int height){
if (height == 0)
{
height = 1;
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluPerspective(45.0f, GLfloat(width) / GLfloat(height), 0.1f, 50.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void display(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0, 0, -25);
glPushMatrix();
glTranslatef(-5, 0, 0);
glRotatef(r, 0, 1, 0);
sphere1.render();
glPopMatrix();
glPushMatrix();
glTranslatef(5, 0, 0);
glRotatef(r, 0, 1, 0);
sphere2.render();
glPopMatrix();
glutSwapBuffers();
r++;
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(0, 0);
glutInitWindowSize(512,512);
glutCreateWindow("Sphere Test");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(display);
glPolygonMode(GL_FRONT, GL_LINE);
glPolygonMode(GL_BACK, GL_LINE);
glutMainLoop();
return 0;
}
Could some one please give me idea how to generate the sphere using number of polygons decided dynamically by up and down arrow (from 100 to 1000) ?
How to get take the number of polygon dynamically by up and down array (from range 100-1000) and how to show those polygons on the screen ?
How to write the logic such that the number of taken polygon will make a sphere ?

Drawing Multiple shapes in openGL/GLUT

I have this code and I am trying to draw two hexagons but only one will show up. This is my first time using openGL although i've used C++ for some time now. The first hexagon shows up but the second one is nowhere to be seen. sorry for all the comments in there I was trying to draw 121 of the hexagons in a for loop.
#include <iostream>
#include <GL/glut.h>
#include <stdlib.h>
#include <string>
#define _USE_MATH_DEFINES
#include <math.h>
void displayCall(){
int x = 0;
int y = 0;
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(.005, .005, .005);
// Enable polygon offsets, and offset filled polygons forward by 2.5
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-2.5f, -2.5f);
// Set the render mode to be line rendering with a thick line width
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth(3.0f);
// Set the colour to be white
//glColor3f(1.0f, 1.0f, 1.0f);
//outline color
glColor3f(0, 0, 0);
//for (int i = 0; i < 11; i++){
// for (int j = 0; j < 11; j++){
glTranslatef(-300 + x, 300 - y, 0);
glBegin(GL_POLYGON);
for (int i = 0; i < 6; ++i) {
glVertex2d(50 * sin(i / 6.0 * 2 * M_PI),
50 * cos(i / 6.0 * 2 * M_PI));
}
glEnd();
glTranslatef(-200 + x, 300 - y, 0);
glBegin(GL_POLYGON);
for (int i = 0; i < 6; ++i) {
glVertex2d(50 * sin(i / 6.0 * 2 * M_PI),
50 * cos(i / 6.0 * 2 * M_PI));
}
glEnd();
// x += 50;
// }
//y += 50;
//x = 0;
// }
glutSwapBuffers();
}
int main(int argc, char **argv){
std::cout << "Test" << std::endl;
char* buf = 0;
size_t sz = 0;
if (_dupenv_s(&buf, &sz, "DISPLAY")){
std::string display(("DISPLAY"));
std::cout << display << std::endl;
}
else{
std::cout << "Empty" << std::endl;
}
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutCreateWindow("RED");
glutDisplayFunc(displayCall);
glutMainLoop();
return 0;
}
You are not resetting transformation matrix.
Try this
glPushMatrix();
glTranslatef(-300 + x, 300 - y, 0);
glBegin(GL_POLYGON);
for (int i = 0; i < 6; ++i) {
glVertex2d(50 * sin(i / 6.0 * 2 * M_PI),
50 * cos(i / 6.0 * 2 * M_PI));
}
glEnd();
glPopMatrix();
glPushMatrix();
glTranslatef(-200 + x, 300 - y, 0);
glBegin(GL_POLYGON);
for (int i = 0; i < 6; ++i) {
glVertex2d(50 * sin(i / 6.0 * 2 * M_PI),
50 * cos(i / 6.0 * 2 * M_PI));
}
glEnd();
glPopMatrix();

How to drag a graph around the window in OpenGL/c++

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 ( );
}