OpenGL ES 11-moving in 3D
(TRANSLATOR: That. In fact, I jumped to another chapter, section 12, and learned how to judge an object in the 2D world, I think most of our game developers have already used huge peanut code, and it is easier to develop games in the 2D world. This chapter is of little use to us. So I am also lazy .)
Bird flu, busy, Mother's Day, and other things mean that I am not here for a while. So now is the time to do things.
3D Movement
My time is very short, so today is a real quick start. We will begin to build a "real" 3D world, building everything from the floor. However, before I start, I like to introduce how to move in 3D.
Today, we will start some new code to touch and move around the ground. When using touch, we can turn left, right, forward and backward. Without running, without looking up, just walking, because it is easier. I don't want to implement it for anyone without an iPod or an iPhone.
Before you start, download the following start function:
OpenGL ES 13-starter
There is not much code here, just let us know what we are going to do.
Virtual camera
I 'd like to tell you that people use cameras to observe things in 3D, although OpenGL does not actually have a camera. So when you move on the screen, you are actually moving all objects, and the feeling of motion is not caused by the creation of a camera to watch movies, instead, all objects in the world are moved with the relative coordinates (0, 0.
It sounds like this is a huge workload, but it is not. According to your application, you will perform a lot of optimization work, and even in a large world, there is not much work. I will mention it later.
For ease of work, I have provided a helper for this tutorial. The function in the library of GL U, the eldest brother of OpenGL ES, is glulookat ().
Generally, I do not mention the advantages of OpenGL, But I think most people know what it is. Unfortunately, OpenGL ES does not support this function library, which means we have fewer useful functions. Porting these functions does not require porting the entire library. You only need to implement a few features that we need.
I found the source code of glulookat (), so the copyright of these codes is not mine.
Use glulookat ()
This function is so simple to use that you only need to understand it and can be used. Let's look at the prototype:
Void glulookat (glfloat eyex,
Glfloat eyey,
Glfloat Eyez,
Glfloat centerx,
Glfloat centery,
Glfloat centerz,
Glfloat UPX,
Glfloat upy,
Glfloat upz)
I know that nine parameters seem daunting, but you can break them down. The first three are the locations of the eyes. Here you are looking for only the coordinates of X, Y, and Z.
The three parameters in the 2nd group refer to the coordinates of X, Y, and Z.
Finally, let's look at the last three "up" vectors. The first two coordinates are what I want.
The coordinates of the eyes are the locations of mysterious cameras. They are in the coordinates of your world. See your world from here. The "center" coordinate is where you are facing. If the Y coordinate in the center is higher than the Y coordinate in your eyes, you can look up. If the Y coordinate is lower, you can look down.
Therefore, in the project we started, we have already prepared how to move the number settings. Now let's take a look at the painted floor.
First, let's use gllookat (). Add the following function to drawview:
Glloadidentity ();
Glulookat (5.0, 1.5, 2.0, // eye location, look "from"
-5.0, 1.5,-10.0, // target location, look ""
0.0, 1.0, 0.0); // ignore for now
For the single function, we can see another place from one place, change the parameter, and see what will happen.
3D Motion
Now you are sure to deal with glulookat (), let's use it to simulate walking on the floor, we can only move (x, z), that is, do not move y, that is, the height.
Therefore, the idea will go to glulookat () and think about what information do you need to move in the 3D world?
You need:
The position or eye you observe
Your orientation or "center"
Once you know these two items, you need to prepare user input for the user to control the movement.
Set the following variables to change the eyes and centers
Glfloat eye [3]; // where we are viewing from
Glfloat Center [3]; // where we are looking
Return to initWithCoder: Before calling gluLookAt (), initialize:
Eye [0] = 5.0;
Eye [1] = 1.5;
Eye [2] = 2.0;
Center [0] =-5.0;
Center [1] = 1.5;
Center [2] =-10.0;
To drawView: Call gluLookAt ():
GluLookAt (eye [0], eye [1], eye [2], center [0], center [1], center [2],
0.0, 1.0, 0.0 );
Preparations for sports
Before we start to execute the touch event and move it in the world, we need to set something in the header file. In the header file, we need to create a new Enumeration type.
First, set our walking speed and turning speed:
# Define pai_speed 0.005
# Define turn_speed0.01
Next, we create an enumeration to indicate what we are doing, as shown below:
Typedef enum _ MOVMENT_TYPE {
MTNone = 0,
Mt1_forward,
Mt1_backward,
MTTurnLeft,
MTTurnRight
} MovementType;
Therefore, when we run the app, we can always stand, move forward, or backward, or turn left or right.
At the very end, we define the state of motion before a variable is saved:
MovementType currentMovement;
Don't forget to set the default value of currentMovement in initWithCoder: function:
CurrentMovement = MTNone;
Get touch
Okay. We have already made a basic introduction. Let's start working on it. If you still remember my previous tutorial, You should know four touch statuses. Today we use
TouchesBegan and touchesEnded.
To determine the type of action, we split the screen into four parts.
Start to touch the function:
-(Void) touchesBegan :( NSSet *) touches withEvent :( UIEvent *) event {
Uitouch * t = [[touches allobjects] objectatindex: 0];
Cgpoint touchpos = [t locationinview: T. View];
// Determine the location on the screen. We are interested in iPhone
// Screen co-ordinates only, not the world co-ordinates
// Because we are just trying to handle movement.
//
// (0, 0)
// + ----------- +
// |
// | 160 |
// | ----------- | 160
// |
// |
// | ----------- | 320
// |
// |
// + ----------- + (320,480)
//
If (touchPos. y <160 ){
// We are moving forward
CurrentMovement = mt1_forward;
} Else if (touchPos. y> 320 ){
// We are moving backward
CurrentMovement = mt1_backward;
} Else if (touchPos. x <160 ){
// Turn left
CurrentMovement = MTTurnLeft;
} Else {
// Turn Right
CurrentMovement = MTTurnRight;
}
}
After a player clicks any position on the screen, the player sets the motion state to a specified state and releases the state when the player is released:
-(Void) touchesEnded :( NSSet *) touches withEvent :( UIEvent *) event {
CurrentMovement = MTNone;
}
Implementation of these methods. Finally, we need an interface to handle these touch events. This time, we need to add a method declaration interface, return to the header file, and add the following method:
-(Void) handleTouches;
Then, switch back and implement this method. We need to execute the 3d world of our motion through computation.
3D space movement theory
Let's take a look at the first walk. When users tell us to move forward, we need to know not only our orientation, but also our target position. This orientation is our current position, and the target we see is our target position. We need to move from the current position to the target position.
The figure below demonstrates our current position and our predefined target position.
In the motion function, we know the distance between the two points, x and zcoordinate. What we need to do is multiply the current coordinate by the "Speed" to obtain the new x and Z coordinates. Like this:
We can easily get the coordinates of red points.
We first design the relative coordinates deltaX and deltaZ of the target location:
DeltaX = 1.5-1.0 = 0.5
DeltaZ =-10-(-5.0) =-5.0
So now we can enjoy our walking speed:
XDisplacement = deltaX * pai_speed
= 0.5*0.01
= 0.005
ZDisplacement = deltaZ * pai_speed
=-5.0*0.01
= 0.05
Therefore, the new red point is:
EyeC + CDisplacement
(Eyex + xDisplacement, eyey, eyez + zDisplacement)
= (0.005 + 1.0, eyey, (-10) + 0.05)
= (1.005, eyey,-9.95)
Now, this method does not have no disadvantages. The main problem is that if the target is farther away from the current location, the "walking speed" will be faster.
Now, let's look at the left and right.
Because we are simulating rotation. In fact, the target position is moving on a circle.
The key here is that you need to understand what I am talking about. You can think of the current position as the center, and the target position is the circular edge. Steering is moving on the edges.
In other words, this is:
NewX = eyeX + radius * cos (TURN_SPEED) * deltaX-
Sin (TURN_SPEED) * deltaZ
NewZ = eyeZ + radius * sin (TURN_SPEED) * deltaX +
Cos (TURN_SPEED) * deltaZ
Processing touch and sports
Now let's turn this into practice.
First, the implementation method and some basic knowledge:
-(Void) handleTouches {
If (currentMovement = MTNone ){
// We're going nowhere, nothing to do here
Return;
}
First, let's see if we are moving. If there is no operation, we will not do anything.
Then, whether we are moving or turning, we need to know the value relative to deltaX and deltaZ. I am looking for a temporary array to save us.
GLfloat vector [3];
Vector [0] = center [0]-eye [0];
Vector [1] = center [1]-eye [1];
Vector [2] = center [2]-eye [2];
I did not calculate the relative value of y because it is meaningless.
Now we use a switch to determine the current status and process it.
Switch (currentMovement ){
Case mt1_forward:
Eye [0] + = vector [0] * pai_speed;
Eye [2] + = vector [2] * pai_speed;
Center [0] + = vector [0] * walk_speed;
Center [2] + = vector [2] * walk_speed;
Break;
Case mt1_backward:
Eye [0]-= vector [0] * pai_speed;
Eye [2]-= vector [2] * pai_speed;
Center [0]-= vector [0] * walk_speed;
Center [2]-= vector [2] * WALK_SPEED;
Break;
Case MTTurnLeft:
Center [0] = eye [0] + cos (-TURN_SPEED) * vector [0]-
Sin (-TURN_SPEED) * vector [2];
Center [2] = eye [2] + sin (-TURN_SPEED) * vector [0] +
Cos (-TURN_SPEED) * vector [2];
Break;
Case MTTurnRight:
Center [0] = eye [0] + cos (TURN_SPEED) * vector [0]-sin (TURN_SPEED) * vector [2];
Center [2] = eye [2] + sin (TURN_SPEED) * vector [0] + cos (TURN_SPEED) * vector [2];
Break;
}
}
The algorithm implemented here is what I just mentioned.
Associate all of this
Return to the drawView function and add this line under the gluLookAt () function:
[Self handleTouches];
And that's it, we're done!
Hit "Build and Go" now! Right now !!