How to draw sphere from polygons taken dynamically from user - c++

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 ?

Related

C++ : How do I make this particle simulation faster?

I have a simple 2D simulation which has particles travelling at given velocities and could collide with each other and the walls. But the fps drops when there are more than 500 particles. I want to simulate at least 5000 particles smoothly because I'll be adding more features to the program. Is there a different and efficient approach to this? Thanks!
gas.cpp:
#include<cstdlib>
#include<vector>
#include<glut.h>
#include "gas.h"
#include<time.h>
float t = 1; //time step
void gas::p(float pos_x, float pos_y, float vx, float vy, float mass)
{
srand(time(0));
m = mass;
x = pos_x;
y = pos_y;
velx = vx;
vely = vy;
size = 3;
}
void gas::draw()
{
glColor3f(1, 1, 1);
glVertex2f(x, y);
}
void gas::move(float t)
{
x += velx * t;
y += vely * t;
}
float temp;
//Function to be ran at every frame:
void run(std::vector <gas>& bn)
{
int it = 0;
for (gas& i : bn)
{
int jt = 0;
for (gas& j : bn)
{
if (it != jt)
{
//Handling collisions:
if (abs(i.y - (j.y + j.size)) < 1 && (abs(j.x - i.x) <= i.size + 1) && i.vely < 0)
{
temp = i.vely;
i.vely = j.vely;
j.vely = temp;
}
if (abs(j.y - (i.y + i.size)) < 1 && (abs(i.x - j.x) <= j.size + 1) && i.vely > 0)
{
temp = i.vely;
i.vely = j.vely;
j.vely = temp;
}
if (abs(j.x - (i.x + i.size)) < 1 && (abs(i.y - j.y) <= i.size + 1) && i.velx > 0)
{
temp = i.velx;
i.velx = j.velx;
j.velx = temp;
}
if (abs(i.x - (j.x + j.size)) < 1 && (abs(j.y - i.y) <= i.size + 1) && i.velx < 0)
{
temp = i.velx;
i.velx = j.velx;
j.velx = temp;
}
}
jt += 1;
}
//Boundary Collisions:
if (i.x > 600 - i.size) { i.x = 600 - i.size; i.velx = -i.velx; }
if (i.x < i.size) { i.x = i.size; i.velx = -i.velx; }
if (i.y > 600 - i.size) { i.y = 600 - i.size; i.vely = -i.vely; }
if (i.y < i.size) { i.y = i.size; i.vely = -i.vely; }
i.move(t);
it += 1;
}
}
gas.h:
#pragma once
class gas
{
public:
float m = 1;
float x = 0;
float y = 0;
float velx = 0;
float vely = 0;
float size = 3;
float density = 100;
float r = 1; float g = 1; float b = 1;
void p(float pos_x, float pos_y, float vx, float vy, float mass);
void draw();
void move(float t);
};
void run(std::vector<gas>& bn);
simulate.cpp (main file):
#include<cstdlib>
#include<glut.h>
#include<vector>
#include "gas.h"
#include<thread>
#include<time.h>
void display();
void reshape(int, int);
const int n = 600; //Number of particles
void init()
{
glClearColor(0, 0, 0, 1);
}
std::vector <gas> b(n);
void timer(int)
{
run(b);
glutPostRedisplay();
glutTimerFunc(1000 / 60, timer, 0);
}
void show(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowPosition(300, 60);
glutInitWindowSize(600, 600);
glutCreateWindow("Particles");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(1000, timer, 0); // Args: Time delay per frame in milliseconds, function to be called
init();
glutMainLoop();
}
int main(int argc, char** argv)
{
int it = 0;
for (gas& i : b)
{
srand(it);
i.p(rand() % 600, rand() % 600, (rand() % 10) * pow(-1, it + 1), (rand() % 10) * pow(-1, it), 1);
it += 1;
}
show(argc, argv);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glPointSize(3);
glBegin(GL_POINTS);
for (gas& i : b)
{
i.draw();
}
glEnd();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 600, 0, 600);
glMatrixMode(GL_MODELVIEW);
}

xzy, to xyz orientation conversion

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.

animation points in OpenGL with C++?

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).

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

Draw A Sphere With 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.