Mandelbrot Set not displayed - c

a Mandelbrot set fractal using C programming and OpenGL. Here is my code. It is only displaying a dot in the center right now. I cannot figure out where I am going wrong. I'm pretty sure my math is correct. Maybe I have something in the wrong loop?
This picture is what Im trying to get
Here is my code so far:
#include <GLUT/glut.h>
#include <math.h>
void init(void);
void display(void);
const int screenWidth = 640;
const int screenHeight = 480;
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(screenWidth, screenHeight);
glutInitWindowPosition(0, 0);
glutCreateWindow("Mandelbrot");
// glViewport(-320, -320, 320, 320);
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
void init(void) {
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-500.0, screenWidth, -500.0, screenHeight);
// A = screenWidth / 4.0;
// B = 0.0;
// C = D = screenHeight / 2.0;
}
void display(void) {
GLdouble x, f, y, xtemp, y0, x0, iteration, maxInteration;
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(1);
glColor3f(0.0, 0.0, 0.0);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (y0 = - 1; y0 < 1.1; y0 = y0 + 0.0025) {
for (x0 = -2.5; x0 < 1.1; x0 = x0 + 0.0025) {
x = 0;
y = 0;
iteration = 0;
maxInteration = 1000;
while (((x * x) + (y * y) < (2 * 2)) && iteration < maxInteration) {
xtemp = (x * x) - (y * y) + x0;
y = (2 * x * y) + y0;
x = xtemp;
iteration = iteration + 1;
if (y <= 2) {
glBegin(GL_POINTS);
glVertex2d(x / 750, y / 750);
glEnd();
}
}
}
}
glFlush();
}
Here is my updated code after fixing suggestions in comments.. It results in the above image.. However, now I am trying to create the grey circles around the object??? Im attempting to do this through the else at the end... any thoughts?
#include <GLUT/glut.h>
#include <math.h>
void init(void);
void display(void);
const int screenWidth = 640;
const int screenHeight = 640;
GLdouble A, B, C, D;
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(screenWidth, screenHeight);
glutInitWindowPosition(0, 0);
glutCreateWindow("Mandelbrot");
glViewport(-1, 1, -1, 1);
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
void init(void) {
//glMatrixMode(GL_PROJECTION);
gluOrtho2D(-3.0, 3.0, -3.0, 3.0);
A = screenWidth / 4.0;
B = 0.0;
C = D = screenHeight / 2.0;
}
void display(void)
{
GLdouble x, f, y, xtemp, y0, x0, iteration, maxInteration;
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(1);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for(y0 = -1; y0< 1.1; y0 = y0 + 0.0025){
for (x0 = -2.5; x0 < 1.1; x0 = x0 + 0.0025) {
x = 0;
y = 0;
iteration = 0;
maxInteration = 200;
while(((x*x) + (y*y) <(2*2)) && iteration <maxInteration){
xtemp = (x*x) - (y*y) + x0;
y = (2*x*y) +y0;
x = xtemp;
iteration = iteration + 1;
}
if(iteration >= maxInteration){
glBegin(GL_POINTS);
glVertex2d(x0 , y0);
glColor3f(0.0, 0.0, 0.0);
glEnd();
}
else{
????
}
}
}
glFlush();
}

