Exemplo n.º 1
0
//draw an object which renders as a vclip
void draw_vclip_object(object *obj,fix timeleft,int lighted, int vclip_num)
{
	int nf,bitmapnum;

	nf = Vclip[vclip_num].num_frames;

	bitmapnum =  (nf - f2i(fixdiv( (nf-1)*timeleft,Vclip[vclip_num].play_time))) - 1;

	if (bitmapnum >= Vclip[vclip_num].num_frames)
		bitmapnum=Vclip[vclip_num].num_frames-1;

	if (bitmapnum >= 0 )	{

		if (Vclip[vclip_num].flags & VF_ROD)
			draw_object_tmap_rod(obj, Vclip[vclip_num].frames[bitmapnum],lighted);
		else {
			Assert(lighted==0);		//blob cannot now be lighted

			draw_object_blob(obj, Vclip[vclip_num].frames[bitmapnum] );
		}
	}

}
Exemplo n.º 2
0
//performs aspect scaling on global view matrix
void scale_matrix(void) {
	Unscaled_matrix = View_matrix;		//so we can use unscaled if we want

	Matrix_scale = Window_scale;

	if (View_zoom <= f1_0) 		//zoom in by scaling z

		Matrix_scale.z = fixmul(Matrix_scale.z, View_zoom);

	else {			//zoom out by scaling x&y

		fix s = fixdiv(f1_0, View_zoom);

		Matrix_scale.x = fixmul(Matrix_scale.x, s);
		Matrix_scale.y = fixmul(Matrix_scale.y, s);
	}

	//now scale matrix elements

	vm_vec_scale(&View_matrix.rvec, Matrix_scale.x);
	vm_vec_scale(&View_matrix.uvec, Matrix_scale.y);
	vm_vec_scale(&View_matrix.fvec, Matrix_scale.z);

}
Exemplo n.º 3
0
void initWeights(filter * f) 
{
	fix sum;
	long i;

	// Generate weights.
	sum = 0;
	for (i=0; i < f->len; i++) {
		//f->weights[i] = i;		// Linear ramp
		//f->weights[i] = i*i;		// Exp ramp
		f->weights[i] = F1_0;		// Average

	}

	// Summate.
	for (i=0; i < f->len; i++) {
		sum += f->weights[i];
	}

	// Normalize and convert to fixed point.
	for (i=0; i < f->len; i++) {
		f->weights[i] = fixdiv(f->weights[i],sum);
	} 
}
Exemplo n.º 4
0
void draw_all_edges(automap *am)	
{
	g3s_codes cc;
	int i,j,nbright;
	ubyte nfacing,nnfacing;
	Edge_info *e;
	vms_vector *tv1;
	fix distance;
	fix min_distance = 0x7fffffff;
	g3s_point *p1, *p2;
	
	
	nbright=0;

	for (i=0; i<=am->highest_edge_index; i++ )	{
		//e = &am->edges[Edge_used_list[i]];
		e = &am->edges[i];
		if (!(e->flags & EF_USED)) continue;

		if ( e->flags & EF_TOO_FAR) continue;

		if (e->flags&EF_FRONTIER) { 	// A line that is between what we have seen and what we haven't
			if ( (!(e->flags&EF_SECRET))&&(e->color==am->wall_normal_color))
				continue; 	// If a line isn't secret and is normal color, then don't draw it
		}

		cc=rotate_list(2,e->verts);
		distance = Segment_points[e->verts[1]].p3_z;

		if (min_distance>distance )
			min_distance = distance;

		if (!cc.uand) {			//all off screen?
			nfacing = nnfacing = 0;
			tv1 = &Vertices[e->verts[0]];
			j = 0;
			while( j<e->num_faces && (nfacing==0 || nnfacing==0) )	{
#ifdef COMPACT_SEGS
				vms_vector temp_v;
				get_side_normal(&Segments[e->segnum[j]], e->sides[j], 0, &temp_v );
				if (!g3_check_normal_facing( tv1, &temp_v ) )
#else
				if (!g3_check_normal_facing( tv1, &Segments[e->segnum[j]].sides[e->sides[j]].normals[0] ) )
#endif
					nfacing++;
				else
					nnfacing++;
				j++;
			}

			if ( nfacing && nnfacing )	{
				// a contour line
				am->drawingListBright[nbright++] = e-am->edges;
			} else if ( e->flags&(EF_DEFINING|EF_GRATE) )	{
				if ( nfacing == 0 )	{
					if ( e->flags & EF_NO_FADE )
						gr_setcolor( e->color );
					else
						gr_setcolor( gr_fade_table[e->color+256*8] );
					g3_draw_line( &Segment_points[e->verts[0]], &Segment_points[e->verts[1]] );
				} 	else {
					am->drawingListBright[nbright++] = e-am->edges;
				}
			}
		}
	}
		
	if ( min_distance < 0 ) min_distance = 0;

	// Sort the bright ones using a shell sort
	{
		int t;
		int i, j, incr, v1, v2;
	
		incr = nbright / 2;
		while( incr > 0 )	{
			for (i=incr; i<nbright; i++ )	{
				j = i - incr;
				while (j>=0 )	{
					// compare element j and j+incr
					v1 = am->edges[am->drawingListBright[j]].verts[0];
					v2 = am->edges[am->drawingListBright[j+incr]].verts[0];

					if (Segment_points[v1].p3_z < Segment_points[v2].p3_z) {
						// If not in correct order, them swap 'em
						t=am->drawingListBright[j+incr];
						am->drawingListBright[j+incr]=am->drawingListBright[j];
						am->drawingListBright[j]=t;
						j -= incr;
					}
					else
						break;
				}
			}
			incr = incr / 2;
		}
	}
					
	// Draw the bright ones
	for (i=0; i<nbright; i++ )	{
		int color;
		fix dist;
		e = &am->edges[am->drawingListBright[i]];
		p1 = &Segment_points[e->verts[0]];
		p2 = &Segment_points[e->verts[1]];
		dist = p1->p3_z - min_distance;
		// Make distance be 1.0 to 0.0, where 0.0 is 10 segments away;
		if ( dist < 0 ) dist=0;
		if ( dist >= am->farthest_dist ) continue;

		if ( e->flags & EF_NO_FADE )	{
			gr_setcolor( e->color );
		} else {
			dist = F1_0 - fixdiv( dist, am->farthest_dist );
			color = f2i( dist*31 );
			gr_setcolor( gr_fade_table[e->color+color*256] );	
		}
		g3_draw_line( p1, p2 );
	}
}
Exemplo n.º 5
0
int gr_set_mode(u_int32_t mode)
{
	unsigned int w, h;
	ggi_mode other_mode;	

#ifdef NOGRAPH
	return 0;
#endif
	if (mode<=0)
		return 0;

	w=SM_W(mode);
	h=SM_H(mode);
	
	
	gr_palette_clear();

	if(ggiCheckGraphMode(screenvis, w, h, GGI_AUTO, GGI_AUTO, GT_8BIT, &other_mode))
		ggiSetMode(screenvis, &other_mode);
	else
		ggiSetGraphMode(screenvis, w, h, GGI_AUTO, GGI_AUTO, GT_8BIT);

	ggiSetFlags(screenvis, GGIFLAG_ASYNC);
		
	if (!ggiDBGetNumBuffers(screenvis))
		use_directbuffer = 0;
	else
	{	
		dbuffer = ggiDBGetBuffer(screenvis, 0);
		if (!(dbuffer->type & GGI_DB_SIMPLE_PLB))
			use_directbuffer = 0;
		else
			use_directbuffer = 1;
	}

        memset(grd_curscreen, 0, sizeof(grs_screen));

	grd_curscreen->sc_mode = mode;
	grd_curscreen->sc_w = w;
	grd_curscreen->sc_h = h;
	grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4);
	grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0;
	grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0;
	grd_curscreen->sc_canvas.cv_bitmap.bm_w = w;
	grd_curscreen->sc_canvas.cv_bitmap.bm_h = h;
	grd_curscreen->sc_canvas.cv_bitmap.bm_type = BM_LINEAR;

	if (use_directbuffer)
	{
	        grd_curscreen->sc_canvas.cv_bitmap.bm_data = dbuffer->write;
        	grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = dbuffer->buffer.plb.stride;
	}
	else
	{
		free(screenbuffer);
		screenbuffer = malloc (w * h);
		grd_curscreen->sc_canvas.cv_bitmap.bm_data = screenbuffer;
		grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = w;
	}

	gr_set_current_canvas(NULL);
	
	gamefont_choose_game_font(w,h);
	
	return 0;
}
Exemplo n.º 6
0
do_endlevel_frame()
{
	static fix timer;
	vms_vector save_last_pos;
	static fix explosion_wait1=0;
	static fix explosion_wait2=0;
	static fix bank_rate;
	static fix ext_expl_halflife;

	save_last_pos = ConsoleObject->last_pos;	//don't let move code change this
	object_move_all();
	ConsoleObject->last_pos = save_last_pos;

	if (ext_expl_playing) {

		external_explosion.lifeleft -= FrameTime;
		do_explosion_sequence(&external_explosion);

		if (external_explosion.lifeleft < ext_expl_halflife)
			mine_destroyed = 1;

		if (external_explosion.flags & OF_SHOULD_BE_DEAD)
			ext_expl_playing = 0;
	}

	if (cur_fly_speed != desired_fly_speed) {
		fix delta = desired_fly_speed - cur_fly_speed;
		fix frame_accel = fixmul(FrameTime,FLY_ACCEL);

		if (abs(delta) < frame_accel)
			cur_fly_speed = desired_fly_speed;
		else
			if (delta > 0)
				cur_fly_speed += frame_accel;
			else
				cur_fly_speed -= frame_accel;
	}

	//do big explosions
	if (!outside_mine) {

		if (Endlevel_sequence==EL_OUTSIDE) {
			vms_vector tvec;

			vm_vec_sub(&tvec,&ConsoleObject->pos,&mine_side_exit_point);

			if (vm_vec_dot(&tvec,&mine_exit_orient.fvec) > 0) {
				object *tobj;

				outside_mine = 1;

				tobj = object_create_explosion(exit_segnum,&mine_side_exit_point,i2f(50),VCLIP_BIG_PLAYER_EXPLOSION);

				if (tobj) {
					external_explosion = *tobj;

					tobj->flags |= OF_SHOULD_BE_DEAD;

					flash_scale = 0;	//kill lights in mine

					ext_expl_halflife = tobj->lifeleft;

					ext_expl_playing = 1;
				}
	
				digi_link_sound_to_pos( SOUND_BIG_ENDLEVEL_EXPLOSION, exit_segnum, 0, &mine_side_exit_point, 0, i2f(3)/4 );
			}
		}

		//do explosions chasing player
		if ((explosion_wait1-=FrameTime) < 0) {
			vms_vector tpnt;
			int segnum;
			object *expl;
			static int sound_count;

			vm_vec_scale_add(&tpnt,&ConsoleObject->pos,&ConsoleObject->orient.fvec,-ConsoleObject->size*5);
			vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.rvec,(rand()-RAND_MAX/2)*15);
			vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.uvec,(rand()-RAND_MAX/2)*15);

			segnum = find_point_seg(&tpnt,ConsoleObject->segnum);

			if (segnum != -1) {
				expl = object_create_explosion(segnum,&tpnt,i2f(20),VCLIP_BIG_PLAYER_EXPLOSION);
				if (rand()<10000 || ++sound_count==7) {		//pseudo-random
					digi_link_sound_to_pos( SOUND_TUNNEL_EXPLOSION, segnum, 0, &tpnt, 0, F1_0 );
					sound_count=0;
				}
			}

			explosion_wait1 = 0x2000 + rand()/4;

		}
	}

	//do little explosions on walls
	if (Endlevel_sequence >= EL_FLYTHROUGH && Endlevel_sequence < EL_OUTSIDE)
		if ((explosion_wait2-=FrameTime) < 0) {
			vms_vector tpnt;
			fvi_query fq;
			fvi_info hit_data;

			//create little explosion on wall

			vm_vec_copy_scale(&tpnt,&ConsoleObject->orient.rvec,(rand()-RAND_MAX/2)*100);
			vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.uvec,(rand()-RAND_MAX/2)*100);
			vm_vec_add2(&tpnt,&ConsoleObject->pos);

			if (Endlevel_sequence == EL_FLYTHROUGH)
				vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.fvec,rand()*200);
			else
				vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.fvec,rand()*60);

			//find hit point on wall

			fq.p0 = &ConsoleObject->pos;
			fq.p1 = &tpnt;
			fq.startseg = ConsoleObject->segnum;
			fq.rad = 0;
			fq.thisobjnum = 0;
			fq.ignore_obj_list = NULL;
			fq.flags = 0;

			find_vector_intersection(&fq,&hit_data);

			if (hit_data.hit_type==HIT_WALL && hit_data.hit_seg!=-1)
				object_create_explosion(hit_data.hit_seg,&hit_data.hit_pnt,i2f(3)+rand()*6,VCLIP_SMALL_EXPLOSION);

			explosion_wait2 = (0xa00 + rand()/8)/2;
		}

	switch (Endlevel_sequence) {

		case EL_OFF: return;

		case EL_FLYTHROUGH: {

			do_endlevel_flythrough(0);

			if (ConsoleObject->segnum == transition_segnum) {
				int objnum;

				Endlevel_sequence = EL_LOOKBACK;

				objnum = obj_create(OBJ_CAMERA, 0, 
					ConsoleObject->segnum,&ConsoleObject->pos,&ConsoleObject->orient,0,
					CT_NONE,MT_NONE,RT_NONE);

				if (objnum == -1) {				//can't get object, so abort
					mprintf((1, "Can't get object for endlevel sequence.  Aborting endlevel sequence.\n"));
					stop_endlevel_sequence();
					return;
				}

				Viewer = endlevel_camera = &Objects[objnum];

				select_cockpit(CM_LETTERBOX);

				fly_objects[1] = fly_objects[0];
				fly_objects[1].obj = endlevel_camera;
				fly_objects[1].speed = (5*cur_fly_speed)/4;
				fly_objects[1].offset_frac = 0x4000;

				vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,i2f(7));

				timer=0x20000;
			}

			break;
		}


		case EL_LOOKBACK: {

			do_endlevel_flythrough(0);
			do_endlevel_flythrough(1);

			if (timer>0) {

				timer -= FrameTime;

				if (timer < 0)		//reduce speed
					fly_objects[1].speed = fly_objects[0].speed;
			}

			if (endlevel_camera->segnum == exit_segnum) {
				vms_angvec cam_angles,exit_seg_angles;

				Endlevel_sequence = EL_OUTSIDE;

				timer = i2f(2);

				vm_vec_negate(&endlevel_camera->orient.fvec);
				vm_vec_negate(&endlevel_camera->orient.rvec);

				vm_extract_angles_matrix(&cam_angles,&endlevel_camera->orient);
				vm_extract_angles_matrix(&exit_seg_angles,&mine_exit_orient);
				bank_rate = (-exit_seg_angles.b - cam_angles.b)/2;

				ConsoleObject->control_type = endlevel_camera->control_type = CT_NONE;

				//_MARK_("Starting outside");//Commented out by KRB

#ifdef SLEW_ON
 slew_obj = endlevel_camera;
#endif
			}
				
			break;
		}

		case EL_OUTSIDE: {
			#ifndef SLEW_ON
			vms_angvec cam_angles;
			#endif

			vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed));
#ifndef SLEW_ON
			vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,fixmul(FrameTime,-2*cur_fly_speed));
			vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.uvec,fixmul(FrameTime,-cur_fly_speed/10));

			vm_extract_angles_matrix(&cam_angles,&endlevel_camera->orient);
			cam_angles.b += fixmul(bank_rate,FrameTime);
			vm_angles_2_matrix(&endlevel_camera->orient,&cam_angles);
