Same fix as r45172 for classes/iconimage:
[AROS-Contrib.git] / Games / XInvaders3D / camera.c
blobfa00b89b88396042e636285e5be67f2ca3d52ff9
1 /*------------------------------------------------------------------
2 camera.c:
4 XINVADERS 3D - 3d Shoot'em up
5 Copyright (C) 2000 Don Llopis
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 ------------------------------------------------------------------*/
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <math.h>
26 #include "mat4x4.h"
27 #include "vec4x1.h"
28 #include "camera.h"
30 /* local variables */
31 static float hfov, vfov, hpc, vpc;
32 static float screen_width, screen_height, half_screen_width,
33 half_screen_height;
34 static float aspect_ratio;
35 static float hadjust, vadjust;
36 static MATRIX4 r_2_l;
39 void Camera_init ( unsigned int width, unsigned int height, float fov )
41 screen_width = (float) width;
42 screen_height = (float) height;
43 half_screen_width = screen_width / 2.0f;
44 half_screen_height = screen_height / 2.0f;
46 /* calculate horizontal & vertical field of view */
48 /* horizontal compensate = HALF_SCREEN_WIDTH / tan ( degrees / 2 )
49 vertical compensate = HALF_SCREEN_HEIGHT / tan ( degrees / 2 )
51 see "Building 3d Game Engine" by Brain Hook
54 hfov = vfov = fov;
56 hpc = half_screen_width / tan ( hfov/1.5f );
57 vpc = half_screen_height / tan ( vfov/1.5f );
59 /* adjust aspect ratio if screen not square ( ie. 4/3 ratio )*/
60 aspect_ratio = screen_height / screen_height;
63 /* calculate perspective adjustment values */
64 hadjust = hpc;
65 vadjust = (vpc * aspect_ratio);
67 /* initialize coordinate system conversion mat */
68 Matrix_id ( r_2_l );
69 r_2_l[2][2] = -1.0f;
73 void Camera_project_point ( VECTOR4 a, int b[2] )
75 if ( a[2] < 0.0 ) {
76 b[0] = b[1] = 0;
77 return;
79 b[0] = (int) ( a[0] * hadjust / a[2] + half_screen_width );
80 b[1] = (int) ( -a[1] * vadjust / a[2] + half_screen_height );
83 void Camera_project_points ( VECTOR4 a[], int b[], int n )
85 int i, j;
87 for ( i=0, j=0; i<n; i++, j+=2 )
89 b[j] = (int) ( a[i][0] * hadjust / a[i][2] + half_screen_width );
90 b[j+1] = (int) ( -a[i][1] * vadjust / a[i][2] + half_screen_height );
94 void Camera_transform ( MATRIX4 r, VECTOR4 up, VECTOR4 from, VECTOR4 at )
96 VECTOR4 x, y, z, tmp, pos;
97 MATRIX4 tmp_mat;
99 /* initialize transformation mat */
100 Matrix_id ( tmp_mat );
102 /* calculate view plane normal -- or view-z-axis */
103 Vector_sub ( from, at, z );
104 Vector_norm ( z );
106 /* calculate view-x-axis */
107 Vector_cross ( up, z, x );
108 Vector_norm ( x );
110 /* calculate view-y-axis */
111 Vector_cross ( z, x, y );
113 /* place axis-vecs into transformation mat
114 To understand how this works see chapter 5
115 and 6 of "Computer Graphics Principles & Practice"
117 Matrix_set_xrow ( tmp_mat, x );
118 Matrix_set_yrow ( tmp_mat, y );
119 Matrix_set_zrow ( tmp_mat, z );
121 /* get camera's world position and rotate it
122 into camera coordinate system. This becomes
123 the new translation which is to be applied
124 to an object's vertices inorder to make its
125 position relative to the camera coordinate system
126 see chapter 6
128 Vector_copy ( from, tmp );
129 Vector_negate ( tmp );
130 Matrix_vec_mult ( tmp_mat, tmp, pos );
131 Matrix_set_trans ( tmp_mat, pos );
133 /* now change from right hand coordinate system
134 to left hand coordinate system
135 leaving the result in 'r'
137 Matrix_mult ( r_2_l, tmp_mat, r );