1 /* $Id: morph.c,v 1.3 2003-01-02 23:31:50 btb Exp $ */
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.
20 * Revision 1.5 1995/08/23 21:36:10 allender
21 * mcc compiler warnings fixed
23 * Revision 1.4 1995/08/12 11:34:19 allender
24 * removed #ifdef NEWDEMO -- always in
26 * Revision 1.3 1995/07/28 15:39:51 allender
27 * removed fixdiv thing
29 * Revision 1.2 1995/07/28 15:21:23 allender
30 * inverse magnitude fixup thing
32 * Revision 1.1 1995/05/16 15:28:05 allender
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.
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.
43 * Revision 1.35 1995/02/22 14:45:37 allender
44 * remove anonymous unions from object structure
46 * Revision 1.34 1995/01/14 19:16:52 john
47 * First version of new bitmap paging code.
49 * Revision 1.33 1995/01/03 20:38:36 john
50 * Externed MAX_MORPH_OBJECTS
52 * Revision 1.32 1994/11/17 15:34:04 matt
53 * Attempt #4 to fix morph bug
55 * Revision 1.31 1994/11/15 10:57:14 matt
56 * Tried again to fix morph
58 * Revision 1.30 1994/11/14 14:06:45 matt
61 * Revision 1.29 1994/11/14 11:55:13 matt
62 * Added divide overflow check
64 * Revision 1.28 1994/09/26 17:28:14 matt
65 * Made new multiple-object morph code work with the demo system
67 * Revision 1.27 1994/09/26 15:39:56 matt
68 * Allow multiple simultaneous morphing objects
70 * Revision 1.26 1994/09/11 22:44:59 mike
71 * quick on vecmat function.
73 * Revision 1.25 1994/08/26 15:36:00 matt
74 * Made eclips usable on more than one object at a time
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.
80 * Revision 1.23 1994/07/12 12:39:58 matt
81 * Revamped physics system
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.
87 * Revision 1.21 1994/06/27 15:53:01 john
88 * #define'd out the newdemo stuff
91 * Revision 1.20 1994/06/16 14:30:19 matt
92 * Moved morph record data call to reder routine
94 * Revision 1.19 1994/06/16 13:57:23 matt
95 * Added support for morphing objects in demos
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.
101 * Revision 1.17 1994/06/14 16:55:01 matt
102 * Got rid of physics_object speed field
104 * Revision 1.16 1994/06/08 21:16:29 matt
105 * Made objects spin while morphing
107 * Revision 1.15 1994/06/08 18:21:53 matt
108 * Made morphing objects light correctly
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.
114 * Revision 1.13 1994/06/01 16:33:59 yuan
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.
121 * Revision 1.11 1994/06/01 12:46:34 matt
122 * Added needed include
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
129 * Revision 1.9 1994/05/31 18:49:53 john
130 * Took out debugging printf's that Matt left in.
132 * Revision 1.8 1994/05/30 22:50:22 matt
133 * Added morph effect for robots
142 static char rcsid[] = "$Id: morph.c,v 1.3 2003-01-02 23:31:50 btb Exp $";
159 #include "lighting.h"
167 morph_data morph_objects[MAX_MORPH_OBJECTS];
169 //returns ptr to data for this object, or NULL if none
170 morph_data *find_morph_data(object *obj)
175 if (Newdemo_state == ND_STATE_PLAYBACK) {
176 morph_objects[0].obj = obj;
177 return &morph_objects[0];
181 for (i=0;i<MAX_MORPH_OBJECTS;i++)
182 if (morph_objects[i].obj == obj)
183 return &morph_objects[i];
189 //takes pm, fills in min & max
190 void find_min_max(polymodel *pm,int submodel_num,vms_vector *minv,vms_vector *maxv)
196 data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]];
200 Assert(type == 7 || type == 1);
205 data+=2; //skip start & pad
207 vp = (vms_vector *) data;
209 *minv = *maxv = *vp++; 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;
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;
225 #define MORPH_RATE (f1_0*3)
227 fix morph_rate = MORPH_RATE;
229 void init_points(polymodel *pm,vms_vector *box_size,int submodel_num,morph_data *md)
236 //printf("initing %d ",submodel_num);
238 data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]];
242 Assert(type == 7 || type == 1);
246 md->n_morphing_points[submodel_num] = 0;
249 i = *data++; //get start point number
253 i = 0; //start at zero
255 Assert(i+nverts < MAX_VECS);
257 md->submodel_startpoints[submodel_num] = i;
259 vp = (vms_vector *) data;
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;
273 if (k==0x7fffffff) k=0;
279 vm_vec_copy_scale(&md->morph_vecs[i],vp,k);
281 dist = vm_vec_normalized_dir_quick(&md->morph_deltas[i],vp,&md->morph_vecs[i]);
283 md->morph_times[i] = fixdiv(dist,morph_rate);
285 if (md->morph_times[i] != 0)
286 md->n_morphing_points[submodel_num]++;
288 vm_vec_scale(&md->morph_deltas[i],morph_rate);
294 //printf("npoints = %d\n",n_morphing_points[submodel_num]);
298 void update_points(polymodel *pm,int submodel_num,morph_data *md)
305 //printf("updating %d ",submodel_num);
307 data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]];
311 Assert(type == 7 || type == 1);
316 i = *data++; //get start point number
320 i = 0; //start at zero
322 vp = (vms_vector *) data;
326 if (md->morph_times[i]) //not done yet
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]--;
335 vm_vec_scale_add2(&md->morph_vecs[i],&md->morph_deltas[i],FrameTime);
341 //printf("npoints = %d\n",n_morphing_points[submodel_num]);
345 //process the morphing object for one frame
346 void do_morph_frame(object *obj)
352 md = find_morph_data(obj);
354 if (md == NULL) { //maybe loaded half-morphed from disk
355 obj->flags |= OF_SHOULD_BE_DEAD; //..so kill it
359 pm = &Polygon_models[md->obj->rtype.pobj_info.model_num];
361 //printf("morph_frame active = ");
362 //for (i=0;i<pm->n_models;i++)
363 // printf("%d ",submodel_active[i]);
367 for (i=0;i<pm->n_models;i++)
368 if (md->submodel_active[i]==1) {
370 update_points(pm,i,md);
372 if (md->n_morphing_points[i] == 0) { //maybe start submodel
375 md->submodel_active[i] = 2; //not animating, just visible
377 md->n_submodels_active--; //this one done animating
379 for (t=0;t<pm->n_models;t++)
380 if (pm->submodel_parents[t] == i) { //start this one
382 init_points(pm,NULL,t,md);
383 md->n_submodels_active++;
384 md->submodel_active[t] = 1;
391 if (!md->n_submodels_active) { //done morphing!
393 md->obj->control_type = md->morph_save_control_type;
394 md->obj->movement_type = md->morph_save_movement_type;
396 md->obj->render_type = RT_POLYOBJ;
398 md->obj->mtype.phys_info = md->morph_save_phys_info;
405 vms_vector morph_rotvel = {0x4000,0x2000,0x1000};
411 for (i=0;i<MAX_MORPH_OBJECTS;i++)
412 morph_objects[i].obj = NULL;
416 //make the object morph
417 void morph_start(object *obj)
420 vms_vector pmmin,pmmax;
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)
429 if (i==MAX_MORPH_OBJECTS) //no free slots
432 md = &morph_objects[i];
434 Assert(obj->render_type == RT_POLYOBJ);
437 md->Morph_sig = obj->signature;
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;
443 Assert(obj->control_type == CT_AI); //morph objects are also AI objects
445 obj->control_type = CT_MORPH;
446 obj->render_type = RT_MORPH;
447 obj->movement_type = MT_PHYSICS; //RT_NONE;
449 obj->mtype.phys_info.rotvel = morph_rotvel;
451 pm = &Polygon_models[obj->rtype.pobj_info.model_num];
453 find_min_max(pm,0,&pmmin,&pmmax);
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;
459 for (i=0;i<MAX_VECS;i++) //clear all points
460 md->morph_times[i] = 0;
462 for (i=1;i<MAX_SUBMODELS;i++) //clear all parts
463 md->submodel_active[i] = 0;
465 md->submodel_active[0] = 1; //1 means visible & animating
467 md->n_submodels_active = 1;
469 //now, project points onto surface of box
471 init_points(pm,&box_size,0,md);
475 void draw_model(polymodel *pm,int submodel_num,vms_angvec *anim_angles,fix light,morph_data *md)
479 int sort_list[MAX_SUBMODELS],sort_n;
482 //first, sort the submodels
484 sort_list[0] = submodel_num;
487 for (i=0;i<pm->n_models;i++)
489 if (md->submodel_active[i] && pm->submodel_parents[i]==submodel_num) {
491 facing = g3_check_normal_facing(&pm->submodel_pnts[i],&pm->submodel_norms[i]);
495 sort_list[sort_n++] = i;
497 else { //put at start
500 for (t=sort_n;t>0;t--)
501 sort_list[t] = sort_list[t-1];
513 //now draw everything
515 for (i=0;i<sort_n;i++) {
519 if (mn == submodel_num) {
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];
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] );
539 // Make sure that they can all fit in memory.
540 Assert( piggy_page_flushed == 0 );
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]]);
551 vm_angles_2_matrix(&orient,&anim_angles[mn]);
553 g3_start_instance_matrix(&pm->submodel_offsets[mn],&orient);
555 draw_model(pm,mn,anim_angles,light,md);
564 void draw_morph_object(object *obj)
571 md = find_morph_data(obj);
574 Assert(obj->rtype.pobj_info.model_num < N_polygon_models);
576 po=&Polygon_models[obj->rtype.pobj_info.model_num];
578 light = compute_object_light(obj,NULL);
580 g3_start_instance_matrix(&obj->pos,&obj->orient);
581 g3_set_interp_points(robot_points);
583 draw_model(po,0,obj->rtype.pobj_info.anim_angles,light,md);
588 if (Newdemo_state == ND_STATE_RECORDING)
589 newdemo_record_morph_frame(md);