Draw doesn't works with OpenGL while drawing sphere - c

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

Related

more than one instance of overloaded function "abs" matches the argument list

The below code is for dynamic sort in visual code but getting an overload in line 116
if ( (abs(initial_x1 - cc2->x) < 0.3 && abs(initial_x2 - cc1->x) < 0.3) ) //set this to speed of animation
**Please note: the same code runs with no error on a mac which I am confused **
I have tried everything adding fabs, labs
according to the research I did but the errors keep piling up
any help will be appreciated
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<glut.h>
#include<conio.h>
#include<string.h>
#define MAX 10
int k = 0;
typedef struct circle
{
GLfloat x; //x axis of center
GLfloat y; //y axis of center
GLfloat r; // radius
}circle;
circle c[MAX]; //array of circles to store the center and radius of each circle
int a[MAX]; // int array for sorting algo
int initial[MAX] = { 10,4,8,6,3,7,9,1,5,2 }; //int array to restore random values after sorting
GLfloat initial_x1, initial_x2; //to set the destiniation for swapping
int global_i = 0, global_j = 0; //i and j values for bubble-sort
int swapping = 0; //flag to check if circle are being swapped
int sorting = 0; //start sorting only after user input
void initialise()
{
global_i = global_j = swapping = 0; //reset all globals
for (int i = 0; i < MAX; i++)
{
a[i] = initial[i]; //if a[] is sorted restore from initial[]
c[i].r = a[i] * 4.0; //4 because to fit 10 circles in screen
c[i].y = 300.0; //vertical center of window
if (i == 0)
c[i].x = 45.0; // first circle starts from 45 offset
else
c[i].x = c[i - 1].x + 90.0;//(c[i-1].r+c[i].r+10.0); //distance between circles = sum of 2 max readii
printf("%f - %f - %f\n", c[i].x, c[i].y, c[i].r); //for testing purpose don worry
}
}
//func to display text on screen char by char
void bitmap_output(int x, int y, const char* string, void* font)
{
int len, i;
glRasterPos2f(x, y);
len = (int)strlen(string);
for (i = 0; i < len; i++) {
glutBitmapCharacter(font, string[i]);
}
}
//function to integer to string
void int_str(int rad, char r[])
{
switch (rad)
{
case 1: strcpy(r, "1"); break;
case 2: strcpy(r, "2"); break;
case 3: strcpy(r, "3"); break;
case 4: strcpy(r, "4"); break;
case 5: strcpy(r, "5"); break;
case 6: strcpy(r, "6"); break;
case 7: strcpy(r, "7"); break;
case 8: strcpy(r, "8"); break;
case 9: strcpy(r, "9"); break;
case 10: strcpy(r, "10"); break;
}
}
//draw circle by drawing consecutive triangle fans
void circle_draw(circle c)
{
float i;
glBegin(GL_TRIANGLE_FAN);
glVertex2f(c.x, c.y); //center of circle
for (i = 0; i < 360; i += 1)
glVertex2f(c.x + sin(i) * c.r, c.y + cos(i) * c.r);
glEnd();
//display the value of circle below
int x = c.x - 2;
int y = c.y - (c.r + 10);
int rad = c.r / 4;
char r[3] = "";
int_str(rad, r);
glColor3f(0.0, 0.0, 0.0);
bitmap_output(x, y, r, GLUT_BITMAP_TIMES_ROMAN_10);
}
// swaps circles cc1 and cc2 by changing their centers
void swap_circles(circle* cc1, circle* cc2)
{
if (swapping == 0) //if circles are not being swapped set destination for each circles
{
initial_x1 = cc1->x; //center of circle in left
initial_x2 = cc2->x; //center of circle in right
swapping = 1; //means cicle are being swapped
printf("%f - %f\n", cc1->r, cc2->r);
}
if (initial_x1 <= cc2->x) //decrease the center of circle in right till its > center of left circle
cc2->x -= 1.0; //speed of animation
if (initial_x2 >= cc1->x)//increase the center of circle in left till its < center of right circle
cc1->x += 1.0;
printf("one %f - %f\n", initial_x1, cc2->x);
printf("two %f - %f\n", initial_x2, cc1->x);
// if difference between destination and center < 0.3 then cicles are swapped
if (abs(initial_x1 - cc2->x) < 0.3 && abs(initial_x2 - cc1->x) < 0.3) //set this to speed of animation
{
swapping = 0;
int temp = cc1->x;
cc1->x = cc2->x;
cc2->x = temp;
temp = cc1->y;
cc1->y = cc2->y;
cc2->y = temp;
temp = cc1->r;
cc1->r = cc2->r;
cc2->r = temp;
}
}
void sort() //bubble sort algo
{
if (!swapping) //if not in process of swappin 2 circles only then get 2 new circles to swap
{
while (global_i < 10)
{
global_j = global_i;
while (global_j < 9)
{
if (a[global_j] > a[global_j + 1])
{
printf("%d %d\n", global_j, a[global_j]);
int temp = a[global_j];
a[global_j] = a[global_j + 1];
a[global_j + 1] = temp;
goto SWAP;
}
global_j++;
}
global_i++;
}
}
SWAP:
printf("swapping --> %d - %d\n", global_j, global_j + 1);
bitmap_output(10, 375, "Swapping ->", GLUT_BITMAP_9_BY_15);
char r[3] = "";
int_str(a[global_j], r);
bitmap_output(150, 375, r, GLUT_BITMAP_9_BY_15);
int_str(a[global_j + 1], r);
bitmap_output(175, 375, r, GLUT_BITMAP_9_BY_15);
swap_circles(&c[global_j], &c[global_j + 1]);
}
void display_text()
{
bitmap_output(200, 565, "DYNAMIC SORTING ALGORITHM VISUALISER", GLUT_BITMAP_TIMES_ROMAN_24);//title larger font
glBegin(GL_LINE_LOOP); //to underline the title
glVertex2f(180, 560);
glVertex2f(750, 560);
glEnd();
//other text small font
bitmap_output(10, 525, "This program sorts a random set of numbers in ascending order displaying them graphically as ", GLUT_BITMAP_9_BY_15);
bitmap_output(10, 505, "circles with varying radii.", GLUT_BITMAP_9_BY_15);
if (sorting == 0)//if not sorting display menu
{
bitmap_output(10, 455, "MENU", GLUT_BITMAP_9_BY_15);
bitmap_output(10, 435, "Press s to SORT", GLUT_BITMAP_9_BY_15);
bitmap_output(10, 415, "Press r to RANDOMISE", GLUT_BITMAP_9_BY_15);
bitmap_output(10, 395, "Esc to QUIT", GLUT_BITMAP_9_BY_15);
}
else if (sorting == 1)
{
glColor3f(0.5, 0.5, 0.5);
bitmap_output(10, 455, "Sorting in progress...", GLUT_BITMAP_9_BY_15);
bitmap_output(10, 435, "Please do not quit", GLUT_BITMAP_9_BY_15);
glColor3f(0.0, 0.0, 0.0);
}
}
void front()
{
glColor3f(0.0, 0.0, 1.0);
bitmap_output(390, 565, "WELCOME!", GLUT_BITMAP_TIMES_ROMAN_24);
glBegin(GL_LINE_LOOP);
glVertex2f(388, 560);
glVertex2f(524, 560);
glEnd();
bitmap_output(440, 535, "TO", GLUT_BITMAP_TIMES_ROMAN_24);
glBegin(GL_LINE_LOOP);
glVertex2f(438, 531);
glVertex2f(475, 531);
glEnd();
bitmap_output(200, 495, "DYNAMIC SORTING ALGORITHM VISUALISER", GLUT_BITMAP_TIMES_ROMAN_24);
glBegin(GL_LINE_LOOP);
glVertex2f(198, 490);
glVertex2f(731, 490);
glEnd();
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_QUADS);
glVertex2f(594, 120.0); glVertex2f(594, 145); glVertex2f(836, 145); glVertex2f(836, 120.0);
glEnd();
glColor3f(0.0, 1.0, 0.0);
bitmap_output(600, 125, "Press Enter to continue.......", GLUT_BITMAP_HELVETICA_18);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
if (k == 0)
front();
else
{
display_text();
glPointSize(2.0);
for (int i = 0; i < MAX; i++)
{
glColor3f(1.0, 0.0, 0.0);
circle_draw(c[i]);
}
if (global_j + 1 < MAX && sorting == 1) // call sort only on key press
sort();
else
sorting = 0;
}
glFlush();
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y)
{
if (key == 13)
k = 1;
if (k == 1)
{
switch (key)
{
case 27: exit(0); //27 is the ascii code for the ESC key
case 's': sorting = 1; break;
case 'r': initialise(); break;
}
}
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-2.0, 2.0, -2.0 * (GLfloat)h / (GLfloat)w, 2.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);
else
glOrtho(-2.0 * (GLfloat)w / (GLfloat)h, 2.0 * (GLfloat)w / (GLfloat)h, -2.0, 2.0, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
}
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 900.0, 0.0, 600.0);
}
void main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition(50, 50);
glutInitWindowSize(900, 600);
glutCreateWindow("Dynamic Sorting Algorithm Visualiser");
init();
initialise();
glutDisplayFunc(display);
glutIdleFunc(display);
glutKeyboardFunc(keyboard);
glutMainLoop();
}
it was as simple as adding "fabs" instead of "abs"
due to the Foat datatype

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

