I've written some articles about iphone OpenGL es programming, but mostly for people who already know at least some 3D programming knowledge. As a starting point, download my OpenGL Xcode project template instead of using apple-provided templates. You can unzip to the following location to install this template: /developer/platforms/iphoneos.platform/developer/library/xcode/project templates/application/There are a lot of good tutorials and books on OpenGL. However, not much is about OpenGL ES, and not (at least when I write this article) is specifically for learning iphone 3D programming. Because most of the material about learning OpenGL starts with the so-called direct mode, and OpenGL ES does not support this mode, it is difficult to use existing books and tutorials for iphone developers without 3D background knowledge. To meet the requirements of some developers, I decided to write a blog series for beginners in 3D. This is the first article in this series. OpenGL data typeThe first thing we want to talk about is the OpenGL data type. Because OpenGL is a cross-platform API, the size of the data type varies depending on the programming language used and the processor (64-bit, 32-bit, 16-bit), so OpenGL defines its own data type. When passing data to OpenGL, you should stick to these OpenGL data types, guaranteeing the correct size and accuracy of the data being passed. Failure to do so can result in unpredictable results or inefficiencies due to data conversion at run time. OpenGL, regardless of platform or language implementation, defines the data type in this way to ensure consistency of the data on each platform and makes it easier to port OpenGL code between platforms. Here are the various data types for OpenGL:
- glenum: Unsigned integer for GL enumeration. Typically used to inform OpenGL of the type of data stored in an array that is passed by the pointer (for example, gl_float is used to indicate that the array consists of glfloat).
- Glboolean: Used for single Boolean values. OpenGL ES also defines its own "true" and "false" values (Gl_true and Gl_false) to avoid platform and language differences. When you pass a Boolean value to OpenGL, use these values instead of Yes or no, even though you accidentally use Yes or no because their definitions actually make no difference. However, it is a good practice to use gl-to define values. )
- Glbitfield: Used to package multiple Boolean values (up to 32) into a single four-byte integer using a bitwise action variable. We will describe the first time we use a bit field variable, see Wikipedia
- glbyte: Signed single-byte integer containing values from 128 to 127
- glshort: Signed Double-byte integer containing values from −32,768 to 32,767
- Glint: Signed four-byte integer containing numeric values from −2,147,483,648 to 2,147,483,647
- Glsizei: Signed four-byte integer that represents the size (in bytes) of the data, similar to the size_t in C
- glubyte: Unsigned single-byte integer containing values from 0 to 255.
- glushort: Unsigned double-byte integer containing values from 0 to 65,535
- gluint: Unsigned four-byte integer containing values from 0 to 4,294,967,295
- glfloat: Four-byte precision IEEE 754-1985 floating-point number
- Glclampf: This is also a four-byte precision floating point number, but OpenGL uses GLCLAMPF specifically to indicate a value of 0.0 to 1.0
- glvoid: Void value is used to indicate that a function has no return value or no parameter
- glfixed: Fixed-point numbers use integers to store real numbers. Since most computer processors handle integer numbers much faster than processing floating-point numbers, this is usually the way to optimize the 3D system. But since the iphone has a vector processor for floating-point arithmetic, we will not discuss fixed-point or glfixed data types.
- glclampx: Another fixed-point type that uses fixed-point arithmetic to represent real numbers between 0.0 and 1.0. As glfixed, we will not discuss or use it.
OpenGL ES (at least the version currently used by the iphone) does not support 8-byte (64-bit) data types, such as long or double. OpenGL actually has these large data types, but the final decision is to exclude these data types from OpenGL ES, given that most of the embedded device screen sizes and the types of programs that may be written for them may adversely affect performance. Point or vertexThe smallest unit of a 3D image is called a point or vertex vertex. They represent a point in a three-dimensional space and are used to construct more complex objects. Polygons are made up of points, and objects are made up of multiple polygons. Although OpenGL typically supports multiple polygons, OpenGL ES supports only three-sided (that is, triangles). If you recall the geometry you learned in high school, you might remember the Cartesian coordinates. The basic concept is to choose one point in space, called the origin . You can then specify any point in the space by referring to the origin and using three values that represent three dimensions, and the coordinates are represented by three imaginary lines of the origin. The imaginary line from left to right is called X-axis. The value of left-to-right is larger along the x-axis, and the left-moving value is smaller. The left x of the origin is negative and the right is positive. The other two axes are likewise. Along the y axis, the Y value increases and the downward Y value decreases. Y is positive above the origin and negative below the origin point. For the z-axis, when the object leaves the Observer, the value becomes smaller, moving to the observer (or exceeding the observer), and the value becomes larger. The z-value ahead of the origin is positive and negative after the origin point. Help illustrates this point:
Note: the other drawing frame core graphics on the iphone uses a slightly different coordinate system, which decreases as the Y value moves toward the top of the screen, and the Y value increases as you move down.
values that increase or decrease along each axis are performed on any scale – they do not represent any real unit, such as feet, inches, or meters. You can choose any scale that makes sense to your program. If you want to design a game in feet, you can do that. If you want the unit to be millimeters, it's also possible. OpenGL regardless of what it represents to the end user, just treat it as a unit, guaranteeing that they have the same distance. Since the azimuth of any object in three-dimensional space can be represented by three values, the position of the object is usually represented in OpenGL by three glfloat variables using a three-dimensional array, the first item in the array (index 0) is the x position, the second item (index 1) is the Y position, and the third item (index 2) is the z position. Here is a simple example of creating OpenGL es vertices: Glfloat vertex[3]; VERTEX[0] = 10.0; X vertex[1] = 23.75; Y vertex[2] = -12.532; Z
In OpenGL ES, it is common to submit all or some of the objects in the scene as vertex arrays . A top point group is a simple array that includes some or all of the vertex data in the scene. I'll discuss in the next tutorial in the series about vertex arrays to keep in mind that their size is based on the number of vertices rendered, multiplied by three (three-dimensional space plots), or two (two-dimensional space plots). So a vertex array with triangles in six three-dimensional space consists of 54 glfloat, because each triangle has three vertices, and each vertex has three coordinates, which is 6 x 3 x 3 = 54. Handle all theseglfloatis a very painful thing to do. Fortunately, there is an easy way. We can define a data structure that holds multiple vertices, like this: typedef struct { Glfloat x; Glfloat y; Glfloat Z; } Vertex3d;By doing this, our code is more readable: Vertex3d Vertex; vertex.x = 10.0; vertex.y = 23.75; Vertex.z =-12.532; Now because Vertex3d consists of three glfloat, passing the pointer to Vertex3d is exactly the same as passing a pointer to an array that contains three glfloat. There is no difference between a computer and the same size, the same number of bytes, and the same order that OpenGL needs. grouping data into a structure simply makes it easier for programmers to handle. If you download the Xcode template at the beginning of the article, you will find that this data structure and the various functions I will discuss later are defined in the file OpenGLCommon.h. There is also an inline function to create a single vertex: Static inline Vertex3d vertex3dmake (cgfloat InX, CGFloat iny, CGFloat InZ) { VERTEX3D ret; Ret.x = InX; Ret.y = Iny; Ret.z = InZ; return ret; } If you recall the contents of geometry (which doesn't matter if you don't remember it), you'll know that the distance between two points in space is calculated using the following formula: We can implement this formula in a simple inline function to calculate the straight-line distance between any two points in a three-dimensional space: Static inline Glfloat vertex3dcalculatedistancebetweenvertices (vertex3d First, vertex3d second) { Glfloat deltax = second.x-first.x; Glfloat DeltaY = Second.y-first.y; Glfloat Deltaz = second.z-first.z; Return Sqrtf (deltax*deltax + Deltay*deltay + Deltaz*deltaz); }; TriangleSince OpenGL ES supports only triangles, we can combine three vertices into a triangular object by creating a data structure. typedef struct { Vertex3d v1; Vertex3d v2; Vertex3d v3;} Triangle3d;
A triangle3d is actually exactly the same as an array of nine glfloat, because we build objects with vertices and triangles instead of glfloat arrays, so it helps us to work with our code more easily. However, you need to know more about triangles. In OpenGL, there is a concept called winding (winding), which indicates that the order in which vertices are drawn is important. Unlike real-world objects, the polygons in OpenGL usually don't have two sides. They have only one side and are treated as front face (front), and the triangles are only visible when the front faces are facing the observer. OpenGL can be set to treat polygons as both sides, but by default, only one of the triangles can be met. By knowing which polygon is in front of the polygon or meeting, you can make OpenGL do only half the calculation. Although sometimes polygons can exist independently, they need to be drawn on the back, but usually the triangles are part of a large object and are never visible to one side of the object. The non-drawn side is called backface (back), and OpenGL determines the front face and backface by observing the drawing order of the vertices. The polygons that draw the vertices in the counter-clockwise order are frontface (by default, can be changed). Because OpenGL can easily determine which triangles are visible to the user, it uses a technique called backface culling (hidden face cancellation) to avoid polygons in the drawing window from being met. The next article will discuss Windows, and now you can think of it as a virtual camera or a virtual window that observes the OpenGL world. , the left Cyan triangle is backface, so it will not be visible. and the triangle on the right is frontface, so it will be drawn. The next article in this series will set up an OpenGL virtual world and use Vertex3d and triangle3d to make some basic drawings. Later, we will discuss transformations, which use linear algebra to move objects in the virtual world. |