#endif

			timer -= FrameTime;

			if (timer < 0) {

				Endlevel_sequence = EL_STOPPED;

				vm_extract_angles_matrix(&player_angles,&ConsoleObject->orient);

				timer = i2f(3);

			}

			break;
		}

		case EL_STOPPED: {

			get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos);
			chase_angles(&player_angles,&player_dest_angles);
			vm_angles_2_matrix(&ConsoleObject->orient,&player_angles);

			vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed));

			timer -= FrameTime;

			if (timer < 0) {

				#ifdef SLEW_ON
				slew_obj = endlevel_camera;
				_do_slew_movement(endlevel_camera,1,1);
				timer += FrameTime;		//make time stop
				break;
				#else

				#ifdef SHORT_SEQUENCE

				stop_endlevel_sequence();

				#else
				Endlevel_sequence = EL_PANNING;

				vm_extract_angles_matrix(&camera_cur_angles,&endlevel_camera->orient);


				timer = i2f(3);

				if (Game_mode & GM_MULTI) { // try to skip part of the seq if multiplayer
					stop_endlevel_sequence();
					return;
				}

				//mprintf((0,"Switching to pan...\n"));
				#endif		//SHORT_SEQUENCE
				#endif		//SLEW_ON

			}
			break;
		}

		#ifndef SHORT_SEQUENCE
		case EL_PANNING: {
			#ifndef SLEW_ON
			int mask;
			#endif

			get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos);
			chase_angles(&player_angles,&player_dest_angles);
			vm_angles_2_matrix(&ConsoleObject->orient,&player_angles);
			vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed));

			#ifdef SLEW_ON
			_do_slew_movement(endlevel_camera,1,1);
			#else

			get_angs_to_object(&camera_desired_angles,&ConsoleObject->pos,&endlevel_camera->pos);
			mask = chase_angles(&camera_cur_angles,&camera_desired_angles);
			vm_angles_2_matrix(&endlevel_camera->orient,&camera_cur_angles);

			if ((mask&5) == 5) {

				vms_vector tvec;

				Endlevel_sequence = EL_CHASING;

				//_MARK_("Done outside");//Commented out -KRB

				vm_vec_normalized_dir_quick(&tvec,&station_pos,&ConsoleObject->pos);
				vm_vector_2_matrix(&ConsoleObject->orient,&tvec,&surface_orient.uvec,NULL);

				desired_fly_speed *= 2;

				//mprintf((0,"Switching to chase...\n"));

			}
			#endif

			break;
		}

		case EL_CHASING: {
			fix d,speed_scale;

			#ifdef SLEW_ON
			_do_slew_movement(endlevel_camera,1,1);
			#endif

			get_angs_to_object(&camera_desired_angles,&ConsoleObject->pos,&endlevel_camera->pos);
			chase_angles(&camera_cur_angles,&camera_desired_angles);

			#ifndef SLEW_ON
			vm_angles_2_matrix(&endlevel_camera->orient,&camera_cur_angles);
			#endif

			d = vm_vec_dist_quick(&ConsoleObject->pos,&endlevel_camera->pos);

			speed_scale = fixdiv(d,i2f(0x20));
			if (d<f1_0) d=f1_0;

			get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos);
			chase_angles(&player_angles,&player_dest_angles);
			vm_angles_2_matrix(&ConsoleObject->orient,&player_angles);

			vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed));
			#ifndef SLEW_ON
			vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,fixmul(FrameTime,fixmul(speed_scale,cur_fly_speed)));

			if (vm_vec_dist(&ConsoleObject->pos,&station_pos) < i2f(10))
				stop_endlevel_sequence();
			#endif

			break;

		}
		#endif		//ifdef SHORT_SEQUENCE
	}
}
Exemplo n.º 7
0
void objfly_move_to_new_segment( object * obj, short newseg, int first_time )
{
	segment *pseg;
	int old_object_seg = obj->segnum;

	if ( newseg != obj->segnum )
		obj_relink(obj-Objects, newseg );

	pseg = &Segments[obj->segnum];

	if ( first_time || obj->segnum != old_object_seg) {		//moved into new seg
		vms_vector curcenter,nextcenter;
		fix step_size,seg_time;
		short entry_side,exit_side;	//what sides we entry and leave through
		vms_vector dest_point;		//where we are heading (center of exit_side)
		vms_angvec dest_angles;		//where we want to be pointing

		//find new exit side

		if ( !first_time ) {

			entry_side = matt_find_connect_side(obj->segnum,old_object_seg);
			exit_side = Side_opposite[entry_side];
		}

		//if (first_time) obj->fly_info.ft_mode = FP_FORWARD;

		if (first_time || entry_side==-1 || (pseg->children[exit_side]==-1) || (obj->fly_info.ft_mode!=FP_FORWARD) ) {
			int i;
			vms_vector prefvec,segcenter,sidevec;
			fix best_val=-f2_0;
			int best_side;

			//find exit side

			if (obj->fly_info.ft_mode == FP_FORWARD) {
				if (first_time) 
					prefvec = obj->orient.fvec;
				else
					prefvec = obj->fly_info.heading;
				vm_vec_normalize(&prefvec);
			}
			else
				prefvec = obj->orient.vecs[obj->fly_info.ft_mode%3];

			if (obj->fly_info.ft_mode >= 3) {prefvec.x = -prefvec.x; prefvec.y = -prefvec.y; prefvec.z = -prefvec.z;}

			compute_segment_center(&segcenter,pseg);

			best_side=-1;
			for (i=MAX_SIDES_PER_SEGMENT;--i >= 0;) {
				fix d;

				if (pseg->children[i]!=-1) {

					compute_center_point_on_side(&sidevec,pseg,i);
					vm_vec_sub2(&sidevec,&segcenter);
					vm_vec_normalize(&sidevec);
					d = vm_vec_dotprod(&sidevec,&prefvec);

					if (labs(d) < MIN_D) d=0;

					if (d > best_val || (d==best_val && i==exit_side)) {best_val=d; best_side=i;}

				}
			}

			if (best_val > 0) obj->fly_info.ft_mode = FP_FORWARD;

			Assert(best_side!=-1);

			exit_side = best_side;
		}

		//update target point & angles

		compute_center_point_on_side(&dest_point,pseg,exit_side);

		//update target point and movement points

		vm_vec_sub(&obj->phys_info.velocity,&dest_point,&obj->pos);
		step_size = vm_vec_normalize(&obj->phys_info.velocity);
		vm_vec_scale(&obj->phys_info.velocity, obj->phys_info.speed);

		compute_segment_center(&curcenter,pseg);
		compute_segment_center(&nextcenter,&Segments[pseg->children[exit_side]]);
		vm_vec_sub(&obj->fly_info.heading,&nextcenter,&curcenter);

		angles_from_vector(&dest_angles,&obj->fly_info.heading);	//extract angles

		if (first_time) 
			angles_from_vector(&obj->phys_info.rotvel,&obj->orient.fvec);

		seg_time = fixdiv(step_size,obj->phys_info.speed);	//how long through seg

		if (seg_time) {
			obj->fly_info.angle_step.p = fixdiv(delta_ang(obj->phys_info.rotvel.p,dest_angles.p),seg_time);
			obj->fly_info.angle_step.b = fixdiv(delta_ang(obj->phys_info.rotvel.b,dest_angles.b),seg_time);
			obj->fly_info.angle_step.h = fixdiv(delta_ang(obj->phys_info.rotvel.h,dest_angles.h),seg_time);
		}
		else {
			obj->phys_info.rotvel = dest_angles;
			obj->fly_info.angle_step.p = obj->fly_info.angle_step.b = obj->fly_info.angle_step.h = 0;
		}
	}
}
Exemplo n.º 8
0
int gr_set_mode(u_int32_t mode)
{
	int w,h;
	
#ifdef NOGRAPH
	return 0;
#endif

	if (mode<=0)
		return 0;

	w=SM_W(mode);
	h=SM_H(mode);
	
	if (screen != NULL) gr_palette_clear();

//added on 11/06/98 by Matt Mueller to set the title bar. (moved from below)
//sekmu: might wanna copy this litte blurb to one of the text files or something
//we want to set it here so that X window manager "Style" type commands work
//for example, in fvwm2 or fvwm95:
//Style "D1X*"  NoTitle, NoHandles, BorderWidth 0
//if you can't use -fullscreen like me (crashes X), this is a big help in
//getting the window centered correctly (if you use SmartPlacement)
	SDL_WM_SetCaption(DESCENT_VERSION " " D1X_DATE, "Descent");
//end addition -MM

//edited 10/05/98 by Matt Mueller - make fullscreen mode optional
	  // changed by adb on 980913: added SDL_HWPALETTE (should be option?)
        // changed by someone on 980923 to add SDL_FULLSCREEN
	if(!checkvidmodeok || SDL_VideoModeOK(w,h,8,sdl_video_flags)){
	  screen = SDL_SetVideoMode(w, h, 8, sdl_video_flags);
	} else {
	  screen=NULL;
	}
        // end changes by someone
        // end changes by adb
//end edit -MM
        if (screen == NULL) {
           Error("Could not set %dx%dx8 video mode\n",w,h);
           exit(1);
        }
	memset( grd_curscreen, 0, sizeof(grs_screen));
	grd_curscreen->sc_mode = mode;
	grd_curscreen->sc_w = w;
	grd_curscreen->sc_h = h;
	grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4);
	grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0;
	grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0;
	grd_curscreen->sc_canvas.cv_bitmap.bm_w = w;
	grd_curscreen->sc_canvas.cv_bitmap.bm_h = h;
	grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = screen->pitch;
	grd_curscreen->sc_canvas.cv_bitmap.bm_type = BM_LINEAR;
	grd_curscreen->sc_canvas.cv_bitmap.bm_data = (unsigned char *)screen->pixels;
	gr_set_current_canvas(NULL);
	//gr_enable_default_palette_loading();

//added on 9/30/98 by Matt Mueller to hide the mouse if its over the game window
	SDL_ShowCursor(0);
