1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * FrCamera.c
21  *
22  * $Source: r:/prj/cit/src/RCS/frcamera.c $
23  * $Revision: 1.15 $
24  * $Author: dc $
25  * $Date: 1994/07/15 13:58:34 $
26  *
27  * Citadel Renderer
28  *  camera position/modification/creation system
29  *
30  * uchar    fr_camera_create (cams *camtype, int *arg1, int *arg2)
31  * int     fr_camera_update (cams *cam, int *arg1, int *arg2)
32  * void    fr_camera_slewone(cams *cam, int which, int how)
33  * fix    *fr_camera_getpos (cams *cam)
34  * void    fr_camera_setdef (cams *cam)
35  * void    fr_camera_slewcam(cams *cam, int which, int how)
36  *
37  * $Log: frcamera.c $
38  * Revision 1.15  1994/07/15  13:58:34  dc
39  * check for cameras off the map at getpos time
40  *
41  * Revision 1.14  1994/06/28  20:07:16  dc
42  * allow null cameras without default cameras without crashing the game
43  *
44  * Revision 1.13  1994/05/03  15:58:57  dc
45  * flatten other 360 side views....
46  *
47  * Revision 1.12  1994/04/10  05:15:26  dc
48  * support for cyberman, vfx1, other 6d control structure, inc. HEAD_H
49  *
50  * Revision 1.11  1994/04/02  03:43:07  dc
51  * clean up errors, so on
52  *
53  * Revision 1.10  1994/01/31  05:31:37  dc
54  * various hacks for reality, new actual use of camera system
55  *
56  * Revision 1.9  1994/01/06  10:35:40  xemu
57  * self/run
58  *
59  * Revision 1.8  1994/01/02  17:11:25  dc
60  * New renderer
61  *
62  * Revision 1.7  1993/12/08  22:01:36  unknown
63  * yea yea yea
64  *
65  * Revision 1.6  1993/12/08  21:38:08  unknown
66  * player model
67  *
68  * Revision 1.5  1993/09/19  19:09:49  xemu
69  * made _def_cam externally accessible
70  *
71  * Revision 1.4  1993/09/17  16:57:47  mahk
72  * Added 360 support
73  *
74  * Revision 1.3  1993/09/16  23:54:54  dc
75  * Yo, use cameras for real, allow type mods on the fly
76  *
77  * Revision 1.2  1993/09/05  20:54:06  dc
78  * new regieme for real
79  *
80  * Revision 1.1  1993/09/05  20:21:57  dc
81  * Initial revision
82  *
83  */
84 
85 #define __FRCAMERA_SRC
86 #include <string.h>
87 #include <stdlib.h> // for abs, of course
88 
89 #include "frcamera.h"
90 #include "froslew.h" // has objects
91 #include "fauxrint.h"
92 #include "map.h"
93 
94 fix fr_camera_last[CAM_COOR_CNT] = {0, 0, 0, 0, 0, 0};
95 fix cam_slew_scale[CAM_COOR_CNT] = {fix_make(4, 0), fix_make(4, 0), fix_make(4, 0), 128, 128, 128};
96 cams *_def_cam = NULL;
97 
98 #define _cam_top(cam)                            \
99     cams *_cam = (cam == NULL) ? _def_cam : cam; \
100     if (_cam == NULL)                            \
101     return
102 
fr_camera_setdef(cams * cam)103 void fr_camera_setdef(cams *cam) { _def_cam = cam; }
104 
fr_camera_getdef(void)105 cams *fr_camera_getdef(void) { return _def_cam; }
106 
fr_camera_create(cams * cam,int camtype,ushort oid,fix * coor,fix * args)107 uchar fr_camera_create(cams *cam, int camtype, ushort oid, fix *coor, fix *args) {
108     DEBUG("Creating camera");
109     _cam_top(cam) FALSE;
110     _cam->type = camtype;
111 
112     if (camtype & CAMBIT_OBJ)
113         _cam->obj_id = oid;
114     else
115         LG_memcpy(_cam->coor, coor, sizeof(fix) * CAM_COOR_CNT);
116 
117     if (args != NULL)
118         LG_memcpy(_cam->args, args, sizeof(fix) * CAM_ARGS_CNT);
119 
120     return TRUE;
121 }
122 
fr_camera_modtype(cams * cam,uchar type_on,uchar type_off)123 uchar fr_camera_modtype(cams *cam, uchar type_on, uchar type_off) {
124     uchar ret;
125     _cam_top(cam) 0;
126     ret = _cam->type;
127     _cam->type &= ~type_off;
128     _cam->type |= type_on;
129     return ret;
130 }
131 
132 // i'll give you fish, i'll give you candy, i'll give you, everything I have in my hand
fr_camera_update(cams * cam,uintptr_t arg1,int whicharg,uintptr_t arg2)133 int fr_camera_update(cams *cam, uintptr_t arg1, int whicharg, uintptr_t arg2) {
134     _cam_top(cam) FALSE;
135     if (arg1 != 0) {
136         if (_cam->type & CAMBIT_OBJ)
137             _cam->obj_id = (unsigned int)arg1;
138         else
139             LG_memcpy(_cam->coor, (void*)arg1, sizeof(fix) * CAM_COOR_CNT);
140     }
141 
142     if (whicharg == CAM_UPDATE_ALL)
143       LG_memcpy(_cam->args, (void*)arg2, sizeof(fix) * CAM_ARGS_CNT);
144     else if (whicharg < CAM_ARGS_CNT)
145         _cam->args[whicharg] = (fix)arg2;
146     return TRUE;
147 }
148 
fr_camera_setone(cams * cam,int which,int newone)149 void fr_camera_setone(cams *cam, int which, int newone) {
150     _cam_top(cam);
151     if (_cam->type & CAMBIT_OBJ)
152         fr_objslew_setone(which, newone);
153     else
154         _cam->coor[which] = newone;
155 }
156 
fr_camera_slewone(cams * cam,int which,int how)157 void fr_camera_slewone(cams *cam, int which, int how) {
158     uchar cv[3] = {0, 2, 1};
159     _cam_top(cam);
160     if (which >= 3) /* angles */
161     {
162         if (which == EYE_RESET)
163             _cam->coor[4] = _cam->coor[5] = 0;
164         else
165             _cam->coor[which] += how * cam_slew_scale[which];
166     } else /* actual move */
167     {
168         g3s_vector v[3];
169         fix tot, _cammul;
170 
171         // this just doesnt work, really
172 
173         tot = how * cam_slew_scale[which];
174         g3_get_slew_step(tot, v + 0, v + 1, v + 2);
175         //      if (which==2) how*=-1;
176         if (_cam->type & CAMFLT_FLAT) {
177             _cammul = fix_sqrt(fix_mul(tot, tot) - (fix_mul(v[cv[which]].gY, v[cv[which]].gY)));
178             _cammul = fix_div(abs(tot), _cammul);
179             //       Warning(("mul %x from %x and %x\n",_cammul,tot,v[cv[which]]));
180         } else {
181             _cam->coor[2] -= fix_int((v[cv[which]].gY)) << 8;
182             _cammul = fix_make(1, 0);
183         }
184         _cam->coor[0] += fix_mul(_cammul, ((v[cv[which]].gX) >> 8));
185         _cam->coor[1] += fix_mul(_cammul, ((v[cv[which]].gZ) >> 8));
186     }
187 }
188 
189 // also in init.c
190 #define MAGIC_SELFRUN_OBJID 0xC3
191 
fr_camera_getobjloc(int oid,fix * store)192 void fr_camera_getobjloc(int oid, fix *store) {
193     Obj *cobj = &objs[oid];
194 
195     if (cobj->info.ph != -1) {
196 #ifndef __RENDTEST__
197         extern uchar get_phys_info(int ph, fix *targ_array, int cnt);
198 #endif
199 
200         get_phys_info(cobj->info.ph, store, 6);
201     } else {
202         store[0] = cobj->loc.x << 8;
203         store[1] = cobj->loc.y << 8;
204         store[2] = cobj->loc.z << (8 + SLOPE_SHIFT_D);
205         store[3] = (cobj->loc.h << 8);
206         store[4] = (cobj->loc.p << 8);
207         store[5] = (cobj->loc.b << 8);
208     }
209 }
210 
fr_camera_getpos(cams * cam)211 fix *fr_camera_getpos(cams *cam) {
212     _cam_top(cam) NULL;
213     if (_cam->type & CAMBIT_OBJ) /* set fix x,y,z etc from the object positions */
214         fr_camera_getobjloc(_cam->obj_id, _cam->coor);
215 
216     LG_memcpy(fr_camera_last, _cam->coor, sizeof(fix) * CAM_COOR_CNT);
217     if (_cam->type & CAMBIT_MOD)
218         fr_camera_last[3] = (fr_camera_last[3] + eye_mods[0]) & 0xffff;
219     if ((_cam->type & (CAMBIT_OFF | CAMBIT_ANG)) != 0) {
220         fr_camera_last[3] += (0x10000) - ((1 << (14 - CAMANG_S)) * (_cam->type & CAMBIT_ANG));
221     } // for now 360 view will stay body flat....
222     else if (_cam->type & CAMBIT_MOD) {
223         //	   fr_camera_last[3]=(fr_camera_last[3]+eye_mods[0])&0xffff;
224         fr_camera_last[4] = (fr_camera_last[4] + eye_mods[1]) & 0xffff;
225         fr_camera_last[5] = (fr_camera_last[5] + eye_mods[2]) & 0xffff;
226     }
227     return &fr_camera_last[0];
228 }
229 
fr_camera_slewcam(cams * cam,int which,int how)230 void fr_camera_slewcam(cams *cam, int which, int how) {
231     _cam_top(cam);
232     if (_cam->type & CAMBIT_OBJ)
233         fr_objslew_moveone(NULL, _cam->obj_id, which, how, TRUE);
234     else
235         fr_camera_slewone(_cam, which, how);
236 }
237