How to Improve Accuracy of Iteration? - c++

I'm trying to make code, c++, to plot the Mandlebrot Set. However, whenever I run my code, see below, the convergence is poor. How do I fix that? I provided some code below. There's also a screenshot of the Mandelbrot Set, red, and my code's approximation, greyscale.
#include <GL/glut.h>
void renderscene(void) {
double x=0;
double y=0;
double ix=0;
double iy=0;
int n=1;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for(x=-3;x<3;x=x+0.01){
for(y=-3;y<3;y=y+0.01){
for(n=1;n<50;n=n+1){
ix=ix*ix-iy*iy+x;
iy=2*iy*ix+y;
if(ix*ix+iy*iy>4){
break;
}
}
ix=0;
iy=0;
glPointSize(1);
glColor3f(0.1*n,0.1*n,0.1*n);
glBegin(GL_POINTS);
glVertex2f(x*0.4,y*0.4);
glEnd();
}
}
glutSwapBuffers();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGBA);
glutInitWindowPosition(300,200);
glutInitWindowSize(500,500);
glutCreateWindow("Hello");
glutDisplayFunc(renderscene);
glutMainLoop();
return 1;
}

You are using the wrong ix in the computation of the new iy.
Try
double nextix=ix*ix-iy*iy+x;
iy=2*iy*ix+y;
ix = nextix;

Related

OpenGL: Bresenham's Line Drawing Algorithm Implementation