//end addition -MM
//--moved up--added on 9/30/98 by Matt Mueller to set the title bar.  Woohoo!
//--moved up--	SDL_WM_SetCaption(DESCENT_VERSION " " D1X_DATE, NULL);
//--moved up--end addition -MM

	gamefont_choose_game_font(w,h);
	return 0;
}
Exemplo n.º 9
0
void do_decloaking_wall_frame(int cloaking_wall_num)
{
	cloaking_wall *d;
	wall *wfront,*wback;
	sbyte old_cloak; // for demo recording

	if ( Newdemo_state==ND_STATE_PLAYBACK ) return;

	d = &CloakingWalls[cloaking_wall_num];
	wfront = &Walls[d->front_wallnum];
	wback = (d->back_wallnum > -1) ? Walls + d->back_wallnum : NULL;

	old_cloak = wfront->cloak_value;

	d->time += FrameTime;

	if (d->time > CLOAKING_WALL_TIME) {
		int i;

		wfront->state = WALL_DOOR_CLOSED;
		if (wback)
			wback->state = WALL_DOOR_CLOSED;

		for (i=0;i<4;i++) {
			Segments[wfront->segnum].sides[wfront->sidenum].uvls[i].l = d->front_ls[i];
			if (wback)
				Segments[wback->segnum].sides[wback->sidenum].uvls[i].l = d->back_ls[i];
		}

		for (i=cloaking_wall_num;i<Num_cloaking_walls;i++)
			CloakingWalls[i] = CloakingWalls[i+1];
		Num_cloaking_walls--;

	}
	else if (d->time > CLOAKING_WALL_TIME/2) {		//fading in
		fix light_scale;
		int i;

		wfront->type = wback->type = WALL_CLOSED;

		light_scale = fixdiv(d->time-CLOAKING_WALL_TIME/2,CLOAKING_WALL_TIME/2);

		for (i=0;i<4;i++) {
			Segments[wfront->segnum].sides[wfront->sidenum].uvls[i].l = fixmul(d->front_ls[i],light_scale);
			if (wback)
			Segments[wback->segnum].sides[wback->sidenum].uvls[i].l = fixmul(d->back_ls[i],light_scale);
		}
	}
	else {		//cloaking in
		wfront->cloak_value = ((CLOAKING_WALL_TIME/2 - d->time) * (GR_FADE_LEVELS-2)) / (CLOAKING_WALL_TIME/2);
		wfront->type = WALL_CLOAKED;
		if (wback) {
			wback->cloak_value = wfront->cloak_value;
			wback->type = WALL_CLOAKED;
		}
	}

	// check if the actual cloak_value changed in this frame to prevent redundant recordings and wasted bytes
	if ( Newdemo_state == ND_STATE_RECORDING && (wfront->cloak_value != old_cloak || d->time == FrameTime) )
		newdemo_record_cloaking_wall(d->front_wallnum, d->back_wallnum, wfront->type, wfront->state, wfront->cloak_value, Segments[wfront->segnum].sides[wfront->sidenum].uvls[0].l, Segments[wfront->segnum].sides[wfront->sidenum].uvls[1].l, Segments[wfront->segnum].sides[wfront->sidenum].uvls[2].l, Segments[wfront->segnum].sides[wfront->sidenum].uvls[3].l);

}
Exemplo n.º 10
0
//	For curtime, return location and pbh
//	Return 1 if demo playback over.
//	Curtime should be current absolute time.  Internally, Demo_start_time is subtracted.
int get_demo_data(fix curtime, vms_vector *pos, vms_angvec *pbh, short *segnum, int *do_fire)
{
	int		rec;
	demorec	*demo_ptr, *demo_ptr2;
	fix		base_x, base_y, base_z;
	fixang	base_p, base_b, base_h;

	fix		delta_x, delta_y, delta_z;
	fixang	delta_p, delta_b, delta_h;
	fix		delta_time, scale_time, extra_time;

	rec = 0;

	curtime -= Demo_start_time;

	while ((curtime > Demo_records[rec].time) && (rec < Num_demo_recs-1))
		rec++;

	if (rec > 0)
		rec--;		// we overshot

//mprintf(0,"Record = %3i ", rec);

	if (rec >= Num_demo_recs-2) {
		// mprintf(0, "DONE!\n");
		start_demo_playback();
		return 1;		// done doing demo playback
	}

	demo_ptr = &Demo_records[rec];
	demo_ptr2 = &Demo_records[rec+1];

	extra_time = curtime - demo_ptr->time;

	base_x = demo_ptr->x;
	base_y = demo_ptr->y;
	base_z = demo_ptr->z;
	base_p = demo_ptr->p;
	base_b = demo_ptr->b;
	base_h = demo_ptr->h;

	delta_x = demo_ptr2->x - base_x;
	delta_y = demo_ptr2->y - base_y;
	delta_z = demo_ptr2->z - base_z;
	delta_p = demo_ptr2->p - base_p;
	delta_b = demo_ptr2->b - base_b;
	delta_h = demo_ptr2->h - base_h;

	delta_time = demo_ptr2->time - demo_ptr->time;

	if (curtime != 0) {
		scale_time = fixdiv(extra_time, delta_time);
		base_x += fixmul(delta_x, scale_time);
		base_y += fixmul(delta_y, scale_time);
		base_z += fixmul(delta_z, scale_time);
		base_p += fixmul(delta_p, scale_time);
		base_b += fixmul(delta_b, scale_time);
		base_h += fixmul(delta_h, scale_time);
	}

//mprintf(0, "%8x %8x %8x %4x %4x %4x\n", base_x, base_y, base_z, base_p, base_b, base_h);

	pos->x = base_x;
	pos->y = base_y;
	pos->z = base_z;

	pbh->p = base_p;
	pbh->b = base_b;
	pbh->h = base_h;

	*segnum = demo_ptr->segnum;

//	if (demo_ptr->specials)
//		*do_fire = 1;
//	else
		*do_fire = 0;
//	if (demo_ptr->specials)
//		switch (Demo_frame_count %10) {
//			case 0:
//			case 1:
//			case 3:
//			case 5:
//			case 8:
//				*do_fire = 1;
//				break;
//			default:
//				*do_fire = 0;
//		}
	return 0;

}
Exemplo n.º 11
0
// ----------------------------------------------------------------------------------------------
void set_dynamic_light(void)
{
	int	objnum,vertnum;
	int	n_render_vertices;
	short	render_vertices[MAX_VERTICES];
	byte	render_vertex_flags[MAX_VERTICES];
	int	render_seg,segnum, v;

	if (!Do_dynamic_light)
		return;

	memset(render_vertex_flags, 0, Highest_vertex_index+1);

	//	Create list of vertices that need to be looked at for setting of ambient light.
	n_render_vertices = 0;
	for (render_seg=0; render_seg<N_render_segs; render_seg++) {
		segnum = Render_list[render_seg];
		if (segnum != -1) {
			short	*vp = Segments[segnum].verts;
			for (v=0; v<MAX_VERTICES_PER_SEGMENT; v++) {
				int	vnum = vp[v];
				if (vnum<0 || vnum>Highest_vertex_index) {
					Int3();		//invalid vertex number
					continue;	//ignore it, and go on to next one
				}
				if (!render_vertex_flags[vnum]) {
					render_vertex_flags[vnum] = 1;
					render_vertices[n_render_vertices++] = vnum;
				}
				//--old way-- for (s=0; s<n_render_vertices; s++)
				//--old way-- 	if (render_vertices[s] == vnum)
				//--old way-- 		break;
				//--old way-- if (s == n_render_vertices)
				//--old way-- 	render_vertices[n_render_vertices++] = vnum;
			}
		}
	}

	for (vertnum=FrameCount&1; vertnum<n_render_vertices; vertnum+=2) {
		Assert(render_vertices[vertnum]>=0 && render_vertices[vertnum]<=Highest_vertex_index);
		Dynamic_light[render_vertices[vertnum]] = 0;
	}

	cast_muzzle_flash_light(n_render_vertices, render_vertices);

	//	Note, starting at 1 to skip player, whose light is handled by a different system, of course.
//	for (objnum=1; objnum<=Highest_object_index; objnum++) {

	for (render_seg=0; render_seg<N_render_segs; render_seg++) {
		int	segnum = Render_list[render_seg];

		objnum = Segments[segnum].objects;

		while (objnum != -1) {
			object		*obj = &Objects[objnum];
			vms_vector	*objpos = &obj->pos;
			int			objtype = obj->type;
			fix			obj_intensity;
	
			switch (objtype) {
				case OBJ_FIREBALL:
					if (obj->id != 0xff) {
						if (obj->lifeleft < F1_0*4)
							obj_intensity = fixmul(fixdiv(obj->lifeleft, Vclip[obj->id].play_time), Vclip[obj->id].light_value);
						else
							obj_intensity = Vclip[obj->id].light_value;
					} else
						obj_intensity = 0;
					break;
				case OBJ_ROBOT:
					obj_intensity = F1_0/2;	// + (FrameCount & 0x1f)*F1_0/16;
					break;
				case OBJ_WEAPON:
					obj_intensity = Weapon_info[obj->id].light;
					if (obj->id == FLARE_ID )
						obj_intensity = 2* (min(obj_intensity, obj->lifeleft) + ((GameTime ^ Obj_light_xlate[objnum&0x0f]) & 0x3fff));
					break;
				case OBJ_POWERUP:
					obj_intensity = Powerup_info[obj->id].light;
					break;
				case OBJ_DEBRIS:
					obj_intensity = F1_0/4;
					break;
				case OBJ_LIGHT:
					obj_intensity = obj->ctype.light_info.intensity;
					break;
				default:
					obj_intensity = 0;
					break;
			}
	
			if (obj_intensity)
				apply_light(obj_intensity, obj->segnum, objpos, n_render_vertices, render_vertices);

			objnum = obj->next;
		}
	}

}
Exemplo n.º 12
0
//clips an edge against one plane. 
g3s_point *clip_edge(int plane_flag,g3s_point *on_pnt,g3s_point *off_pnt)
{
	fix psx_ratio;
	fix a,b,kn,kd;
	g3s_point *tmp;

	//compute clipping value k = (xs-zs) / (xs-xe-zs+ze)
	//use x or y as appropriate, and negate x/y value as appropriate

	if (plane_flag & (CC_OFF_RIGHT | CC_OFF_LEFT)) {
		a = on_pnt->p3_x;
		b = off_pnt->p3_x;
	}
	else {
		a = on_pnt->p3_y;
		b = off_pnt->p3_y;
	}

	if (plane_flag & (CC_OFF_LEFT | CC_OFF_BOT)) {
		a = -a;
		b = -b;
	}

	kn = a - on_pnt->p3_z;						//xs-zs
	kd = kn - b + off_pnt->p3_z;				//xs-zs-xe+ze

	tmp = get_temp_point();

	psx_ratio = fixdiv( kn, kd );

	
// PSX_HACK!!!!
//	tmp->p3_x = on_pnt->p3_x + fixmuldiv(off_pnt->p3_x-on_pnt->p3_x,kn,kd);
//	tmp->p3_y = on_pnt->p3_y + fixmuldiv(off_pnt->p3_y-on_pnt->p3_y,kn,kd);

	tmp->p3_x = on_pnt->p3_x + fixmul( (off_pnt->p3_x-on_pnt->p3_x), psx_ratio);
	tmp->p3_y = on_pnt->p3_y + fixmul( (off_pnt->p3_y-on_pnt->p3_y), psx_ratio);

	if (plane_flag & (CC_OFF_TOP|CC_OFF_BOT))
		tmp->p3_z = tmp->p3_y;
	else
		tmp->p3_z = tmp->p3_x;

	if (plane_flag & (CC_OFF_LEFT|CC_OFF_BOT))
		tmp->p3_z = -tmp->p3_z;

	if (on_pnt->p3_flags & PF_UVS) {
// PSX_HACK!!!!
//		tmp->p3_u = on_pnt->p3_u + fixmuldiv(off_pnt->p3_u-on_pnt->p3_u,kn,kd);
//		tmp->p3_v = on_pnt->p3_v + fixmuldiv(off_pnt->p3_v-on_pnt->p3_v,kn,kd);
		tmp->p3_u = on_pnt->p3_u + fixmul((off_pnt->p3_u-on_pnt->p3_u), psx_ratio);
		tmp->p3_v = on_pnt->p3_v + fixmul((off_pnt->p3_v-on_pnt->p3_v), psx_ratio);

		tmp->p3_flags |= PF_UVS;
	}

	if (on_pnt->p3_flags & PF_LS) {
// PSX_HACK
//		tmp->p3_r = on_pnt->p3_r + fixmuldiv(off_pnt->p3_r-on_pnt->p3_r,kn,kd);
//		tmp->p3_g = on_pnt->p3_g + fixmuldiv(off_pnt->p3_g-on_pnt->p3_g,kn,kd);
//		tmp->p3_b = on_pnt->p3_b + fixmuldiv(off_pnt->p3_b-on_pnt->p3_b,kn,kd);

		tmp->p3_l = on_pnt->p3_l + fixmul((off_pnt->p3_l-on_pnt->p3_l), psx_ratio);

		tmp->p3_flags |= PF_LS;
	}

	G3EncodePoint(tmp);

	return tmp;	
}
Exemplo n.º 13
0
//compute the corners of a rod.  fills in vertbuf.
static int calc_rod_corners(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width)
{
	vms_vector delta_vec,top,tempv,rod_norm;
	ubyte codes_and;
	int i;

	//compute vector from one point to other, do cross product with vector
	//from eye to get perpendiclar

	vm_vec_sub(&delta_vec,&bot_point->p3_vec,&top_point->p3_vec);

	//unscale for aspect

	delta_vec.x = fixdiv(delta_vec.x,Matrix_scale.x);
	delta_vec.y = fixdiv(delta_vec.y,Matrix_scale.y);

	//calc perp vector

	//do lots of normalizing to prevent overflowing.  When this code works,
	//it should be optimized

	vm_vec_normalize(&delta_vec);

	vm_vec_copy_normalize(&top,&top_point->p3_vec);

	vm_vec_cross(&rod_norm,&delta_vec,&top);

	vm_vec_normalize(&rod_norm);

	//scale for aspect

	rod_norm.x = fixmul(rod_norm.x,Matrix_scale.x);
	rod_norm.y = fixmul(rod_norm.y,Matrix_scale.y);

	//now we have the usable edge.  generate four points

	//top points

	vm_vec_copy_scale(&tempv,&rod_norm,top_width);
	tempv.z = 0;

	vm_vec_add(&rod_points[0].p3_vec,&top_point->p3_vec,&tempv);
	vm_vec_sub(&rod_points[1].p3_vec,&top_point->p3_vec,&tempv);

	vm_vec_copy_scale(&tempv,&rod_norm,bot_width);
	tempv.z = 0;

	vm_vec_sub(&rod_points[2].p3_vec,&bot_point->p3_vec,&tempv);
	vm_vec_add(&rod_points[3].p3_vec,&bot_point->p3_vec,&tempv);


	//now code the four points

	for (i=0,codes_and=0xff;i<4;i++)
		codes_and &= g3_code_point(&rod_points[i]);

	if (codes_and)
		return 1;		//1 means off screen

	//clear flags for new points (not projected)

	for (i=0;i<4;i++)
		rod_points[i].p3_flags = 0;

	return 0;
}
Exemplo n.º 14
0
// -------------------------------------------------------------------------------------
// Interface from Matt's data structures to Mike's texture mapper.
// -------------------------------------------------------------------------------------
void draw_tmap(grs_bitmap *bp,int nverts,g3s_point **vertbuf)
{
	int	i;

	//	These variables are used in system which renders texture maps which lie on one scanline as a line.
#if SC2000K
	int	flat_flag;							// Set to 1 and remains 1 so long as all y coords are the same (in integer portion).
	int	last_y;								// Y coordinate of previous vertex.
	fix	min_x = 0xfff0000, max_x = 0;	// Minimum and maximum bounds of line to render in place of flat texture map.
#endif
	// fix	div_numerator;
	int	lighting_on_save = Lighting_on;

	Assert(nverts <= MAX_TMAP_VERTS);


#ifdef USE_MULT_CODE
	if ( !divide_table_filled ) fill_divide_table();
#endif

	// -- now called from g3_start_frame -- init_interface_vars_to_assembler();

	//	If no transparency and seg depth is large, render as flat shaded.
	if ((Current_seg_depth > Max_linear_depth) && ((bp->bm_flags & 3) == 0)) {
		draw_tmap_flat(bp, nverts, vertbuf);
		return;
	}

	if ( bp->bm_flags & BM_FLAG_RLE )
		bp = rle_expand_texture( bp );		// Expand if rle'd

	Transparency_on = bp->bm_flags & BM_FLAG_TRANSPARENT;
	if (bp->bm_flags & BM_FLAG_NO_LIGHTING)
		Lighting_on = 0;

	//	Set selector for current texture map.
	if ( bp->bm_selector == 0 )	{
		if (gr_bitmap_assign_selector( bp ) )
			Error( "Couldn't assign selector in ntmap.c!\n" );
	}
	pixel_data_selector = bp->bm_selector;

	// Setup texture map in Tmap1
	Tmap1.nv = nverts;						// Initialize number of vertices

#if SC2000K
	last_y = f2i(vertbuf[0]->p3_sy);
	flat_flag = 1;								// Says so far, this texture map exists all on one scan line
#endif
// 	div_numerator = DivNum;	//f1_0*3;

	for (i=0; i<nverts; i++) {
		g3ds_vertex	*tvp = &Tmap1.verts[i];
		g3s_point	*vp = vertbuf[i];

		tvp->x2d = vp->p3_sx;
		tvp->y2d = vp->p3_sy;

#if SC2000K
		//	If y coordinates are not the same (in integer portion), then this texture map is not all on one scan line
		if (f2i(tvp->y2d) != last_y)
			flat_flag = 0;

		// If everything is flat so far, set minimum x and y for rendering a scanline
		if (flat_flag) {
			if (tvp->x2d < min_x)
				min_x = tvp->x2d;

			if (tvp->x2d > max_x)
				max_x = tvp->x2d;
		}
#endif
		//	Check for overflow on fixdiv.  Will overflow on vp->z <= something small.  Allow only as low as 256.
		if (vp->z < 256) {
			vp->z = 256;
			// Int3();		// we would overflow if we divided!
		}

		tvp->z = fixdiv(F1_0*12, vp->z);
 		tvp->u = vp->p3_u << 6; //* bp->bm_w;
		tvp->v = vp->p3_v << 6; //* bp->bm_h;

		Assert(Lighting_on < 3);

		if (Lighting_on)
			tvp->l = vp->p3_l * NUM_LIGHTING_LEVELS;
	}

#if SC2000K
	// Render a horizontal line instead of a texture map if flat_flag still set (all vertices on one scanline).
	if (SC2000 && flat_flag) {
		fix y,cvw;

		Int3();
		y = Tmap1.verts[0].y2d;
		cvw = i2f(grd_curcanv->cv_bitmap.bm_w-1);

		if (y<0 || y>i2f(grd_curcanv->cv_bitmap.bm_h-1)) { Lighting_on = lighting_on_save; return; }

		//if (min_x < 0) min_x = 0;
		//if (max_x > cvw) max_x = cvw;

		gr_setcolor(*(bp->bm_data+32*32+32));				// Read center pixel of 64x64 bitmap, use as line color.
		gr_line(min_x, Tmap1.verts[0].y2d, max_x, Tmap1.verts[0].y2d);

		Lighting_on = lighting_on_save;
		return;
	}
#endif

	Lighting_enabled = Lighting_on;

	// Now, call my texture mapper.
	if (Lighting_on) {
		switch (Interpolation_method) {	// 0 = choose, 1 = linear, 2 = /8 perspective, 3 = full perspective
			case 0:								// choose best interpolation
				per2_flag = 1;
				if (Current_seg_depth > Max_perspective_depth)
					ntexture_map_lighted_linear(bp, &Tmap1);
				else
					ntexture_map_lighted(bp, &Tmap1);
				break;
			case 1:								// linear interpolation
				per2_flag = 1;
				ntexture_map_lighted_linear(bp, &Tmap1);
				break;
			case 2:								// perspective every 8th pixel interpolation
				per2_flag = 1;
				ntexture_map_lighted(bp, &Tmap1);
				break;
			case 3:								// perspective every pixel interpolation
				per2_flag = 0;					// this hack means do divide every pixel
				ntexture_map_lighted(bp, &Tmap1);
				break;
			default:
				Assert(0);				// Illegal value for Interpolation_method, must be 0,1,2,3
		}
	} else {
		switch (Interpolation_method) {	// 0 = choose, 1 = linear, 2 = /8 perspective, 3 = full perspective
			case 0:								// choose best interpolation
				per2_flag = 1;
				if (Current_seg_depth > Max_perspective_depth)
					ntexture_map_lighted_linear(bp, &Tmap1);
				else
					ntexture_map_lighted(bp, &Tmap1);
				break;
			case 1:								// linear interpolation
				per2_flag = 1;
				ntexture_map_lighted_linear(bp, &Tmap1);
				break;
			case 2:								// perspective every 8th pixel interpolation
				per2_flag = 1;
				ntexture_map_lighted(bp, &Tmap1);
				break;
			case 3:								// perspective every pixel interpolation
				per2_flag = 0;					// this hack means do divide every pixel
				ntexture_map_lighted(bp, &Tmap1);
				break;
			default:
				Assert(0);				// Illegal value for Interpolation_method, must be 0,1,2,3
		}
	}

	Lighting_on = lighting_on_save;

}
Exemplo n.º 15
0
void init_points(polymodel *pm,vms_vector *box_size,int submodel_num,morph_data *md)
{
	ushort nverts;
	vms_vector *vp;
	ushort *data,type;
	int i;

	//printf("initing %d ",submodel_num);

	data = (ushort *) &pm->model_data[pm->submodel_ptrs[submodel_num]];

	type = *data++;

	Assert(type == 7 || type == 1);

	nverts = *data++;

	md->n_morphing_points[submodel_num] = 0;

	if (type==7) {
		i = *data++;		//get start point number
		data++;				//skip pad
	}
	else
		i = 0;				//start at zero

	Assert(i+nverts < MAX_VECS);

	md->submodel_startpoints[submodel_num] = i;

	vp = (vms_vector *) data;

	while (nverts--) {
		fix k,dist;

		if (box_size) {
			fix t;

			k = 0x7fffffff;

			if (vp->x && f2i(box_size->x)<abs(vp->x)/2 && (t = fixdiv(box_size->x,abs(vp->x))) < k) k=t;
			if (vp->y && f2i(box_size->y)<abs(vp->y)/2 && (t = fixdiv(box_size->y,abs(vp->y))) < k) k=t;
			if (vp->z && f2i(box_size->z)<abs(vp->z)/2 && (t = fixdiv(box_size->z,abs(vp->z))) < k) k=t;

			if (k==0x7fffffff) k=0;

		}
		else
			k=0;

		vm_vec_copy_scale(&md->morph_vecs[i],vp,k);

		dist = vm_vec_normalized_dir_quick(&md->morph_deltas[i],vp,&md->morph_vecs[i]);

		md->morph_times[i] = fixdiv(dist,morph_rate);

		if (md->morph_times[i] != 0)
			md->n_morphing_points[submodel_num]++;

		vm_vec_scale(&md->morph_deltas[i],morph_rate);

		vp++; i++;

	}

	//printf("npoints = %d\n",n_morphing_points[submodel_num]);

}
Exemplo n.º 16
0
/* clip3d:
 *  A fixed point version of clip3d_f. Works suprisingly well.
 */