First of all, here's some advices regarding to your code:
When working with complex numbers or vectors i'd recommend you to use a proper fast math library so you can avoid operating with individual components, there are very fast cpu math libraries out there which can use SIMD instructions and your code will become more readable
The way your drawing the mandelbrot is really a bad idea. I mean, yeah, it's alright if you just want to dump simple images and learning the basics but that's pretty much. Don't use GL_POINTS and try to render/update textures directly, or even better, use fragment shaders + glsl (recommended way) so your mandelbrot will be rendered very fast even if you're using non-optimized maths.
Coordinate systems, if you still insist on using GL_POINTS the way you're doing, i'd just use directly the window coordinates and going from that space to the mandelbrot math domain ie: [0,0,w,h]<->[-1,-1,1,1]
Here's a little example of what i mean:
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
const int screen_width = 640;
const int screen_height = 480;
float c[4];
float z[4];
float clamp(float x, float vmin, float vmax) {
if (x < vmin) {
return vmin;
} else if (x > vmax) {
return vmax;
}
return x;
}
void dc_add(float *a, float *b, float *res) {
res[0] = a[0] + b[0];
res[1] = a[1] + b[1];
res[2] = a[2] + b[2];
res[3] = a[3] + b[3];
}
void dc_mul(float *a, float *b, float *res) {
res[0] = a[0] * b[0] - a[1] * b[1];
res[1] = a[0] * b[1] + a[1] * b[0];
res[2] = a[0] * b[2] + a[2] * b[0] - a[1] * b[3] - a[3] * b[1];
res[3] = a[0] * b[3] + a[3] * b[0] + a[2] * b[1] + a[1] * b[2];
}
void dc_sqr(float *a, float *res) {
res[0] = a[0] * a[0] - a[1] * a[1];
res[1] = 2.0f * a[0] * a[1];
res[2] = 2.0f * (a[0] * a[2] - a[1] * a[3]);
res[3] = 2.0f * (a[0] * a[3] + a[1] * a[2]);
}
float dot(float x, float y) { return x * x + y * y; }
void init(void) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, screen_width, 0, screen_height);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (int y = 0; y < screen_height; y++) {
for (int x = 0; x < screen_width; x++) {
float px = -1.0f + 2.0f * (float)x / (float)screen_width;
float py = -1.0f + 2.0f * (float)y / (float)screen_height;
px *= (float)screen_width / (float)screen_height;
float tz = 0.5f;
float zo = powf(1.2f, 1.2f);
float m2 = 0.0f;
float co = 0.0f;
float temp[4];
c[0] = px * zo; c[1] = py * zo; c[2] = 1.0; c[3] = 0.0;
z[0] = 0.0f; z[1] = 0.0f; z[2] = 0.0f; z[3] = 0.0f;
for (int i = 0; i < 256; i++) {
if (m2 > 1024.0f) continue;
dc_sqr(z, temp);
dc_add(temp, c, z);
m2 = dot(z[0], z[1]);
co += 1.0f;
}
float d = 0.0f;
if (co < 256.0f) {
d = sqrtf((dot(z[0], z[1]) / dot(z[2], z[3]))) *
logf(dot(z[0], z[1]));
}
d = clamp(4.0f * d / zo, 0.0f, 1.0f);
d = powf(d, 0.25f);
glColor3f(d, d, d);
glBegin(GL_POINTS);
glVertex2d(x, y);
glEnd();
}
}
glFlush();
glutSwapBuffers();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(screen_width, screen_height);
glutInitWindowPosition(0, 0);
glutCreateWindow("Mandelbrot");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutMainLoop();
return 0;
}
And here's the output:
Maths of the above example are based on this shadertoy.
The above code is terrible unefficient and slow but it serves the main purpose to prove you the way you shouldn't ever code a proper mandelbrot.
Happy coding.

There is a simple problem in you code: you use a division instead of a multiplication to compute the pixel coordinates: change glVertex2d(x / 750, y / 750); to
glVertex2d(x * 750, y * 750);
However, this is not the correct method to compute the Mandelbrot set. You should instead compute the number of iterations for the squared module to exceed 4.0, and then set the color of the pixel at (x0 * 300, y0 * 300) to that number as a palette entry or a gray level.

Related

Mandelbrot set in OpenGL - C

