1 /* $Id: morph.c,v 1.4 2004-08-28 23:17:45 schaffner 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.
26 static char rcsid[] = "$Id: morph.c,v 1.4 2004-08-28 23:17:45 schaffner Exp $";
51 morph_data morph_objects[MAX_MORPH_OBJECTS];
53 //returns ptr to data for this object, or NULL if none
54 morph_data *find_morph_data(object *obj)
59 if (Newdemo_state == ND_STATE_PLAYBACK) {
60 morph_objects[0].obj = obj;
61 return &morph_objects[0];
65 for (i=0;i<MAX_MORPH_OBJECTS;i++)
66 if (morph_objects[i].obj == obj)
67 return &morph_objects[i];
73 //takes pm, fills in min & max
74 void find_min_max(polymodel *pm,int submodel_num,vms_vector *minv,vms_vector *maxv)
80 data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]];
84 Assert(type == 7 || type == 1);
89 data+=2; //skip start & pad
91 vp = (vms_vector *) data;
93 *minv = *maxv = *vp++; nverts--;
96 if (vp->x > maxv->x) maxv->x = vp->x;
97 if (vp->y > maxv->y) maxv->y = vp->y;
98 if (vp->z > maxv->z) maxv->z = vp->z;
100 if (vp->x < minv->x) minv->x = vp->x;
101 if (vp->y < minv->y) minv->y = vp->y;
102 if (vp->z < minv->z) minv->z = vp->z;
109 #define MORPH_RATE (f1_0*3)
111 fix morph_rate = MORPH_RATE;
113 void init_points(polymodel *pm,vms_vector *box_size,int submodel_num,morph_data *md)
120 //printf("initing %d ",submodel_num);
122 data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]];
126 Assert(type == 7 || type == 1);
130 md->n_morphing_points[submodel_num] = 0;
133 i = *data++; //get start point number
137 i = 0; //start at zero
139 Assert(i+nverts < MAX_VECS);
141 md->submodel_startpoints[submodel_num] = i;
143 vp = (vms_vector *) data;
153 if (vp->x && f2i(box_size->x)<abs(vp->x)/2 && (t = fixdiv(box_size->x,abs(vp->x))) < k) k=t;
154 if (vp->y && f2i(box_size->y)<abs(vp->y)/2 && (t = fixdiv(box_size->y,abs(vp->y))) < k) k=t;
155 if (vp->z && f2i(box_size->z)<abs(vp->z)/2 && (t = fixdiv(box_size->z,abs(vp->z))) < k) k=t;
157 if (k==0x7fffffff) k=0;
163 vm_vec_copy_scale(&md->morph_vecs[i],vp,k);
165 dist = vm_vec_normalized_dir_quick(&md->morph_deltas[i],vp,&md->morph_vecs[i]);
167 md->morph_times[i] = fixdiv(dist,morph_rate);
169 if (md->morph_times[i] != 0)
170 md->n_morphing_points[submodel_num]++;
172 vm_vec_scale(&md->morph_deltas[i],morph_rate);
178 //printf("npoints = %d\n",n_morphing_points[submodel_num]);
182 void update_points(polymodel *pm,int submodel_num,morph_data *md)
189 //printf("updating %d ",submodel_num);
191 data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]];
195 Assert(type == 7 || type == 1);
200 i = *data++; //get start point number
204 i = 0; //start at zero
206 vp = (vms_vector *) data;
210 if (md->morph_times[i]) //not done yet
213 if ((md->morph_times[i] -= FrameTime) <= 0) {
214 md->morph_vecs[i] = *vp;
215 md->morph_times[i] = 0;
216 md->n_morphing_points[submodel_num]--;
219 vm_vec_scale_add2(&md->morph_vecs[i],&md->morph_deltas[i],FrameTime);
225 //printf("npoints = %d\n",n_morphing_points[submodel_num]);
229 //process the morphing object for one frame
230 void do_morph_frame(object *obj)
236 md = find_morph_data(obj);
238 if (md == NULL) { //maybe loaded half-morphed from disk
239 obj->flags |= OF_SHOULD_BE_DEAD; //..so kill it
243 pm = &Polygon_models[md->obj->rtype.pobj_info.model_num];
245 //printf("morph_frame active = ");
246 //for (i=0;i<pm->n_models;i++)
247 // printf("%d ",submodel_active[i]);
251 for (i=0;i<pm->n_models;i++)
252 if (md->submodel_active[i]==1) {
254 update_points(pm,i,md);
256 if (md->n_morphing_points[i] == 0) { //maybe start submodel
259 md->submodel_active[i] = 2; //not animating, just visible
261 md->n_submodels_active--; //this one done animating
263 for (t=0;t<pm->n_models;t++)
264 if (pm->submodel_parents[t] == i) { //start this one
266 init_points(pm,NULL,t,md);
267 md->n_submodels_active++;
268 md->submodel_active[t] = 1;
275 if (!md->n_submodels_active) { //done morphing!
277 md->obj->control_type = md->morph_save_control_type;
278 md->obj->movement_type = md->morph_save_movement_type;
280 md->obj->render_type = RT_POLYOBJ;
282 md->obj->mtype.phys_info = md->morph_save_phys_info;
289 vms_vector morph_rotvel = {0x4000,0x2000,0x1000};
295 for (i=0;i<MAX_MORPH_OBJECTS;i++)
296 morph_objects[i].obj = NULL;
300 //make the object morph
301 void morph_start(object *obj)
304 vms_vector pmmin,pmmax;
309 for (i=0;i<MAX_MORPH_OBJECTS;i++)
310 if (morph_objects[i].obj == NULL || morph_objects[i].obj->type==OBJ_NONE || morph_objects[i].obj->signature!=morph_objects[i].Morph_sig)
313 if (i==MAX_MORPH_OBJECTS) //no free slots
316 md = &morph_objects[i];
318 Assert(obj->render_type == RT_POLYOBJ);
321 md->Morph_sig = obj->signature;
323 md->morph_save_control_type = obj->control_type;
324 md->morph_save_movement_type = obj->movement_type;
325 md->morph_save_phys_info = obj->mtype.phys_info;
327 Assert(obj->control_type == CT_AI); //morph objects are also AI objects
329 obj->control_type = CT_MORPH;
330 obj->render_type = RT_MORPH;
331 obj->movement_type = MT_PHYSICS; //RT_NONE;
333 obj->mtype.phys_info.rotvel = morph_rotvel;
335 pm = &Polygon_models[obj->rtype.pobj_info.model_num];
337 find_min_max(pm,0,&pmmin,&pmmax);
339 box_size.x = max(-pmmin.x,pmmax.x) / 2;
340 box_size.y = max(-pmmin.y,pmmax.y) / 2;
341 box_size.z = max(-pmmin.z,pmmax.z) / 2;
343 for (i=0;i<MAX_VECS;i++) //clear all points
344 md->morph_times[i] = 0;
346 for (i=1;i<MAX_SUBMODELS;i++) //clear all parts
347 md->submodel_active[i] = 0;
349 md->submodel_active[0] = 1; //1 means visible & animating
351 md->n_submodels_active = 1;
353 //now, project points onto surface of box
355 init_points(pm,&box_size,0,md);
359 void draw_model(polymodel *pm,int submodel_num,vms_angvec *anim_angles,fix light,morph_data *md)
363 int sort_list[MAX_SUBMODELS],sort_n;
366 //first, sort the submodels
368 sort_list[0] = submodel_num;
371 for (i=0;i<pm->n_models;i++)
373 if (md->submodel_active[i] && pm->submodel_parents[i]==submodel_num) {
375 facing = g3_check_normal_facing(&pm->submodel_pnts[i],&pm->submodel_norms[i]);
379 sort_list[sort_n++] = i;
381 else { //put at start
384 for (t=sort_n;t>0;t--)
385 sort_list[t] = sort_list[t-1];
397 //now draw everything
399 for (i=0;i<sort_n;i++) {
403 if (mn == submodel_num) {
406 for (i=0;i<pm->n_textures;i++) {
407 texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[pm->first_texture+i]];
408 texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[pm->first_texture+i]].index];
411 #ifdef PIGGY_USE_PAGING
412 // Make sure the textures for this object are paged in...
413 piggy_page_flushed = 0;
414 for (i=0;i<pm->n_textures;i++)
415 PIGGY_PAGE_IN( texture_list_index[i] );
416 // Hmmm... cache got flushed in the middle of paging all these in,
417 // so we need to reread them all in.
418 if (piggy_page_flushed) {
419 piggy_page_flushed = 0;
420 for (i=0;i<pm->n_textures;i++)
421 PIGGY_PAGE_IN( texture_list_index[i] );
423 // Make sure that they can all fit in memory.
424 Assert( piggy_page_flushed == 0 );
428 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]]);
435 vm_angles_2_matrix(&orient,&anim_angles[mn]);
437 g3_start_instance_matrix(&pm->submodel_offsets[mn],&orient);
439 draw_model(pm,mn,anim_angles,light,md);
448 void draw_morph_object(object *obj)
455 md = find_morph_data(obj);
458 Assert(obj->rtype.pobj_info.model_num < N_polygon_models);
460 po=&Polygon_models[obj->rtype.pobj_info.model_num];
462 light = compute_object_light(obj,NULL);
464 g3_start_instance_matrix(&obj->pos,&obj->orient);
465 g3_set_interp_points(robot_points);
467 draw_model(po,0,obj->rtype.pobj_info.anim_angles,light,md);
472 if (Newdemo_state == ND_STATE_RECORDING)
473 newdemo_record_morph_frame(md);