int clip3d(int type, fixed min_z, fixed max_z, int vc, AL_CONST V3D *vtx[], V3D *vout[], V3D *vtmp[], int out[])
{
   int i, j, vo, vt, flags;
   fixed t;
   V3D *v3;

   AL_CONST V3D *v1, *v2, **vin;

   static int flag_table[] = {
      INT_NONE,                             /* flat */
      INT_3COLP,                            /* gcol */
      INT_3COL,                             /* grgb */
      INT_UV,                               /* atex */
      INT_UV,                               /* ptex */
      INT_UV,                               /* atex mask */
      INT_UV,                               /* ptex mask */
      INT_UV + INT_1COL,                    /* atex lit */
      INT_UV + INT_1COL,                    /* ptex lit */
      INT_UV + INT_1COL,                    /* atex mask lit */
      INT_UV + INT_1COL,                    /* ptex mask lit */
      INT_UV,                               /* atex trans */
      INT_UV,                               /* ptex trans */
      INT_UV,                               /* atex mask trans */
      INT_UV                                /* ptex mask trans */
   };

   type &= ~POLYTYPE_ZBUF;
   flags = flag_table[type];

   if (max_z > min_z) {
      vt = 0;

      for (i=0; i<vc; i++)
	 out[i] = (vtx[i]->z > max_z);

      for (i=0, j=vc-1; i<vc; j=i, i++) {
	 v1 = vtx[j];
	 v2 = vtx[i];
	 v3 = vtmp[vt];

	 if ((out[j] & out[i]) != 0)
	    continue;

	 if ((out[j] | out[i]) == 0) {
	    point_inside(vt);
	    continue;
	 }

	 t = fixdiv(max_z - v1->z, v2->z - v1->z);
	 point_interp(vt);
	 v3 = vtmp[vt];

	 if (out[j])
	    point_inside(vt);
      }
      vin = (AL_CONST V3D**)vtmp;
   }
   else {
      vt = vc;
      vin = vtx;
   }

   vo = 0;

   for (i=0; i<vt; i++)
      out[i] = (vin[i]->z < min_z);

   for (i=0, j=vt-1; i<vt; j=i, i++) {
      v1 = vin[j];
      v2 = vin[i];
      v3 = vout[vo];

      if ((out[j] & out[i]) != 0)
	 continue;

      if ((out[j] | out[i]) == 0) {
	 point_inside(vo);
	 continue;
      }

      t = fixdiv(min_z - v1->z, v2->z - v1->z);
      point_interp(vo);
      v3 = vout[vo];

      if (out[j])
	 point_inside(vo);
   }

   vt = 0;

   for (i=0; i<vo; i++)
      out[i] = (vout[i]->x < -vout[i]->z);

   for (i=0, j=vo-1; i<vo; j=i, i++) {
      v1 = vout[j];
      v2 = vout[i];
      v3 = vtmp[vt];

      if ((out[j] & out[i]) != 0)
	 continue;

      if ((out[j] | out[i]) == 0) {
	 point_inside(vt);
	 continue;
      }

      t = fixdiv(-v1->z - v1->x, v2->x - v1->x + v2->z - v1->z);
      point_interp(vt);
      v3 = vtmp[vt];

      if (out[j])
	 point_inside(vt);
   }

   vo = 0;

   for (i=0; i<vt; i++)
      out[i] = (vtmp[i]->x > vtmp[i]->z);

   for (i=0, j=vt-1; i<vt; j=i, i++) {
      v1 = vtmp[j];
      v2 = vtmp[i];
      v3 = vout[vo];

      if ((out[j] & out[i]) != 0)
	 continue;

      if ((out[j] | out[i]) == 0) {
	 point_inside(vo);
	 continue;
      }

      t = fixdiv(v1->z - v1->x, v2->x - v1->x - v2->z + v1->z);
      point_interp(vo);
      v3 = vout[vo];

      if (out[j])
	 point_inside(vo);
   }

   vt = 0;

   for (i=0; i<vo; i++)
      out[i] = (vout[i]->y < -vout[i]->z);

   for (i=0, j=vo-1; i<vo; j=i, i++) {
      v1 = vout[j];
      v2 = vout[i];
      v3 = vtmp[vt];

      if ((out[j] & out[i]) != 0)
	 continue;

      if ((out[j] | out[i]) == 0) {
	 point_inside(vt);
	 continue;
      }

      t = fixdiv(-v1->z - v1->y, v2->y - v1->y + v2->z - v1->z);
      point_interp(vt);
      v3 = vtmp[vt];

      if (out[j])
	 point_inside(vt);
   }

   vo = 0;

   for (i=0; i<vt; i++)
      out[i] = (vtmp[i]->y > vtmp[i]->z);

   for (i=0, j=vt-1; i<vt; j=i, i++) {
      v1 = vtmp[j];
      v2 = vtmp[i];
      v3 = vout[vo];

      if ((out[j] & out[i]) != 0)
	 continue;

      if ((out[j] | out[i]) == 0) {
	 point_inside(vo);
	 continue;
      }

      t = fixdiv(v1->z - v1->y, v2->y - v1->y - v2->z + v1->z);
      point_interp(vo);
      v3 = vout[vo];

      if (out[j])
	 point_inside(vo);
   }

   if (type == POLYTYPE_FLAT)
      vout[0]->c = vtx[0]->c;

   return vo;
}
Exemplo n.º 17
0
fixed operator/(const fixed &f1, const fixed &f2){fixed temp; temp.intValue = fixdiv(f1.intValue, f2.intValue); return temp;}
Exemplo n.º 18
0
void modex_print_message(int x, int y, char *str)
{

#ifndef AUTOMAP_DIRECT_RENDER
#ifndef AUTOMAP_NO_PAGING
	int	i;
	for (i=0; i<2; i++ )	{
		gr_set_current_canvas(&Pages[i]);
#else
	{
		gr_set_current_canvas(OffscreenPage);
#endif		
#endif
		modex_printf(x, y, str, GFONT_MEDIUM_1);
#ifndef AUTOMAP_DIRECT_RENDER
	}

	gr_set_current_canvas(&DrawingPages[current_page]);
#endif
}

extern void GameLoop(int, int );
extern int set_segment_depths(int start_seg, ubyte *segbuf);

u_int32_t automap_mode = SM(640,480);
int automap_width = 640;
int automap_height = 480;
int automap_use_game_res=0;
int nice_automap=0;

void do_automap( int key_code )	{
	int done=0;
	vms_matrix	tempm;
	vms_angvec	tangles;
	int leave_mode=0;
	int first_time=1;
//        int pcx_error;
	int c;
//        char filename[] = "MAP.PCX";
	fix entry_time;
	int pause_game=1;		// Set to 1 if everything is paused during automap...No pause during net.
	fix t1, t2;
	control_info saved_control_info;
	grs_bitmap Automap_background;
	int Max_segments_away = 0;
	int SegmentLimit = 1;
//added on 10/28/98 by adb to fix compile versions
        #if !defined (NDEBUG) || (!defined(AUTOMAP_NO_PAGING) && !defined(AUTOMAP_DIRECT_RENDER)) 
        int i;
        #endif

	key_code = key_code;	// disable warning...

	if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence))
		pause_game = 0;

	if (pause_game)
		stop_time();

	create_name_canv();

	Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES);			//make maybe smaller than max
	//Edges	= malloc( sizeof(Edge_info)*Max_edges);
	//if ( Edges == NULL )	{
	//	mprintf((0, "Couldn't get %dK for automap!", sizeof(Edge_info)*Max_edges/1024));
	//	return;
	//}
	//DrawingListBright = malloc( sizeof(short)*Max_edges);
	//if ( DrawingListBright == NULL )	{
	//	mprintf((0, "Couldn't get %dK for automap!", sizeof(short)*Max_edges/1024));
	//	return;
	//}

	mprintf( (0, "Num_vertices=%d, Max_edges=%d, (MAX:%d)\n", Num_vertices, Max_edges, MAX_EDGES ));
	mprintf( (0, "Allocated %d K for automap edge list\n", (sizeof(Edge_info)+sizeof(short))*Max_edges/1024 ));
	

	//edit 4/23/99 Matt Mueller - don't switch res unless we need to
	if (grd_curscreen->sc_mode != AUTOMAP_MODE)
		gr_set_mode( AUTOMAP_MODE );
	else
		gr_set_current_canvas(NULL);
	//end edit -MM
	automap_width=grd_curscreen->sc_canvas.cv_bitmap.bm_w;
	automap_height=grd_curscreen->sc_canvas.cv_bitmap.bm_h;

	gr_palette_clear();

#ifndef AUTOMAP_DIRECT_RENDER
	gr_init_sub_canvas(&Pages[0],grd_curcanv,0,0,automap_width,automap_height);
#ifndef AUTOMAP_NO_PAGING
	// NOTICE: should be 0,401! FIXME!
	gr_init_sub_canvas(&Pages[1],grd_curcanv,0,0,automap_width,automap_height);
	gr_init_sub_canvas(&DrawingPages[0],&Pages[0],0,0,automap_width,automap_height);
	gr_init_sub_canvas(&DrawingPages[1],&Pages[1],0,0,automap_width,automap_height);
#else
	OffscreenPage = gr_create_canvas( automap_width,automap_height );
	if (!OffscreenPage) {
    	nm_messagebox("No memory for automap", 1, "Ok");
	    return;
	}
	gr_init_sub_canvas(&DrawingPages[0],OffscreenPage,0,0,automap_width,automap_height);
#endif
#endif

	gr_init_bitmap_data (&Automap_background);
//	pcx_error = pcx_read_bitmap(filename,&Automap_background,BM_LINEAR,NULL);
//	if ( pcx_error != PCX_ERROR_NONE )	{
//		printf("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
//		Error("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
//		return;
//	}

#ifndef AUTOMAP_DIRECT_RENDER
#ifndef AUTOMAP_NO_PAGING
        for (i=0; i<2; i++ )        {
		gr_set_current_canvas(&Pages[i]);
#else
	{
		gr_set_current_canvas(OffscreenPage);
#endif
//		gr_bitmap( 0, 0, &Automap_background );
//		modex_printf( 40, 22,TXT_AUTOMAP,GFONT_BIG_1);
//		modex_printf( 70,353,TXT_TURN_SHIP,GFONT_SMALL);
//		modex_printf( 70,369,TXT_SLIDE_UPDOWN,GFONT_SMALL);
//		modex_printf( 70,385,TXT_VIEWING_DISTANCE,GFONT_SMALL);
	}
#ifdef AUTOMAP_NO_PAGING
//killed 05/17/99 Matt Mueller - this seems to merely copy undefined bytes around.. not needed
//--killed--	gr_bm_ubitblt(automap_width,automap_height, 0, 0, 0, 0, &OffscreenPage->cv_bitmap,&Pages[0].cv_bitmap);
//end kill -MM
#endif
	gr_free_bitmap_data (&Automap_background);
	gr_set_current_canvas(&DrawingPages[current_page]);
#endif
	automap_build_edge_list();

	if ( ViewDist==0 ) 
		ViewDist = ZOOM_DEFAULT;
	ViewMatrix = Objects[Players[Player_num].objnum].orient;

	tangles.p = PITCH_DEFAULT;
	tangles.h  = 0;
	tangles.b  = 0;

	done = 0;

	view_target = Objects[Players[Player_num].objnum].pos;

	t1 = entry_time = timer_get_fixed_seconds();
	t2 = t1;

	//Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum
	Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
	SegmentLimit = Max_segments_away;

	adjust_segment_limit(SegmentLimit);

	while(!done)	{
		if ( leave_mode==0 && Controls.automap_state && (timer_get_fixed_seconds()-entry_time)>LEAVE_TIME)
			leave_mode = 1;

		if ( !Controls.automap_state && (leave_mode==1) )
			done=1;

		if (!pause_game)	{
			ushort old_wiggle;
			saved_control_info = Controls;				// Save controls so we can zero them
			memset(&Controls,0,sizeof(control_info));	// Clear everything...
			old_wiggle = ConsoleObject->mtype.phys_info.flags & PF_WIGGLE;	// Save old wiggle
			ConsoleObject->mtype.phys_info.flags &= ~PF_WIGGLE;		// Turn off wiggle
			#ifdef NETWORK
			if (multi_menu_poll())
				done = 1;
			#endif
//			GameLoop( 0, 0 );		// Do game loop with no rendering and no reading controls.
			ConsoleObject->mtype.phys_info.flags |= old_wiggle;	// Restore wiggle
			Controls = saved_control_info;
		} 

		controls_read_all();		
		if ( Controls.automap_down_count )	{
			if (leave_mode==0)
				done = 1;
			c = 0;
		}

		while( (c=key_inkey()) )	{
			switch( c ) {
			#ifndef NDEBUG
			case KEY_BACKSP: Int3(); break;
			#endif
	
			case KEY_PRINT_SCREEN: save_screen_shot(1); break;
	
			case KEY_ESC:
				if (leave_mode==0)
					done = 1;
				 break;
			case KEY_ALTED+KEY_F:		// Alt+F shows full map, if cheats enabled
				if (Cheats_enabled) 
				{
					uint t;	
					t = Players[Player_num].flags;
					Players[Player_num].flags |= PLAYER_FLAGS_MAP_ALL_CHEAT;
					automap_build_edge_list();
					Players[Player_num].flags=t;
			 	}
				break;
	
	#ifndef NDEBUG
		  	case KEY_DEBUGGED+KEY_F: 	{
				for (i=0; i<=Highest_segment_index; i++ )
					Automap_visited[i] = 1;
				automap_build_edge_list();
				Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
				SegmentLimit = Max_segments_away;
				adjust_segment_limit(SegmentLimit);
				}
				break;
	#endif
			case KEY_MINUS:
				if (SegmentLimit > 1) 		{
					SegmentLimit--;
					adjust_segment_limit(SegmentLimit);
				}
				break;
			case KEY_EQUAL:
				if (SegmentLimit < Max_segments_away) 	{
					SegmentLimit++;
					adjust_segment_limit(SegmentLimit);
				}
				break;
			}
		}

		if ( Controls.fire_primary_down_count )	{
			// Reset orientation
			ViewDist = ZOOM_DEFAULT;
			tangles.p = PITCH_DEFAULT;
			tangles.h  = 0;
			tangles.b  = 0;
			view_target = Objects[Players[Player_num].objnum].pos;
		}

		ViewDist -= Controls.forward_thrust_time*ZOOM_SPEED_FACTOR;

		tangles.p += fixdiv( Controls.pitch_time, ROT_SPEED_DIVISOR );
		tangles.h  += fixdiv( Controls.heading_time, ROT_SPEED_DIVISOR );
		tangles.b  += fixdiv( Controls.bank_time, ROT_SPEED_DIVISOR*2 );
		
		if ( Controls.vertical_thrust_time || Controls.sideways_thrust_time )	{
			vms_angvec	tangles1;
			vms_vector	old_vt;
			old_vt = view_target;
			tangles1 = tangles;
			vm_angles_2_matrix(&tempm,&tangles1);
			vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);
			vm_vec_scale_add2( &view_target, &ViewMatrix.uvec, Controls.vertical_thrust_time*SLIDE_SPEED );
			vm_vec_scale_add2( &view_target, &ViewMatrix.rvec, Controls.sideways_thrust_time*SLIDE_SPEED );
			if ( vm_vec_dist_quick( &view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) )	{
				view_target = old_vt;
			}
		} 

		vm_angles_2_matrix(&tempm,&tangles);
		vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);

		if ( ViewDist < ZOOM_MIN_VALUE ) ViewDist = ZOOM_MIN_VALUE;
		if ( ViewDist > ZOOM_MAX_VALUE ) ViewDist = ZOOM_MAX_VALUE;

		draw_automap();

		if ( first_time )	{
			first_time = 0;
			gr_palette_load( gr_palette );
		}
		t2 = timer_get_fixed_seconds();
		while (t2-t1<F1_0/100){//ogl is fast enough that the automap can read the input too fast and you start to turn really slow.  So delay a bit (and free up some cpu :)
			if (nice_automap)
				d_delay(1);

			t2 = timer_get_fixed_seconds();
		}
		if (pause_game)
			FrameTime=t2-t1;
		t1 = t2;
	}

	//free(Edges);
	//free(DrawingListBright);
	gr_free_canvas(name_canv);  name_canv=NULL;
#ifdef AUTOMAP_NO_PAGING
	gr_free_canvas(OffscreenPage);
	OffscreenPage = NULL;
#endif

	mprintf( (0, "Automap memory freed\n" ));

	game_flush_inputs();

	if (pause_game)
		start_time();
}