Mandelbrot Set not displayed

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.

Drawing multiple objects in OpenGL using C

I have an OpenGL program to draw a circle by mouse click. The program works fine except when I try to draw multiple circles the previous circle disappears. Here is the code:
#include <GL/glut.h>
#include<math.h>
#include<stdio.h>
struct position
{
float x;
float y;
};
typedef struct position Position;
Position start;
Position finish;
void setPixel(int x, int y)
{
glBegin(GL_POINTS);
glVertex2f(x, y);
glEnd();
}
void circle(int a0, int b0, int a1, int b1)
{
int i, x, y, x1, y1, r, p;
x1 = (a0+a1)/2;
y1 = (b0+b1)/2;
r = sqrt((((a1-x1)*(a1-x1))+((b1-y1)*(b1-y1))));
p = (5/4-r);
x = 0;
y = r;
while(x <= y)
{
setPixel( x+x1, y+y1);
setPixel( x+x1, -y+y1);
setPixel(-x+x1, -y+y1);
setPixel(-x+x1, y+y1);
setPixel( y+x1, x+y1);
setPixel( y+x1, -x+y1);
setPixel(-y+x1, -x+y1);
setPixel(-y+x1, x+y1);
x = x+1;
if (p<0)
p = p+2*x+1;
else {
y = y-1;
p = p+2*x-2*y+1;
}
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glPushMatrix();
circle(start.x, start.y, finish.x, finish.y);
glPopMatrix();
glutSwapBuffers();
}
void reshape( int w, int h)
{
glViewport( 0, 0, w, h);
glMatrixMode( GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, w, h, 0, -1, 1);
}
void mouse(int button, int state, int x, int y)
{
switch(button)
{
case GLUT_LEFT_BUTTON:
if(state == GLUT_DOWN)
{
start.x = x; //x1
start.y = y; //y1
}
if(state == GLUT_UP)
{
finish.x = x; //x2
finish.y = y; //y2
}
break;
glutPostRedisplay();
}
}
void motion( int x, int y)
{
finish.x = x;
finish.y = y;
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(100, 100);
glutCreateWindow("");
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
How can I display multiple images together?
If you want to draw multiple things, then draw multiple things. You're only drawing one circle. If you change the position of that circle, it will just be drawn in a different place.
However I really wouldn't recommend drawing like this in GL. Using the fixed-function pipeline to draw individual pixels as GL_POINTS is exceedingly inefficient. GL is not designed as a raster drawing API.

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

Resources