I've been trying to generate a line using Bresenham's Algorithm (Yes, I know in built functions exist, but this is something I've been asked to implement) using the following code.
But for some reason, I am not being able to see the line on the window. I just get an empty window.
I initially tried drawing points with SetPixel() but I was short of 2 arguments(HDC and COLORREF) apart from just the X and Y coordinates. I don't know what the other 2 arguments do, so I had to try something else.
So I used a solution I found here on StackOverflow to generate the point. Though I do not get any compilation error or warnings, the code just doesn't seem to work. How about you try looking for the problem:
#include<iostream>
#include<GL/glut.h>
#include<stdlib.h>
#include<math.h>
using namespace std;
int x00;
int y00;
int xEnd;
int yEnd;
void init(){
glClearColor(1,0,0,0);
glMatrixMode( GL_PROJECTION );
gluOrtho2D(0,500,0,500);
}
void bres()
{
int dx = fabs(xEnd - x00), dy = fabs(yEnd - y00);
int p = 2*dy-dx;
int x, y;
if(x00>xEnd){
x=xEnd;
y=yEnd;
xEnd=x00;
}
else{
x=x00;
y=y00;
}
//Stack Overflow Solution to generate a point:
glBegin(GL_POINTS);
glColor3f(0,0,0);
glVertex2i(x,y);
glEnd();
while(x<xEnd){
x++;
if(p<0){
p = p + 2*dy;
}
else{
y++;
p= p + 2*dy - 2*dx;
}
glBegin(GL_POINTS);
glColor3f(0,0,0);
glVertex2i(x,y);
glEnd();
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
bres();
glFlush();
}
int main(int argc, char* argv[])
{
cout<<"Enter the co ordinates for 2 points: ";
cin>>x00>>y00>>xEnd>>yEnd;
glutInit(&argc, argv);
glutInitWindowSize(600,600);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Bresenham's Algo");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Since you are using a double buffered window
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
you have to call glutSwapBuffers instead of glFlush.
If you would use a single buffered window
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
then glFlush would work.
Change your code somehow like this:
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
bres();
//glFlush();
glutSwapBuffers();
}

plotting points in opengl

I am trying to print some points on the window and nothing is getting displayed on the window.The window background is set to grey color and that is all that happens.No points appear on the screen.here is my code
#include <GL/freeglut.h>
#include <GL/gl.h>
#include<unistd.h>
#include<iostream>
using namespace std;
float a[2]={0,0.7},b[2]={-0.3,-0.5},c[2]={0.5,-0.55};
float m[2]={0.0,0.0};
int roll_die() {
int k= (rand()%6) + 1;
return k;
}
void midpoint(float p[],float q[],float *k )
{
for(int i=0;i<2;i++)
{
k[i]=(p[i]+q[i])/2;
}
}
void displaypoint(float a[])
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
glBegin(GL_POINT);
glVertex2f(a[0], a[1]);
glEnd();
glPointSize(8.0);
glFlush();
}
void setup()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_POINTS);
glVertex2f(a[0], a[1]);
glVertex2f(b[0],b[1]);
glVertex2f(c[0],c[1]);
glEnd();
glPointSize(8.0);
glFlush();
}
void chaos()
{
int num;
for(int i=0;i<1000;i++)
{
num=roll_die();
if(num==1 || num==2)
midpoint(m,a,m);
else if(num==3 || num==4)
midpoint(m,b,m);
else
midpoint(m,c,m);
displaypoint(m);
usleep(2000);
}
}
int main(int argc, char **argv)
{
int num;
float a[2]={0,0.7},b[2]={-0.3,-0.5},c[2]={0.5,-0.55};
float m[2]={0.0,0.0};
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("OpenGL - Creating a triangle");
glClearColor(0.4, 0.4, 0.4, 0.4);
glutDisplayFunc(setup);
glutDisplayFunc(chaos);
glutMainLoop();
return 0;
}
There were several problems. To find them I just compiled it myself and worked through them:
GL_POINT should be GL_POINTS in displaypoint. GL_POINT means something else entirely -- you still use GL_POINTS even if you only display one point
You were clearing each time you drew a point, so you would only ever see one point (but the point wasn't drawing in the first place due to the above). Only clear when you want to wipe the whole screen.
I've not used glut so I'm not positive, but it looks like you immediately overrode the displayFunc callback with chaos, so I don't think setup was ever called. I just pushed setup into the beginning of your chaos loop.
You defined your arrays again in main -- it doesn't matter, but those were not being used. Only the global ones were used. I recommend adding -Wall to your compiler flags if you haven't already, as the compiler would have told you this :)
Really the point of failure was that you were clearing each time you drew a point while also not actually drawing that point due to the use of GL_POINT.
Since you're new to GL, I'll mention that glGetError() is extremely useful as a first-pass debugging mechanism. You can call it and check the return value at various points in your program to see if GL is telling you that you've done something wrong. In this case, for example, calling glGetError() after your drawpoint function would have returned the error GL_INVALID_ENUM, because you used an invalid enum value (GL_POINT rather than GL_POINTS) for your call to glBegin().
Here is a working example for you in case it helps. I hope you don't mind that I reformatted & compacted it to make it easier to share here (and some was to help me read and understand it). That's a neat program, I had no idea it was going to output what it did when I got it working. Cool :)
#include <GL/freeglut.h>
#include <GL/gl.h>
#include <unistd.h>
float a[2] = { 0.0f, 0.70f };
float b[2] = { -0.3f, -0.50f };
float c[2] = { 0.5f, -0.55f };
float m[2] = { 0.0f, 0.00f };
void midpoint(float p[], float q[], float* k) {
for (int i = 0; i < 2; i++)
k[i] = (p[i] + q[i]) / 2;
}
void chaos() {
glPointSize(1.0);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
for(int i = 0; i < 100000; i++) {
int num = (rand() % 6) + 1;
if (num < 3)
midpoint(m, a, m);
else if (num < 5)
midpoint(m, b, m);
else
midpoint(m, c, m);
glBegin(GL_POINTS);
glVertex2f(m[0], m[1]);
glEnd();
glFlush();
}
}
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("OpenGL - Creating a triangle");
glutDisplayFunc(chaos);
glutMainLoop();
return 0;
}
Output:
Let me know if anything doesn't make sense.

