1 /* $Id: morph.c,v 1.3 2003/01/02 23:31:50 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
13 */
14
15 /*
16 *
17 * Morphing code
18 *
19 * Old Log:
20 * Revision 1.5 1995/08/23 21:36:10 allender
21 * mcc compiler warnings fixed
22 *
23 * Revision 1.4 1995/08/12 11:34:19 allender
24 * removed #ifdef NEWDEMO -- always in
25 *
26 * Revision 1.3 1995/07/28 15:39:51 allender
27 * removed fixdiv thing
28 *
29 * Revision 1.2 1995/07/28 15:21:23 allender
30 * inverse magnitude fixup thing
31 *
32 * Revision 1.1 1995/05/16 15:28:05 allender
33 * Initial revision
34 *
35 * Revision 2.1 1995/02/27 18:26:33 john
36 * Fixed bug that was caused by externing Polygon_models, and I had
37 * changed the type of it in polyobj.c, thus causing page faults.
38 *
39 * Revision 2.0 1995/02/27 11:27:44 john
40 * New version 2.0, which has no anonymous unions, builds with
41 * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
42 *
43 * Revision 1.35 1995/02/22 14:45:37 allender
44 * remove anonymous unions from object structure
45 *
46 * Revision 1.34 1995/01/14 19:16:52 john
47 * First version of new bitmap paging code.
48 *
49 * Revision 1.33 1995/01/03 20:38:36 john
50 * Externed MAX_MORPH_OBJECTS
51 *
52 * Revision 1.32 1994/11/17 15:34:04 matt
53 * Attempt #4 to fix morph bug
54 *
55 * Revision 1.31 1994/11/15 10:57:14 matt
56 * Tried again to fix morph
57 *
58 * Revision 1.30 1994/11/14 14:06:45 matt
59 * Fixed stupid bug
60 *
61 * Revision 1.29 1994/11/14 11:55:13 matt
62 * Added divide overflow check
63 *
64 * Revision 1.28 1994/09/26 17:28:14 matt
65 * Made new multiple-object morph code work with the demo system
66 *
67 * Revision 1.27 1994/09/26 15:39:56 matt
68 * Allow multiple simultaneous morphing objects
69 *
70 * Revision 1.26 1994/09/11 22:44:59 mike
71 * quick on vecmat function.
72 *
73 * Revision 1.25 1994/08/26 15:36:00 matt
74 * Made eclips usable on more than one object at a time
75 *
76 * Revision 1.24 1994/07/25 00:02:46 matt
77 * Various changes to accomodate new 3d, which no longer takes point numbers
78 * as parms, and now only takes pointers to points.
79 *
80 * Revision 1.23 1994/07/12 12:39:58 matt
81 * Revamped physics system
82 *
83 * Revision 1.22 1994/06/28 11:54:51 john
84 * Made newdemo system record/play directly to/from disk, so
85 * we don't need the 4 MB buffer anymore.
86 *
87 * Revision 1.21 1994/06/27 15:53:01 john
88 * #define'd out the newdemo stuff
89 *
90 *
91 * Revision 1.20 1994/06/16 14:30:19 matt
92 * Moved morph record data call to reder routine
93 *
94 * Revision 1.19 1994/06/16 13:57:23 matt
95 * Added support for morphing objects in demos
96 *
97 * Revision 1.18 1994/06/16 12:24:23 matt
98 * Made robot lighting not mess with Lighting_on so robots now night
99 * according to this variable.
100 *
101 * Revision 1.17 1994/06/14 16:55:01 matt
102 * Got rid of physics_object speed field
103 *
104 * Revision 1.16 1994/06/08 21:16:29 matt
105 * Made objects spin while morphing
106 *
107 * Revision 1.15 1994/06/08 18:21:53 matt
108 * Made morphing objects light correctly
109 *
110 * Revision 1.14 1994/06/07 16:50:49 matt
111 * Made object lighting work correctly; changed name of Ambient_light to
112 * Dynamic_light; cleaned up polygobj object rendering a little.
113 *
114 * Revision 1.13 1994/06/01 16:33:59 yuan
115 * Fixed bug.
116 *
117 *
118 * Revision 1.12 1994/06/01 16:29:08 matt
119 * If morph_frame called on object this isn't the morph object, kill it.
120 *
121 * Revision 1.11 1994/06/01 12:46:34 matt
122 * Added needed include
123 *
124 * Revision 1.10 1994/05/31 22:12:41 matt
125 * Set lighting for morph objects
126 * Don't let another object start morph while one is morphing, unless
127 * that one dies.
128 *
129 * Revision 1.9 1994/05/31 18:49:53 john
130 * Took out debugging printf's that Matt left in.
131 *
132 * Revision 1.8 1994/05/30 22:50:22 matt
133 * Added morph effect for robots
134 *
135 */
136
137 #ifdef HAVE_CONFIG_H
138 #include <conf.h>
139 #endif
140
141 #ifdef RCS
142 static char rcsid[] = "$Id: morph.c,v 1.3 2003/01/02 23:31:50 btb Exp $";
143 #endif
144
145 #include <stdio.h>
146 #include <stdlib.h>
147 #include <string.h>
148
149 #include "fix.h"
150 #include "vecmat.h"
151 #include "gr.h"
152 #include "texmap.h"
153 #include "error.h"
154
155 #include "inferno.h"
156 #include "morph.h"
157 #include "polyobj.h"
158 #include "game.h"
159 #include "lighting.h"
160 #include "newdemo.h"
161 #include "piggy.h"
162
163 #include "mono.h"
164 #include "bm.h"
165 #include "interp.h"
166
167 morph_data morph_objects[MAX_MORPH_OBJECTS];
168
169 //returns ptr to data for this object, or NULL if none
find_morph_data(object * obj)170 morph_data *find_morph_data(object *obj)
171 {
172 int i;
173
174 #ifdef NEWDEMO
175 if (Newdemo_state == ND_STATE_PLAYBACK) {
176 morph_objects[0].obj = obj;
177 return &morph_objects[0];
178 }
179 #endif
180
181 for (i=0;i<MAX_MORPH_OBJECTS;i++)
182 if (morph_objects[i].obj == obj)
183 return &morph_objects[i];
184
185 return NULL;
186 }
187
188
189 //takes pm, fills in min & max
find_min_max(polymodel * pm,int submodel_num,vms_vector * minv,vms_vector * maxv)190 void find_min_max(polymodel *pm,int submodel_num,vms_vector *minv,vms_vector *maxv)
191 {
192 ushort nverts;
193 vms_vector *vp;
194 ushort *data,type;
195
196 data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]];
197
198 type = *data++;
199
200 Assert(type == 7 || type == 1);
201
202 nverts = *data++;
203
204 if (type==7)
205 data+=2; //skip start & pad
206
207 vp = (vms_vector *) data;
208
209 *minv = *maxv = *vp++; nverts--;
210
211 while (nverts--) {
212 if (vp->x > maxv->x) maxv->x = vp->x;
213 if (vp->y > maxv->y) maxv->y = vp->y;
214 if (vp->z > maxv->z) maxv->z = vp->z;
215
216 if (vp->x < minv->x) minv->x = vp->x;
217 if (vp->y < minv->y) minv->y = vp->y;
218 if (vp->z < minv->z) minv->z = vp->z;
219
220 vp++;
221 }
222
223 }
224
225 #define MORPH_RATE (f1_0*3)
226
227 fix morph_rate = MORPH_RATE;
228
init_points(polymodel * pm,vms_vector * box_size,int submodel_num,morph_data * md)229 void init_points(polymodel *pm,vms_vector *box_size,int submodel_num,morph_data *md)
230 {
231 ushort nverts;
232 vms_vector *vp;
233 ushort *data,type;
234 int i;
235
236 //printf("initing %d ",submodel_num);
237
238 data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]];
239
240 type = *data++;
241
242 Assert(type == 7 || type == 1);
243
244 nverts = *data++;
245
246 md->n_morphing_points[submodel_num] = 0;
247
248 if (type==7) {
249 i = *data++; //get start point number
250 data++; //skip pad
251 }
252 else
253 i = 0; //start at zero
254
255 Assert(i+nverts < MAX_VECS);
256
257 md->submodel_startpoints[submodel_num] = i;
258
259 vp = (vms_vector *) data;
260
261 while (nverts--) {
262 fix k,dist;
263
264 if (box_size) {
265 fix t;
266
267 k = 0x7fffffff;
268
269 if (vp->x && f2i(box_size->x)<abs(vp->x)/2 && (t = fixdiv(box_size->x,abs(vp->x))) < k) k=t;
270 if (vp->y && f2i(box_size->y)<abs(vp->y)/2 && (t = fixdiv(box_size->y,abs(vp->y))) < k) k=t;
271 if (vp->z && f2i(box_size->z)<abs(vp->z)/2 && (t = fixdiv(box_size->z,abs(vp->z))) < k) k=t;
272
273 if (k==0x7fffffff) k=0;
274
275 }
276 else
277 k=0;
278
279 vm_vec_copy_scale(&md->morph_vecs[i],vp,k);
280
281 dist = vm_vec_normalized_dir_quick(&md->morph_deltas[i],vp,&md->morph_vecs[i]);
282
283 md->morph_times[i] = fixdiv(dist,morph_rate);
284
285 if (md->morph_times[i] != 0)
286 md->n_morphing_points[submodel_num]++;
287
288 vm_vec_scale(&md->morph_deltas[i],morph_rate);
289
290 vp++; i++;
291
292 }
293
294 //printf("npoints = %d\n",n_morphing_points[submodel_num]);
295
296 }
297
update_points(polymodel * pm,int submodel_num,morph_data * md)298 void update_points(polymodel *pm,int submodel_num,morph_data *md)
299 {
300 ushort nverts;
301 vms_vector *vp;
302 ushort *data,type;
303 int i;
304
305 //printf("updating %d ",submodel_num);
306
307 data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]];
308
309 type = *data++;
310
311 Assert(type == 7 || type == 1);
312
313 nverts = *data++;
314
315 if (type==7) {
316 i = *data++; //get start point number
317 data++; //skip pad
318 }
319 else
320 i = 0; //start at zero
321
322 vp = (vms_vector *) data;
323
324 while (nverts--) {
325
326 if (md->morph_times[i]) //not done yet
327 {
328
329 if ((md->morph_times[i] -= FrameTime) <= 0) {
330 md->morph_vecs[i] = *vp;
331 md->morph_times[i] = 0;
332 md->n_morphing_points[submodel_num]--;
333 }
334 else
335 vm_vec_scale_add2(&md->morph_vecs[i],&md->morph_deltas[i],FrameTime);
336 }
337
338 vp++; i++;
339 }
340
341 //printf("npoints = %d\n",n_morphing_points[submodel_num]);
342 }
343
344
345 //process the morphing object for one frame
do_morph_frame(object * obj)346 void do_morph_frame(object *obj)
347 {
348 int i;
349 polymodel *pm;
350 morph_data *md;
351
352 md = find_morph_data(obj);
353
354 if (md == NULL) { //maybe loaded half-morphed from disk
355 obj->flags |= OF_SHOULD_BE_DEAD; //..so kill it
356 return;
357 }
358
359 pm = &Polygon_models[md->obj->rtype.pobj_info.model_num];
360
361 //printf("morph_frame active = ");
362 //for (i=0;i<pm->n_models;i++)
363 // printf("%d ",submodel_active[i]);
364 //printf("\n");
365
366
367 for (i=0;i<pm->n_models;i++)
368 if (md->submodel_active[i]==1) {
369
370 update_points(pm,i,md);
371
372 if (md->n_morphing_points[i] == 0) { //maybe start submodel
373 int t;
374
375 md->submodel_active[i] = 2; //not animating, just visible
376
377 md->n_submodels_active--; //this one done animating
378
379 for (t=0;t<pm->n_models;t++)
380 if (pm->submodel_parents[t] == i) { //start this one
381
382 init_points(pm,NULL,t,md);
383 md->n_submodels_active++;
384 md->submodel_active[t] = 1;
385
386 }
387 }
388
389 }
390
391 if (!md->n_submodels_active) { //done morphing!
392
393 md->obj->control_type = md->morph_save_control_type;
394 md->obj->movement_type = md->morph_save_movement_type;
395
396 md->obj->render_type = RT_POLYOBJ;
397
398 md->obj->mtype.phys_info = md->morph_save_phys_info;
399
400 md->obj = NULL;
401 }
402
403 }
404
405 vms_vector morph_rotvel = {0x4000,0x2000,0x1000};
406
init_morphs()407 void init_morphs()
408 {
409 int i;
410
411 for (i=0;i<MAX_MORPH_OBJECTS;i++)
412 morph_objects[i].obj = NULL;
413 }
414
415
416 //make the object morph
morph_start(object * obj)417 void morph_start(object *obj)
418 {
419 polymodel *pm;
420 vms_vector pmmin,pmmax;
421 vms_vector box_size;
422 int i;
423 morph_data *md;
424
425 for (i=0;i<MAX_MORPH_OBJECTS;i++)
426 if (morph_objects[i].obj == NULL || morph_objects[i].obj->type==OBJ_NONE || morph_objects[i].obj->signature!=morph_objects[i].Morph_sig)
427 break;
428
429 if (i==MAX_MORPH_OBJECTS) //no free slots
430 return;
431
432 md = &morph_objects[i];
433
434 Assert(obj->render_type == RT_POLYOBJ);
435
436 md->obj = obj;
437 md->Morph_sig = obj->signature;
438
439 md->morph_save_control_type = obj->control_type;
440 md->morph_save_movement_type = obj->movement_type;
441 md->morph_save_phys_info = obj->mtype.phys_info;
442
443 Assert(obj->control_type == CT_AI); //morph objects are also AI objects
444
445 obj->control_type = CT_MORPH;
446 obj->render_type = RT_MORPH;
447 obj->movement_type = MT_PHYSICS; //RT_NONE;
448
449 obj->mtype.phys_info.rotvel = morph_rotvel;
450
451 pm = &Polygon_models[obj->rtype.pobj_info.model_num];
452
453 find_min_max(pm,0,&pmmin,&pmmax);
454
455 box_size.x = max(-pmmin.x,pmmax.x) / 2;
456 box_size.y = max(-pmmin.y,pmmax.y) / 2;
457 box_size.z = max(-pmmin.z,pmmax.z) / 2;
458
459 for (i=0;i<MAX_VECS;i++) //clear all points
460 md->morph_times[i] = 0;
461
462 for (i=1;i<MAX_SUBMODELS;i++) //clear all parts
463 md->submodel_active[i] = 0;
464
465 md->submodel_active[0] = 1; //1 means visible & animating
466
467 md->n_submodels_active = 1;
468
469 //now, project points onto surface of box
470
471 init_points(pm,&box_size,0,md);
472
473 }
474
draw_model(polymodel * pm,int submodel_num,vms_angvec * anim_angles,fix light,morph_data * md)475 void draw_model(polymodel *pm,int submodel_num,vms_angvec *anim_angles,fix light,morph_data *md)
476 {
477 int i,mn;
478 int facing;
479 int sort_list[MAX_SUBMODELS],sort_n;
480
481
482 //first, sort the submodels
483
484 sort_list[0] = submodel_num;
485 sort_n = 1;
486
487 for (i=0;i<pm->n_models;i++)
488
489 if (md->submodel_active[i] && pm->submodel_parents[i]==submodel_num) {
490
491 facing = g3_check_normal_facing(&pm->submodel_pnts[i],&pm->submodel_norms[i]);
492
493 if (!facing)
494
495 sort_list[sort_n++] = i;
496
497 else { //put at start
498 int t;
499
500 for (t=sort_n;t>0;t--)
501 sort_list[t] = sort_list[t-1];
502
503 sort_list[0] = i;
504
505 sort_n++;
506
507
508 }
509
510 }
511
512
513 //now draw everything
514
515 for (i=0;i<sort_n;i++) {
516
517 mn = sort_list[i];
518
519 if (mn == submodel_num) {
520 int i;
521
522 for (i=0;i<pm->n_textures;i++) {
523 texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[pm->first_texture+i]];
524 texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[pm->first_texture+i]].index];
525 }
526
527 #ifdef PIGGY_USE_PAGING
528 // Make sure the textures for this object are paged in...
529 piggy_page_flushed = 0;
530 for (i=0;i<pm->n_textures;i++)
531 PIGGY_PAGE_IN( texture_list_index[i] );
532 // Hmmm... cache got flushed in the middle of paging all these in,
533 // so we need to reread them all in.
534 if (piggy_page_flushed) {
535 piggy_page_flushed = 0;
536 for (i=0;i<pm->n_textures;i++)
537 PIGGY_PAGE_IN( texture_list_index[i] );
538 }
539 // Make sure that they can all fit in memory.
540 Assert( piggy_page_flushed == 0 );
541 #endif
542
543
544 g3_draw_morphing_model(&pm->model_data[pm->submodel_ptrs[submodel_num]],texture_list,anim_angles,light,&md->morph_vecs[md->submodel_startpoints[submodel_num]]);
545
546 }
547 else {
548
549 vms_matrix orient;
550
551 vm_angles_2_matrix(&orient,&anim_angles[mn]);
552
553 g3_start_instance_matrix(&pm->submodel_offsets[mn],&orient);
554
555 draw_model(pm,mn,anim_angles,light,md);
556
557 g3_done_instance();
558
559 }
560 }
561
562 }
563
draw_morph_object(object * obj)564 void draw_morph_object(object *obj)
565 {
566 // int save_light;
567 polymodel *po;
568 fix light;
569 morph_data *md;
570
571 md = find_morph_data(obj);
572 Assert(md != NULL);
573
574 Assert(obj->rtype.pobj_info.model_num < N_polygon_models);
575
576 po=&Polygon_models[obj->rtype.pobj_info.model_num];
577
578 light = compute_object_light(obj,NULL);
579
580 g3_start_instance_matrix(&obj->pos,&obj->orient);
581 g3_set_interp_points(robot_points);
582
583 draw_model(po,0,obj->rtype.pobj_info.anim_angles,light,md);
584
585 g3_done_instance();
586
587 #ifdef NEWDEMO
588 if (Newdemo_state == ND_STATE_RECORDING)
589 newdemo_record_morph_frame(md);
590 #endif
591
592 }
593
594