-
Notifications
You must be signed in to change notification settings - Fork 1
/
seb_camera.c~
366 lines (299 loc) · 12.5 KB
/
seb_camera.c~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
/*
seb_camera.c
*/
#include "seb_camera.h"
// This is how fast our camera moves (in units/sec)
#define kSpeed 100.0f
ScePspFVector3 Substract (ScePspFVector3 vVector1, ScePspFVector3 vVector2);
ScePspFVector3 Add (ScePspFVector3 vVector1, ScePspFVector3 vVector2);
scam_t *SCAM_Init (void)
{
scam_t *new;
ScePspFVector3 vZero = {0.0, 0.0, 0.0}; // Init a vVector to 0 0 0 for our position
ScePspFVector3 vView = {0.0, 1.0, 0.5}; // Init a starting view vVector (looking up and out the screen)
ScePspFVector3 vUp = {0.0, 0.0, 1.0}; // Init a standard up vVector (Rarely ever changes)
new = (scam_t *)malloc (sizeof (scam_t));
new->position = vZero; // Init the position to zero
new->view = vView; // Init the view to a std starting view
new->up_vector = vUp; // Init the UpVector
return new;
}
void SCAM_Dispose (scam_t *camera)
{
free (camera);
}
// This intializes the camera's sphere radius
void SCAM_SetRadius(scam_t *camera, float radius)
{
camera->radius = radius;
}
// This changes the position, view, and up vector of the camera.
// This is primarily used for initialization
void SCAM_Position (scam_t *camera, ScePspFVector3 *vPosition, ScePspFVector3 *vView, ScePspFVector3 *vUpVector)
{
camera->position = vPosition; // Assign the position
camera->view = vView; // Assign the view
camera->up_vector = vUpVector; // Assign the up vector
}
/////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This allows us to look around using the mouse, like in most first person games.
/////
///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void SCAM_SetViewByPad (scam_t *camera, SceCtrlData pad)
{
float angleY = 0.0f; // This is the direction for looking up or down
float angleZ = 0.0f; // This will be the value we need to rotate around the Y axis (Left and Right)
static float currentRotX = 0.0f;
const int zones[6] = {30, 70, 100, 112, 125, 130};
const float response[6] = {0.0f, 0.1f, 0.5f, 1.0f, 4.0f, 8.0f};
float direction;
int i, u, v;
// non linear response
u = pad.Lx - 128;
if (u < 0)
{
direction = 1.0f;
u = -u;
}
else
{
direction = -1.0f;
}
for (i = 0; i < 6; i++)
{
if (u < zones[i])
{
u = response[i] * direction;
break;
}
}
v = pad.Ly - 128;
if (v < 0)
{
direction = 1.0f;
v = -v;
}
else
{
direction = -1.0f;
}
for (i = 0; i < 6; i++)
{
if (v < zones[i])
{
v = response[i] * direction;
break;
}
}
// Get the direction the pad moved in, but bring the number down to a reasonable amount
angleY = (float)u / 500.0f;
angleZ = (float)v / 500.0f;
// Here we keep track of the current rotation (for up and down) so that
// we can restrict the camera from doing a full 360 loop.
currentRotX -= angleZ;
// If the current rotation (in radians) is greater than 1.0, we want to cap it.
if (currentRotX > 1.0f)
currentRotX = 1.0f;
// Check if the rotation is below -1.0, if so we want to make sure it doesn't continue
else if (currentRotX < -1.0f)
currentRotX = -1.0f;
// Otherwise, we can rotate the view around our position
else
{
// To find the axis we need to rotate around for up and down
// movements, we need to get a perpendicular vector from the
// camera's view vector and up vector. This will be the axis.
ScePspFVector3 vAxis, vSub;
vSub = Substract (camera->view, camera->position);
gumCrossProduct (&vAxis, &vSub, &(camera->up_vector));
gumNormalize (&vAxis);
// Rotate around our perpendicular axis and along the y-axis
SCAM_RotateView (camera, angleZ, vAxis.x, vAxis.y, vAxis.z);
SCAM_RotateView (camera, angleY, 0, 1, 0);
}
}
///////////////////////////////// ROTATE VIEW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This rotates the view around the position using an axis-angle rotation
/////
///////////////////////////////// ROTATE VIEW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void SCAM_RotateView (scam_t *camera, float angle, float x, float y, float z)
{
ScePspFVector3 vNewView;
// Get the view vector (The direction we are facing)
ScePspFVector3 vView = Substract (camera->view, camera->position);
// Calculate the sine and cosine of the angle once
float cosTheta = (float)cos (angle);
float sinTheta = (float)sin (angle);
// Find the new x position for the new rotated point
vNewView.x = (cosTheta + (1 - cosTheta) * x * x) * vView.x;
vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta) * vView.y;
vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta) * vView.z;
// Find the new y position for the new rotated point
vNewView.y = ((1 - cosTheta) * x * y + z * sinTheta) * vView.x;
vNewView.y += (cosTheta + (1 - cosTheta) * y * y) * vView.y;
vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta) * vView.z;
// Find the new z position for the new rotated point
vNewView.z = ((1 - cosTheta) * x * z - y * sinTheta) * vView.x;
vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta) * vView.y;
vNewView.z += (cosTheta + (1 - cosTheta) * z * z) * vView.z;
// Now we just add the newly rotated vector to our position to set
// our new rotated view of our camera.
camera->view = Add (camera->position, vNewView);
}
///////////////////////////////// ROTATE AROUND POINT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This rotates the position around a given point
/////
///////////////////////////////// ROTATE AROUND POINT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void SCAM_RotateAroundPoint (scam_t *camera, ScePspFVector3 vCenter, float angle, float x, float y, float z)
{
ScePspFVector3 vNewPosition;
// To rotate our position around a point, what we need to do is find
// a vector from our position to the center point we will be rotating around.
// Once we get this vector, then we rotate it along the specified axis with
// the specified degree. Finally the new vector is added center point that we
// rotated around (vCenter) to become our new position. That's all it takes.
// Get the vVector from our position to the center we are rotating around
ScePspFVector3 vPos = Substract (camera->position, vCenter);
// Calculate the sine and cosine of the angle once
float cosTheta = (float)cos(angle);
float sinTheta = (float)sin(angle);
// Find the new x position for the new rotated point
vNewPosition.x = (cosTheta + (1 - cosTheta) * x * x) * vPos.x;
vNewPosition.x += ((1 - cosTheta) * x * y - z * sinTheta) * vPos.y;
vNewPosition.x += ((1 - cosTheta) * x * z + y * sinTheta) * vPos.z;
// Find the new y position for the new rotated point
vNewPosition.y = ((1 - cosTheta) * x * y + z * sinTheta) * vPos.x;
vNewPosition.y += (cosTheta + (1 - cosTheta) * y * y) * vPos.y;
vNewPosition.y += ((1 - cosTheta) * y * z - x * sinTheta) * vPos.z;
// Find the new z position for the new rotated point
vNewPosition.z = ((1 - cosTheta) * x * z - y * sinTheta) * vPos.x;
vNewPosition.z += ((1 - cosTheta) * y * z + x * sinTheta) * vPos.y;
vNewPosition.z += (cosTheta + (1 - cosTheta) * z * z) * vPos.z;
// Now we just add the newly rotated vector to our position to set
// our new rotated position of our camera.
camera->position = Add (vCenter, vNewPosition);
}
///////////////////////////////// STRAFE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This strafes the camera left and right depending on the speed (-/+)
/////
///////////////////////////////// STRAFE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void SCAM_Strafe (scam_t *camera, float speed)
{
// Add the strafe vector to our position
camera->position.x += camera->strafe.x * speed;
camera->position.z += camera->strafe.z * speed;
// Add the strafe vector to our view
camera->view.x += camera->strafe.x * speed;
camera->view.z += camera->strafe.z * speed;
}
///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This will move the camera forward or backward depending on the speed
/////
///////////////////////////////// MOVE CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void SCAM_Move (scam_t *camera, float speed)
{
// Get the current view vector (the direction we are looking)
ScePspFVector3 vVector = Substract (camera->view, camera->position);
gumNormalize (&vVector);
camera->position.x += vVector.x * speed; // Add our acceleration to our position's X
camera->position.y += vVector.y * speed; // Add our acceleration to our position's Y
camera->position.z += vVector.z * speed; // Add our acceleration to our position's Z
camera->view.x += vVector.x * speed; // Add our acceleration to our view's X
camera->view.y += vVector.y * speed; // Add our acceleration to our view's Y
camera->view.z += vVector.z * speed; // Add our acceleration to our view's Z
}
//////////////////////////// CHECK FOR MOVEMENT \\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This function handles the input faster than in the WinProc()
/////
//////////////////////////// CHECK FOR MOVEMENT \\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void SCAM_CheckForMovement (scam_t *camera, SceCtrlData pad, float g_FrameInterval)
{
// Once we have the frame interval, we find the current speed
float speed = kSpeed * g_FrameInterval;
// Check if we hit the Up arrow
if (pad.Buttons & PSP_CTRL_UP)
{
// Move our camera forward by a positive SPEED
SCAM_Move (camera, speed);
}
// Check if we hit the Down arrow
if (pad.Buttons & PSP_CTRL_DOWN)
{
// Move our camera backward by a negative SPEED
SCAM_Move (camera, -speed);
}
// Check if we hit the Left arrow
if (pad.Buttons & PSP_CTRL_LEFT)
{
// Strafe the camera left
SCAM_Strafe (camera, -speed);
}
// Check if we hit the Right arrow
if (pad.Buttons & PSP_CTRL_RIGHT)
{
// Strafe the camera right
SCAM_Strafe (camera, speed);
}
}
/////////////////////////////////////// MAGNITUDE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This returns the magnitude of a vector
/////
/////////////////////////////////////// MAGNITUDE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
float Magnitude (ScePspFVector3 vNormal)
{
// Here is the equation: magnitude = sqrt(V.x^2 + V.y^2 + V.z^2) : Where V is the vector
return (float)sqrt( (vNormal.x * vNormal.x) +
(vNormal.y * vNormal.y) +
(vNormal.z * vNormal.z) );
}
ScePspFVector3 Substract (ScePspFVector3 vVector1, ScePspFVector3 vVector2)
{
ScePspFVector3 vSub;
vSub.x = vVector1.x - vVector2.x;
vSub.y = vVector1.y - vVector2.y;
vSub.z = vVector1.z - vVector2.z;
return vSub;
}
ScePspFVector3 Add (ScePspFVector3 vVector1, ScePspFVector3 vVector2)
{
ScePspFVector3 vSum;
vSum.x = vVector1.x + vVector2.x;
vSum.y = vVector1.y + vVector2.y;
vSum.z = vVector1.z + vVector2.z;
return vSum;
}
///////////////////////////////// UPDATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This updates the camera's view and strafe vector
/////
///////////////////////////////// UPDATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void SCAM_Update (scam_t *camera, SceCtrlData pad, float g_FrameInterval)
{
ScePspFVector3 vSub = Substract (camera->view, camera->position);
gumCrossProduct (&(camera->strafe), &vSub, &(camera->up_vector));
// Normalize the strafe vector
gumNormalize (&(camera->strafe));
// Move the camera's view by the mouse
SCAM_SetViewByPad (camera, pad);
// This checks to see if the keyboard was pressed
SCAM_CheckForMovement (camera, pad, g_FrameInterval);
}
///////////////////////////////// LOOK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
/////
///// This updates the camera according to the
/////
///////////////////////////////// LOOK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
void SCAM_Look (scam_t *camera)
{
// Give PSP our camera position, then camera view, then camera up vector
sceGumLookAt (&(camera->position),
&(camera->view),
&(camera->up_vector));
}