OpenGL drawing a grid

Im new in OpenGL and im trying to make a 12x15 grid, so it appears something like an array but still a grid. I have this code so far:
#include <windows.h>
#include <GL/glut.h>
void display(){
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
// Horizontal lines.
for (int i=0; i<=12; i++) {
glVertex2f(0, i);
glVertex2f(15, i);
}
// Vertical lines.
for (int i=0; i<=15; i++) {
glVertex2f(i, 0);
glVertex2f(i, 12);
}
glEnd();
glFlush();
}
void handleKeypress(unsigned char key, int x, int y){
switch (key){
case 27: //Escape key
exit(0);
}
}
main(int argc, char** argv){
glutInit(&argc, argv);
glutCreateWindow("Grid Test");
glutInitWindowSize(600, 480);
glutInitWindowPosition(100, 100);
glutDisplayFunc(display);
glutKeyboardFunc(handleKeypress);
glutMainLoop();
}
and yet the program window has this:
test grid
What is the mistake I made? Should I write a function for the grid drawing out of the display function?
When no projection or other transformation is applied, the visible coordinates range from -1 to 1 on each axis. What you see is the lower left part starting from (0,0). If you want to see the whole grid, you will have to set transformation matrices to get it where you want.

Why is my OpenGL code not working

I'm a complete novice in OpenGL and have started following a book on this topic. The first program that they demonstrate is the Sierpinski Gasket program. Here's what the code looks like in the book:
#include<GL/glut.h>
#include<stdlib.h>
void myinit()
{
//attributes
glClearColor(1.0,1.0,1.0,1.0);
glColor3f(1.0,0.0,0.0); //draw in red
//set up viewing
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,50.0,0.0,50.0);
glMatrixMode(GL_MODELVIEW);
}
void display()
{
GLfloat vertices[3][2]={{0.0,0.0},{25.0,50.0},{50.0,0.0}}; //triangle
GLfloat p[2]={7.5,5.0}; //arbitrary point
glClear(GL_COLOR_BUFFER_BIT); //clear the window
glBegin(GL_POINTS);
//Gasket Program
for(int i=0;i<5000;i++){
int j=rand()%3;
//compute points halfway between random vertex and arbitrary point
p[0]=(vertices[j][0]+p[0])/2;
p[1]=(vertices[j][1]+p[1])/2;
//plot the point
glVertex2fv(p);
}
glEnd();
glFlush();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(500,500);
glutInitWindowPosition(0,0);
glutCreateWindow("Sierpinski Gasket");
glutDisplayFunc(display);
myinit();
glutMainLoop();
return 0;
}
However, when I compile the program it only displays a window completely filled with white and nothing else. Why isn't the above code working the way it should?
Swap glFlush() for glutSwapBuffers():
#include<GL/glut.h>
void display()
{
glClearColor(1.0,1.0,1.0,1.0);
glClear(GL_COLOR_BUFFER_BIT); //clear the window
//set up viewing
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,50.0,0.0,50.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat vertices[3][2]={{0.0,0.0},{25.0,50.0},{50.0,0.0}}; //triangle
GLfloat p[2]={7.5,5.0}; //arbitrary point
glColor3f(1.0,0.0,0.0); //draw in red
glBegin(GL_POINTS);
//Gasket Program
for(int i=0;i<5000;i++)
{
int j=rand()%3;
//compute points halfway between random vertex and arbitrary point
p[0]=(vertices[j][0]+p[0])/2;
p[1]=(vertices[j][1]+p[1])/2;
//plot the point
glVertex2fv(p);
}
glEnd();
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(500,500);
glutCreateWindow("Sierpinski Gasket");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
glFlush() won't actually swap the back/front buffers requested by GLUT_DOUBLE. You need glutSwapBuffers() for that.

An OpenGL qeustion:why doesn't glutSwapBuffer() function work?

This code is from the red book, example 2-15 (well, the code is not exactly the one in the book). Take care of the note I noted.
#include <fstream>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>
#pragma comment(lib,"glew32.lib")
using namespace std;
#define BUFFER_OFFSET(offset) ((GLubyte *)NULL+offset)
#define XStart -0.8
#define XEnd 0.8
#define YStart -0.8
#define YEnd 0.8
#define NumXPoints 11
#define NumYPoints 11
#define NumPoints (NumXPoints * NumYPoints)
#define NumPointsPerStrip (2*NumXPoints)
#define NumStrips (NumYPoints-1)
#define RestartIndex 0xffff
void display(void)
{
int i,start;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1,1,1);
glDrawElements(GL_TRIANGLE_STRIP,NumStrips*(NumPointsPerStrip+1),GL_UNSIGNED_SHORT,BUFFER_OFFSET(0));
//glFlush();//it works,show a white square with black backgroud
glutSwapBuffers();///it doesn't work,show what tha area looked like before
}
void init (void)
{
GLuint vbo,ebo;
GLfloat *vertices;
GLushort *indices;
glewInit();
glGenBuffers(1,&vbo);
glBindBuffer(GL_ARRAY_BUFFER,vbo);
glBufferData(GL_ARRAY_BUFFER,2*NumPoints*sizeof(GLfloat),NULL,GL_STATIC_DRAW);
vertices=(GLfloat *)glMapBuffer(GL_ARRAY_BUFFER,GL_WRITE_ONLY);
if(vertices==NULL)
{
fprintf(stderr,"Unable to map vertex buffer\n");
exit(EXIT_FAILURE);
}
else
{
int i,j;
GLfloat dx=(XEnd-XStart)/(NumXPoints-1);
GLfloat dy=(YEnd-YStart)/(NumYPoints-1);
GLfloat *tmp=vertices;
int n=0;
for(j=0;j<NumYPoints;++j)
{
GLfloat y=YStart+j*dy;
for(i=0;i<NumXPoints;++i)
{
GLfloat x=XStart + i*dx;
*tmp++=x;
*tmp++=y;
}
}
glUnmapBuffer(GL_ARRAY_BUFFER);
glVertexPointer(2,GL_FLOAT,0,BUFFER_OFFSET(0));
glEnableClientState(GL_VERTEX_ARRAY);
}
glGenBuffers(1,&ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,NumStrips*(NumPointsPerStrip+1)*sizeof(GLushort),NULL,GL_STATIC_DRAW);
indices=(GLushort *)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER,GL_WRITE_ONLY);
if(indices==NULL)
{
fprintf(stderr,"Unable to map index buffer\n");
exit(EXIT_FAILURE);
}
else
{
int i,j;
GLushort *index=indices;
for(j=0;j<NumStrips;++j)
{
GLushort bottomRow=j*NumYPoints;
GLushort topRow=bottomRow+NumYPoints;
for(i=0;i<NumXPoints;++i)
{
*index++=topRow+i;
*index++=bottomRow+i;
}
*index++=RestartIndex;
}
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
}
glPrimitiveRestartIndex(RestartIndex);
glEnable(GL_PRIMITIVE_RESTART);
}
void reshape (int w, int h)
{
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (-1,1,-1,1);
glViewport (0,0,w,h);
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (200, 200);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc (keyboard);
glutMainLoop();
return 0;
}
as the http://www.opengl.org/resources/libraries/glut/spec3/node21.html says:
An implicit glFlush is done by glutSwapBuffers before it returns. Subsequent OpenGL commands can be issued immediately after calling glutSwapBuffers, but are not executed until the buffer exchange is completed.
If the layer in use is not double buffered, glutSwapBuffers has no effect.
How do I know whether the layer in use is double buffered?give an double buffered example.is this code I wrote is double buffered?
In your main function, you call
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
That needs to be GLUT_DOUBLE. See the documentation for glutInitDisplayMode().