Related
I want to draw 2 circles, and here are the necessary bits from three files of my project.
circle.h
#include "main.h"
#ifndef CIRCLE_H
#define CIRCLE_H
class Circle{
public:
Circle(){};
Circle(float x, float y, float radius, float fraction, color_t color);
void set_position(float x, float y);
void draw(glm::mat4 VP);
bounding_box_t bounding_box();
glm::vec3 position;
float rotation;
float radius;
float fraction;
private:
VAO *object;
};
#endif //CIRCLE_H
circle.cpp
#include "circle.h"
#include "main.h"
#include <iostream>
#define PI 3.14159265358979323846
typedef struct {
GLfloat x;
GLfloat y;
GLfloat z;
}point;
point rotate_by(double angle, point inp_point){
point new_point;
new_point.x = inp_point.x*cos(angle) - inp_point.y*sin(angle);
new_point.y = inp_point.x*sin(angle) + inp_point.y*cos(angle);
return new_point;
};
void fill_array(int sides, float radius, int fraction, GLfloat array[]){
double angle = 2 * PI / sides;
point vertex;
vertex.x = 0.0f;
vertex.y = 0.0f;
vertex.z = 0.0f;
point oldpoint;
oldpoint.x = 0.0f;
oldpoint.y = radius;
oldpoint.z = 0.0f;
int iterations = (int)(fraction*sides);
std::cout<< iterations <<std::endl;
//For each triangle
for(int i = 0; i < iterations; i++){
// setting the vertex
array[9*i + 0] = vertex.x;
array[9*i + 1] = vertex.y;
array[9*i + 2] = vertex.z;
// setting the oldpoint
array[9*i + 3] = oldpoint.x;
array[9*i + 4] = oldpoint.y;
array[9*i + 5] = oldpoint.z;
// making the new point
point newpoint = rotate_by(angle, oldpoint);
// setting the new point
array[9*i + 6] = newpoint.x;
array[9*i + 7] = newpoint.y;
array[9*i + 8] = newpoint.z;
// New point is now old
oldpoint = newpoint;
}
};
Circle::Circle(float x, float y, float radius, float fraction, color_t color) {
this->position = glm::vec3(x, y, 0);
this->rotation = 0;
int sides = 50;
this->radius = radius;
this->fraction = fraction;
static GLfloat vertex_buffer_data[1000];
fill_array(sides, radius, fraction, vertex_buffer_data);
int num_vertices = (int)(fraction*sides)*3;
std::cout << num_vertices <<std::endl;
this->object = create3DObject(GL_TRIANGLES, num_vertices, vertex_buffer_data, color, GL_FILL);
}
void Circle::draw(glm::mat4 VP) {
Matrices.model = glm::mat4(1.0f);
glm::mat4 translate = glm::translate (this->position); // glTranslatef
glm::mat4 rotate = glm::rotate((float) (this->rotation * M_PI / 180.0f), glm::vec3(0, 0, 1));
rotate = rotate * glm::translate(glm::vec3(0, -0.6, 0));
Matrices.model *= (translate * rotate);
glm::mat4 MVP = VP * Matrices.model;
glUniformMatrix4fv(Matrices.MatrixID, 1, GL_FALSE, &MVP[0][0]);
draw3DObject(this->object);
}
main.cpp
//-------------------Necessary tools----------------------------------------------
#include <vector>
#include <random>
#include "timer.h"
#include "main.h"
using namespace std;
//------------------Template Imports---------------------------------------------
#include "circle.h"
//---------------Important declarations-------------------------------------------
GLMatrices Matrices;
GLuint programID;
GLFWwindow *window;
float screen_zoom = 1, screen_center_x = 0, screen_center_y = 0;
Timer t60(1.0 / 60);
//--------------Object declarations-----------------------------------------------
Circle c1;
Circle c2;
// -------------Functions----------------------------------------------------------
void draw() {
//---------Don't touch---------------------------------------------------------
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram (programID);
Matrices.view = glm::lookAt(glm::vec3(0, 0, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); // Fixed camera for 2D (ortho) in XY plane
glm::mat4 VP = Matrices.projection * Matrices.view;
glm::mat4 MVP;
//---------Scene render--------------------------------------------------------
c1.draw(VP);
c2.draw(VP);
}
void initGL(GLFWwindow *window, int width, int height) {
//-----------Create objects----------------------------------------------
c1 = Circle(1,1,1.0f,1.0f,COLOR_BLACK);
c2 = Circle(2,2,1.0f,1.0f, COLOR_RED);
//-----------Don't touch-------------------------------------------------
programID = LoadShaders("Sample_GL.vert", "Sample_GL.frag");
Matrices.MatrixID = glGetUniformLocation(programID, "MVP");
reshapeWindow (window, width, height);
glClearColor (COLOR_BACKGROUND.r / 256.0, COLOR_BACKGROUND.g / 256.0, COLOR_BACKGROUND.b / 256.0, 0.0f); // R, G, B, A
glClearDepth (1.0f);
glEnable (GL_DEPTH_TEST);
glDepthFunc (GL_LEQUAL);
cout << "VENDOR: " << glGetString(GL_VENDOR) << endl;
cout << "RENDERER: " << glGetString(GL_RENDERER) << endl;
cout << "VERSION: " << glGetString(GL_VERSION) << endl;
cout << "GLSL: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl;
}
int main(int argc, char **argv) {
srand(time(0));
int width = 600;
int height = 600;
window = initGLFW(width, height);
initGL (window, width, height);
/* Draw in loop */
while (!glfwWindowShouldClose(window)) {
// Process timers
if (t60.processTick()) {
// 60 fps
// OpenGL Draw commands
draw();
// Swap Frame Buffer in double buffering
glfwSwapBuffers(window);
tick_elements();
//tick_input(window);
}
// Poll for Keyboard and mouse events
glfwPollEvents();
}
quit(window);
}
void reset_screen() {
float top = screen_center_y + 4 / screen_zoom;
float bottom = screen_center_y - 4 / screen_zoom;
float left = screen_center_x - 4 / screen_zoom;
float right = screen_center_x + 4 / screen_zoom;
Matrices.projection = glm::ortho(left, right, bottom, top, 0.1f, 500.0f);
}
For some reason, sometimes, I get the right output, but sometimes, I get funny outputs.
This is the correct image that I want:
But several times nothing appears at all:
Sometimes really funny outputs appear, like this:
... And this:
Notice that I am not even running make again and again, these variations happen each time I am opening the executable itself.
How can I get the correct output every time?
Do you call reset_screen() function somewhere? Because in this function you are creating your projection matrix. It looks like this matrix is uninitialized (initialized with some trash).
I am trying to draw a Bezier curve in OpenGL using floating point values. I have tried using many different code examples. My current code below, runs ,but does not show the curve on screen. The usual way to draw Bezier curves are with integer values, which means using the GLUORTHO2D() function for drawing the curve. But I want to draw a curve using floating point values. Such as x range(-1,1) and y range(-1,1).
like if x=(500) then consider it (-1 to 1) and if y=(800) then consider it (-1,1).
I have already tried using integer values and it worked for me. my code using integer values is below:
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
#define CTRL_COUNT 100
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
int X1[3]={20,25,20}, Y1[3]={5,24,38}; //first point(x1[0],y1[0]) second(x1[1],y1[1]) third(x1[2],y1[2])
void myInit()
{
glClearColor(0.0,0.0,0.0,0.0);
glColor3f(1.0,0.0,0.0);
glPointSize(8.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,128.0,0.0,96.0);
}
//p(t)=(1-t)^3*p0+3t(1-t)^2*p1+3t^2(1-t)p2+t^3p3
float getNextBezierPointX(float t)
{
float x=0.0;
for(int i=0; i<ctrlPointsCount; i++)
{
int c;
if(i==0 || i==ctrlPointsCount-1)
c = 1;
else
{
c = ctrlPointsCount-1;
}
x += c * pow(t, i) * pow(1-t, ctrlPointsCount-1-i) * ctrlPointsX[i];
}
return x;
}
float getNextBezierPointY(float t)
{
float y=0.0;
for(int i=0; i<ctrlPointsCount; i++)
{
int c;
if(i==0 || i==ctrlPointsCount-1)
c = 1;
else
{
c = ctrlPointsCount-1;
}
y += c * pow(t, i) * pow(1-t, ctrlPointsCount-1-i) * ctrlPointsY[i];
}
return y;
}
void drawline()
{
// draw control points using red color
for(int i=0; i < 3; i++)
{
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
// draw bezier curve using control poitns by calculating next points using cubic bezier curve formula
float oldX=ctrlPointsX[0], oldY=ctrlPointsY[0];
for(double t = 0.0;t <= 1.0; t += 0.01) {
float x = getNextBezierPointX(t);
float y = getNextBezierPointY(t);
//glColor3f(1.0,t,1.0);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
void myDisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
ctrlPointsCount=3;
for(int i=0;i<3;i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glFlush();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(640,480);
glutInitWindowPosition(100,150);
glutCreateWindow("Bezier Curve");
glutDisplayFunc(myDisplay);
myInit();
glutMainLoop();
return 0;
}
But when i tried using floating point values , it does not work for me. It does not show the curved line on screen. My code using floating point values is below:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
using namespace std;
#define CTRL_COUNT 100
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = { 0.946875, 0.884375, 0.946875 };
//Initializes 3D rendering
void initRendering() {
glEnable(GL_DEPTH_TEST);
}
float getNextBezierPointX(float t)
{
float x = 0.0;
for (int i = 0; i<ctrlPointsCount; i++)
{
int c;
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
{
c = ctrlPointsCount - 1;
}
x += c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsX[i];
}
return x;
}
float getNextBezierPointY(float t)
{
float y = 0.0;
for (int i = 0; i<ctrlPointsCount; i++)
{
int c;
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
{
c = ctrlPointsCount - 1;
}
y += c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsY[i];
}
return y;
}
void drawline()
{
// draw control points using red color
for (int i = 0; i < 3; i++)
{
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
// draw bezier curve using control poitns by calculating next points using cubic bezier curve formula
float oldX = ctrlPointsX[0], oldY = ctrlPointsY[0];
for (double t = 0.0; t <= 1.0; t += 0.01)
{
float x = getNextBezierPointX(t);
float y = getNextBezierPointY(t);
//glColor3f(1.0,t,1.0);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
//Called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}
float _angle = 0.0;
float _cameraAngle = 0.0;
float _ang_tri = 0.0;
//Draws the 3D scene
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //Reset the drawing perspective
ctrlPointsCount = 3;
for (int i = 0; i<3; i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glutSwapBuffers();
}
void update(int value) {
_angle += 2.0f;
if (_angle > 360) {
_angle -= 360;
}
_ang_tri += 2.0f;
if (_ang_tri > 360) {
_ang_tri -= 360;
}
glutPostRedisplay(); //Tell GLUT that the display has changed
//Tell GLUT to call update again in 25 milliseconds
glutTimerFunc(25, update, 0);
}
int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1331, 641);
glutInitWindowPosition(0, 0);
//Create the window
glutCreateWindow("Our cg project");
initRendering();
//Set handler functions
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0); //Add a timer
glClearColor(0.0, 0.7, 1.5,0.0);
glutMainLoop();
return 0;
}
The problem is this here:
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {0.946875, 0.884375, 0.946875 };
for (int i = 0; i<3; i++)
{
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
ctrlPointsX and ctrlPointsYcan only hold integer values. So when you do ctrlPointsX[i] = X1[i] and ctrlPointsY[i] = Y1[i] you are converting the floats to integers, which will round them down. So all your controlPoints will be 0.
You have to declare the controlPoints arrays as type double too:
double ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
double X1[3] = { 0.26015037593985, 0.43609022556391, 0.6 }, Y1[3] = {0.946875, 0.884375, 0.946875 };
This should fix your problem.
I am extremely interested in making a heart.
I am aware of the geometric primitive types.
http://www.opentk.com/doc/chapter/2/opengl/geometry/primitives
I am curious about how I would go about getting a curved line. Would I have to use the cmath library and connect it from two points somehow?
I have been looking at a lot of different sites about the math behind making hearts.
http://www16.ocn.ne.jp/~akiko-y/heart2/index_heart2_E.html
http://www.mathematische-basteleien.de/heart.htm
I'm struggling with porting this math to c++, not the actual math; I am just beginning to learn the language.
I would love it if someone could please provide me with some example code and an explanation as I am unable to find this on the internet. Also I am using the SFML framework for this project.
Thank you!
Here is an example of the current code.
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
int main()
{
sf::RenderWindow Window;
Window.create(sf::VideoMode(800, 600), "My First Smfl Game");
Window.setKeyRepeatEnabled(false);
sf::Texture pTexture;
while(Window.isOpen())
{
sf::Event Event;
while(Window.pollEvent(Event))
{
switch(Event.type)
{
case sf::Event::Closed:
Window.close();
break;
}
}
sf::VertexArray vArray(sf::Lines, 20);
vArray[0].position = sf::Vector2f(82, 300);
vArray[1].position = sf::Vector2f(82, 84);
vArray[2].position = sf::Vector2f(82, 84);
vArray[3].position = sf::Vector2f(200, 84);
vArray[4].position = sf::Vector2f(200, 84);
vArray[5].position = sf::Vector2f(200, 100);
vArray[6].position = sf::Vector2f(200, 100);
vArray[7].position = sf::Vector2f(99, 100);
vArray[8].position = sf::Vector2f(99, 100);
vArray[9].position = sf::Vector2f(99, 284);
vArray[10].position = sf::Vector2f(99, 284);
vArray[11].position = sf::Vector2f(200, 284);
vArray[12].position = sf::Vector2f(200, 284);
vArray[13].position = sf::Vector2f(200, 300);
vArray[14].position = sf::Vector2f(200, 300);
vArray[15].position = sf::Vector2f(82, 300);
vArray[16].position = sf::Vector2f(250, 300);
vArray[17].position = sf::Vector2f(300, 82);
vArray[18].position = sf::Vector2f(380, 300);
vArray[19].position = sf::Vector2f(320, 82);
for(int k = 0; k < 20; k++)
{
int red = rand() % 255;
int green = rand() % 255;
int blue = rand() % 255;
vArray[k].color = sf::Color(red, green, blue);
}
Window.draw(vArray);
Window.display();
Window.clear();
}
}
Replace the hard-coded coordinates for your curve (all the vArray[.].position assignments) by code that generates the coordinates. To generate these coordinates, you simply have to sample one of the proposed curves from your references. What follows is a possible implementation of method 3 from your second link (it's the one with the four squares, which seemed simple enough to implement):
#include <vector>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif // M_PI
// ...
int x0 = 800 / 2; // Coordinates of the center of the heart
int y0 = 600 / 2;
int size = 400; // Size of the heart
int r = size / 4; // Radius of the curves
int total_curve_vertex_count = 40; // Maximum number of vertices per curve
int total_vertex_count = 80; // Total number of vertices: 30 + 10 + 10 + 30
struct CurveInfo // Store information for each of the four square curves
{
int vertex_count;
double t0; // Angle origin
double s; // Angle sign: +1 or -1
int cx, cy; // (Relative) coordinates of the center of the curve
}
curve_infos[4] =
{
// Upper-left
{ 3 * total_curve_vertex_count / 4, 0.0, -1.0, -r, -r},
// Lower-left
{ total_curve_vertex_count / 4, 1.5 * M_PI, 1.0, -r, r},
// Lower-right
{ total_curve_vertex_count / 4, M_PI, 1.0, r, r},
// Upper-right
{ 3 * total_curve_vertex_count / 4, 0.5 * M_PI, -1.0, r, -r},
};
std::vector<sf::Vector2f> vertices(total_vertex_count);
int vertex_index = 0;
for(int i = 0; i < 4; i++)
{
CurveInfo& curve_info = curve_infos[i];
int vertex_count = curve_info.vertex_count;
double t0 = curve_info.t0;
double s = curve_info.s;
int cx = x0 + curve_info.cx;
int cy = y0 + curve_info.cy;
for(int j = 0; j < vertex_count; j++)
{
double dt = s * 2.0 * M_PI * j / (total_curve_vertex_count - 1);
int x = cx + r * cos(t0 + dt);
int y = cy + r * sin(t0 + dt);
vertices[vertex_index++] = sf::Vector2f(x, y);
}
}
// Generate the vertices of the lines primitives
int total_line_count = total_vertex_count - 1;
// Don't duplicate the first and last vertices
int line_vertex_count = 2 * total_vertex_count - 2;
sf::VertexArray vArray(sf::Lines, line_vertex_count);
int line_index = 0;
vertex_index = 0;
for(int k = 0; k < total_line_count; k++)
{
vArray[line_index++].position = vertices[vertex_index++];
vArray[line_index++].position = vertices[vertex_index];
}
for(int k = 0; k < line_vertex_count; k++)
{
int red = rand() % 255;
int green = rand() % 255;
int blue = rand() % 255;
vArray[k].color = sf::Color(red, green, blue);
}
// ...
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).
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.