void adjust_segment_limit(int SegmentLimit)
{
	int i,e1;
	Edge_info * e;

	mprintf(( 0, "Seglimit: %d\n", SegmentLimit ));
	
	for (i=0; i<=Highest_edge_index; i++ )	{
		e = &Edges[i];
		e->flags |= EF_TOO_FAR;
		for (e1=0; e1<e->num_faces; e1++ )	{
			if ( Automap_visited[e->segnum[e1]] <= SegmentLimit )	{
				e->flags &= (~EF_TOO_FAR);
				break;
			}
		}
	}
	
}
Exemplo n.º 19
0
fixed operator/(const int   &i,  const fixed &f ){fixed temp; temp.intValue = fixdiv(i<<16, f.intValue); return temp; }
Exemplo n.º 20
0
int main(int argc, char *argv[])
{
     World *w;
     FILE *fp;
     Boolean quit = False;
     Intent *intent;
     fixed v = FIXED_ZERO;
     double vx = 0.0, vy = 0.0, va = 0.0;
     #ifdef MSDOS
     long       frames;
     time_t     starttime, endtime;
     #endif


     if (argc != 2) {
	  fprintf(stderr, "Usage:  wt <world file>\n");
	  exit(EXIT_FAILURE);
     }

     if ((fp = fopen(argv[1], "r")) == NULL) {
	  perror(argv[1]);
	  exit(EXIT_FAILURE);
     }
     w = read_world_file(fp);
     fclose(fp);

     init_graphics();
     init_renderer(SCREEN_WIDTH, SCREEN_HEIGHT);
     init_input_devices();

     /* setup view */
     view = new_view(fixdiv(FIXED_2PI, INT_TO_FIXED(4)));

     view->x = FIXED_ZERO;
     view->y = FIXED_ZERO;
     view->height = FIXED_ONE;
     view->angle = FIXED_ZERO;

     #ifdef MSDOS
     starttime = time(NULL);
     frames = 0;
     #endif

     while (!quit) {
	  double sin_facing, cos_facing;

	  render(w, view);
      #ifdef MSDOS
      frames++;
      #endif
	  intent = read_input_devices();

	  /* This block code is a hack to do acceleration and deceleration. */
	  if (fabs(vx) > fabs(intent->force_x)) {
	       if (vx < 0.0)
		    vx = MIN(vx + 0.1, intent->force_x);
	       else
		    vx = MAX(vx - 0.1, intent->force_x);
	  } else if (fabs(vx) < fabs(intent->force_x)) {
	       vx += intent->force_x / 5.0;
	       if (fabs(vx) > fabs(intent->force_x))
		    vx = intent->force_x;
	  }
	  if (fabs(vy) > fabs(intent->force_y)) {
	       if (vy < 0.0)
		    vy = MIN(vy + 0.1, intent->force_y);
	       else
		    vy = MAX(vy - 0.1, intent->force_y);
	  } else if (fabs(vy) < fabs(intent->force_y)) {
	       vy += intent->force_y / 5.0;
	       if (fabs(vy) > fabs(intent->force_y))
		    vy = intent->force_y;
	  }
	  if (fabs(vy) > fabs(intent->force_y)) {
	       if (vy < 0.0)
		    vy = MIN(vy + 0.1, intent->force_y);
	       else
		    vy = MAX(vy - 0.1, intent->force_y);
	  } else if (fabs(vy) < fabs(intent->force_y)) {
	       vy += intent->force_y / 5.0;
	       if (fabs(vy) > fabs(intent->force_y))
		    vy = intent->force_y;
	  }
	  /* Angular deceleration here is weird and unrealistic, but it feels
	  **   right to me.
	  */
	  if (fabs(va) > fabs(intent->force_rotate))
	       va *= 0.6;
	  else if (fabs(va) < fabs(intent->force_rotate)) {
	       va += intent->force_rotate / 8.0;
	       if (fabs(va) > fabs(intent->force_rotate))
		    va = intent->force_rotate;
	  }
	  view->angle += FLOAT_TO_FIXED(0.3 * va);
	  sin_facing = sin(FIXED_TO_FLOAT(view->angle));
	  cos_facing = cos(FIXED_TO_FLOAT(view->angle));

	  view->x += FLOAT_TO_FIXED(0.8 * vx * cos_facing);
	  view->y += FLOAT_TO_FIXED(0.8 * vx * sin_facing);
	  view->x += FLOAT_TO_FIXED(0.8 * vy * -sin_facing);
	  view->y += FLOAT_TO_FIXED(0.8 * vy * cos_facing);
	  if (view->height > FIXED_ONE)
	       v -= FIXED_ONE / 16;
	  view->height += v;
	  if (view->height < FIXED_ONE) {
	       v = FIXED_ZERO;
	       view->height = FIXED_ONE;
	  }
	  while (intent->n_special--) {
	       if (intent->special[intent->n_special] == INTENT_END_GAME)
		    quit = True;
	       else
		    v = FIXED_ONE / 2;
	  }
     }

     #ifdef MSDOS
     endtime = time(NULL);
     #endif

     end_input_devices();
     end_graphics();

     #ifdef MSDOS
     printf("%li frames in %lu seconds - %.2f frames per second",
        (long) frames, (long) endtime - starttime,
        (float) frames / (float) (endtime-starttime));
     #endif

     return EXIT_SUCCESS;
}
Exemplo n.º 21
0
//	-----------------------------------------------------------------------------------------------------------
//Simulate a physics object for this frame
do_physics_sim(object *obj)
{
	int ignore_obj_list[MAX_IGNORE_OBJS],n_ignore_objs;
	int iseg;
	int try_again;
	int fate;
	vms_vector frame_vec;			//movement in this frame
	vms_vector new_pos,ipos;		//position after this frame
	int count=0;
	int objnum;
	int WallHitSeg, WallHitSide;
	fvi_info hit_info;
	fvi_query fq;
	vms_vector save_pos;
	int save_seg;
	fix drag;
	fix sim_time;
	vms_vector start_pos;
	int obj_stopped=0;
	fix moved_time;			//how long objected moved before hit something
	vms_vector save_p0,save_p1;
	physics_info *pi;
	int orig_segnum = obj->segnum;

	Assert(obj->type != OBJ_NONE);
	Assert(obj->movement_type == MT_PHYSICS);

#ifndef NDEBUG
if (Dont_move_ai_objects)
	if (obj->control_type == CT_AI)
		return;
#endif

	pi = &obj->mtype.phys_info;

	do_physics_sim_rot(obj);

	if (!(pi->velocity.x || pi->velocity.y || pi->velocity.z || pi->thrust.x || pi->thrust.y || pi->thrust.z))
		return;

	objnum = obj-Objects;

	n_phys_segs = 0;

	disable_new_fvi_stuff = (obj->type != OBJ_PLAYER);

	sim_time = FrameTime;

//debug_obj = obj;

	#ifdef EXTRA_DEBUG
	if (obj == debug_obj) {
		printf("object %d:\n  start pos = %x %x %x\n",objnum,XYZ(&obj->pos));
		printf("  thrust = %x %x %x\n",XYZ(&obj->mtype.phys_info.thrust));
		printf("  sim_time = %x\n",sim_time);
	}

	//check for correct object segment 
	if(!get_seg_masks(&obj->pos,obj->segnum,0).centermask==0) {
		#ifndef NDEBUG
		mprintf((0,"Warning: object %d not in given seg!\n",objnum));
		#endif
		//Int3();  Removed by Rob 10/5/94
		if (!update_object_seg(obj)) {
			#ifndef NDEBUG
			mprintf((0,"Warning: can't find seg for object %d - moving\n",objnum));
			#endif
			if (!(Game_mode & GM_MULTI))
				Int3();
			compute_segment_center(&obj->pos,&Segments[obj->segnum]);
			obj->pos.x += objnum;
		}
	}
	#endif

	start_pos = obj->pos;

	n_ignore_objs = 0;

	Assert(obj->mtype.phys_info.brakes==0);		//brakes not used anymore?

		//if uses thrust, cannot have zero drag
	Assert(!(obj->mtype.phys_info.flags&PF_USES_THRUST) || obj->mtype.phys_info.drag!=0);

//mprintf((0,"thrust=%x  speed=%x\n",vm_vec_mag(&obj->mtype.phys_info.thrust),vm_vec_mag(&obj->mtype.phys_info.velocity)));

	//do thrust & drag
	
	if ((drag = obj->mtype.phys_info.drag) != 0) {

		int count;
		vms_vector accel;
		fix r,k;

		count = sim_time / FT;
		r = sim_time % FT;
		k = fixdiv(r,FT);

		if (obj->mtype.phys_info.flags & PF_USES_THRUST) {

			vm_vec_copy_scale(&accel,&obj->mtype.phys_info.thrust,fixdiv(f1_0,obj->mtype.phys_info.mass));

			while (count--) {

				vm_vec_add2(&obj->mtype.phys_info.velocity,&accel);

				vm_vec_scale(&obj->mtype.phys_info.velocity,f1_0-drag);
			}

			//do linear scale on remaining bit of time

			vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&accel,k);

			vm_vec_scale(&obj->mtype.phys_info.velocity,f1_0-fixmul(k,drag));
		}
		else {
			fix total_drag=f1_0;

			while (count--)
				total_drag = fixmul(total_drag,f1_0-drag);

			//do linear scale on remaining bit of time

			total_drag = fixmul(total_drag,f1_0-fixmul(k,drag));

			vm_vec_scale(&obj->mtype.phys_info.velocity,total_drag);
		}
	}

	#ifdef EXTRA_DEBUG
	if (obj == debug_obj)
		printf("  velocity = %x %x %x\n",XYZ(&obj->mtype.phys_info.velocity));
	#endif

	do {
		try_again = 0;

		//Move the object
		vm_vec_copy_scale(&frame_vec, &obj->mtype.phys_info.velocity, sim_time);

		#ifdef EXTRA_DEBUG
		if (obj == debug_obj)
			printf("  pass %d, frame_vec = %x %x %x\n",count,XYZ(&frame_vec));
		#endif

		if ( (frame_vec.x==0) && (frame_vec.y==0) && (frame_vec.z==0) )	
			break;

		count++;

		//	If retry count is getting large, then we are trying to do something stupid.
		if ( count > 3) 	{
			if (obj->type == OBJ_PLAYER) {
				if (count > 8)
					break;
			} else
				break;
		}

		vm_vec_add(&new_pos,&obj->pos,&frame_vec);

		#ifdef EXTRA_DEBUG
		if (obj == debug_obj)
			printf("   desired_pos  = %x %x %x\n",XYZ(&new_pos));
		#endif

		ignore_obj_list[n_ignore_objs] = -1;

		#ifdef EXTRA_DEBUG
		if (obj == debug_obj) {
			printf("   FVI parms: p0 = %8x %8x %8x, segnum=%x, size=%x\n",XYZ(&obj->pos),obj->segnum,obj->size);
			printf("              p1 = %8x %8x %8x\n",XYZ(&new_pos));
		}
		#endif

		fq.p0						= &obj->pos;
		fq.startseg				= obj->segnum;
		fq.p1						= &new_pos;
		fq.rad					= obj->size;
		fq.thisobjnum			= objnum;
		fq.ignore_obj_list	= ignore_obj_list;
		fq.flags					= FQ_CHECK_OBJS;

		if (obj->type == OBJ_WEAPON)
			fq.flags |= FQ_TRANSPOINT;

		if (obj->type == OBJ_PLAYER)
			fq.flags |= FQ_GET_SEGLIST;

//@@			if (get_seg_masks(&obj->pos,obj->segnum,0).centermask!=0)
//@@				Int3();

save_p0 = *fq.p0;
save_p1 = *fq.p1;


		fate = find_vector_intersection(&fq,&hit_info);
		//	Matt: Mike's hack.
		if (fate == HIT_OBJECT) {
			object	*objp = &Objects[hit_info.hit_object];

			if ((objp->type == OBJ_WEAPON) && (objp->id == PROXIMITY_ID))
				count--;
		}

		#ifndef NDEBUG
		if (fate == HIT_BAD_P0) {
			mprintf((0,"Warning: Bad p0 in physics!  Object = %i, type = %i [%s]\n", obj-Objects, obj->type, Object_type_names[obj->type]));
			Int3();
		}
		#endif

		if (obj->type == OBJ_PLAYER) {
			int i;

			if (n_phys_segs && phys_seglist[n_phys_segs-1]==hit_info.seglist[0])
				n_phys_segs--;

			for (i=0;(i<hit_info.n_segs) && (n_phys_segs<MAX_FVI_SEGS-1);  )
				phys_seglist[n_phys_segs++] = hit_info.seglist[i++];
		}

		#ifdef EXTRA_DEBUG
		if (obj == debug_obj)
			printf("   fate  = %d, hit_pnt = %8x %8x %8x\n",fate,XYZ(&hit_info.hit_pnt));;
		#endif

		ipos = hit_info.hit_pnt;
		iseg = hit_info.hit_seg;
		WallHitSide = hit_info.hit_side;
		WallHitSeg = hit_info.hit_side_seg;

		if (iseg==-1) {		//some sort of horrible error
			#ifndef NDEBUG
			mprintf((1,"iseg==-1 in physics!  Object = %i, type = %i (%s)\n", obj-Objects, obj->type, Object_type_names[obj->type]));
			#endif
			//Int3();
			//compute_segment_center(&ipos,&Segments[obj->segnum]);
			//ipos.x += objnum;
			//iseg = obj->segnum;
			//fate = HIT_NONE;
			if (obj->type == OBJ_WEAPON)
				obj->flags |= OF_SHOULD_BE_DEAD;
			break;
		}

		Assert(!((fate==HIT_WALL) && ((WallHitSeg == -1) || (WallHitSeg > Highest_segment_index))));

		//if(!get_seg_masks(&hit_info.hit_pnt,hit_info.hit_seg,0).centermask==0)
		//	Int3();

		save_pos = obj->pos;			//save the object's position
		save_seg = obj->segnum;

		// update object's position and segment number
		obj->pos = ipos;

		#ifdef EXTRA_DEBUG
		if (obj == debug_obj)
			printf("   new pos = %x %x %x\n",XYZ(&obj->pos));
		#endif

		if ( iseg != obj->segnum )
			obj_relink(objnum, iseg );

		//if start point not in segment, move object to center of segment
		if (get_seg_masks(&obj->pos,obj->segnum,0).centermask!=0) {
			int n;

			if ((n=find_object_seg(obj))==-1) {
				//Int3();
				if (obj->type==OBJ_PLAYER && (n=find_point_seg(&obj->last_pos,obj->segnum))!=-1) {
					obj->pos = obj->last_pos;
					obj_relink(objnum, n );
				}
				else {
					compute_segment_center(&obj->pos,&Segments[obj->segnum]);
					obj->pos.x += objnum;
				}
				if (obj->type == OBJ_WEAPON)
					obj->flags |= OF_SHOULD_BE_DEAD;
			}
			return;
		}

		//calulate new sim time
		{
			//vms_vector moved_vec;
			vms_vector moved_vec_n;
			fix attempted_dist,actual_dist;

			actual_dist = vm_vec_normalized_dir(&moved_vec_n,&obj->pos,&save_pos);

			if (fate==HIT_WALL && vm_vec_dot(&moved_vec_n,&frame_vec) < 0) {		//moved backwards

				//don't change position or sim_time

//*******					mprintf((0,"Obj %d moved backwards\n",obj-Objects));

				#ifdef EXTRA_DEBUG
				if (obj == debug_obj)
					printf("   Warning: moved backwards!\n");
				#endif

				obj->pos = save_pos;
		
				//iseg = obj->segnum;		//don't change segment

				obj_relink(objnum, save_seg );

				moved_time = 0;
			}
			else {
				fix old_sim_time;

				//if (obj == debug_obj)
				//	printf("   moved_vec = %x %x %x\n",XYZ(&moved_vec));
			
				attempted_dist = vm_vec_mag(&frame_vec);

				old_sim_time = sim_time;

				sim_time = fixmuldiv(sim_time,attempted_dist-actual_dist,attempted_dist);

				moved_time = old_sim_time - sim_time;

				if (sim_time < 0 || sim_time>old_sim_time) {
					#ifndef NDEBUG
					mprintf((0,"Bogus sim_time = %x, old = %x\n",sim_time,old_sim_time));
					if (obj == debug_obj)
						printf("   Bogus sim_time = %x, old = %x, attempted_dist = %x, actual_dist = %x\n",sim_time,old_sim_time,attempted_dist,actual_dist);
					//Int3(); Removed by Rob
					#endif
					sim_time = old_sim_time;
					//WHY DOES THIS HAPPEN??

					moved_time = 0;
				}
			}

			#ifdef EXTRA_DEBUG
			if (obj == debug_obj)
				printf("   new sim_time = %x\n",sim_time);
			#endif

		}


		switch( fate )		{

			case HIT_WALL:		{
				vms_vector moved_v;
				//@@fix total_d,moved_d;
				fix hit_speed,wall_part;
	
				// Find hit speed	

				vm_vec_sub(&moved_v,&obj->pos,&save_pos);

				wall_part = vm_vec_dot(&moved_v,&hit_info.hit_wallnorm);

				if (wall_part != 0 && moved_time>0 && (hit_speed=-fixdiv(wall_part,moved_time))>0)
					collide_object_with_wall( obj, hit_speed, WallHitSeg, WallHitSide, &hit_info.hit_pnt );
				else
					scrape_object_on_wall(obj, WallHitSeg, WallHitSide, &hit_info.hit_pnt );

				Assert( WallHitSeg > -1 );				
				Assert( WallHitSide > -1 );				

				if ( !(obj->flags&OF_SHOULD_BE_DEAD) )	{


					Assert(! (obj->mtype.phys_info.flags & PF_STICK && obj->mtype.phys_info.flags & PF_BOUNCE));	//can't be bounce and stick

					if (obj->mtype.phys_info.flags & PF_STICK) {		//stop moving

						// mprintf((0, "Object %i stuck at %i:%i\n", obj-Objects, WallHitSeg, WallHitSide));
						add_stuck_object(obj, WallHitSeg, WallHitSide);

						vm_vec_zero(&obj->mtype.phys_info.velocity);
						obj_stopped = 1;
						try_again = 0;
					}
					else {					// Slide object along wall

						//We're constrained by wall, so subtract wall part from 
						//velocity vector

						wall_part = vm_vec_dot(&hit_info.hit_wallnorm,&obj->mtype.phys_info.velocity);

						if (obj->mtype.phys_info.flags & PF_BOUNCE)		//bounce off wall
							wall_part *= 2;	//Subtract out wall part twice to achieve bounce

						vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&hit_info.hit_wallnorm,-wall_part);

						#ifdef EXTRA_DEBUG
						if (obj == debug_obj) {
							printf("   sliding - wall_norm %x %x %x\n",wall_part,XYZ(&hit_info.hit_wallnorm));
							printf("   wall_part %x, new velocity = %x %x %x\n",wall_part,XYZ(&obj->mtype.phys_info.velocity));
						}
						#endif

						try_again = 1;
					}
				}
				break;
			}

			case HIT_OBJECT:		{
				vms_vector old_vel;

				// Mark the hit object so that on a retry the fvi code
				// ignores this object.

				Assert(hit_info.hit_object != -1);

				//	Calculcate the hit point between the two objects.
				{	vms_vector	*ppos0, *ppos1, pos_hit;
					fix			size0, size1;
					ppos0 = &Objects[hit_info.hit_object].pos;
					ppos1 = &obj->pos;
					size0 = Objects[hit_info.hit_object].size;
					size1 = obj->size;
					Assert(size0+size1 != 0);	// Error, both sizes are 0, so how did they collide, anyway?!?
					//vm_vec_scale(vm_vec_sub(&pos_hit, ppos1, ppos0), fixdiv(size0, size0 + size1));
					//vm_vec_add2(&pos_hit, ppos0);
					vm_vec_sub(&pos_hit, ppos1, ppos0);
					vm_vec_scale_add(&pos_hit,ppos0,&pos_hit,fixdiv(size0, size0 + size1));

					old_vel = obj->mtype.phys_info.velocity;

					collide_two_objects( obj, &Objects[hit_info.hit_object], &pos_hit);

				}

				// Let object continue its movement
				if ( !(obj->flags&OF_SHOULD_BE_DEAD)  )	{
					//obj->pos = save_pos;

					if (obj->mtype.phys_info.flags&PF_PERSISTENT || (old_vel.x == obj->mtype.phys_info.velocity.x && old_vel.y == obj->mtype.phys_info.velocity.y && old_vel.z == obj->mtype.phys_info.velocity.z)) {
						//if (Objects[hit_info.hit_object].type == OBJ_POWERUP)
							ignore_obj_list[n_ignore_objs++] = hit_info.hit_object;
						try_again = 1;
					}
				}

				break;
			}	
			case HIT_NONE:		
				break;

			#ifndef NDEBUG
			case HIT_BAD_P0:
				Int3();		// Unexpected collision type: start point not in specified segment.
				mprintf((0,"Warning: Bad p0 in physics!!!\n"));
				break;
			default:
				// Unknown collision type returned from find_vector_intersection!!
				Int3();
				break;
			#endif
		}

	} while ( try_again );

	//	Pass retry count info to AI.
	if (obj->control_type == CT_AI) {
		if (count > 0) {
			Ai_local_info[objnum].retry_count = count-1;
			Total_retries += count-1;
			Total_sims++;
		}
	}

	if (! obj_stopped)	{	//Set velocity from actual movement
		vms_vector moved_vec;
		vm_vec_sub(&moved_vec,&obj->pos,&start_pos);
		vm_vec_copy_scale(&obj->mtype.phys_info.velocity,&moved_vec,fixdiv(f1_0,FrameTime));

		#ifdef BUMP_HACK
		if (obj==ConsoleObject && (obj->mtype.phys_info.velocity.x==0 && obj->mtype.phys_info.velocity.y==0 && obj->mtype.phys_info.velocity.z==0) &&
			  !(obj->mtype.phys_info.thrust.x==0 && obj->mtype.phys_info.thrust.y==0 && obj->mtype.phys_info.thrust.z==0)) {
			vms_vector center,bump_vec;

			//bump player a little towards center of segment to unstick

			compute_segment_center(&center,&Segments[obj->segnum]);
			vm_vec_normalized_dir_quick(&bump_vec,&center,&obj->pos);
			vm_vec_scale_add2(&obj->pos,&bump_vec,obj->size/5);
		}
		#endif
	}

	//Assert(check_point_in_seg(&obj->pos,obj->segnum,0).centermask==0);

	//if (obj->control_type == CT_FLYING)
	if (obj->mtype.phys_info.flags & PF_LEVELLING)
		do_physics_align_object( obj );


	//hack to keep player from going through closed doors
	if (obj->type==OBJ_PLAYER && obj->segnum!=orig_segnum && (Physics_cheat_flag!=0xBADA55) ) {
		int sidenum;

		sidenum = find_connect_side(&Segments[obj->segnum],&Segments[orig_segnum]);

		if (sidenum != -1) {

			if (! (WALL_IS_DOORWAY(&Segments[orig_segnum],sidenum) & WID_FLY_FLAG)) {
				side *s;
				int vertnum,num_faces,i;
				fix dist;
				int vertex_list[6];

				//bump object back

				s = &Segments[orig_segnum].sides[sidenum];

				create_abs_vertex_lists( &num_faces, vertex_list, orig_segnum, sidenum);

				//let's pretend this wall is not triangulated
				vertnum = vertex_list[0];
				for (i=1;i<4;i++)
					if (vertex_list[i] < vertnum)
						vertnum = vertex_list[i];

				#ifdef COMPACT_SEGS
					{
					vms_vector _vn;
					get_side_normal(&Segments[orig_segnum], sidenum, 0, &_vn );
					dist = vm_dist_to_plane(&start_pos, &_vn, &Vertices[vertnum]);
					vm_vec_scale_add(&obj->pos,&start_pos,&_vn,obj->size-dist);
					}
				#else
					dist = vm_dist_to_plane(&start_pos, &s->normals[0], &Vertices[vertnum]);
					vm_vec_scale_add(&obj->pos,&start_pos,&s->normals[0],obj->size-dist);
				#endif
				update_object_seg(obj);

			}
		}
	}

