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