I'm new to OpenGL and I am trying to get a mandelbrot set computed with OpenGL and GLFW.
I found the code here but freeglut is broken on my system and for some reason complains about no callback being set even though it clearly is being set. It does however flash one frame and then crash, in that frame I can see the mandelbrot set so I know the math is correct.
I figured this would be a good opportunity to learn more about OpenGL and GLFW, so I set to work making this happen.
After double checking everything, I can see that it definitely calculates the values then switches the buffers properly.
However, I think I'm missing two things:
A vertex which the texture can actually be applied to
EDIT: (from learnopengl.com) "Once glTexImage2D is called, the currently bound texture object now has the texture image attached to it.", so it can't be #2
not sure what's happening with the calculation but it looks like it's binding a texture named 'texture' but then calculating the values in a struct array which don't seem to be associated in any way. I bind the texture with tex (texture) and then send the struct array to glTexImage2D
If someone could just point me in the right direction or confirm my suspicions that would be awesome.
My code is here:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define GLEW_STATIC
#include <GL/glew.h>
#include <pthread.h>
#include <GLFW/glfw3.h>
#include <GL/gl.h>
#define VAL 255
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
}rgb_t;
rgb_t **tex_array = 0;
rgb_t *image;
int gwin;
int width = 640;
int height = 480;
int tex_w, tex_h;
double scale = 1./256;
double cx = -.6, cy = 0;
int color_rotate = 0;
int saturation = 1;
int invert = 0;
int max_iter = 256;
int dump = 1;
GLFWwindow* window;
int global_iterator = 0;
int conversion_iterator_x = 0;
int conversion_iterator_y = 0;
GLFWwindow* init_glfw();
void set_texture(GLuint tex);
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void render(GLuint tex);
void screen_dump();
void keypress(unsigned char key, int x, int y);
void hsv_to_rgb(int hue, int min, int max, rgb_t *p);
void calc_mandel(rgb_t* px);
void alloc_texture();
void set_texture();
void mouseclick(int button, int state, int x, int y);
void resize(int w, int h);
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
int main(int c, char **v)
{
GLFWwindow* win = init_glfw();
glfwSetWindowPos(win, 1000, 500);
GLuint texture;
glGenTextures(1, &texture);
set_texture(texture);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(win))
{
render(texture);
/* Swap front and back buffers */
glfwSwapBuffers(win);
/* Poll for and process events */
glfwPollEvents();
if(glfwGetKey(win, GLFW_KEY_ESCAPE) == GLFW_PRESS){
glfwSetWindowShouldClose(win, GL_TRUE);
}
}
return 0;
}
void set_texture(GLuint tex)
{
printf("Allocating space\n");
alloc_texture();
printf("Calculating mandel... %d\n", global_iterator);
++global_iterator;
calc_mandel(image);
printf("mandel calculation complete\n");
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_w, tex_h,
0, GL_RGB, GL_UNSIGNED_BYTE, tex_array[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
printf("Rendering to screen...\n");
render(tex);
}
void alloc_texture()
{
int i;
int ow = tex_w;
int oh = tex_h;
for (tex_w = 1; tex_w < width; tex_w <<= 1);
for (tex_h = 1; tex_h < height; tex_h <<= 1);
if (tex_h != oh || tex_w != ow){
tex_array = realloc(tex_array, tex_h * tex_w * 3 + tex_h * sizeof(rgb_t*));
}
for (tex_array[0] = (rgb_t *)(tex_array + tex_h), i = 1; i < tex_h; i++){
tex_array[i] = tex_array[i - 1] + tex_w;
}
}
void render(GLuint tex)
{
double x = (double)width /tex_w,
y = (double)height/tex_h;
glClear(GL_COLOR_BUFFER_BIT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, tex);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2i(0, 0);
glTexCoord2f(x, 0); glVertex2i(width, 0);
glTexCoord2f(x, y); glVertex2i(width, height);
glTexCoord2f(0, y); glVertex2i(0, height);
glEnd();
glFlush();
glFinish();
}
GLFWwindow* init_glfw()
{
/* Initialize the library */
if (!glfwInit()){
return NULL;
}
/*
* Configure window options here if you so desire
*
* i.e.
*/
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
//glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
//the fourth parameter of glfwCreateWindow should be NULL for windowed mode and
//glfGetPrimaryMonitor() for full screen mode
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(width, height, "Mandelbrot", NULL, NULL);
if (!window)
{
glfwTerminate();
return NULL;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
/*
* Initialize glew here
*/
glewExperimental = GL_TRUE;
glewInit();
return window;
}
void calc_mandel(rgb_t* px)
{
int i, j, iter, min, max;
double x, y, zx, zy, zx2, zy2;
min = max_iter;
max = 0;
for (i = 0; i < height; i++) {
px = tex_array[i];
y = (i - height/2) * scale + cy;
for (j = 0; j < width; j++, px++) {
x = (j - width/2) * scale + cx;
iter = 0;
zx = hypot(x - .25, y);
if (x < zx - 2 * zx * zx + .25){
iter = max_iter;
}
if ((x + 1)*(x + 1) + y * y < 1/16){
iter = max_iter;
}
zx = zy = zx2 = zy2 = 0;
for (; iter < max_iter && zx2 + zy2 < 4; iter++) {
zy = 2 * zx * zy + y;
zx = zx2 - zy2 + x;
zx2 = zx * zx;
zy2 = zy * zy;
}
if (iter < min){
min = iter;
}
if (iter > max){
max = iter;
}
*(unsigned short *)px = iter;
}
}
for (i = 0; i < height; i++){
for (j = 0, px = tex_array[i]; j < width; j++, px++){
hsv_to_rgb(*(unsigned short*)px, min, max, px);
}
}
}
void hsv_to_rgb(int hue, int min, int max, rgb_t *p)
{
printf("Converting hsv to rbg... \n");
if (min == max){
max = min + 1;
}
if (invert){
hue = max - (hue - min);
}
if (!saturation) {
p->r = p->g = p->b = 255 * (max - hue) / (max - min);
printf("done! (!saturation)\n");
return;
}
double h = fmod(color_rotate + 1e-4 + 4.0 * (hue - min) / (max - min), 6);
double c = VAL * saturation;
double X = c * (1 - fabs(fmod(h, 2) - 1));
p->r = p->g = p->b = 0;
switch((int)h) {
case 0: p->r = c; p->g = X; break;
case 1: p->r = X; p->g = c; break;
case 2: p->g = c; p->b = X; break;
case 3: p->g = X; p->b = c; break;
case 4: p->r = X; p->b = c; break;
default:p->r = c; p->b = X; break;
}
printf("done! (sauration)\n");
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
glOrtho(0, width, 0, height, -1, 1);
//set_texture();
}
[1]: https://rosettacode.org/wiki/Mandelbrot_set#PPM_non_interactive

Converting projectile simulation to 3D causes drawing to disasppear?

I have a code that successfully draws projectiles in 2D, but I need to apply changes to make it in 3D.
#include <stdio.h>
#include <GL/glut.h>
#include <math.h>
#include <unistd.h>
#define g 9.8
#define PI 3.14
#define ESC 27
void initialize(void)
{
glClearColor(0, 0, 0, 0);
glColor3f(0.0, 1.0, 0.0);
glPointSize(3.0);
glEnable(GL_POINT_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 1000, 0, 500);
}
static void keyPressFunc(unsigned char key, int x, int y)
{
switch(key) {
case ESC:
exit(1);
}
}
void display(void)
{
float Pheta, Pheta2, Pheta3,Pheta4, Vo, time, time_top, d1, d2, d3, Uox1, Uox2, Uox3;
Vo = 60;
Pheta = 60;
Pheta2 = 30;
Pheta3 = 40;
Pheta4 = 50;
time = (2 * Vo * sin(Pheta * PI / 180)) / g;
time_top = time/2;
d1 = 500;
d2 = 650;
d3 = 800;
Uox1 = (d1 - Vo * cos(Pheta * PI / 180) * 2)/2;
Uox2 = (d2 - Vo * cos(Pheta * PI / 180)* time_top)/time_top;
Uox3 = (d3 - Vo * cos(Pheta * PI / 180) * 8)/8;
for(float t=0; t < 12 ; t += 0.0005)
{
float x1 = (Vo * cos(Pheta * PI / 180) * t);
float y1 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x2 = (d1 - Uox1 * t);
float y2 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x3 = (d2 - Uox2 * t);
float y3 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x4 = (d3 - Uox3 * t);
float y4 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
glBegin(GL_POINTS);
glVertex2d(x1, y1);
glVertex2d(x2, y2);
glVertex2d(x3, y3);
glVertex2d(x4, y4);
if (x1+0.1 >= x4 && x4+0.1 >= x1)
{
break;
}
glEnd();
glFlush();
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(800, 600);
glutInitWindowPosition(0, 0);
glutCreateWindow("C-Lang-Project");
glutKeyboardFunc(keyPressFunc);
initialize();
glutDisplayFunc(display);
glutMainLoop();
}
To make it 3D, I changed glVertex2d into glVertex3d, set a variable z and added it to the glVertex3d.
The final code that I've got:
#include <stdio.h>
#include <GL/glut.h>
#include <math.h>
#include <unistd.h>
#define g 9.8
#define PI 3.14
#define ESC 27
void initialize(void)
{
glClearColor(0, 0, 0, 0);
glColor3f(0.0, 1.0, 0.0);
glPointSize(3.0);
glEnable(GL_POINT_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 1000, 0, 500);
}
static void keyPressFunc(unsigned char key, int x, int y)
{
switch(key) {
case ESC:
exit(1);
}
}
void display(void)
{
float Pheta, Pheta2, Pheta3,Pheta4, Vo, time, time_top, d1, d2, d3, Uox1, Uox2, Uox3, z;
Vo = 60;
Pheta = 60;
Pheta2 = 30;
Pheta3 = 40;
Pheta4 = 50;
time = (2 * Vo * sin(Pheta * PI / 180)) / g;
time_top = time/2;
d1 = 500;
d2 = 650;
d3 = 800;
z = 15;
Uox1 = (d1 - Vo * cos(Pheta * PI / 180) * 2)/2;
Uox2 = (d2 - Vo * cos(Pheta * PI / 180)* time_top)/time_top;
Uox3 = (d3 - Vo * cos(Pheta * PI / 180) * 8)/8;
for(float t=0; t < 12 ; t += 0.0005)
{
float x1 = (Vo * cos(Pheta * PI / 180) * t);
float y1 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x2 = (d1 - Uox1 * t);
float y2 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x3 = (d2 - Uox2 * t);
float y3 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x4 = (d3 - Uox3 * t);
float y4 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
glBegin(GL_POINTS);
glVertex3d(x1, y1, z);
glVertex3d(x2, y2, z);
glVertex3d(x3, y3, z);
glVertex3d(x4, y4, z);
if (x1+0.1 >= x4 && x4+0.1 >= x1)
{
break;
}
glEnd();
glFlush();
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(800, 600);
glutInitWindowPosition(0, 0);
glutCreateWindow("C-Lang-Project");
glutKeyboardFunc(keyPressFunc);
initialize();
glutDisplayFunc(display);
glutMainLoop();
}
But it does not show any mistake, just shows a black window.
P.S. I am using OpenGL & freeglut
The scene is clipped by by the near plane of the orthographic projection.
The z coordiante of the geoemtry is set z=15; but the orthographic projection is set gluOrtho2D(0, 1000, 0, 500);. gluOrtho2D sets a near plane of -1 and a far plane of 1.
The view space z coordinate has to be between the near and far plane.
Since the view space z axis points out of the viewport, the view space z coordinate is -15.
This means, if z=15 then the following condition has to be fulfilled:
near < -15 < far
Change the orthographic projection to solve the issue. Use glOrtho:
e.g.
void initialize(void)
{
// [...]
glOrtho(0, 1000, 0, 500, -20, 1);
}
Of course it is possible to switch to perspective projection. In this case you've to invert the and z coordinate.
To get all the geometry on the screen (in clip space), I recommend to increase the amount to of the z coordinate and (of course) the distance to the far plane:
e.g.
void display(void)
{
float z = -500;
// [...]
}
void initialize(void)
{
// [...]
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 90.0, 1000.0 / 500.0, 0.1, 1000.0 );
}
Don't implement a render loop in the event processing loop. Use glutPostRedisplay to force the display to be repainted:
float t=0;
void display(void)
{
float Pheta, Pheta2, Pheta3,Pheta4, Vo, time, time_top, d1, d2, d3, Uox1, Uox2, Uox3, z;
Vo = 60; Pheta = 60; Pheta2 = 30; Pheta3 = 40; Pheta4 = 50;
time = (2 * Vo * sin(Pheta * PI / 180)) / g;
time_top = time/2; d1 = 500; d2 = 650; d3 = 800;
z = 15;
Uox1 = (d1 - Vo * cos(Pheta * PI / 180) * 2)/2;
Uox2 = (d2 - Vo * cos(Pheta * PI / 180)* time_top)/time_top;
Uox3 = (d3 - Vo * cos(Pheta * PI / 180) * 8)/8;
float x1 = (Vo * cos(Pheta * PI / 180) * t);
float y1 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x2 = (d1 - Uox1 * t);
float y2 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x3 = (d2 - Uox2 * t);
float y3 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x4 = (d3 - Uox3 * t);
float y4 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
glBegin(GL_POINTS);
glVertex3d(x1, y1, z);
glVertex3d(x2, y2, z);
glVertex3d(x3, y3, z);
glVertex3d(x4, y4, z);
glEnd();
t += 0.0005;
glFlush();
glutPostRedisplay();
}

Draw doesn't works with OpenGL while drawing sphere

I'm first in OpenGL, and i want to draw a sphere with 3D graphical view.
For first step, i just want to draw a belt that contained to result sphere.
But there's no result, all of my result window is cleared with white.
Is there any problem in my code?
Here is my Code :
void init();
void display();
void drawPath(int pi, int theta);
void drawQuad(int pi, int theta);
int we = -80; // - 파이
int kyong = -180; // - 세타
int main(int argc, const char * argv[]) {
glutInit(&argc, (char**)argv);
glutInitWindowSize(500, 500);
glutCreateWindow("Prog09 - Goo");
glutDisplayFunc(display);
init();
glutMainLoop();
return 0;
}
void init(){
glClearColor(1, 1, 1, 1);
glOrtho(0, 50, 0, 50, -50, 50);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
}
void display(){
glColor3f(1.0, 1.0, 1.0);
drawPath(0, 0);
}
void drawPath(int pi, int theta){
drawQuad(pi, theta);
}
void drawQuad(pi, theta){
int i;
GLfloat x[4],y[4],z[4];
// theta = (theta * 3.14)/180;
// pi = (pi * 3.14)/180;
x[0] = sin(theta)*cos(pi);
y[0] = cos(theta)*sin(pi);
z[0] = sin(pi);
x[1] = sin(theta)*cos(pi+20);
y[1] = cos(theta)*sin(pi+20);
z[1] = sin(pi+20);
x[2] = sin(theta+20)*cos(pi+20);
y[2] = cos(theta+20)*sin(pi+20);
z[2] = sin(pi+20);
x[3] = sin(theta+20)*cos(pi);
y[3] = cos(theta+20)*sin(pi);
z[3] = sin(pi);
for (i = 0; i < 4; i++) {
glBegin(GL_POLYGON);
glVertex3f(x[i]*10, y[i]*10, z[i]*10);
glEnd();
}
glFlush();
for (i = 0; i < 4; i++) {
printf("%d. %f %f %f\n",i+1, x[i], y[i], z[i]);
}
printf("WHY?\n");
}
I know it's a basic question, but i have know idea why my codes doesn't work.
Thanks for your helps.
You are drawing a number of polygons, were each polygon contains exactly one point:
for (i = 0; i < 4; i++) {
glBegin(GL_POLYGON);
glVertex3f(x[i]*10, y[i]*10, z[i]*10);
glEnd();
}
If you want to draw one polygon with all the points, then you'll have to do something like:
glBegin(GL_POLYGON);
for (i = 0; i < 4; i++) {
glVertex3f(x[i]*10, y[i]*10, z[i]*10);
}
glEnd();

how to convert simple opengl line plotting code to use vertex array

I wrote a simple opengl application in C which plots sin(x). This is my current draw function which runs very slow. How do I have to convert this code to make use of the faster 'vertex array' mode?
list of variables and functions used:
N = total number of points
x1 = min(x)
x2 = max(x)
y1 = min(y)
y2 = max(y)
func(x) = sin(x)
and here's the entire code:
/* to compile, do:
$ gcc -o out simple.c -lglut
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include <time.h>
float xmin = -10, xmax = 10, ymin = -5, ymax = 5;
int nPoints = 3000;
/* function to calculate each data point */
float func(float x)
{
return sin(x);
}
/* plotting function - very slow */
void draw(float (* func)(float x), float x1, float x2, float y1, float y2, int N)
{
float x, dx = 1.0/N;
glPushMatrix();
glScalef(1.0 / (x2 - x1), 1.0 / (y2 - y1), 1.0);
glTranslatef(-x1, -y1, 0.0);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_STRIP);
for(x = x1; x < x2; x += dx)
{
glVertex2f(x, func(x));
}
glEnd();
glPopMatrix();
};
/* Redrawing func */
void redraw(void)
{
clock_t start = clock();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// -x, +x, -y, +y, number points
draw(func, xmin, xmax, ymin, ymax, nPoints);
glutSwapBuffers();
printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC);
};
/* Idle proc. Redisplays, if called. */
void idle(void)
{
// shift 'xmin' & 'xmax' by one.
xmin++;
xmax++;
glutPostRedisplay();
};
/* Key press processing */
void key(unsigned char c, int x, int y)
{
if(c == 27) exit(0);
};
/* Window reashape */
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 0, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
};
/* Main function */
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("Graph plotter");
glutReshapeWindow(1024, 800);
glutPostRedisplay(); // This call may or may not be necessary
/* Register GLUT callbacks. */
glutDisplayFunc(redraw);
glutKeyboardFunc(key);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
/* Init the GL state */
glLineWidth(2.0);
/* Main loop */
glutMainLoop();
return 0;
}
In terms of LodePNG's C-style vector struct/functions:
// shared
vector pts;
vector_init( &pts, sizeof( float ) );
// whenever x1, x2, or N changes
vector_cleanup( &pts );
float x, dx = 1.0/N;
for(x = x1; x < x2; x += dx)
{
vector_resize( &pts, pts.size + 2 );
*(float*)vector_get( &pts, pts.size-2 ) = x;
*(float*)vector_get( &pts, pts.size-1 ) = func(x);
}
// whenever you want to draw
glPushMatrix();
glScalef(1.0 / (x2 - x1), 1.0 / (y2 - y1), 1.0);
glTranslatef(-x1, -y1, 0.0);
glColor3f(1.0, 1.0, 1.0);
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, (float*)pts.data );
glDrawArrays( GL_LINE_STRIP, 0, pts.size / 2 );
glDisableClientState( GL_VERTEX_ARRAY );
glPopMatrix();
EDIT: Complete code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include <time.h>
typedef struct vector /*dynamic vector of void* pointers. This one is used only by the deflate compressor*/
{
void* data;
size_t size; /*in groups of bytes depending on type*/
size_t allocsize; /*in bytes*/
unsigned typesize; /*sizeof the type you store in data*/
} vector;
static unsigned vector_resize(vector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/
{
if(size * p->typesize > p->allocsize)
{
size_t newsize = size * p->typesize * 2;
void* data = realloc(p->data, newsize);
if(data)
{
p->allocsize = newsize;
p->data = data;
p->size = size;
}
else return 0;
}
else p->size = size;
return 1;
}
static void vector_cleanup(void* p)
{
((vector*)p)->size = ((vector*)p)->allocsize = 0;
free(((vector*)p)->data);
((vector*)p)->data = NULL;
}
static void vector_init(vector* p, unsigned typesize)
{
p->data = NULL;
p->size = p->allocsize = 0;
p->typesize = typesize;
}
static void* vector_get(vector* p, size_t index)
{
return &((char*)p->data)[index * p->typesize];
}
float xmin = -10, xmax = 10, ymin = -5, ymax = 5;
int nPoints = 3000;
vector pts;
/* function to calculate each data point */
float func(float x)
{
return sin(x);
}
void update(float (* func)(float x), float x1, float x2, int N)
{
float x, dx = 1.0/N;
vector_cleanup( &pts );
for(x = x1; x < x2; x += dx)
{
vector_resize( &pts, pts.size + 2 );
*(float*)vector_get( &pts, pts.size-2 ) = x;
*(float*)vector_get( &pts, pts.size-1 ) = func(x);
}
}
/* plotting function - very slow */
void draw(float x1, float x2, float y1, float y2)
{
glPushMatrix();
glScalef(1.0 / (x2 - x1), 1.0 / (y2 - y1), 1.0);
glTranslatef(-x1, -y1, 0.0);
glColor3f(1.0, 1.0, 1.0);
if( pts.size > 0 )
{
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, (float*)pts.data );
glDrawArrays( GL_LINE_STRIP, 0, pts.size / 2 );
glDisableClientState( GL_VERTEX_ARRAY );
}
glPopMatrix();
};
/* Redrawing func */
void redraw(void)
{
clock_t start = clock();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// -x, +x, -y, +y, number points
draw(xmin, xmax, ymin, ymax);
glutSwapBuffers();
printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC);
};
/* Idle proc. Redisplays, if called. */
void idle(void)
{
// shift 'xmin' & 'xmax' by one.
xmin++;
xmax++;
update(func, xmin, xmax, nPoints);
glutPostRedisplay();
};
/* Key press processing */
void key(unsigned char c, int x, int y)
{
if(c == 27) exit(0);
};
/* Window reashape */
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 0, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
};
/* Main function */
int main(int argc, char **argv)
{
vector_init( &pts, sizeof( float ) );
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("Graph plotter");
glutReshapeWindow(1024, 800);
glutPostRedisplay(); // This call may or may not be necessary
/* Register GLUT callbacks. */
glutDisplayFunc(redraw);
glutKeyboardFunc(key);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
/* Init the GL state */
glLineWidth(2.0);
/* Main loop */
glutMainLoop();
return 0;
}