//--WE ALWYS WANT THIS IN, MATT AND MIKE DECISION ON 12/10/94, TWO MONTHS AFTER FINAL 	#ifndef NDEBUG
	//if end point not in segment, move object to last pos, or segment center
	if (get_seg_masks(&obj->pos,obj->segnum,0).centermask!=0) {
		if (find_object_seg(obj)==-1) {
			int n;

			//Int3();
			if (obj->type==OBJ_PLAYER && (n=find_point_seg(&obj->last_pos,obj->segnum))!=-1) {
				obj->pos = obj->last_pos;
				obj_relink(objnum, n );
			}
			else {
				compute_segment_center(&obj->pos,&Segments[obj->segnum]);
				obj->pos.x += objnum;
			}
			if (obj->type == OBJ_WEAPON)
				obj->flags |= OF_SHOULD_BE_DEAD;
		}
	}
//--WE ALWYS WANT THIS IN, MATT AND MIKE DECISION ON 12/10/94, TWO MONTHS AFTER FINAL 	#endif


}
Exemplo n.º 22
0
//	-----------------------------------------------------------------------------------------------------------
//Simulate a physics object for this frame
void do_physics_sim(object *obj)
{
	int ignore_obj_list[MAX_IGNORE_OBJS],n_ignore_objs;
	int iseg;
	int try_again;
	int fate=0;
	vms_vector frame_vec;			//movement in this frame
	vms_vector new_pos,ipos;		//position after this frame
	int count=0;
	int objnum;
	int WallHitSeg, WallHitSide;
	fvi_info hit_info;
	fvi_query fq;
	vms_vector save_pos;
	int save_seg;
	fix drag;
	fix sim_time;
	vms_vector start_pos;
	int obj_stopped=0;
	fix moved_time; 			//how long objected moved before hit something
	physics_info *pi;
	int orig_segnum = obj->segnum;
	fix PhysTime = (FrameTime<F1_0/30?F1_0/30:FrameTime);

	Assert(obj->movement_type == MT_PHYSICS);

#ifndef NDEBUG
	if (Dont_move_ai_objects)
		if (obj->control_type == CT_AI)
			return;
#endif

	pi = &obj->mtype.phys_info;

	do_physics_sim_rot(obj);

	if (!(pi->velocity.x || pi->velocity.y || pi->velocity.z || pi->thrust.x || pi->thrust.y || pi->thrust.z))
		return;

	objnum = obj-Objects;

	n_phys_segs = 0;

	/* As this engine was not designed for that high FPS as we intend, we use F1_0/30 max. for sim_time to ensure
	   scaling and dot products stay accurate and reliable. The object position intended for this frame will be scaled down later,
	   after the main collision-loop is done.
	   This won't make collision results be equal in all FPS settings, but hopefully more accurate, the higher our FPS are.
	*/
	sim_time = PhysTime; //FrameTime;

	//debug_obj = obj;

#ifdef EXTRA_DEBUG
	//check for correct object segment 
        if(!get_seg_masks(&obj->pos,obj->segnum,0,__FILE__,__LINE__).centermask==0) {
		//Int3();  Removed by Rob 10/5/94
		if (!update_object_seg(obj)) {
			if (!(Game_mode & GM_MULTI))
				Int3();
			compute_segment_center(&obj->pos,&Segments[obj->segnum]);
			obj->pos.x += objnum;
		}
	}
#endif

	start_pos = obj->pos;

	n_ignore_objs = 0;

	Assert(obj->mtype.phys_info.brakes==0);		//brakes not used anymore?

		//if uses thrust, cannot have zero drag
        Assert(!(obj->mtype.phys_info.flags&PF_USES_THRUST) || obj->mtype.phys_info.drag!=0);

	//do thrust & drag
	// NOTE: this always must be dependent on FrameTime, if sim_time differs!
	if ((drag = obj->mtype.phys_info.drag) != 0) {

		int count;
		vms_vector accel;
		fix r,k,have_accel;

		count = FrameTime / FT;
		r = FrameTime % FT;
		k = fixdiv(r,FT);

		if (obj->mtype.phys_info.flags & PF_USES_THRUST) {

			vm_vec_copy_scale(&accel,&obj->mtype.phys_info.thrust,fixdiv(f1_0,obj->mtype.phys_info.mass));
			have_accel = (accel.x || accel.y || accel.z);

			while (count--) {
				if (have_accel)
					vm_vec_add2(&obj->mtype.phys_info.velocity,&accel);

				vm_vec_scale(&obj->mtype.phys_info.velocity,f1_0-drag);
			}

			//do linear scale on remaining bit of time

			vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&accel,k);
			if (drag)
				vm_vec_scale(&obj->mtype.phys_info.velocity,f1_0-fixmul(k,drag));
		}
		else if (drag)
		{
			fix total_drag=f1_0;

			while (count--)
				total_drag = fixmul(total_drag,f1_0-drag);

			//do linear scale on remaining bit of time

			total_drag = fixmul(total_drag,f1_0-fixmul(k,drag));

			vm_vec_scale(&obj->mtype.phys_info.velocity,total_drag);
		}
	}

	do {
		try_again = 0;

		//Move the object
		vm_vec_copy_scale(&frame_vec, &obj->mtype.phys_info.velocity, sim_time);

		if ( (frame_vec.x==0) && (frame_vec.y==0) && (frame_vec.z==0) )	
			break;

		count++;

		//	If retry count is getting large, then we are trying to do something stupid.
		if (count > 8) break; // in original code this was 3 for all non-player objects. still leave us some limit in case fvi goes apeshit.

		vm_vec_add(&new_pos,&obj->pos,&frame_vec);

		ignore_obj_list[n_ignore_objs] = -1;

		fq.p0						= &obj->pos;
		fq.startseg				= obj->segnum;
		fq.p1						= &new_pos;
		fq.rad					= obj->size;
		fq.thisobjnum			= objnum;
		fq.ignore_obj_list	= ignore_obj_list;
		fq.flags					= FQ_CHECK_OBJS;

		if (obj->type == OBJ_WEAPON)
			fq.flags |= FQ_TRANSPOINT;

		if (obj->type == OBJ_PLAYER)
			fq.flags |= FQ_GET_SEGLIST;

		fate = find_vector_intersection(&fq,&hit_info);
		//	Matt: Mike's hack.
		if (fate == HIT_OBJECT) {
			object	*objp = &Objects[hit_info.hit_object];

			if (((objp->type == OBJ_WEAPON) && (objp->id == PROXIMITY_ID)) || objp->type == OBJ_POWERUP) // do not increase count for powerups since they *should* not change our movement
				count--;
		}

#ifndef NDEBUG
		if (fate == HIT_BAD_P0) {
			Int3();
		}
#endif

		if (obj->type == OBJ_PLAYER) {
			int i;

			if (n_phys_segs && phys_seglist[n_phys_segs-1]==hit_info.seglist[0])
				n_phys_segs--;

			for (i=0;(i<hit_info.n_segs) && (n_phys_segs<MAX_FVI_SEGS-1);  )
				phys_seglist[n_phys_segs++] = hit_info.seglist[i++];
		}

		ipos = hit_info.hit_pnt;
		iseg = hit_info.hit_seg;
		WallHitSide = hit_info.hit_side;
		WallHitSeg = hit_info.hit_side_seg;

		if (iseg==-1) {		//some sort of horrible error
			if (obj->type == OBJ_WEAPON)
				obj->flags |= OF_SHOULD_BE_DEAD;
			break;
		}

		Assert(!((fate==HIT_WALL) && ((WallHitSeg == -1) || (WallHitSeg > Highest_segment_index))));

		//if(!get_seg_masks(&hit_info.hit_pnt,hit_info.hit_seg,0).centermask==0)
		//	Int3();

		save_pos = obj->pos;			//save the object's position
		save_seg = obj->segnum;

		// update object's position and segment number
		obj->pos = ipos;

		if ( iseg != obj->segnum )
			obj_relink(objnum, iseg );

		//if start point not in segment, move object to center of segment
                if (get_seg_masks(&obj->pos,obj->segnum,0,__FILE__,__LINE__).centermask!=0) {
			int n;

			if ((n=find_object_seg(obj))==-1) {
				//Int3();
				if (obj->type==OBJ_PLAYER && (n=find_point_seg(&obj->last_pos,obj->segnum))!=-1) {
					obj->pos = obj->last_pos;
					obj_relink(objnum, n );
				}
				else {
					compute_segment_center(&obj->pos,&Segments[obj->segnum]);
					obj->pos.x += objnum;
				}
				if (obj->type == OBJ_WEAPON)
					obj->flags |= OF_SHOULD_BE_DEAD;
			}
			return;
		}

		//calulate new sim time
		{
			//vms_vector moved_vec;
			vms_vector moved_vec_n;
			fix attempted_dist,actual_dist;

			actual_dist = vm_vec_normalized_dir(&moved_vec_n,&obj->pos,&save_pos);

			if (fate==HIT_WALL && vm_vec_dot(&moved_vec_n,&frame_vec) < 0) {		//moved backwards

				//don't change position or sim_time

				obj->pos = save_pos;
		
				//iseg = obj->segnum;		//don't change segment

				obj_relink(objnum, save_seg );

				moved_time = 0;
			}
			else {
				fix old_sim_time;

				attempted_dist = vm_vec_mag(&frame_vec);

				old_sim_time = sim_time;

				sim_time = fixmuldiv(sim_time,attempted_dist-actual_dist,attempted_dist);

				moved_time = old_sim_time - sim_time;

				if (sim_time < 0 || sim_time>old_sim_time) {
					sim_time = old_sim_time;
					//WHY DOES THIS HAPPEN??

					moved_time = 0;
				}
			}
		}


		switch( fate )		{

			case HIT_WALL:		{
				vms_vector moved_v;
				fix hit_speed=0, wall_part=0;

				// Find hit speed	

				vm_vec_sub(&moved_v,&obj->pos,&save_pos);

				wall_part = vm_vec_dot(&moved_v,&hit_info.hit_wallnorm);

				if ((wall_part != 0 && moved_time>0 && (hit_speed=-fixdiv(wall_part,moved_time))>0) || obj->type == OBJ_WEAPON || obj->type == OBJ_DEBRIS)
					collide_object_with_wall( obj, hit_speed, WallHitSeg, WallHitSide, &hit_info.hit_pnt );
				if (obj->type == OBJ_PLAYER)
					scrape_player_on_wall(obj, WallHitSeg, WallHitSide, &hit_info.hit_pnt );

				Assert( WallHitSeg > -1 );				
				Assert( WallHitSide > -1 );				

				if ( !(obj->flags&OF_SHOULD_BE_DEAD) )	{


					Assert(! (obj->mtype.phys_info.flags & PF_STICK && obj->mtype.phys_info.flags & PF_BOUNCE));	//can't be bounce and stick

					if (obj->mtype.phys_info.flags & PF_STICK) {		//stop moving

						add_stuck_object(obj, WallHitSeg, WallHitSide);

						vm_vec_zero(&obj->mtype.phys_info.velocity);
						obj_stopped = 1;
						try_again = 0;
					}
					else {					// Slide object along wall

						//We're constrained by wall, so subtract wall part from 
						//velocity vector

						wall_part = vm_vec_dot(&hit_info.hit_wallnorm,&obj->mtype.phys_info.velocity);

						// if wall_part, make sure the value is sane enough to get usable velocity computed
						if (wall_part < 0 && wall_part > -f1_0) wall_part = -f1_0;
						if (wall_part > 0 && wall_part < f1_0) wall_part = f1_0;

						if (obj->mtype.phys_info.flags & PF_BOUNCE)		//bounce off wall
							wall_part *= 2;	//Subtract out wall part twice to achieve bounce

						vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&hit_info.hit_wallnorm,-wall_part);

						try_again = 1;
					}
				}

				break;
			}

			case HIT_OBJECT:		{
				vms_vector old_vel;

				// Mark the hit object so that on a retry the fvi code
				// ignores this object.

				Assert(hit_info.hit_object != -1);
				//	Calculcate the hit point between the two objects.
				{	vms_vector	*ppos0, *ppos1, pos_hit;
					fix			size0, size1;
					ppos0 = &Objects[hit_info.hit_object].pos;
					ppos1 = &obj->pos;
					size0 = Objects[hit_info.hit_object].size;
					size1 = obj->size;
					Assert(size0+size1 != 0);	// Error, both sizes are 0, so how did they collide, anyway?!?
					//vm_vec_scale(vm_vec_sub(&pos_hit, ppos1, ppos0), fixdiv(size0, size0 + size1));
					//vm_vec_add2(&pos_hit, ppos0);
					vm_vec_sub(&pos_hit, ppos1, ppos0);
					vm_vec_scale_add(&pos_hit,ppos0,&pos_hit,fixdiv(size0, size0 + size1));

					old_vel = obj->mtype.phys_info.velocity;

					collide_two_objects( obj, &Objects[hit_info.hit_object], &pos_hit);

				}

				// Let object continue its movement
				if ( !(obj->flags&OF_SHOULD_BE_DEAD)  )	{
					//obj->pos = save_pos;

					if (obj->mtype.phys_info.flags&PF_PERSISTENT || (old_vel.x == obj->mtype.phys_info.velocity.x && old_vel.y == obj->mtype.phys_info.velocity.y && old_vel.z == obj->mtype.phys_info.velocity.z)) {
						//if (Objects[hit_info.hit_object].type == OBJ_POWERUP)
							ignore_obj_list[n_ignore_objs++] = hit_info.hit_object;
						try_again = 1;
					}
				}

				break;
			}	
			case HIT_NONE:		
				break;

#ifndef NDEBUG
			case HIT_BAD_P0:
				Int3();		// Unexpected collision type: start point not in specified segment.
				break;
			default:
				// Unknown collision type returned from find_vector_intersection!!
				Int3();
				break;
#endif
		}
	} while ( try_again );

	//	Pass retry count info to AI.
	if (obj->control_type == CT_AI) {
		if (count > 0) {
			Ai_local_info[objnum].retry_count = count-1;
			Total_retries += count-1;
			Total_sims++;
		}
	}

	// As sim_time may not base on FrameTime, scale actual object position to get accurate movement
	if (PhysTime/FrameTime > 0)
	{
		vms_vector md;
		vm_vec_sub(&md, &obj->pos, &start_pos);
		vm_vec_scale(&md, F1_0/((float)PhysTime/FrameTime));
		vm_vec_add(&obj->pos,&start_pos, &md);
		//check for and update correct object segment
		if(!get_seg_masks(&obj->pos, obj->segnum, 0, __FILE__, __LINE__).centermask == 0)
		{
			if (!update_object_seg(obj)) {
				if (!(Game_mode & GM_MULTI))
					Int3();
				compute_segment_center(&obj->pos,&Segments[obj->segnum]);
				obj->pos.x += objnum;
			}
		}
	}

	// After collision with objects and walls, set velocity from actual movement
	if (!obj_stopped
		&& ((obj->type == OBJ_PLAYER) || (obj->type == OBJ_ROBOT) || (obj->type == OBJ_DEBRIS)) 
		&& ((fate == HIT_WALL) || (fate == HIT_OBJECT) || (fate == HIT_BAD_P0))
		)
	{	
		vms_vector moved_vec;
		vm_vec_sub(&moved_vec,&obj->pos,&start_pos);
		vm_vec_copy_scale(&obj->mtype.phys_info.velocity,&moved_vec,fixdiv(f1_0,FrameTime));
	}

	fix_illegal_wall_intersection(obj, &start_pos);

	//Assert(check_point_in_seg(&obj->pos,obj->segnum,0).centermask==0);

	//if (obj->control_type == CT_FLYING)
	if (obj->mtype.phys_info.flags & PF_LEVELLING)
		do_physics_align_object( obj );


	//hack to keep player from going through closed doors
	if (obj->type==OBJ_PLAYER && obj->segnum!=orig_segnum && (!cheats.ghostphysics) ) {
		int sidenum;

		sidenum = find_connect_side(&Segments[obj->segnum],&Segments[orig_segnum]);

		if (sidenum != -1) {

			if (! (WALL_IS_DOORWAY(&Segments[orig_segnum],sidenum) & WID_FLY_FLAG)) {
				side *s;
				int vertnum,num_faces,i;
				fix dist;
				int vertex_list[6];

				//bump object back

				s = &Segments[orig_segnum].sides[sidenum];

                                create_abs_vertex_lists( &num_faces, vertex_list, orig_segnum, sidenum, __FILE__,__LINE__);

				//let's pretend this wall is not triangulated
				vertnum = vertex_list[0];
				for (i=1;i<4;i++)
					if (vertex_list[i] < vertnum)
						vertnum = vertex_list[i];

#ifdef COMPACT_SEGS
					{
						vms_vector _vn;
						get_side_normal(&Segments[orig_segnum], sidenum, 0, &_vn );
						dist = vm_dist_to_plane(&start_pos, &_vn, &Vertices[vertnum]);
						vm_vec_scale_add(&obj->pos,&start_pos,&_vn,obj->size-dist);
					}
#else
					dist = vm_dist_to_plane(&start_pos, &s->normals[0], &Vertices[vertnum]);
					vm_vec_scale_add(&obj->pos,&start_pos,&s->normals[0],obj->size-dist);
#endif
				update_object_seg(obj);

			}
		}
	}

