Built in Function to Draw Circle in Opengl
Section 3.1
Shapes and Colors in OpenGL 1.1
This section introduces some of the cadre features of OpenGL. Much of the discussion in this section is express to 2nd. For now, all you demand to know about 3D is that it adds a third direction to the x and y directions that are used in 2D. Past convention, the third direction is chosenz. In the default coordinate system, the 10 and y axes lie in the airplane of the image, and the positive management of the z-axis points in a direction perpendicular to the image.
In the default coordinate arrangement for OpenGL, the image shows a region of 3D space in which ten, y, and z all range from minus one to i. To bear witness a different region, you lot take to utilise a transform. For now, we will just utilise coordinates that prevarication betwixt -1 and 1.
A note about programming: OpenGL tin can be implemented in many dissimilar programming languages, just the API specification more or less assumes that the linguistic communication is C. (See Department A.2 for a short introduction to C.) For the virtually function, the C specification translates directly into other languages. The master differences are due to the special characteristics of arrays in the C language. My examples volition follow the C syntax, with a few notes most how things can be dissimilar in other languages. Since I'one thousand post-obit the C API, I will refer to "functions" rather than "subroutines" or "methods." Section 3.half dozen explains in detail how to write OpenGL programs in C and in Java. You lot will demand to consult that department before you tin can practise any actual programming. The alive OpenGL 1.1 demos for this book are written using a JavaScript simulator that implements a subset of OpenGL 1.1. That simulator is discussed in Subsection iii.6.3.
3.ane.1 OpenGL Primitives
OpenGL tin can draw only a few bones shapes, including points, lines, and triangles. At that place is no built-in back up for curves or curved surfaces; they must exist approximated past simpler shapes. The basic shapes are referred to every bit primitives. A primitive in OpenGL is defined past its vertices. A vertex is simply a point in 3D, given by its x, y, and z coordinates. Permit'due south spring right in and come across how to describe a triangle. Information technology takes a few steps:
glBegin(GL_TRIANGLES); glVertex2f( -0.seven, -0.5 ); glVertex2f( 0.7, -0.5 ); glVertex2f( 0, 0.seven ); glEnd();
Each vertex of the triangle is specified by a call to the part glVertex2f. Vertices must be specified between calls to glBegin and glEnd. The parameter to glBegin tells which type of primitive is being drawn. The GL_TRIANGLES primitive allows you to depict more one triangle: Just specify 3 vertices for each triangle that y'all want to draw. Annotation that using glBegin/glEnd is not the preferred way to specify primitives, even in OpenGL 1.1. However, the alternative, which is covered in Subsection iii.4.two, is more than complicated to utilise. You should consider glBegin/glEnd to be a convenient way to acquire nigh vertices and their properties, but not the way that yous will actually do things in mod graphics APIs.
(I should annotation that OpenGL functions actually just send commands to the GPU. OpenGL tin can save up batches of commands to transmit together, and the drawing won't really exist washed until the commands are transmitted. To ensure that that happens, the function glFlush() must be called. In some cases, this function might be chosen automatically by an OpenGL API, simply you might well come across times when you have to call it yourself.)
For OpenGL, vertices accept iii coordinates. The function glVertex2f specifies the x and y coordinates of the vertex, and the z coordinate is ready to naught. There is also a office glVertex3f that specifies all three coordinates. The "two" or "3" in the name tells how many parameters are passed to the part. The "f" at the terminate of the name indicates that the parameters are of type bladder. In fact, at that place are other "glVertex" functions, including versions that take parameters of type int or double, with named like glVertex2i and glVertex3d. At that place are even versions that take iv parameters, although it won't be clear for a while why they should exist. And, as we will run into later, at that place are versions that take an assortment of numbers instead of individual numbers as parameters. The unabridged set of vertex functions is often referred to as "glVertex*", with the "*" standing in for the parameter specification. (The proliferation of names is due to the fact that the C programming language doesn't support overloading of role names; that is, C distinguishes functions only by their names and not by the number and type of parameters that are passed to the function.)
OpenGL ane.1 has ten kinds of archaic. Seven of them notwithstanding exist in modern OpenGL; the other 3 have been dropped. The simplest archaic is GL_POINTS, which simply renders a point at each vertex of the primitive. Past default, a point is rendered every bit a single pixel. The size of bespeak primitives tin be changed by calling
glPointSize(size);
where the parameter, size, is of blazon bladder and specifies the bore of the rendered point, in pixels. By default, points are squares. You lot can become circular points by calling
glEnable(GL_POINT_SMOOTH);
The functions glPointSize and glEnable change the OpenGL "state." The state includes all the settings that affect rendering. We volition encounter many state-irresolute functions. The functions glEnable and glDisable can be used to plough many features on and off. In full general, the dominion is that whatever rendering feature that requires extra computation is turned off by default. If you want that characteristic, you have to plough it on by calling glEnable with the appropriate parameter.
There are iii primitives for drawing line segments: GL_LINES, GL_LINE_STRIP, and GL_LINE_LOOP. GL_LINES draws disconnected line segments; specify ii vertices for each segment that you lot want to draw. The other 2 primitives depict continued sequences of line segments. The only difference is that GL_LINE_LOOP adds an actress line segment from the final vertex dorsum to the first vertex. Here is what y'all become if use the same half dozen vertices with the four primitives we accept seen so far:
The points A, B, C, D, Eastward, and F were specified in that order. In this illustration, all the points lie in the same plane, but keep in mind that in full general, points tin can be anywhere in 3D infinite.
The width for line primitives tin can exist set by calling glLineWidth(width). The line width is ever specified in pixels. Information technology is non subject to scaling past transformations.
Let'due south look at an example. OpenGL does not take a circle primitive, simply we tin gauge a circle by drawing a polygon with a large number of sides. To draw an outline of the polygon, nosotros tin can apply a GL_LINE_LOOP primitive:
glBegin( GL_LINE_LOOP ); for (i = 0; i < 64; i++) { angle = vi.2832 * i / 64; // half dozen.2832 represents 2*PI 10 = 0.5 * cos(angle); y = 0.five * sin(angle); glVertex2f( x, y ); } glEnd();
This draws an approximation for the circumference of a circle of radius 0.5 with center at (0,0). Remember that to learn how to use examples similar this one in a complete, running program, you will have to read Department iii.vi. Also, you might have to make some changes to the code, depending on which OpenGL implementation you are using.
The next set of primitives is for drawing triangles. There are three of them: GL_TRIANGLES, GL_TRIANGLE_STRIP, and GL_TRIANGLE_FAN.
The three triangles on the left make upwards 1 GL_TRIANGLES primitive, with nine vertices. With that primitive, every gear up of three vertices makes a separate triangle. For a GL_TRIANGLE_STRIP primitive, the offset 3 vertices produce a triangle. After that, every new vertex adds another triangle to the strip, connecting the new vertex to the two previous vertices. Two GL_TRIANGLE_FAN primitives are shown on the correct. Again for a GL_TRIANGLE_FAN, the outset three vertices make a triangle, and every vertex after that adds anther triangle, just in this instance, the new triangle is made by connecting the new vertex to the previous vertex and to the very start vertex that was specified (vertex "A" in the picture). Note that Gl_TRIANGLE_FAN can exist used for cartoon filled-in polygons. In this flick, by the fashion, the dots and lines are not part of the archaic; OpenGL would but draw the filled-in, green interiors of the figures.
The three remaining primitives, which accept been removed from modern OpenGL, are GL_QUADS, GL_QUAD_STRIP, and GL_POLYGON. The name "quad" is short for quadrilateral, that is, a four-sided polygon. A quad is determined by iv vertices. In gild for a quad to be rendered correctly in OpenGL, all vertices of the quad must lie in the same airplane. The aforementioned is true for polygon primitives. Similarly, to be rendered correctly, quads and polygons must be convex (encounter Subsection 2.2.3). Since OpenGL doesn't bank check whether these conditions are satisfied, the use of quads and polygons is mistake-prone. Since the same shapes can easily be produced with the triangle primitives, they are not really necessary, merely here for the record are some examples:
The vertices for these primitives are specified in the order A, B, C, .... Note how the order differs for the two quad primitives: For GL_QUADS, the vertices for each private quad should be specified in counterclockwise order around the quad; for GL_QUAD_STRIP, the vertices should alternate from 1 side of the strip to the other.
3.1.2 OpenGL Color
OpenGL has a large collection of functions that tin exist used to specify colors for the geometry that we describe. These functions have names of the form glColor*, where the "*" stands for a suffix that gives the number and type of the parameters. I should warn you lot now that for realistic 3D graphics, OpenGL has a more than complicated notion of colour that uses a unlike set of functions. You will learn well-nigh that in the next affiliate, simply for now we will stick to glColor*.
For example, the function glColor3f has iii parameters of blazon bladder. The parameters give the red, green, and blue components of the color as numbers in the range 0.0 to 1.0. (In fact, values exterior this range are allowed, even negative values. When colour values are used in computations, out-of-range values volition exist used every bit given. When a color actually appears on the screen, its component values are clamped to the range 0 to 1. That is, values less than zero are changed to zero, and values greater than one are changed to one.)
You tin add a fourth component to the color by using glColor4f(). The fourth component, known as blastoff, is not used in the default drawing fashion, but it is possible to configure OpenGL to apply it as the degree of transparency of the color, similarly to the use of the alpha component in the 2d graphics APIs that we have looked at. Yous need two commands to turn on transparency:
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
The first control enables use of the alpha component. It tin can be disabled past calling glDisable(GL_BLEND). When the GL_BLEND option is disabled, alpha is just ignored. The second command tells how the blastoff component of a color volition be used. The parameters shown hither are the virtually common; they implement transparency in the usual manner. I should note that while transparency works fine in 2nd, it is much more difficult to employ transparency correctly in 3D.
If you would like to use integer color values in the range 0 to 255, you can employ glColor3ub() or glColor4ub to set the color. In these office names, "ub" stands for "unsigned byte." Unsigned byte is an eight-bit data type with values in the range 0 to 255. Here are some examples of commands for setting drawing colors in OpenGL:
glColor3f(0,0,0); // Describe in blackness. glColor3f(1,1,1); // Describe in white. glColor3f(1,0,0); // Draw in full-intensity ruddy. glColor3ub(1,0,0); // Describe in a colour just a tiny bit unlike from // black. (The suffix, "ub" or "f", is important!) glColor3ub(255,0,0); // Depict in total-intensity red. glColor4f(1, 0, 0, 0.5); // Draw in transparent red, only only if OpenGL // has been configured to practise transparency. By // default this is the same as cartoon in plain reddish.
Using whatever of these functions sets the value of a "current color," which is part of the OpenGL country. When you generate a vertex with one of the glVertex* functions, the electric current color is saved along with the vertex coordinates, as an aspect of the vertex. We will meet that vertices can have other kinds of attribute besides as color. One interesting bespeak most OpenGL is that colors are associated with individual vertices, not with complete shapes. Past irresolute the electric current colour between calls to glBegin() and glEnd(), yous can get a shape in which different vertices have different color attributes. When you exercise this, OpenGL will compute the colors of pixels inside the shape by interpolating the colors of the vertices. (Over again, since OpenGL is extremely configurable, I have to note that interpolation of colors is but the default behavior.) For example, here is a triangle in which the iii vertices are assigned the colors ruby, green, and blue:
This prototype is oft used equally a kind of "Hello World" example for OpenGL. The triangle tin can be drawn with the commands
glBegin(GL_TRIANGLES); glColor3f( 1, 0, 0 ); // ruddy glVertex2f( -0.viii, -0.viii ); glColor3f( 0, 1, 0 ); // dark-green glVertex2f( 0.8, -0.8 ); glColor3f( 0, 0, 1 ); // blue glVertex2f( 0, 0.9 ); glEnd();
Note that when drawing a primitive, you do not need to explicitly set a color for each vertex, equally was washed here. If you want a shape that is all one colour, yous simply accept to fix the electric current color once, before cartoon the shape (or merely afterward the phone call to glBegin(). For example, we tin draw a solid yellow triangle with
glColor3ub(255,255,0); // yellow glBegin(GL_TRIANGLES); glVertex2f( -0.5, -0.5 ); glVertex2f( 0.v, -0.5 ); glVertex2f( 0, 0.5 ); glEnd();
Also remember that the color for a vertex is specified before the phone call to glVertex* that generates the vertex.
Hither is an interactive demo that draws the basic OpenGL triangle, with different colored vertices. You tin command the colors of the vertices to come across how the interpolated colors in the interior of the triangle are affected. This is our first OpenGL example. The demo actually uses WebGL, so you tin use it every bit a examination to check whether your spider web browser supports WebGL.
The sample program jogl/FirstTriangle.java draws the basic OpenGL triangle using Java. The program glut/first-triangle.c does the aforementioned using the C programming language. And glsim/first-triangle.html is a version that uses my JavaScript simulator, which implements just the parts of OpenGL 1.1 that are covered in this book. Whatever of those programs could be used to experiment with second drawing in OpenGL. And yous tin use them to test your OpenGL programming surroundings.
A common operation is to clear the drawing surface area by filling it with some background color. It is be possible to do that by drawing a big colored rectangle, but OpenGL has a potentially more than efficient fashion to practice information technology. The function
glClearColor(r,g,b,a);
sets up a color to be used for clearing the cartoon surface area. (This only sets the color; the color isn't used until you actually give the command to clear the drawing area.) The parameters are floating point values in the range 0 to one. There are no variants of this function; you must provide all iv color components, and they must exist in the range 0 to ane. The default clear color is all zeros, that is, blackness with an alpha component also equal to zero. The command to do the actual clearing is:
glClear( GL_COLOR_BUFFER_BIT );
The correct term for what I accept been calling the cartoon area is the colour buffer, where "buffer" is a full general term referring to a region in memory. OpenGL uses several buffers in addition to the color buffer. We will meet the "depth buffer" in just a moment. The glClear command can exist used to clear several unlike buffers at the same time, which tin be more than efficient than clearing them separately since the clearing tin can be done in parallel. The parameter to glClear tells information technology which buffer or buffers to clear. To clear several buffers at once, combine the constants that represent them with an arithmetics OR operation. For example,
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
This is the form of glClear that is generally used in 3D graphics, where the depth buffer plays an essential part. For 2nd graphics, the depth buffer is generally not used, and the appropriate parameter for glClear is just GL_COLOR_BUFFER_BIT.
3.1.3 glColor and glVertex with Arrays
We take run across that there are versions of glColor* and glVertex* that accept different numbers and types of parameters. There are also versions that permit you place all the data for the command in a unmarried assortment parameter. The names for such versions end with "v". For case: glColor3fv, glVertex2iv, glColor4ubv, and glVertex3dv. The "v" really stands for "vector," significant essentially a one-dimensional array of numbers. For example, in the part call glVertex3fv(coords), coords would be an array containing at to the lowest degree iii floating betoken numbers.
The being of assortment parameters in OpenGL forces some differences between OpenGL implementations in different programming languages. Arrays in Java are different from arrays in C, and arrays in JavaScript are dissimilar from both. Let'south expect at the state of affairs in C first, since that's the language of the original OpenGL API.
In C, assortment variables are a sort of variation on arrow variables, and arrays and pointers tin be used interchangeably in many circumstances. In fact, in the C API, array parameters are actually specified as pointers. For example, the parameter for glVertex3fv is of blazon "pointer to float." The bodily parameter in a call to glVertex3fv can be an array variable, just information technology can also exist any pointer that points to the commencement of a sequence of iii floats. As an instance, suppose that we desire to depict a foursquare. We need two coordinates for each vertex of the square. In C, we can put all 8 coordinates into 1 assortment and use glVertex2fv to pull out the coordinates that we need:
float coords[] = { -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.five, 0.5 }; glBegin(GL_TRIANGLE_FAN); glVertex2fv(coords); // Uses coords[0] and coords[1]. glVertex2fv(coords + 2); // Uses coords[2] and coords[3]. glVertex2fv(coords + 4); // Uses coords[4] and coords[5]. glVertex2fv(coords + 6); // Uses coords[6] and coords[vii]. glEnd();
This example uses "pointer arithmetic," in which coords + N represents a pointer to the Northward-thursday element of the assortment. An culling note would exist &coords[N], where "&" is the address operator, and &coords[N] means "a arrow to coords[N]". This will all seem very conflicting to people who are simply familiar with Java or JavaScript. In my examples, I will avoid using pointer arithmetic, simply I will occasionally use address operators.
As for Java, the people who designed JOGL wanted to preserve the ability to pull data out of the eye of an array. Nevertheless, it's not possible to work with pointers in Coffee. The solution was to replace a pointer parameter in the C API with a pair of parameters in the JOGL API—one parameter to specify the array that contains the data and one to specify the starting index of the data in the array. For case, here is how the foursquare-drawing code translates into Coffee:
float[] coords = { -0.5F, -0.5F, 0.5F, -0.5F, 0.5F, 0.5F, -0.5F, 0.5F }; gl2.glBegin(GL2.GL_TRIANGLES); gl2.glVertex2fv(coords, 0); // Uses coords[0] and coords[one]. gl2.glVertex2fv(coords, two); // Uses coords[2] and coords[iii]. gl2.glVertex2fv(coords, 4); // Uses coords[4] and coords[v]. gl2.glVertex2fv(coords, 6); // Uses coords[six] and coords[seven]. gl2.glEnd();
There is really not much difference in the parameters, although the nada in the offset glVertex2fv is a little abrasive. The main difference is the prefixes "gl2" and "GL2", which are required past the object-oriented nature of the JOGL API. I won't say more near JOGL hither, but if y'all need to translate my examples into JOGL, yous should keep in mind the extra parameter that is required when working with arrays.
For the record, here are the glVertex* and glColor* functions that I will use in this book. This is not the complete set that is available in OpenGL:
glVertex2f( x, y ); glVertex2fv( xyArray ); glVertex2d( x, y ); glVertex2dv( xyArray ); glVertex2i( x, y ); glVertex2iv( xyArray ); glVertex3f( x, y, z ); glVertex3fv( xyzArray ); glVertex3d( 10, y, z ); glVertex3dv( xyzArray ); glVertex3i( x, y, z ); glVertex3iv( xyzArray ); glColor3f( r, g, b ); glColor3f( rgbArray ); glColor3d( r, g, b ); glColor3d( rgbArray ); glColor3ub( r, g, b ); glColor3ub( rgbArray ); glColor4f( r, g, b, a); glColor4f( rgbaArray ); glColor4d( r, g, b, a); glColor4d( rgbaArray ); glColor4ub( r, g, b, a); glColor4ub( rgbaArray );
For glColor*, continue in heed that the "ub" variations require integers in the range 0 to 255, while the "f" and "d" variations require floating-point numbers in the range 0.0 to 1.0.
3.ane.iv The Depth Test
An obvious signal well-nigh viewing in 3D is that one object can be behind another object. When this happens, the back object is hidden from the viewer by the front object. When we create an image of a 3D globe, we have to make certain that objects that are supposed to be hidden behind other objects are in fact not visible in the paradigm. This is the hidden surface problem.
The solution might seem simple enough: Simply draw the objects in gild from back to front. If one object is behind another, the back object will be covered up later when the forepart object is drawn. This is called the painter's algorithm. It's essentially what you are used to doing in 2D. Unfortunately, it's not so easy to implement. First of all, you tin can have objects that intersect, then that part of each object is subconscious by the other. Whatever order you draw the objects in, there will be some points where the wrong object is visible. To fix this, you would take to cutting the objects into pieces, along the intersection, and treat the pieces equally separate objects. In fact, there can be issues fifty-fifty if at that place are no intersecting objects: It'due south possible to have three non-intersecting objects where the first object hides office of the second, the 2d hides part of the third, and the third hides part of the get-go. The painter's algorithm will fail regardless of the social club in which the iii objects are drawn. The solution again is to cut the objects into pieces, but now information technology's not so obvious where to cutting.
Fifty-fifty though these bug tin be solved, there is another issue. The right cartoon order tin can alter when the point of view is changed or when a geometric transformation is practical, which ways that the right cartoon order has to be recomputed every time that happens. In an animation, that would mean for every frame.
So, OpenGL does not utilise the painter's algorithm. Instead, it uses a technique chosen the depth exam. The depth test solves the hidden surface problem no matter what order the objects are drawn in, so you can describe them in any club you want! The term "depth" here has to do with the altitude from the viewer to the object. Objects at greater depth are further from the viewer. An object with smaller depth will hide an object with greater depth. To implement the depth examination algorithm, OpenGL stores a depth value for each pixel in the epitome. The extra memory that is used to store these depth values makes up the depth buffer that I mentioned earlier. During the cartoon procedure, the depth buffer is used to keep track of what is currently visible at each pixel. When a second object is fatigued at that pixel, the information in the depth buffer can be used to decide whether the new object is in forepart of or behind the object that is currently visible there. If the new object is in front end, and so the color of the pixel is changed to show the new object, and the depth buffer is also updated. If the new object is behind the current object, then the data for the new object is discarded and the color and depth buffers are left unchanged.
By default, the depth test is not turned on, which tin can pb to very bad results when drawing in 3D. Yous tin enable the depth test past calling
glEnable( GL_DEPTH_TEST );
It can be turned off by calling glDisable(GL_DEPTH_TEST). If you forget to enable the depth test when drawing in 3D, the image that yous go will likely exist confusing and will make no sense physically. You lot can also go quite a mess if you forget to clear the depth buffer, using the glClear command shown earlier in this section, at the aforementioned time that y'all clear the color buffer.
Here is a demo that lets you experiment with the depth test. Information technology besides lets yous encounter what happens when office of your geometry extends exterior the visible range of z-values.
Here are are a few details about the implementation of the depth examination: For each pixel, the depth buffer stores a representation of the distance from the viewer to the betoken that is currently visible at that pixel. This value is essentially the z-coordinate of the point, after any transformations have been practical. (In fact, the depth buffer is often called the "z-buffer".) The range of possible z-coordinates is scaled to the range 0 to 1. The fact that there is merely a limited range of depth buffer values means that OpenGL tin can only display objects in a express range of distances from the viewer. A depth value of 0 corresponds to the minimal distance; a depth value of 1 corresponds to the maximal distance. When yous clear the depth buffer, every depth value is set to ane, which can be thought of as representing the background of the image.
You go to choose the range of z-values that is visible in the image, past the transformations that you apply. The default range, in the absence of any transformations, is -1 to 1. Points with z-values outside the range are not visible in the image. It is a common problem to use too minor a range of z-values, so that objects are missing from the scene, or have their fronts or backs cutting off, because they prevarication outside of the visible range. You might be tempted to use a huge range, to brand sure that the objects that you desire to include in the image are included within the range. However, that's not a good idea: The depth buffer has a limited number of bits per pixel and therefore a limited amount of accuracy. The larger the range of values that it must stand for, the harder it is to distinguish between objects that are almost at the aforementioned depth. (Think about what would happen if all objects in your scene have depth values between 0.499999 and 0.500001—the depth buffer might see them all as being at exactly the aforementioned depth!)
In that location is another event with the depth buffer algorithm. It can give some foreign results when two objects have exactly the same depth value. Logically, information technology's not fifty-fifty clear which object should be visible, but the real problem with the depth test is that it might prove i object at some points and the second object at some other points. This is possible because numerical calculations are not perfectly accurate. Hither an bodily example:
In the 2 pictures shown hither, a gray square was fatigued, followed by a white square, followed past a black square. The squares all lie in the same aeroplane. A very small rotation was applied, to force the reckoner exercise some calculations before drawing the objects. The picture show on the left was drawn with the depth test disabled, so that, for instance, when a pixel of the white foursquare was drawn, the calculator didn't try to figure out whether it lies in front end of or backside the grey square; it merely colored the pixel white. On the right, the depth test was enabled, and you lot can meet the foreign result.
Finally, by the way, notation that the give-and-take here assumes that at that place are no transparent objects. Unfortunately, the depth exam does not handle transparency correctly, since transparency ways that ii or more than objects can contribute to the color of the pixel, just the depth test assumes that the pixel color is the color of the object nearest to the viewer at that point. To handle 3D transparency correctly in OpenGL, you pretty much take to resort to implementing the painter's algorithm past hand, at least for the transparent objects in the scene.
Source: https://math.hws.edu/graphicsbook/c3/s1.html
Post a Comment for "Built in Function to Draw Circle in Opengl"