Link to home
Start Free TrialLog in
Avatar of missymadi
missymadi

asked on

How to draw a cardioid in Opengl?

Experts,

        I am learning Opengl and I am looking for an example of how to draw a cardioid curve. I have the formula as f(0) = K(1+cos(0). How do I code this in Opengl to render a cardioid curve?

Thanks, MissyMadi
Avatar of ikework
ikework
Flag of Germany image

Hi MissyMadi,

Where exactly are you stuck?

Do you know how to draw a simple line in OpenGL?


ike
Avatar of missymadi
missymadi

ASKER

Hi ikework

      Yes, here's how I would render a line:

//Draw a triangle to the window
void renderScene(void) {
      glClear(GL_COLOR_BUFFER_BIT);
      glBegin(GL_LINE);
            glVertex3f(1,0,0);
            glVertex3f(0,1,0);
            glVertex3f(0,0,1);
                                           glVertex3f(0,0,0);

      glEnd();
      glFlush();

My whole OpenGL program is below.  I have looked around at some example of the cardioid curve but cannot find the formula to use in the Opengl program.  I'm still very new in learning Opengl, I just learned the viewing volume, gluPerspective, and Matrix mode so that my object would be seen in the viewport. I am still stuggling with matrices and how they are used to draw an object and also  using formulas, such as the  f(0) = K(1+cos(0) to get a cardioid curve to render where I can see it in the viewport. Any help is appreciated!

Missy Madi
}
// Curves.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

// OpenGLProgram.cpp : Defines the entry point for the console application.
//
#include "stdafx.h" //put this first or weird errors occur
#include <stdlib.h>
#include <glut.h>



//Make sure the perspective does not become distorted when the window size is changed
void reshape(int w, int h) {

	// Prevent a divide by zero, when window is too short
	// (you cant make a window of zero width).
	if(h == 0)
		h = 1;

	float ratio = 1.0* w / h;

	// Reset the coordinate system before modifying
	glMatrixMode(GL_PROJECTION); //projection defines the viewing volume. 
	glLoadIdentity(); //load identity matrix to initialize it. 
	
	// Set the viewport to be the entire window
	glViewport(0, 0, w, h); //first two parameters are top r corner. last two are bottom left. Relative to client area of window not screen. 

	// Set the correct perspective.
	gluPerspective(45,ratio,1,1000); //first param. defines field of view angle in yz plane. ratio defines relation between w and h of the viewport.
	                                 //last two define the near and far clipping planes. BEWARE of this setting or the picture may not be drawn to screen. 
	glMatrixMode(GL_MODELVIEW);//current matrix. defines both camera setting and modeling transformations. 
	glLoadIdentity(); //load identity matrix to avoid past transformations to affect the camera settings.
	//set the camera position and orientation.
	gluLookAt//(0.0,0.0,5.0, //camera position
		     (0.5,0.5,2.0,	      0.0,0.0,-1.0, //defines the point we're looking at
			  //0.0f,1.0f,0.0f; //up vector (usually (0.0,1.0, 0.0)- camera not tilted. (turn everything upside down (0.0, -1.0, 0.0) 
              0.0, -1.0, 0.0);

}

//Draw a triangle to the window
void renderScene(void) {
	//glClear(GL_COLOR_BUFFER_BIT); 
	//glBegin(GL_TRIANGLES);
	//	glVertex3f(-0.5,-0.5,0.0);
	//	glVertex3f(0.5,0.0,0.0);
	//	glVertex3f(0.0,0.5,0.0);
	//glEnd();
	//glFlush();

glClear(GL_COLOR_BUFFER_BIT); 
	glBegin(GL_LINES);
		glVertex3f(-0.5,-0.5,0.0); // origin of the FIRST line
        glVertex3f(0.5, 0.0, 0.0); // ending point of the FIRST line
        glVertex3f(0.0, 0.5, 0.0); // origin of the SECOND line
    glEnd();
	glFlush();
}



//main function that performs required initializations and start the event processing loop

void main(int argc, char **argv) { // argc - pointer to the unmodified argc variable, argv - pointer to the unmodified argv variable from main funciton
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA); //mode specifies the display mode of color and buffers
	glutInitWindowPosition(100,100);// x number of pixels from l of screen, y number of pixels from top of screen
	glutInitWindowSize(320,320);  //width of the window, height of window
	glutCreateWindow("OpenGL Template"); //Set window title
	glutDisplayFunc(renderScene);
	glutReshapeFunc(reshape);
	glutMainLoop();
}

Open in new window

I see, so the problem is the formula rather then the rendering.

The formula is actually:

  f(phi) = 2r(1-cos(phi))

Its phi, not zero. phi is the angle. This is the equation for the cardioid in polar-coordinates. Have a look at:

    http://en.wikipedia.org/wiki/Cardioid

There the formula is explained in detail. If you have further questions, feel free to ask more :)
This is where I get confused...actually applying the formula to the get the object rendered. How would I approach to apply this formula?

For example :
void renderScene(void) {
GLfloat phi;                                          // Angle
glBegin(GL_LINES);
for (f(phi) = 2r(1-cos(phi))
glVertex3f( ??)  ***not sure how to continue.....
glEnd();
glFlush();
My concern is that I should be able to construct on graph paper what object/objects (circle, cardioid etc) I want to render then use a matrix to apply transformation, rotation and scaling...I'm not getting how to do this part...  For example, let's say I have cardiod. I draw on graph where I want the cardiod to exisit:
Then maybe glRotate(1.0, 0.0, 0.0) around the X axis. -popmatrix. How would I code this? I have coded where I rendered a pre-existing object in the GLlibrary and called it but not sure how to create my own objects.

Thanks, MissyMadi


There are at least 2 ways. Probably easier to understand is to use the following equation, which is basically the same, but not in polar-coordinates (from the wiki page mentioned above):

    x(t) = 2r * cos(t) * (1-cos(t))
    y(t) = 2r * sin(t) * (1-cos(t))

This way its easier to calculate. "t" is the angle. To render the full cardioid you must use an angle between 0 to 2PI.

Now you calculate the function in descrete steps for "t" and connect the points with lines.

Attached you find the code, feel free to ask if its not clear what it does.
glBegin(GL_LINE_STRIP);
        static const float r = 1.0f;
        static const float pi = 3.1415926535897932384626433832795029f;
        for(float angle = 0.0f; angle < (pi * 2.0f); angle += 0.05f)
        {
            float x = 2.0f * r * cos(angle) * (1.0f - cos(angle));
            float y = 2.0f * r * sin(angle) * (1.0f - cos(angle));
            glVertex3f(x, y, 0.0f);
        }
    glEnd();

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of ikework
ikework
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This is exactly what I needed!! I got everything working! Thanks so much.