//--WE ALWYS WANT THIS IN, MATT AND MIKE DECISION ON 12/10/94, TWO MONTHS AFTER FINAL 	#ifndef NDEBUG
	//if end point not in segment, move object to last pos, or segment center
        if (get_seg_masks(&obj->pos,obj->segnum,0,__FILE__,__LINE__).centermask!=0) {
		if (find_object_seg(obj)==-1) {
			int n;

			//Int3();
			if (obj->type==OBJ_PLAYER && (n=find_point_seg(&obj->last_pos,obj->segnum))!=-1) {
				obj->pos = obj->last_pos;
				obj_relink(objnum, n );
			}
			else {
				compute_segment_center(&obj->pos,&Segments[obj->segnum]);
				obj->pos.x += objnum;
			}
			if (obj->type == OBJ_WEAPON)
				obj->flags |= OF_SHOULD_BE_DEAD;
		}
	}
//--WE ALWYS WANT THIS IN, MATT AND MIKE DECISION ON 12/10/94, TWO MONTHS AFTER FINAL 	#endif
}
Exemplo n.º 23
0
GLvoid glRotatex(GLfixed theta, GLfixed x, GLfixed y, GLfixed z) // p35 2.9.2
{
	int i, j, k;

	// Ensure we have an axis of rotation!
	if(x == 0 && y == 0 && z == 0)
		return;

	// Mark dirty
	gl_mat_gte_isdirty = GL_TRUE;

	// OPTIMISATION: If on a single axis we don't need to tweak as much
	int zeros = 0;
	if(x == 0) zeros++;
	if(y == 0) zeros++;
	if(z == 0) zeros++;

	//if(0)
	if(zeros == 2)
	{
		// Rotate around an axis
		// FIXME: get correct rotation orders
		int a, b;
		if(x != 0) { a = 1; b = 2; }
		else if(y != 0) { a = 2; b = 0; }
		else { a = 0; b = 1; }

		// Get matrix pointer
		GLint stackidx = gl_mat_stack[gl_mat_cur];
		GLfixed *rot = gl_mat_rot[gl_mat_cur][stackidx];

		// Get sin/cos
		//theta /= 360; // dropping the "degrees" requirement, using direct angles instead
		GLfixed tsin = fixsin(theta);
		GLfixed tcos = fixcos(theta);

		// Get old values
		GLfixed ta0 = rot[a*3 + 0];
		GLfixed ta1 = rot[a*3 + 1];
		GLfixed ta2 = rot[a*3 + 2];
		GLfixed tb0 = rot[b*3 + 0];
		GLfixed tb1 = rot[b*3 + 1];
		GLfixed tb2 = rot[b*3 + 2];

		// Write new values
		// TODO: get this to behave
		rot[a*3 + 0] = fixmulf(ta0, tcos) - fixmulf(tb0, tsin);
		rot[a*3 + 1] = fixmulf(ta1, tcos) - fixmulf(tb1, tsin);
		rot[a*3 + 2] = fixmulf(ta2, tcos) - fixmulf(tb2, tsin);
		rot[b*3 + 0] = fixmulf(ta0, tsin) + fixmulf(tb0, tcos);
		rot[b*3 + 1] = fixmulf(ta1, tsin) + fixmulf(tb1, tcos);
		rot[b*3 + 2] = fixmulf(ta2, tsin) + fixmulf(tb2, tcos);

		return;
	}

	//
	// GENERIC OPENGL ROTATION
	//

	// Normalise x,y,z
	GLfixed vlen2 = fixmul(x,x) + fixmul(y,y) + fixmul(z,z);
	if(vlen2 >= 0x100)
	{
		GLfixed vlen = fixsqrt(vlen2);
		x = fixdiv(x, vlen);
		y = fixdiv(y, vlen);
		z = fixdiv(z, vlen);
	} else {
		// Length is too small to get a sane result
		// Use int multiplies instead and shift later

		// FIXME get this working correctly
		vlen2 = x*x + y*y + z*z;

		// Skip if we get 0
		if(vlen2 == 0)
			return;

		GLfixed vlen = fixsqrt(vlen2)<<8;
		x = fixdiv(x, vlen);
		y = fixdiv(y, vlen);
		z = fixdiv(z, vlen);

	}

	// Get sin/cos
	theta /= 360;
	GLfixed tsin = fixsin(theta);
	GLfixed tcos = fixcos(theta);

	// Generate rotation matrix
	GLfixed itcos = 0x10000-tcos;
	GLfixed base_rot[3][3] = {
		{
			fixmulf(itcos, fixmulf(x, x))+tcos,
			fixmulf(itcos, fixmulf(x, y))-fixmulf(tsin, z),
			fixmulf(itcos, fixmulf(x, z))+fixmulf(tsin, y),
		},
		{
			fixmulf(itcos, fixmulf(y, x))+fixmulf(tsin, z),
			fixmulf(itcos, fixmulf(y, y))+tcos,
			fixmulf(itcos, fixmulf(y, z))-fixmulf(tsin, x),
		},
		{
			fixmulf(itcos, fixmulf(z, x))-fixmulf(tsin, y),
			fixmulf(itcos, fixmulf(z, y))+fixmulf(tsin, x),
			fixmulf(itcos, fixmulf(z, z))+tcos,
		},
	};

	// Apply rotation matrix
	GLint stackidx = gl_mat_stack[gl_mat_cur];
	GLfixed *rot = gl_mat_rot[gl_mat_cur][stackidx];
	//GLfixed *trn = gl_mat_trn[gl_mat_cur][stackidx];
	GLfixed oldrot[9];
	//GLfixed oldtrn[3];
	memcpy(oldrot, rot, sizeof(GLfixed)*9);
	//memcpy(oldtrn, trn, sizeof(GLfixed)*3);

	// FIXME: translate properly
	// FIXME: ensure correct order
	for(i = 0; i < 3; i++)
	for(j = 0; j < 3; j++)
	{
		GLfixed sum = 0;
		for(k = 0; k < 3; k++)
			//sum += fixmulf(oldrot[3*i + k], base_rot[k][j]);
			sum += fixmulf(oldrot[3*k + j], base_rot[i][k]);

		rot[3*i + j] = sum;
	}

	/*
	for(i = 0; i < 3; i++)
	{
		GLfixed sum = 0;
		for(k = 0; k < 3; k++)
			sum += fixmulf(oldtrn[k], rot[k*3 + i]);
			//sum += fixmulf(oldtrn[k], rot[i*3 + k]);
			//sum += fixmulf(oldtrn[k], base_rot[k][i]);
			//sum += fixmulf(oldtrn[k], base_rot[i][k]);

		//trn[i] = sum;
	}
	*/
}
Exemplo n.º 24
0
void do_automap( int key_code )	{
	int done=0;
	vms_matrix	tempm;
	vms_angvec	tangles;
	int leave_mode=0;
	int first_time=1;
	int pcx_error;
	int i;
	int c;
	char filename[] = "MAP.PCX";
	fix entry_time;
	int pause_game=1;		// Set to 1 if everything is paused during automap...No pause during net.
	fix t1, t2;
	control_info saved_control_info;
	int Max_segments_away = 0;
	int SegmentLimit = 1;

	key_code = key_code;	// disable warning...

	if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence))
		pause_game = 0;

	if (pause_game)
		stop_time();

	create_name_canv();

	Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES);			//make maybe smaller than max
	//Edges	= malloc( sizeof(Edge_info)*Max_edges);
	//if ( Edges == NULL )	{
	//	mprintf((0, "Couldn't get %dK for automap!", sizeof(Edge_info)*Max_edges/1024));
	//	return;
	//}
	//DrawingListBright = malloc( sizeof(short)*Max_edges);
	//if ( DrawingListBright == NULL )	{
	//	mprintf((0, "Couldn't get %dK for automap!", sizeof(short)*Max_edges/1024));
	//	return;
	//}

	mprintf( (0, "Num_vertices=%d, Max_edges=%d, (MAX:%d)\n", Num_vertices, Max_edges, MAX_EDGES ));
	mprintf( (0, "Allocated %d K for automap edge list\n", (sizeof(Edge_info)+sizeof(short))*Max_edges/1024 ));

	gr_palette_clear();
	gr_init_sub_canvas(&Page,&VR_render_buffer[0],0, 0, 640, 480);
	gr_init_sub_canvas(&DrawingPage,&Page,38,77,564,381);

#if 0
	gr_init_sub_canvas(&Pages[0],grd_curcanv,0,0,320,400);
	gr_init_sub_canvas(&Pages[1],grd_curcanv,0,401,320,400);
	gr_init_sub_canvas(&DrawingPages[0],&Pages[0],16,69,288,272);
	gr_init_sub_canvas(&DrawingPages[1],&Pages[1],16,69,288,272);