Can anyone give me a short code example in c using opengl where clicking in two different squares changes their color?

Can anyone give me a short code example in c using opengl where clicking in two different squares changes their color? I'm particularly interested in knowing how to detect that a mouse click has happened to a particular primitive.
Here's a GL selection-mode example
/* Copyright (c) Mark J. Kilgard, 1994. */
/**
* (c) Copyright 1993, Silicon Graphics, Inc.
* ALL RIGHTS RESERVED
* Permission to use, copy, modify, and distribute this software for
* any purpose and without fee is hereby granted, provided that the above
* copyright notice appear in all copies and that both the copyright notice
* and this permission notice appear in supporting documentation, and that
* the name of Silicon Graphics, Inc. not be used in advertising
* or publicity pertaining to distribution of the software without specific,
* written prior permission.
*
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
*
* US Government Users Restricted Rights
* Use, duplication, or disclosure by the Government is subject to
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
* clause at DFARS 252.227-7013 and/or in similar or successor
* clauses in the FAR or the DOD or NASA FAR Supplement.
* Unpublished-- rights reserved under the copyright laws of the
* United States. Contractor/manufacturer is Silicon Graphics,
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
*
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <GL/glut.h>
#define MAXOBJS 10000
#define MAXSELECT 100
#define MAXFEED 300
#define SOLID 1
#define LINE 2
#define POINT 3
GLint windW = 300, windH = 300;
GLuint selectBuf[MAXSELECT];
GLfloat feedBuf[MAXFEED];
GLint vp[4];
float zRotation = 90.0;
float zoom = 1.0;
GLint objectCount;
GLint numObjects;
struct object {
float v1[2];
float v2[2];
float v3[2];
float color[3];
} objects[MAXOBJS];
GLenum linePoly = GL_FALSE;
static void InitObjects(GLint num)
{
GLint i;
float x, y;
if (num > MAXOBJS) {
num = MAXOBJS;
}
if (num < 1) {
num = 1;
}
objectCount = num;
srand((unsigned int) time(NULL));
for (i = 0; i < num; i++) {
x = (rand() % 300) - 150;
y = (rand() % 300) - 150;
objects[i].v1[0] = x + (rand() % 50) - 25;
objects[i].v2[0] = x + (rand() % 50) - 25;
objects[i].v3[0] = x + (rand() % 50) - 25;
objects[i].v1[1] = y + (rand() % 50) - 25;
objects[i].v2[1] = y + (rand() % 50) - 25;
objects[i].v3[1] = y + (rand() % 50) - 25;
objects[i].color[0] = ((rand() % 100) + 50) / 150.0;
objects[i].color[1] = ((rand() % 100) + 50) / 150.0;
objects[i].color[2] = ((rand() % 100) + 50) / 150.0;
}
}
static void Init(void)
{
numObjects = 10;
InitObjects(numObjects);
}
static void Reshape(int width, int height)
{
windW = width;
windH = height;
glViewport(0, 0, windW, windH);
glGetIntegerv(GL_VIEWPORT, vp);
}
static void Render(GLenum mode)
{
GLint i;
for (i = 0; i < objectCount; i++) {
if (mode == GL_SELECT) {
glLoadName(i);
}
glColor3fv(objects[i].color);
glBegin(GL_POLYGON);
glVertex2fv(objects[i].v1);
glVertex2fv(objects[i].v2);
glVertex2fv(objects[i].v3);
glEnd();
}
}
static GLint DoSelect(GLint x, GLint y)
{
GLint hits;
glSelectBuffer(MAXSELECT, selectBuf);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(~0);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPickMatrix(x, windH - y, 4, 4, vp);
gluOrtho2D(-175, 175, -175, 175);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glScalef(zoom, zoom, zoom);
glRotatef(zRotation, 0, 0, 1);
Render(GL_SELECT);
glPopMatrix();
hits = glRenderMode(GL_RENDER);
if (hits <= 0) {
return -1;
}
return selectBuf[(hits - 1) * 4 + 3];
}
static void RecolorTri(GLint h)
{
objects[h].color[0] = ((rand() % 100) + 50) / 150.0;
objects[h].color[1] = ((rand() % 100) + 50) / 150.0;
objects[h].color[2] = ((rand() % 100) + 50) / 150.0;
}
static void DeleteTri(GLint h)
{
objects[h] = objects[objectCount - 1];
objectCount--;
}
static void GrowTri(GLint h)
{
float v[2];
float *oldV;
GLint i;
v[0] = objects[h].v1[0] + objects[h].v2[0] + objects[h].v3[0];
v[1] = objects[h].v1[1] + objects[h].v2[1] + objects[h].v3[1];
v[0] /= 3;
v[1] /= 3;
for (i = 0; i < 3; i++) {
switch (i) {
case 0:
oldV = objects[h].v1;
break;
case 1:
oldV = objects[h].v2;
break;
case 2:
oldV = objects[h].v3;
break;
}
oldV[0] = 1.5 * (oldV[0] - v[0]) + v[0];
oldV[1] = 1.5 * (oldV[1] - v[1]) + v[1];
}
}
static void Mouse(int button, int state, int mouseX, int mouseY)
{
GLint hit;
if (state == GLUT_DOWN) {
hit = DoSelect((GLint) mouseX, (GLint) mouseY);
if (hit != -1) {
if (button == GLUT_LEFT_BUTTON) {
RecolorTri(hit);
} else if (button == GLUT_MIDDLE_BUTTON) {
GrowTri(hit);
} else if (button == GLUT_RIGHT_BUTTON) {
DeleteTri(hit);
}
glutPostRedisplay();
}
}
}
static void Draw(void)
{
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-175, 175, -175, 175);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glScalef(zoom, zoom, zoom);
glRotatef(zRotation, 0, 0, 1);
Render(GL_RENDER);
glPopMatrix();
glutSwapBuffers();
}
static void DumpFeedbackVert(GLint * i, GLint n)
{
GLint index;
index = *i;
if (index + 7 > n) {
*i = n;
printf(" ???\n");
return;
}
printf(" (%g %g %g), color = (%4.2f %4.2f %4.2f)\n",
feedBuf[index],
feedBuf[index + 1],
feedBuf[index + 2],
feedBuf[index + 3],
feedBuf[index + 4],
feedBuf[index + 5]);
index += 7;
*i = index;
}
static void DrawFeedback(GLint n)
{
GLint i;
GLint verts;
printf("Feedback results (%d floats):\n", n);
for (i = 0; i < n; i++) {
switch ((GLint) feedBuf[i]) {
case GL_POLYGON_TOKEN:
printf("Polygon");
i++;
if (i < n) {
verts = (GLint) feedBuf[i];
i++;
printf(": %d vertices", verts);
} else {
verts = 0;
}
printf("\n");
while (verts) {
DumpFeedbackVert(&i, n);
verts--;
}
i--;
break;
case GL_LINE_TOKEN:
printf("Line:\n");
i++;
DumpFeedbackVert(&i, n);
DumpFeedbackVert(&i, n);
i--;
break;
case GL_LINE_RESET_TOKEN:
printf("Line Reset:\n");
i++;
DumpFeedbackVert(&i, n);
DumpFeedbackVert(&i, n);
i--;
break;
default:
printf("%9.2f\n", feedBuf[i]);
break;
}
}
if (i == MAXFEED) {
printf("...\n");
}
printf("\n");
}
static void DoFeedback(void)
{
GLint x;
glFeedbackBuffer(MAXFEED, GL_3D_COLOR, feedBuf);
(void) glRenderMode(GL_FEEDBACK);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-175, 175, -175, 175);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glScalef(zoom, zoom, zoom);
glRotatef(zRotation, 0, 0, 1);
Render(GL_FEEDBACK);
glPopMatrix();
x = glRenderMode(GL_RENDER);
if (x == -1) {
x = MAXFEED;
}
DrawFeedback((GLint) x);
}
static void Key(unsigned char key, int x, int y)
{
switch (key) {
case 'z':
zoom /= 0.75;
glutPostRedisplay();
break;
case 'Z':
zoom *= 0.75;
glutPostRedisplay();
break;
case 'f':
DoFeedback();
glutPostRedisplay();
break;
case 'l':
linePoly = !linePoly;
if (linePoly) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
} else {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
glutPostRedisplay();
break;
case 27:
exit(0);
}
}
static void SpecialKey(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_LEFT:
zRotation += 0.5;
glutPostRedisplay();
break;
case GLUT_KEY_RIGHT:
zRotation -= 0.5;
glutPostRedisplay();
break;
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow("Select Test");
Init();
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutSpecialFunc(SpecialKey);
glutMouseFunc(Mouse);
glutDisplayFunc(Draw);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}
That program is a part of some other GLUT examples.
The GL selection buffer is old and busted though, you're probably better off using color-readback selection or some CPU-side "ray casting" system that integrates with your geometry representation.
Read up on OpenGL's selection feature. That is the classical way of doing it, and should work well for at least small amount of object (which sounds right for your question).
Not a complete example, but there's also a section on the OpenGL FAQ on Picking and Selection which should be noted.

Resources