#endif

	gr_set_current_canvas(&Page);
	pcx_error = pcx_read_bitmap(filename,&(grd_curcanv->cv_bitmap),BM_LINEAR,NULL);
	if ( pcx_error != PCX_ERROR_NONE )	{
		printf("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
		Error("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
		return;
	}

	gr_set_curfont(Gamefonts[GFONT_BIG_1]);
	gr_set_fontcolor(BM_XRGB(20, 20, 20), -1);
	gr_printf( 80, 36,TXT_AUTOMAP,GFONT_BIG_1);
	gr_set_curfont(Gamefonts[GFONT_SMALL]);
	gr_set_fontcolor(BM_XRGB(20, 20, 20), -1);
	gr_printf( 265, 27,TXT_TURN_SHIP);
	gr_printf( 265, 44,TXT_SLIDE_UPDOWN);
	gr_printf( 265, 61,TXT_VIEWING_DISTANCE);

	gr_set_current_canvas(&DrawingPage);

	automap_build_edge_list();

	if ( ViewDist==0 ) 
		ViewDist = ZOOM_DEFAULT;
	ViewMatrix = Objects[Players[Player_num].objnum].orient;

	tangles.p = PITCH_DEFAULT;
	tangles.h  = 0;
	tangles.b  = 0;

	done = 0;

	view_target = Objects[Players[Player_num].objnum].pos;

	t1 = entry_time = timer_get_fixed_seconds();
	t2 = t1;

	//Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum
	Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
	SegmentLimit = Max_segments_away;

	adjust_segment_limit(SegmentLimit);

	while(!done)	{
#ifndef MAC_SHAREWARE
		redbook_restart_track();
#endif
		
		if ( leave_mode==0 && Controls.automap_state && (timer_get_fixed_seconds()-entry_time)>LEAVE_TIME)
			leave_mode = 1;

		if ( !Controls.automap_state && (leave_mode==1) )
			done=1;

		if (!pause_game)	{
			ushort old_wiggle;

			saved_control_info = Controls;				// Save controls so we can zero them
			memset(&Controls,0,sizeof(control_info));	// Clear everything...
			old_wiggle = ConsoleObject->mtype.phys_info.flags & PF_WIGGLE;	// Save old wiggle
			ConsoleObject->mtype.phys_info.flags &= ~PF_WIGGLE;		// Turn off wiggle
			#ifdef NETWORK
			if (multi_menu_poll())
				done = 1;
			#endif
//			GameLoop( 0, 0 );		// Do game loop with no rendering and no reading controls.
			ConsoleObject->mtype.phys_info.flags |= old_wiggle;	// Restore wiggle
			Controls = saved_control_info;
		} 

		controls_read_all();		
		if ( Controls.automap_down_count )	{
			if (leave_mode==0)
				done = 1;
			c = 0;
		}

		while( (c=key_inkey()) )	{
			switch( c ) {
			#ifndef NDEBUG
			case KEY_BACKSP: Int3(); break;
			#endif
	
			case KEY_PRINT_SCREEN: save_screen_shot(1); break;
	
			case KEY_ESC:
				if (leave_mode==0)
					done = 1;
				 break;
			case KEY_ALTED+KEY_F:		// Alt+F shows full map, if cheats enabled
				if (Cheats_enabled) 
				{
					uint t;	
					t = Players[Player_num].flags;
					Players[Player_num].flags |= PLAYER_FLAGS_MAP_ALL_CHEAT;
					automap_build_edge_list();
					Players[Player_num].flags=t;
			 	}
				break;
	
	#ifndef NDEBUG
		  	case KEY_DEBUGGED+KEY_F: 	{
				for (i=0; i<=Highest_segment_index; i++ )
					Automap_visited[i] = 1;
				automap_build_edge_list();
				Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
				SegmentLimit = Max_segments_away;
				adjust_segment_limit(SegmentLimit);
				}
				break;
	#endif
			case KEY_MINUS:
				if (SegmentLimit > 1) 		{
					SegmentLimit--;
					adjust_segment_limit(SegmentLimit);
				}
				break;
			case KEY_EQUAL:
				if (SegmentLimit < Max_segments_away) 	{
					SegmentLimit++;
					adjust_segment_limit(SegmentLimit);
				}
				break;
			}
		}

		if ( Controls.fire_primary_down_count )	{
			// Reset orientation
			ViewDist = ZOOM_DEFAULT;
			tangles.p = PITCH_DEFAULT;
			tangles.h  = 0;
			tangles.b  = 0;
			view_target = Objects[Players[Player_num].objnum].pos;
		}

		ViewDist -= Controls.forward_thrust_time*ZOOM_SPEED_FACTOR;

		tangles.p += fixdiv( Controls.pitch_time, ROT_SPEED_DIVISOR );
		tangles.h  += fixdiv( Controls.heading_time, ROT_SPEED_DIVISOR );
		tangles.b  += fixdiv( Controls.bank_time, ROT_SPEED_DIVISOR*2 );
		
		if ( Controls.vertical_thrust_time || Controls.sideways_thrust_time )	{
			vms_angvec	tangles1;
			vms_vector	old_vt;
			old_vt = view_target;
			tangles1 = tangles;
			vm_angles_2_matrix(&tempm,&tangles1);
			vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);
			vm_vec_scale_add2( &view_target, &ViewMatrix.uvec, Controls.vertical_thrust_time*SLIDE_SPEED );
			vm_vec_scale_add2( &view_target, &ViewMatrix.rvec, Controls.sideways_thrust_time*SLIDE_SPEED );
			if ( vm_vec_dist_quick( &view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) )	{
				view_target = old_vt;
			}
		} 

		vm_angles_2_matrix(&tempm,&tangles);
		vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);

		if ( ViewDist < ZOOM_MIN_VALUE ) ViewDist = ZOOM_MIN_VALUE;
		if ( ViewDist > ZOOM_MAX_VALUE ) ViewDist = ZOOM_MAX_VALUE;

		draw_automap();

		if ( first_time )	{
			first_time = 0;
			gr_palette_load( gr_palette );
		}

		t2 = timer_get_fixed_seconds();
		if (pause_game)
			FrameTime=t2-t1;
		t1 = t2;
	}

	//free(Edges);
	//free(DrawingListBright);
	gr_free_canvas(name_canv);  name_canv=NULL;

	mprintf( (0, "Automap memory freed\n" ));

	game_flush_inputs();

	if (pause_game)
		start_time();
}
Exemplo n.º 25
0
//	-----------------------------------------------------------------------------------------------------------
// add rotational velocity & acceleration
void do_physics_sim_rot(object *obj)
{
	vms_angvec	tangles;
	vms_matrix	rotmat,new_orient;
	//fix		rotdrag_scale;
	physics_info *pi;

	Assert(FrameTime > 0);	//Get MATT if hit this!

	pi = &obj->mtype.phys_info;

	if (!(pi->rotvel.x || pi->rotvel.y || pi->rotvel.z || pi->rotthrust.x || pi->rotthrust.y || pi->rotthrust.z))
		return;

	if (obj->mtype.phys_info.drag) {
		int count;
		vms_vector accel;
		fix drag,r,k;

		count = FrameTime / FT;
		r = FrameTime % FT;
		k = fixdiv(r,FT);

                drag = (obj->mtype.phys_info.drag*5)/2;

		if (obj->mtype.phys_info.flags & PF_USES_THRUST) {

			vm_vec_copy_scale(&accel,&obj->mtype.phys_info.rotthrust,fixdiv(f1_0,obj->mtype.phys_info.mass));

			while (count--) {

				vm_vec_add2(&obj->mtype.phys_info.rotvel,&accel);

                                vm_vec_scale(&obj->mtype.phys_info.rotvel,f1_0-drag);
			}

			//do linear scale on remaining bit of time

			vm_vec_scale_add2(&obj->mtype.phys_info.rotvel,&accel,k);
                        vm_vec_scale(&obj->mtype.phys_info.rotvel,f1_0-fixmul(k,drag));
		}
		else {
                        fix total_drag=f1_0;

			while (count--)
				total_drag = fixmul(total_drag,f1_0-drag);

			//do linear scale on remaining bit of time

			total_drag = fixmul(total_drag,f1_0-fixmul(k,drag));

			vm_vec_scale(&obj->mtype.phys_info.rotvel,total_drag);
		}

	}

	//now rotate object 

	//unrotate object for bank caused by turn
	if (obj->mtype.phys_info.turnroll) {
		vms_matrix new_pm;

		tangles.p = tangles.h = 0;
		tangles.b = -obj->mtype.phys_info.turnroll;
		vm_angles_2_matrix(&rotmat,&tangles);
		vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat);
		obj->orient = new_pm;
	}

	tangles.p = fixmul(obj->mtype.phys_info.rotvel.x,FrameTime);
	tangles.h = fixmul(obj->mtype.phys_info.rotvel.y,FrameTime);
	tangles.b = fixmul(obj->mtype.phys_info.rotvel.z,FrameTime);

	vm_angles_2_matrix(&rotmat,&tangles);
	vm_matrix_x_matrix(&new_orient,&obj->orient,&rotmat);
	obj->orient = new_orient;

	if (obj->mtype.phys_info.flags & PF_TURNROLL)
		set_object_turnroll(obj);

	//re-rotate object for bank caused by turn
	if (obj->mtype.phys_info.turnroll) {
		vms_matrix new_pm;

		tangles.p = tangles.h = 0;
		tangles.b = obj->mtype.phys_info.turnroll;
		vm_angles_2_matrix(&rotmat,&tangles);
		vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat);
		obj->orient = new_pm;
	}

	check_and_fix_matrix(&obj->orient);
}
Exemplo n.º 26
0
Arquivo: ntmap.c Projeto: jihnsius/d2r
// -------------------------------------------------------------------------------------
// Interface from Matt's data structures to Mike's texture mapper.
// -------------------------------------------------------------------------------------
void draw_tmap(grs_bitmap *bp,int nverts,g3s_point **vertbuf)
{
	int	i;

	//	These variables are used in system which renders texture maps which lie on one scanline as a line.
	// fix	div_numerator;
	int	lighting_on_save = Lighting_on;

	Assert(nverts <= MAX_TMAP_VERTS);


#ifdef USE_MULT_CODE
	if ( !divide_table_filled ) fill_divide_table();
#endif

	// -- now called from g3_start_frame -- init_interface_vars_to_assembler();

	//	If no transparency and seg depth is large, render as flat shaded.
	if ((Current_seg_depth > Max_linear_depth) && ((bp->bm_flags & 3) == 0)) {
		draw_tmap_flat(bp, nverts, vertbuf);
		return;
	}

	if ( bp->bm_flags & BM_FLAG_RLE )
		bp = rle_expand_texture( bp );		// Expand if rle'd

	Transparency_on = bp->bm_flags & BM_FLAG_TRANSPARENT;
	if (bp->bm_flags & BM_FLAG_NO_LIGHTING)
		Lighting_on = 0;


	// Setup texture map in Tmap1
	Tmap1.nv = nverts;						// Initialize number of vertices

// 	div_numerator = DivNum;	//f1_0*3;

	for (i=0; i<nverts; i++) {
		g3ds_vertex	*tvp = &Tmap1.verts[i];
		g3s_point	*vp = vertbuf[i];

		tvp->x2d = vp->p3_sx;
		tvp->y2d = vp->p3_sy;

		//	Check for overflow on fixdiv.  Will overflow on vp->z <= something small.  Allow only as low as 256.
		if (vp->p3_z < 256) {
			vp->p3_z = 256;
			// Int3();		// we would overflow if we divided!
		}

		tvp->z = fixdiv(F1_0*12, vp->p3_z);
		tvp->u = vp->p3_u << 6; //* bp->bm_w;
		tvp->v = vp->p3_v << 6; //* bp->bm_h;

		Assert(Lighting_on < 3);

		if (Lighting_on)
			tvp->l = vp->p3_l * NUM_LIGHTING_LEVELS;
	}


	Lighting_enabled = Lighting_on;

	// Now, call my texture mapper.
	if (Lighting_on) {
		switch (Interpolation_method) {	// 0 = choose, 1 = linear, 2 = /8 perspective, 3 = full perspective
			case 0:								// choose best interpolation
				per2_flag = 1;
				if (Current_seg_depth > Max_perspective_depth)
					ntexture_map_lighted_linear(bp, &Tmap1);
				else
					ntexture_map_lighted(bp, &Tmap1);
				break;
			case 1:								// linear interpolation
				per2_flag = 1;
				ntexture_map_lighted_linear(bp, &Tmap1);
				break;
			case 2:								// perspective every 8th pixel interpolation
				per2_flag = 1;
				ntexture_map_lighted(bp, &Tmap1);
				break;
			case 3:								// perspective every pixel interpolation
				per2_flag = 0;					// this hack means do divide every pixel
				ntexture_map_lighted(bp, &Tmap1);
				break;
			default:
				Assert(0);				// Illegal value for Interpolation_method, must be 0,1,2,3
		}
	} else {
		switch (Interpolation_method) {	// 0 = choose, 1 = linear, 2 = /8 perspective, 3 = full perspective
			case 0:								// choose best interpolation
				per2_flag = 1;
				if (Current_seg_depth > Max_perspective_depth)
					ntexture_map_lighted_linear(bp, &Tmap1);
				else
					ntexture_map_lighted(bp, &Tmap1);
				break;
			case 1:								// linear interpolation
				per2_flag = 1;
				ntexture_map_lighted_linear(bp, &Tmap1);
				break;
			case 2:								// perspective every 8th pixel interpolation
				per2_flag = 1;
				ntexture_map_lighted(bp, &Tmap1);
				break;
			case 3:								// perspective every pixel interpolation
				per2_flag = 0;					// this hack means do divide every pixel
				ntexture_map_lighted(bp, &Tmap1);
				break;
			default:
				Assert(0);				// Illegal value for Interpolation_method, must be 0,1,2,3
		}
	}

	Lighting_on = lighting_on_save;

}
Exemplo n.º 27
0
do_endlevel_flythrough(int n)
{
	object *obj;
	segment *pseg;
	int old_player_seg;

	flydata = &fly_objects[n];
	obj = flydata->obj;
	
	old_player_seg = obj->segnum;

	//move the player for this frame

	if (!flydata->first_time) {

		vm_vec_scale_add2(&obj->pos,&flydata->step,FrameTime);
		angvec_add2_scale(&flydata->angles,&flydata->angstep,FrameTime);

		vm_angles_2_matrix(&obj->orient,&flydata->angles);
	}

	//check new player seg

	update_object_seg(obj);
	pseg = &Segments[obj->segnum];

	if (flydata->first_time || obj->segnum != old_player_seg) {		//moved into new seg
		vms_vector curcenter,nextcenter;
		fix step_size,seg_time;
		short entry_side,exit_side;	//what sides we entry and leave through
		vms_vector dest_point;		//where we are heading (center of exit_side)
		vms_angvec dest_angles;		//where we want to be pointing
		vms_matrix dest_orient;
		int up_side;

		//find new exit side

		if (!flydata->first_time) {

			entry_side = matt_find_connect_side(obj->segnum,old_player_seg);
			exit_side = Side_opposite[entry_side];
		}

		if (flydata->first_time || entry_side==-1 || pseg->children[exit_side]==-1)
			exit_side = find_exit_side(obj);

		{										//find closest side to align to
			fix d,largest_d=-f1_0;
			int i;

			for (i=0;i<6;i++) {
				#ifdef COMPACT_SEGS
				vms_vector v1;
				get_side_normal(pseg, i, 0, &v1 );
				d = vm_vec_dot(&v1,&flydata->obj->orient.uvec);
				#else
				d = vm_vec_dot(&pseg->sides[i].normals[0],&flydata->obj->orient.uvec);
				#endif
				if (d > largest_d) {largest_d = d; up_side=i;}
			}

		}

		//update target point & angles

		compute_center_point_on_side(&dest_point,pseg,exit_side);

		//update target point and movement points

		//offset object sideways
		if (flydata->offset_frac) {
			int s0=-1,s1,i;
			vms_vector s0p,s1p;
			fix dist;

			for (i=0;i<6;i++)
				if (i!=entry_side && i!=exit_side && i!=up_side && i!=Side_opposite[up_side])
					if (s0==-1)
						s0 = i;
					else
						s1 = i;

			compute_center_point_on_side(&s0p,pseg,s0);
			compute_center_point_on_side(&s1p,pseg,s1);
			dist = fixmul(vm_vec_dist(&s0p,&s1p),flydata->offset_frac);

			if (dist-flydata->offset_dist > MAX_SLIDE_PER_SEGMENT)
				dist = flydata->offset_dist + MAX_SLIDE_PER_SEGMENT;

			flydata->offset_dist = dist;

			vm_vec_scale_add2(&dest_point,&obj->orient.rvec,dist);

		}

		vm_vec_sub(&flydata->step,&dest_point,&obj->pos);
		step_size = vm_vec_normalize_quick(&flydata->step);
		vm_vec_scale(&flydata->step,flydata->speed);

		compute_segment_center(&curcenter,pseg);
		compute_segment_center(&nextcenter,&Segments[pseg->children[exit_side]]);
		vm_vec_sub(&flydata->headvec,&nextcenter,&curcenter);

		#ifdef COMPACT_SEGS	
		{
			vms_vector _v1;
			get_side_normal(pseg, up_side, 0, &_v1 );
			vm_vector_2_matrix(&dest_orient,&flydata->headvec,&_v1,NULL);
		}
		#else
		vm_vector_2_matrix(&dest_orient,&flydata->headvec,&pseg->sides[up_side].normals[0],NULL);
		#endif
		vm_extract_angles_matrix(&dest_angles,&dest_orient);

		if (flydata->first_time)
			vm_extract_angles_matrix(&flydata->angles,&obj->orient);

		seg_time = fixdiv(step_size,flydata->speed);	//how long through seg

		if (seg_time) {
			flydata->angstep.x = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.p,dest_angles.p),seg_time)));
			flydata->angstep.z = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.b,dest_angles.b),seg_time)));
			flydata->angstep.y = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.h,dest_angles.h),seg_time)));

		}
		else {
			flydata->angles = dest_angles;
			flydata->angstep.x = flydata->angstep.y = flydata->angstep.z = 0;
		}
	}

	flydata->first_time=0;
}
Exemplo n.º 28
0
//	-----------------------------------------------------------------------------------------------------------------
//	Gauss-Jordan elimination solution of a system of linear equations.
//	a[1..n][1..n] is the input matrix.  b[1..n][1..m] is input containing the m right-hand side vectors.
//	On output, a is replaced by its matrix inverse and b is replaced by the corresponding set of solution vectors.
void gaussj(fix **a, int n, fix **b, int m)
{
	int	indxc[4], indxr[4], ipiv[4];
        int     i, icol=0, irow=0, j, k, l, ll;
	fix	big, dum, pivinv, temp;

	if (n > 4) {
		Int3();
	}

	for (j=1; j<=n; j++)
		ipiv[j] = 0;

	for (i=1; i<=n; i++) {
		big = 0;
		for (j=1; j<=n; j++)
			if (ipiv[j] != 1)
				for (k=1; k<=n; k++) {
					if (ipiv[k] == 0) {
						if (abs(a[j][k]) >= big) {
							big = abs(a[j][k]);
							irow = j;
							icol = k;
						}
					} else if (ipiv[k] > 1) {
						Int3();
					}
				}

		++(ipiv[icol]);

		// We now have the pivot element, so we interchange rows, if needed, to put the pivot
		//	element on the diagonal.  The columns are not physically interchanged, only relabeled:
		//	indxc[i], the column of the ith pivot element, is the ith column that is reduced, while
		//	indxr[i] is the row in which that pivot element was originally located.  If indxr[i] !=
		//	indxc[i] there is an implied column interchange.  With this form of bookkeeping, the
		//	solution b's will end up in the correct order, and the inverse matrix will be scrambled
		//	by columns.

		if (irow != icol) {
			for (l=1; l<=n; l++)
				SWAP(a[irow][l], a[icol][l]);
			for (l=1; l<=m; l++)
				SWAP(b[irow][l], b[icol][l]);
		}

		indxr[i] = irow;
		indxc[i] = icol;
		if (a[icol][icol] == 0) {
			Int3();
		}
		pivinv = fixdiv(F1_0, a[icol][icol]);
		a[icol][icol] = F1_0;

		for (l=1; l<=n; l++)
			a[icol][l] = fixmul(a[icol][l], pivinv);
		for (l=1; l<=m; l++)
			b[icol][l] = fixmul(b[icol][l], pivinv);

		for (ll=1; ll<=n; ll++)
			if (ll != icol) {
				dum = a[ll][icol];
				a[ll][icol] = 0;
				for (l=1; l<=n; l++)
					a[ll][l] -= a[icol][l]*dum;
				for (l=1; l<=m; l++)
					b[ll][l] -= b[icol][l]*dum;
			}
	}

	//	This is the end of the main loop over columns of the reduction.  It only remains to unscramble
	//	the solution in view of the column interchanges.  We do this by interchanging pairs of
	//	columns in the reverse order that the permutation was built up.
	for (l=n; l>=1; l--) {
		if (indxr[l] != indxc[l])
			for (k=1; k<=n; k++)
				SWAP(a[k][indxr[l]], a[k][indxc[l]]);
	}

}
Exemplo n.º 29
0
fix timer_get_fixed_seconds(void) {
  fix x;
  unsigned long tv_now = SDL_GetTicks();
  x=i2f(tv_now/1000) | fixdiv(i2f(tv_now % 1000),i2f(1000));
  return x;
}
Exemplo n.º 30
0
int automap_process_input(window *wind, d_event *event, automap *am)
{
	vms_matrix tempm;

	Controls = am->controls;
	kconfig_read_controls(event, 1);
	am->controls = Controls;
	memset(&Controls, 0, sizeof(control_info));

	if ( !am->controls.automap_state && (am->leave_mode==1) )
	{
		window_close(wind);
		return 1;
	}
	
	if ( am->controls.automap_count > 0)
	{
		am->controls.automap_count = 0;
		if (am->leave_mode==0)
		{
			window_close(wind);
			return 1;
		}
	}
	
	if (PlayerCfg.AutomapFreeFlight)
	{
		if ( am->controls.fire_primary_count > 0)
		{
			// Reset orientation
			am->viewMatrix = Objects[Players[Player_num].objnum].orient;
			vm_vec_scale_add(&am->view_position, &Objects[Players[Player_num].objnum].pos, &am->viewMatrix.fvec, -ZOOM_DEFAULT );
			am->controls.fire_primary_count = 0;
		}
		
		if (am->controls.pitch_time || am->controls.heading_time || am->controls.bank_time)
		{
			vms_angvec tangles;
			vms_matrix new_m;

			tangles.p = fixdiv( am->controls.pitch_time, ROT_SPEED_DIVISOR );
			tangles.h = fixdiv( am->controls.heading_time, ROT_SPEED_DIVISOR );
			tangles.b = fixdiv( am->controls.bank_time, ROT_SPEED_DIVISOR*2 );

			vm_angles_2_matrix(&tempm, &tangles);
			vm_matrix_x_matrix(&new_m,&am->viewMatrix,&tempm);
			am->viewMatrix = new_m;
			check_and_fix_matrix(&am->viewMatrix);
		}
		
		if ( am->controls.forward_thrust_time || am->controls.vertical_thrust_time || am->controls.sideways_thrust_time )
		{
			vm_vec_scale_add2( &am->view_position, &am->viewMatrix.fvec, am->controls.forward_thrust_time*ZOOM_SPEED_FACTOR );
			vm_vec_scale_add2( &am->view_position, &am->viewMatrix.uvec, am->controls.vertical_thrust_time*SLIDE_SPEED );
			vm_vec_scale_add2( &am->view_position, &am->viewMatrix.rvec, am->controls.sideways_thrust_time*SLIDE_SPEED );
			
			// Crude wrapping check
			if (am->view_position.x >  F1_0*32000) am->view_position.x =  F1_0*32000;
			if (am->view_position.x < -F1_0*32000) am->view_position.x = -F1_0*32000;
			if (am->view_position.y >  F1_0*32000) am->view_position.y =  F1_0*32000;
			if (am->view_position.y < -F1_0*32000) am->view_position.y = -F1_0*32000;
			if (am->view_position.z >  F1_0*32000) am->view_position.z =  F1_0*32000;
			if (am->view_position.z < -F1_0*32000) am->view_position.z = -F1_0*32000;
		}
	}
	else
	{
		if ( am->controls.fire_primary_count > 0)
		{
			// Reset orientation
			am->viewDist = ZOOM_DEFAULT;
			am->tangles.p = PITCH_DEFAULT;
			am->tangles.h  = 0;
			am->tangles.b  = 0;
			am->view_target = Objects[Players[Player_num].objnum].pos;
			am->controls.fire_primary_count = 0;
		}

		am->viewDist -= am->controls.forward_thrust_time*ZOOM_SPEED_FACTOR;
		am->tangles.p += fixdiv( am->controls.pitch_time, ROT_SPEED_DIVISOR );
		am->tangles.h  += fixdiv( am->controls.heading_time, ROT_SPEED_DIVISOR );
		am->tangles.b  += fixdiv( am->controls.bank_time, ROT_SPEED_DIVISOR*2 );

		if ( am->controls.vertical_thrust_time || am->controls.sideways_thrust_time )
		{
			vms_angvec      tangles1;
			vms_vector      old_vt;

			old_vt = am->view_target;
			tangles1 = am->tangles;
			vm_angles_2_matrix(&tempm,&tangles1);
			vm_matrix_x_matrix(&am->viewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);
			vm_vec_scale_add2( &am->view_target, &am->viewMatrix.uvec, am->controls.vertical_thrust_time*SLIDE_SPEED );
			vm_vec_scale_add2( &am->view_target, &am->viewMatrix.rvec, am->controls.sideways_thrust_time*SLIDE_SPEED );
			if ( vm_vec_dist_quick( &am->view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) )
				am->view_target = old_vt;
		}

		vm_angles_2_matrix(&tempm,&am->tangles);
		vm_matrix_x_matrix(&am->viewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);

		if ( am->viewDist < ZOOM_MIN_VALUE ) am->viewDist = ZOOM_MIN_VALUE;
		if ( am->viewDist > ZOOM_MAX_VALUE ) am->viewDist = ZOOM_MAX_VALUE;
	}
	
	return 0;
}