// Try and find a new locking point
void hud_lock_get_new_lock_pos(object *target_objp, vector *lock_world_pos)
{
	ship			*target_shipp=NULL;
	int			lock_in_range=0;
	float			best_lock_dot=-1.0f, lock_dot=-1.0f;
	ship_subsys	*ss;
	vector		subsys_world_pos, vec_to_lock;

	if ( target_objp->type == OBJ_SHIP ) {
		target_shipp = &Ships[target_objp->instance];
	}

	// if a large ship, lock to pos closest to center and within range
	if ( (target_shipp) && (Ship_info[target_shipp->ship_info_index].flags & (SIF_BIG_SHIP|SIF_HUGE_SHIP)) ) {
		// check all the subsystems and the center of the ship
		
		// assume best lock pos is the center of the ship
		*lock_world_pos=target_objp->pos;
		Player->locking_on_center=1;
		Player->locking_subsys=NULL;
		Player->locking_subsys_parent=-1;
		lock_in_range = hud_lock_world_pos_in_range(lock_world_pos, &vec_to_lock);
		vm_vec_normalize(&vec_to_lock);
		if ( lock_in_range ) {
			best_lock_dot=vm_vec_dot(&Player_obj->orient.vec.fvec, &vec_to_lock);
		} 
		// take center if reasonable dot
		if ( best_lock_dot > 0.95 ) {
			return;
		}

		// iterate through subsystems to see if we can get a better choice
		ss = GET_FIRST(&target_shipp->subsys_list);
		while ( ss != END_OF_LIST( &target_shipp->subsys_list ) ) {

			// get world pos of subsystem
			get_subsystem_world_pos(target_objp, ss, &subsys_world_pos);

			if ( hud_lock_world_pos_in_range(&subsys_world_pos, &vec_to_lock) ) {
				vm_vec_normalize(&vec_to_lock);
				lock_dot=vm_vec_dot(&Player_obj->orient.vec.fvec, &vec_to_lock);
				if ( lock_dot > best_lock_dot ) {
					best_lock_dot=lock_dot;
					Player->locking_on_center=0;
					Player->locking_subsys=ss;
					Player->locking_subsys_parent=Player_ai->target_objnum;
					*lock_world_pos=subsys_world_pos;
				}
			}
			ss = GET_NEXT( ss );
		}
	} else {
		// if small ship (or weapon), just go for the center
		*lock_world_pos = target_objp->pos;
		Player->locking_on_center=1;
		Player->locking_subsys=NULL;
		Player->locking_subsys_parent=-1;
	}
}
void supernova_get_eye(vec3d *eye_pos, matrix *eye_orient)
{
	// supernova camera pos
	vec3d Supernova_camera_pos;
	static matrix Supernova_camera_orient;

	vec3d at;
	vec3d sun_temp, sun_vec;
	vec3d view;

	// set the controls for the heart of the sun
	stars_get_sun_pos(0, &sun_temp);
	vm_vec_add2(&sun_temp, &Player_obj->pos);
	vm_vec_sub(&sun_vec, &sun_temp, &Player_obj->pos);
	vm_vec_normalize(&sun_vec);

	// always set the camera pos
	vec3d move;
	matrix whee;
	vm_vector_2_matrix(&whee, &move, NULL, NULL);
	vm_vec_scale_add(&Supernova_camera_pos, &Player_obj->pos, &whee.vec.rvec, sn_cam_distance);
	vm_vec_scale_add2(&Supernova_camera_pos, &whee.vec.uvec, 30.0f);
	//cam->set_position(&Supernova_camera_pos);
	*eye_pos = Supernova_camera_pos;

	// if we're no longer moving the camera
	if(Supernova_time < (SUPERNOVA_CUT_TIME - SUPERNOVA_CAMERA_MOVE_TIME)) {
		// *eye_pos = Supernova_camera_pos;
		//cam->set_rotation(&Supernova_camera_orient);
		*eye_orient = Supernova_camera_orient;
	}
	// otherwise move it
	else {
		// get a vector somewhere between the supernova shockwave and the player ship
		at = Player_obj->pos;
		vm_vec_scale_add2(&at, &sun_vec, sn_distance);
		vm_vec_sub(&move, &Player_obj->pos, &at);
		vm_vec_normalize(&move);

		// linearly move towards the player pos
		float pct = ((SUPERNOVA_CUT_TIME - Supernova_time) / SUPERNOVA_CAMERA_MOVE_TIME);
		vm_vec_scale_add2(&at, &move, sn_distance * pct);

		vm_vec_sub(&view, &at, &Supernova_camera_pos);
		vm_vec_normalize(&view);
		vm_vector_2_matrix(&Supernova_camera_orient, &view, NULL, NULL);
		//cam->set_rotation(&Supernova_camera_orient);
		*eye_orient = Supernova_camera_orient;
	}
	//return supernova_camera;
}
// output top and bottom vectors
// fvec == forward vector (eye viewpoint basically. in world coords)
// pos == world coordinate of the point we're calculating "around"
// w == width of the diff between top and bottom around pos
void trail_calc_facing_pts( vec3d *top, vec3d *bot, vec3d *fvec, vec3d *pos, float w )
{
	vec3d uvec, rvec;

	vm_vec_sub( &rvec, &Eye_position, pos );
	if (!IS_VEC_NULL(&rvec))
		vm_vec_normalize( &rvec );

	vm_vec_crossprod(&uvec,fvec,&rvec);
	if (!IS_VEC_NULL(&uvec))
		vm_vec_normalize(&uvec);

	vm_vec_scale_add( top, pos, &uvec, w * 0.5f );
	vm_vec_scale_add( bot, pos, &uvec, -w * 0.5f );
}
Beispiel #4
0
// add some jitter to a flak gun's aiming direction, take into account range to target so that we're never _too_ far off
// assumes dir is normalized
void flak_jitter_aim(vec3d* dir, float dist_to_target, float weapon_subsys_strength)
{
	vec3d rand_twist_pre, rand_twist_post;
	matrix temp;
	vec3d final_aim;
	float error_val;

	// get the matrix needed to rotate the base direction to the actual direction		
	vm_vector_2_matrix(&temp, dir, NULL, NULL);

	// error value	
	error_val = Flak_error + (Flak_error * 0.65f * (1.0f - weapon_subsys_strength));

	// scale the rvec by some random value and make it the "pre-twist" value
	float rand_dist = frand_range(0.0f, error_val);
	// no jitter - so do nothing
	if (rand_dist <= 0.0f)
	{
		return;
	}
	vm_vec_copy_scale(&rand_twist_pre, &temp.vec.rvec, rand_dist);

	// now rotate the twist vector around the x axis (the base aim axis) at a random angle
	vm_rot_point_around_line(&rand_twist_post, &rand_twist_pre, fl_radian(359.0f * frand_range(0.0f,
		1.0f)), &vmd_zero_vector, dir);

	// add the resulting vector to the base aim vector and normalize
	final_aim = *dir;
	vm_vec_scale(&final_aim, dist_to_target);
	vm_vec_add(dir, &final_aim, &rand_twist_post);
	vm_vec_normalize(dir);
}
/*
  This works like any other clip plane... if this is enabled and you
rotate a point, the CC_OFF_USER bit will be set in the clipping codes.
It is completely handled by most g3_draw primitives, except maybe lines.

  As far as performance, when enabled, it will slow down each point
rotation (or g3_code_vertex call) by a vector subtraction and dot
product.   It won't slow anything down for polys that are completely
clipped on or off by the plane, and will slow each clipped polygon by
not much more than any other clipping we do.
*/
void g3_start_user_clip_plane( vector *plane_point, vector *plane_normal )
{
	float mag = vm_vec_mag( plane_normal );
	if ( (mag < 0.1f) || (mag > 1.5f ) )	{
		// Invalid plane_normal passed in.  Get Allender (since it is
		// probably a ship warp in bug:) or John.   
		Int3();			
		return;
	}

	G3_user_clip = 1;
	if(!Cmdline_nohtl) {
		G3_user_clip_normal = *plane_normal;
		G3_user_clip_point = *plane_point;
//	return;


		gr_start_clip();
	}
	vm_vec_rotate(&G3_user_clip_normal, plane_normal, &View_matrix );
	vm_vec_normalize(&G3_user_clip_normal);

	vector tempv;
	vm_vec_sub(&tempv,plane_point,&View_position);
	vm_vec_rotate(&G3_user_clip_point,&tempv,&View_matrix );
}
Beispiel #6
0
void HudGaugeRadarOrb::drawContactHtl(vec3d *pnt, int rad)
{
    vec3d p;

    p=*pnt;

    vm_vec_normalize(&p);

    float size = fl_sqrt(vm_vec_dist(&Orb_eye_position, pnt) * 8.0f);
    if (size < i2fl(rad))	size = i2fl(rad);

    if (rad == Radar_blip_radius_target)
    {
        if (radar_target_id_flags & RTIF_PULSATE) {
            // use mask to make the darn thing work faster
            size *= 1.3f + (sinf(10 * f2fl(Missiontime)) * 0.3f);
        }
        if (radar_target_id_flags & RTIF_BLINK) {
            if (Missiontime & 8192)
                return;
        }
        g3_render_sphere(pnt,size/100.0f);
    }
    else
    {
        g3_render_sphere(pnt,size/300.0f);
    }

    //g3_draw_htl_line(&p,pnt);
    g3_render_line_3d(false, &p, pnt);
}
Beispiel #7
0
void HudGaugeRadarOrb::drawContact(vec3d *pnt, int rad)
{
    vertex verts[2];
    vec3d p;

    p=*pnt;
    vm_vec_normalize(&p);

    g3_rotate_vertex(&verts[0], &p);
    g3_project_vertex(&verts[0]);

    g3_rotate_vertex(&verts[1], pnt);
    g3_project_vertex(&verts[1]);

    float size = fl_sqrt(vm_vec_dist(&Orb_eye_position, pnt) * 8.0f);
    if (size < i2fl(rad))	size = i2fl(rad);

    if (rad == Radar_blip_radius_target)
    {
        g3_draw_sphere(&verts[1],size/100.0f);
    }
    else
    {
        g3_draw_sphere(&verts[1],size/300.0f);
    }

    g3_draw_line(&verts[0],&verts[1]);
}
Beispiel #8
0
//	------------------------------------------------------------------------------------------------------
int	ObjectMoveDown(void)
{
	object *obj;
	vms_vector	uvec;
	vms_vector	newpos;

	if (Cur_object_index == -1) {
		editor_status("No current object, cannot move.");
		return 1;
	}

	obj = &Objects[Cur_object_index];

	extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
	vm_vec_normalize(&uvec);

	vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));

	if (!verify_object_seg(obj, &newpos))
		obj->pos = newpos;

	Update_flags |= UF_WORLD_CHANGED;

	return 1;
}
void HudGaugeRadarDradis::plotBlip(blip* b, vec3d *pos, float *alpha)
{
	*pos = b->position;
	vm_vec_normalize(pos);

	if (ship_is_tagged(b->objp)) {
		*alpha = 1.0f;
		return;
	}

	float fade_multi = 1.5f;
	
	if (b->objp->type == OBJ_SHIP) {
		if (Ships[b->objp->instance].flags[Ship::Ship_Flags::Stealth]) {
			fade_multi *= 2.0f;
		}
	}
	
	b->time_since_update += flFrametime;
	// If the blip has been pinged by the local x-axis sweep, update
	if (std::abs(vm_vec_dot(&sweep_normal_x, pos)) < 0.01f) {
		b->time_since_update = 0.0f;
	}

	*alpha = ((sweep_duration - b->time_since_update)/sweep_duration)*fade_multi/2.0f;
	
	if (*alpha < 0.0f) {
		*alpha = 0.0f;
	}
}
Beispiel #10
0
// if i'm an observer, zoom to near my targted object (if any)
void multi_obs_zoom_to_target()
{
	vec3d direct;
	float dist;

	// if i'm not an observer, do nothing
	if (!(Game_mode & GM_MULTIPLAYER) || (Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_OBSERVER) ||
		(Player_obj->type != OBJ_OBSERVER))
	{
		return;
	}

	// if I have no targeted object, do nothing
	if (Player_ai->target_objnum == -1)
	{
		return;
	}

	// get the normalized direction vector between the observer and the targeted object
	vm_vec_sub(&direct, &Objects[Player_ai->target_objnum].pos, &Player_obj->pos);
	dist = vm_vec_mag(&direct);
	vm_vec_normalize(&direct);

	// orient the guy correctly
	vm_vec_ang_2_matrix(&Player_obj->orient, &direct, 0.0f);

	// keep about 3 object radii away when moving
	dist -= (Objects[Player_ai->target_objnum].radius * 3.0f);

	// get the movement vector
	vm_vec_scale(&direct, dist);

	// move
	vm_vec_add2(&Player_obj->pos, &direct);
}
Beispiel #11
0
vms_vector *vm_vec_interp(vms_vector *result, vms_vector *v0, vms_vector *v1, fix scale) {
    vms_vector tvec;

	vm_vec_sub(&tvec, v1, v0);
    vm_vec_scale_add(result, v0, &tvec, scale);
    vm_vec_normalize(result);
    return result;
}
void supernova_do_particles()
{
	int idx;
	vec3d a, b, ta, tb;
	vec3d norm, sun_temp;

	// no player ship
	if((Player_obj == NULL) || (Player_ship == NULL)) {
		return;
	}

	// timestamp
	if((Supernova_particle_stamp == -1) || timestamp_elapsed(Supernova_particle_stamp)) {
		Supernova_particle_stamp = timestamp(sn_particles);

		// get particle norm
		stars_get_sun_pos(0, &sun_temp);
		vm_vec_add2(&sun_temp, &Player_obj->pos);
		vm_vec_sub(&norm, &Player_obj->pos, &sun_temp);
		vm_vec_normalize(&norm);

		particle_emitter whee;
		whee.max_life = 1.0f;
		whee.min_life = 0.6f;
		whee.max_vel = 50.0f;
		whee.min_vel = 25.0f;
		whee.normal_variance = 0.75f;
		whee.num_high = 5;
		whee.num_low = 2;
		whee.min_rad = 0.5f;
		whee.max_rad = 1.25f;

		// emit
		for(idx=0; idx<10; idx++) {
			if ( Cmdline_old_collision_sys ) {
				submodel_get_two_random_points(Ship_info[Player_ship->ship_info_index].model_num, 0, &ta, &tb);
			} else {
				submodel_get_two_random_points_better(Ship_info[Player_ship->ship_info_index].model_num, 0, &ta, &tb);
			}

			// rotate into world space
			vm_vec_unrotate(&a, &ta, &Player_obj->orient);
			vm_vec_add2(&a, &Player_obj->pos);
			whee.pos = a;
			whee.vel = norm;
			vm_vec_scale(&whee.vel, 30.0f);
			vm_vec_add2(&whee.vel, &Player_obj->phys_info.vel);
			whee.normal = norm;
			particle_emit(&whee, PARTICLE_FIRE, 0);

			vm_vec_unrotate(&b, &tb, &Player_obj->orient);
			vm_vec_add2(&b, &Player_obj->pos);
			whee.pos = b;
			particle_emit(&whee, PARTICLE_FIRE, 0);
		}
	}
}
Beispiel #13
0
//	-----------------------------------------------------------------------------------------------------------------
//	Return true if side is planar, else return false.
int side_is_planar_p(segment *sp, int side)
{
	sbyte			*vp;
	vms_vector	*v0,*v1,*v2,*v3;
	vms_vector	va,vb;

	vp = Side_to_verts[side];
	v0 = &Vertices[sp->verts[vp[0]]];
	v1 = &Vertices[sp->verts[vp[1]]];
	v2 = &Vertices[sp->verts[vp[2]]];
	v3 = &Vertices[sp->verts[vp[3]]];

	vm_vec_normalize(vm_vec_normal(&va,v0,v1,v2));
	vm_vec_normalize(vm_vec_normal(&vb,v0,v2,v3));
	
	// If the two vectors are very close to being the same, then generate one quad, else generate two triangles.
	return (vm_vec_dist(&va,&vb) < F1_0/1000);
}
void nav_warp(bool prewarp=false)
{
	/* ok... find our end distance - norm1 is still a unit vector in the
	direction from the flight leader to the navpoint */
	vec3d targetPos, tpos=Autopilot_flight_leader->pos, pos, velocity;

	/* calculate a vector that we can use to make a path from the flight
	leader's location to the nav point */
	vm_vec_sub(&pos, Navs[CurrentNav].GetPosition(), &Autopilot_flight_leader->pos);
	vm_vec_normalize(&pos);
	velocity = pos;	// make a copy for later when we do setup veleocity vector
	vm_vec_scale(&pos, 250.0f); // we move by increments of 250
	
	/* using the vector of the flight leaders's path, simulate moving the 
	flight along this path by checking the autopilot conditions as specific
	intervals along the path*/
	while (CanAutopilot(tpos))
	{
		vm_vec_add(&tpos, &tpos, &pos);
	}
	vm_vec_sub(&targetPos, &tpos, &Autopilot_flight_leader->pos);
	/* targetPos is actually a vector that describes the exact 3D movement that
	the flgith leader needs to execute to reach the location that the auto 
	pilot is to shut off */

	// Check if we are actually just setting up for the cinimatic shot of the
	// flight flying on autopilot. Only jump halfway.  Also we also need to
	// put the camera in the correct position to show the player this cinimatic
	if (prewarp)
	{
		vm_vec_scale(&targetPos, 0.5);
		vm_vec_add(&cameraPos, &cameraPos, &targetPos);
	}

	/* calcuate the speed that everyone is supposed to be going so that there
	is no need for anyone to accelerate or decelerate (most obvious with
	the player's fighter slowing down as it changes the camera pan speed). */
	Assert( Ai_info[Ships[Autopilot_flight_leader->instance].ai_index].waypoint_speed_cap > 0 );
	vm_vec_scale(&velocity, (float)Ai_info[Ships[Autopilot_flight_leader->instance].ai_index].waypoint_speed_cap);

	// Find all ships that are supposed to autopilot with the player and move them
	// to the cinimatic location or the final destination
	for (int i = 0; i < MAX_SHIPS; i++)
	{
		if (Ships[i].objnum != -1
			&& (Ships[i].flags2 & SF2_NAVPOINT_CARRY 
				|| (Ships[i].wingnum != -1 && Wings[Ships[i].wingnum].flags & WF_NAV_CARRY)))
		{
				vm_vec_add(&Objects[Ships[i].objnum].pos, &Objects[Ships[i].objnum].pos, &targetPos);
				Objects[Ships[i].objnum].phys_info.vel = velocity;
		}
	}

	// retime all collision pairs
	obj_collide_retime_cached_pairs();
}
Beispiel #15
0
//	Project the viewer's position onto the grid plane.  If more than threshold distance
//	from grid center, move grid center.
void maybe_create_new_grid(grid* gridp, vector *pos, matrix *orient, int force)
{
	int roundoff;
	plane	tplane;
	vector	gpos, tmp, c;
	float	dist_to_plane;
	float	square_size, ux, uy, uz;

	ux = tplane.A = gridp->gmatrix.v.uvec.xyz.x;
	uy = tplane.B = gridp->gmatrix.v.uvec.xyz.y;
	uz = tplane.C = gridp->gmatrix.v.uvec.xyz.z;
	tplane.D = gridp->planeD;

	compute_point_on_plane(&c, &tplane, pos);
	dist_to_plane = fl_abs(vm_dist_to_plane(pos, &gridp->gmatrix.v.uvec, &c));
	square_size = 1.0f;
	while (dist_to_plane >= 25.0f)
	{
		square_size *= 10.0f;
		dist_to_plane /= 10.0f;
	}
	
	if (fvi_ray_plane(&gpos, &gridp->center, &gridp->gmatrix.v.uvec, pos, &orient->v.fvec, 0.0f)<0.0f)	{
		vector p;
		vm_vec_scale_add(&p,pos,&orient->v.fvec, 100.0f );
		compute_point_on_plane(&gpos, &tplane, &p );
	}

	if (vm_vec_dist(&gpos, &c) > 50.0f * square_size)
	{
		vm_vec_sub(&tmp, &gpos, &c);
		vm_vec_normalize(&tmp);
		vm_vec_scale_add(&gpos, &c, &tmp, 50.0f * square_size);
	}

	roundoff = (int) square_size * 10;
	if (!ux)
		gpos.xyz.x = fl_roundoff(gpos.xyz.x, roundoff);
	if (!uy)
		gpos.xyz.y = fl_roundoff(gpos.xyz.y, roundoff);
	if (!uz)
		gpos.xyz.z = fl_roundoff(gpos.xyz.z, roundoff);

	if ((square_size != gridp->square_size) ||
		(gpos.xyz.x != gridp->center.xyz.x) ||
		(gpos.xyz.y != gridp->center.xyz.y) ||
		(gpos.xyz.z != gridp->center.xyz.z) || force)
	{
		gridp->square_size = square_size;
		gridp->center = gpos;
		modify_grid(gridp);
	}
}
Beispiel #16
0
void curve_dir(vms_equation *coeffs, int degree, fix t0, vms_vector *dir) {
    fix t2;

    if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n");

    t2 = fixmul(t0,t0);

    dir->x = fixmul(3*F1_0,fixmul(coeffs->x3,t2)) + fixmul(2*F1_0,fixmul(coeffs->x2,t0)) + coeffs->x1;
    dir->y = fixmul(3*F1_0,fixmul(coeffs->y3,t2)) + fixmul(2*F1_0,fixmul(coeffs->y2,t0)) + coeffs->y1;
    dir->z = fixmul(3*F1_0,fixmul(coeffs->z3,t2)) + fixmul(2*F1_0,fixmul(coeffs->z2,t0)) + coeffs->z1;
    vm_vec_normalize( dir );

}
Beispiel #17
0
//from a 2d point, compute the vector through that point.
// This can be called outside of a g3_start_frame/g3_end_frame
// pair as long g3_start_frame was previously called.
void g3_point_to_vec_delayed(vector *v,int sx,int sy)
{
	vector	tempv;

	tempv.xyz.x =  ((float)sx - Canv_w2) / Canv_w2;
	tempv.xyz.y = -((float)sy - Canv_h2) / Canv_h2;
	tempv.xyz.z = 1.0f;

	tempv.xyz.x = tempv.xyz.x * Matrix_scale.xyz.z / Matrix_scale.xyz.x;
	tempv.xyz.y = tempv.xyz.y * Matrix_scale.xyz.z / Matrix_scale.xyz.y;

	vm_vec_normalize(&tempv);
	vm_vec_unrotate(v, &tempv, &Unscaled_matrix);
}
Beispiel #18
0
//from a 2d point, compute the vector through that point
void g3_point_2_vec(vms_vector *v, short sx, short sy) {
	vms_vector tempv;
	vms_matrix tempm;

	tempv.x = fixmuldiv(fixdiv((sx << 16) - Canv_w2, Canv_w2), Matrix_scale.z, Matrix_scale.x);
	tempv.y = -fixmuldiv(fixdiv((sy << 16) - Canv_h2, Canv_h2), Matrix_scale.z, Matrix_scale.y);
	tempv.z = f1_0;

	vm_vec_normalize(&tempv);

	vm_copy_transpose_matrix(&tempm, &Unscaled_matrix);

	vm_vec_rotate(v, &tempv, &tempm);

}
Beispiel #19
0
void HudGaugeRadarOrb::plotBlip(blip *b, vec3d *scaled_pos)
{
    *scaled_pos = b->position;

    if (IS_VEC_NULL_SQ_SAFE(scaled_pos)) {
        vm_vec_make(scaled_pos, 1.0f, 0.0f, 0.0f);
    } else {
        vm_vec_normalize(scaled_pos);
    }

    float scale = b->dist / Radar_bright_range;
    if (scale > 1.25f) scale = 1.25f;
    if (scale < .75f) scale = .75f;

    vm_vec_scale(scaled_pos, scale);
}
Beispiel #20
0
int HudGaugeRadarOrb::calcAlpha(vec3d* pt)
{
    Assert(pt);
    Assert(Player_obj);

    vec3d new_pt;
    vec3d fvec = { { { 0.0f, 0.0f, 1.0f } } };

    vm_vec_unrotate(&new_pt, pt, &Player_obj->orient);
    vm_vec_normalize(&new_pt);

    float dot = vm_vec_dot(&fvec, &new_pt);
    float angle = fabs(acosf(dot));
    int alpha = int(angle*192.0f/PI);

    return alpha;
}
Beispiel #21
0
int	ObjectMoveFurther(void)
{
	vms_vector	result;

	if (Cur_object_index == -1) {
		editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
		return 1;
	}

//	move_object_to_mouse_click_delta(+4*F1_0);		//	Move four units further from eye

	vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
	vm_vec_normalize(&result);
	move_object_to_vector(&result, 4*F1_0);

	return 1;	
}
void physics_apply_whack(vec3d *impulse, vec3d *pos, physics_info *pi, matrix *orient, float mass)
{
	vec3d	local_torque, torque;
//	vec3d	npos;

	//	Detect null vector.
	if ((fl_abs(impulse->xyz.x) <= WHACK_LIMIT) && (fl_abs(impulse->xyz.y) <= WHACK_LIMIT) && (fl_abs(impulse->xyz.z) <= WHACK_LIMIT))
		return;

	// first do the rotational velocity
	// calculate the torque on the body based on the point on the
	// object that was hit and the momentum being applied to the object

	vm_vec_crossprod(&torque, pos, impulse);
	vm_vec_rotate ( &local_torque, &torque, orient );

	vec3d delta_rotvel;
	vm_vec_rotate( &delta_rotvel, &local_torque, &pi->I_body_inv );
	vm_vec_scale ( &delta_rotvel, (float) ROTVEL_WHACK_CONST );
	vm_vec_add2( &pi->rotvel, &delta_rotvel );

	//mprintf(("Whack: %7.3f %7.3f %7.3f\n", pi->rotvel.xyz.x, pi->rotvel.xyz.y, pi->rotvel.xyz.z));

	// instant whack on the velocity
	// reduce damping on all axes
	pi->flags |= PF_REDUCED_DAMP;
	update_reduced_damp_timestamp( pi, vm_vec_mag(impulse) );

	// find time for shake from weapon to end
	int dtime = timestamp_until(pi->afterburner_decay);
	if (dtime < WEAPON_SHAKE_TIME) {
		pi->afterburner_decay = timestamp( WEAPON_SHAKE_TIME );
	}

	// Goober5000 - pi->mass should probably be just mass, as specified in the header
	vm_vec_scale_add2( &pi->vel, impulse, 1.0f / mass );
	if (!(pi->flags & PF_USE_VEL) && (vm_vec_mag_squared(&pi->vel) > MAX_SHIP_SPEED*MAX_SHIP_SPEED)) {
		// Get DaveA
		nprintf(("Physics", "speed reset in physics_apply_whack [speed: %f]\n", vm_vec_mag(&pi->vel)));
		vm_vec_normalize(&pi->vel);
		vm_vec_scale(&pi->vel, (float)RESET_SHIP_SPEED);
	}
	vm_vec_rotate( &pi->prev_ramp_vel, &pi->vel, orient );		// set so velocity will ramp starting from current speed
																					// ramped velocity is now affected by collision
}
void initial_status::undock(object *objp1, object *objp2)
{
	vec3d v;
	int ship_num, other_ship_num;

	if (objp1 == NULL || objp2 == NULL)
		return;

	vm_vec_sub(&v, &objp2->pos, &objp1->pos);
	vm_vec_normalize(&v);
	ship_num = get_ship_from_obj(OBJ_INDEX(objp1));
	other_ship_num = get_ship_from_obj(OBJ_INDEX(objp2));

	if (ship_class_compare(Ships[ship_num].ship_info_index, Ships[other_ship_num].ship_info_index) <= 0)
		vm_vec_scale_add2(&objp2->pos, &v, objp2->radius * 2.0f);
	else
		vm_vec_scale_add2(&objp1->pos, &v, objp1->radius * -2.0f);

	ai_do_objects_undocked_stuff(objp1, objp2);

	// check to see if one of these ships has an arrival cue of false.  If so, then
	// reset it back to default value of true.  be sure to correctly update before
	// and after setting data.
	// Goober5000 - but don't reset it if it's part of a wing!
	Ship_editor_dialog.update_data(1);

	if ( Ships[ship_num].arrival_cue == Locked_sexp_false && Ships[ship_num].wingnum < 0 ) {
		Ships[ship_num].arrival_cue = Locked_sexp_true;
	} else if ( Ships[other_ship_num].arrival_cue == Locked_sexp_false && Ships[other_ship_num].wingnum < 0 ) {
		Ships[other_ship_num].arrival_cue = Locked_sexp_true;
	}

	// if this ship is no longer docked, ensure its dock leader flag is clear
    if (!object_is_docked(&Objects[Ships[ship_num].objnum]))
        Ships[ship_num].flags.remove(Ship::Ship_Flags::Dock_leader);

	// same for the other ship
    if (!object_is_docked(&Objects[Ships[other_ship_num].objnum]))
        Ships[other_ship_num].flags.remove(Ship::Ship_Flags::Dock_leader);

	Ship_editor_dialog.initialize_data(1);
}
Beispiel #24
0
// radar is damaged, so make blips dance around
void HudGaugeRadarOrb::blipDrawDistorted(blip *b, vec3d *pos)
{
    float scale;
    float dist=vm_vec_normalize(pos);
    vec3d out;
    float distortion_angle=20;

    // maybe alter the effect if EMP is active
    if(emp_active_local()) {
        scale = emp_current_intensity();
        distortion_angle *= frand_range(-3.0f,3.0f)*frand_range(0.0f, scale);
        dist *= frand_range(MAX(0.75f, 0.75f*scale), MIN(1.25f, 1.25f*scale));

        if (dist > 1.25f) dist = 1.25f;
        if (dist < 0.75f) dist = 0.75f;
    }

    vm_vec_random_cone(&out,pos,distortion_angle);
    vm_vec_scale(&out,dist);

    drawContactHtl(&out,b->rad);
}
// radar is damaged, so make blips dance around
void HudGaugeRadarDradis::blipDrawDistorted(blip *b, vec3d *pos, float alpha)
{
	float temp_scale;
	float dist = vm_vec_normalize(pos);
	vec3d out;
	float distortion_angle=20;

	// maybe alter the effect if EMP is active
	if (emp_active_local())
	{
		temp_scale = emp_current_intensity();
		dist *= frand_range(MAX(0.75f, 0.75f*temp_scale), MIN(1.25f, 1.25f*temp_scale));
		distortion_angle *= frand_range(-3.0f,3.0f)*frand_range(0.0f, temp_scale);

		if (dist > 1.0f) dist = 1.0f;
		if (dist < 0.1f) dist = 0.1f;
	}

	vm_vec_random_cone(&out, pos, distortion_angle);
	vm_vec_scale(&out, dist);

	drawContact(&out, -1, unknown_contact_icon, b->dist, alpha, 1.0f);
}
Beispiel #26
0
// blip is for a target immune to sensors, so cause to flicker in/out with mild distortion
void HudGaugeRadarOrb::blipDrawFlicker(blip *b, vec3d *pos)
{
    int flicker_index;

    float dist=vm_vec_normalize(pos);
    vec3d out;
    float distortion_angle=10;

    if ( (b-Blips) & 1 ) {
        flicker_index=0;
    } else {
        flicker_index=1;
    }

    if ( timestamp_elapsed(Radar_flicker_timer[flicker_index]) ) {
        Radar_flicker_timer[flicker_index] = timestamp_rand(50,1000);
        Radar_flicker_on[flicker_index] ^= 1;
    }

    if ( !Radar_flicker_on[flicker_index] ) {
        return;
    }

    if ( rand() & 1 ) {

        distortion_angle *= frand_range(0.1f,2.0f);
        dist *= frand_range(0.75f, 1.25f);

        if (dist > 1.25f) dist = 1.25f;
        if (dist < 0.75f) dist = 0.75f;
    }

    vm_vec_random_cone(&out,pos,distortion_angle);
    vm_vec_scale(&out,dist);

    drawContactHtl(&out,b->rad);
}
void physics_collide_whack( vec3d *impulse, vec3d *world_delta_rotvel, physics_info *pi, matrix *orient, bool is_landing )
{
	vec3d	body_delta_rotvel;

	//	Detect null vector.
	if ((fl_abs(impulse->xyz.x) <= WHACK_LIMIT) && (fl_abs(impulse->xyz.y) <= WHACK_LIMIT) && (fl_abs(impulse->xyz.z) <= WHACK_LIMIT))
		return;

	vm_vec_rotate( &body_delta_rotvel, world_delta_rotvel, orient );
//	vm_vec_scale( &body_delta_rotvel, (float)	ROTVEL_COLLIDE_WHACK_CONST );
	vm_vec_add2( &pi->rotvel, &body_delta_rotvel );

	update_reduced_damp_timestamp( pi, vm_vec_mag(impulse) );

	// find time for shake from weapon to end
	if (!is_landing) {
		int dtime = timestamp_until(pi->afterburner_decay);
		if (dtime < WEAPON_SHAKE_TIME) {
			pi->afterburner_decay = timestamp( WEAPON_SHAKE_TIME );
		}
	}

	pi->flags |= PF_REDUCED_DAMP;
	vm_vec_scale_add2( &pi->vel, impulse, 1.0f / pi->mass );
	// check that collision does not give ship too much speed
	// reset if too high
	if (!(pi->flags & PF_USE_VEL) && (vm_vec_mag_squared(&pi->vel) > MAX_SHIP_SPEED*MAX_SHIP_SPEED)) {
		// Get DaveA
		nprintf(("Physics", "speed reset in physics_collide_whack [speed: %f]\n", vm_vec_mag(&pi->vel)));
		vm_vec_normalize(&pi->vel);
		vm_vec_scale(&pi->vel, (float)RESET_SHIP_SPEED);
	}
	vm_vec_rotate( &pi->prev_ramp_vel, &pi->vel, orient );		// set so velocity will ramp starting from current speed
																					// ramped velocity is now affected by collision
	// rotate previous ramp velocity (in model coord) to be same as vel (in world coords)
}
// blip is for a target immune to sensors, so cause to flicker in/out with mild distortion
void HudGaugeRadarDradis::blipDrawFlicker(blip *b, vec3d *pos, float alpha)
{
	int flicker_index;

	float dist=vm_vec_normalize(pos);
	vec3d out;
	float distortion_angle=10;

	if ((b-Blips) & 1)
		flicker_index=0;
	else
		flicker_index=1;
	

	if (timestamp_elapsed(Radar_flicker_timer[flicker_index])) {
		Radar_flicker_timer[flicker_index] = timestamp_rand(50,1000);
		Radar_flicker_on[flicker_index] ^= 1;
	}

	if (!Radar_flicker_on[flicker_index])
		return;

	if (rand() & 1)
	{
		distortion_angle *= frand_range(0.1f,2.0f);
		dist *= frand_range(0.75f, 1.25f);

		if (dist > 1.0f) dist = 1.0f;
		if (dist < 0.1f) dist = 0.1f;
	}
	
	vm_vec_random_cone(&out,pos,distortion_angle);
	vm_vec_scale(&out,dist);

	drawContact(&out, -1, unknown_contact_icon, b->dist, alpha, 1.0f);
}
void HudGaugeRadarDradis::plotBlip(blip* b, vec3d *pos, float *alpha)
{
	*pos = b->position;
	vm_vec_normalize(pos);

	if (ship_is_tagged(b->objp)) {
		*alpha = 1.0f;
		return;
	}

	float fade_multi = 1.5f;
	
	if (b->objp->type == OBJ_SHIP) {
		if (Ships[b->objp->instance].flags2 & SF2_STEALTH) {
			fade_multi *= 2.0f;
		}
	}

	*alpha = 1.0f - (sweep_percent /(PI*2))*fade_multi/2.0f;
	
	if (*alpha < 0.0f) {
		*alpha = 0.0f;
	}
}
void physics_apply_shock(vec3d *direction_vec, float pressure, physics_info *pi, matrix *orient, vec3d *min, vec3d *max, float radius)
{
	vec3d normal;
	vec3d local_torque, temp_torque, torque;
	vec3d impact_vec;
	vec3d area;
	vec3d sin;

	if (radius > MAX_RADIUS) {
		return;
	}

	vm_vec_normalize_safe ( direction_vec );

	area.xyz.x = (max->xyz.y - min->xyz.z) * (max->xyz.z - min->xyz.z);
	area.xyz.y = (max->xyz.x - min->xyz.x) * (max->xyz.z - min->xyz.z);
	area.xyz.z = (max->xyz.x - min->xyz.x) * (max->xyz.y - min->xyz.y);

	normal.xyz.x = vm_vec_dotprod( direction_vec, &orient->vec.rvec );
	normal.xyz.y = vm_vec_dotprod( direction_vec, &orient->vec.uvec );
	normal.xyz.z = vm_vec_dotprod( direction_vec, &orient->vec.fvec );

	sin.xyz.x = fl_sqrt( fl_abs(1.0f - normal.xyz.x*normal.xyz.x) );
	sin.xyz.y = fl_sqrt( fl_abs(1.0f - normal.xyz.y*normal.xyz.y) );
	sin.xyz.z = fl_sqrt( fl_abs(1.0f - normal.xyz.z*normal.xyz.z) );

	vm_vec_make( &torque, 0.0f, 0.0f, 0.0f );

	// find the torque exerted due to the shockwave hitting each face
	//  model the effect of the shockwave as if the shockwave were a plane of projectiles,
	//  all moving in the direction direction_vec.  then find the torque as the cross prod
	//  of the force (pressure * area * normal * sin * scale * mass)
	//  normal takes account the fraction of the surface exposed to the shockwave
	//  the sin term is not technically needed but "feels" better
	//  scale factors out the increase in area with larger objects
	//  more massive objects get less rotation

	// find torque due to forces on the right/left face
	if ( normal.xyz.x < 0.0f )		// normal < 0, hits the right face
		vm_vec_copy_scale( &impact_vec, &orient->vec.rvec, max->xyz.x * pressure * area.xyz.x *  normal.xyz.x * sin.xyz.x / pi->mass );
	else								// normal > 0, hits the left face
		vm_vec_copy_scale( &impact_vec, &orient->vec.rvec, min->xyz.x * pressure * area.xyz.x * -normal.xyz.x * sin.xyz.x / pi->mass );

	vm_vec_crossprod( &temp_torque, &impact_vec, direction_vec );
	vm_vec_add2( &torque, &temp_torque );

	// find torque due to forces on the up/down face
	if ( normal.xyz.y < 0.0f )
		vm_vec_copy_scale( &impact_vec, &orient->vec.uvec, max->xyz.y * pressure * area.xyz.y *  normal.xyz.y * sin.xyz.y / pi->mass );
	else
		vm_vec_copy_scale( &impact_vec, &orient->vec.uvec, min->xyz.y * pressure * area.xyz.y * -normal.xyz.y * sin.xyz.y / pi->mass );

	vm_vec_crossprod( &temp_torque, &impact_vec, direction_vec );
	vm_vec_add2( &torque, &temp_torque );

	// find torque due to forces on the forward/backward face
	if ( normal.xyz.z < 0.0f )
		vm_vec_copy_scale( &impact_vec, &orient->vec.fvec, max->xyz.z * pressure * area.xyz.z *  normal.xyz.z * sin.xyz.z / pi->mass );
	else
		vm_vec_copy_scale( &impact_vec, &orient->vec.fvec, min->xyz.z * pressure * area.xyz.z * -normal.xyz.z * sin.xyz.z / pi->mass );

	vm_vec_crossprod( &temp_torque, &impact_vec, direction_vec );
	vm_vec_add2( &torque, &temp_torque );

	// compute delta rotvel, scale according to blast and radius
	float scale;

	if (radius < MIN_RADIUS) {
		scale = 1.0f;
	} else {
		scale = (MAX_RADIUS - radius)/(MAX_RADIUS-MIN_RADIUS);
	}

	// set shockwave shake amplitude, duration, flag
	pi->shockwave_shake_amp = (float)(MAX_SHAKE*(pressure/STD_PRESSURE)*scale);
	pi->shockwave_decay = timestamp( SW_BLAST_DURATION );
	pi->flags |= PF_IN_SHOCKWAVE;

	// safety dance
	if (!(IS_VEC_NULL_SQ_SAFE(&torque))) {
		vec3d delta_rotvel;
		vm_vec_rotate( &local_torque, &torque, orient );
		vm_vec_copy_normalize(&delta_rotvel, &local_torque);
		
		vm_vec_scale(&delta_rotvel, (float)(MAX_ROTVEL*(pressure/STD_PRESSURE)*scale));
		// nprintf(("Physics", "rotvel scale %f\n", (MAX_ROTVEL*(pressure/STD_PRESSURE)*scale)));
		vm_vec_add2(&pi->rotvel, &delta_rotvel);
	}

	// set reduced translational damping, set flags
	float velocity_scale = (float)MAX_VEL*scale;
	pi->flags |= PF_REDUCED_DAMP;
	update_reduced_damp_timestamp( pi, velocity_scale*pi->mass );
	vm_vec_scale_add2( &pi->vel, direction_vec, velocity_scale );
	vm_vec_rotate(&pi->prev_ramp_vel, &pi->vel, orient);	// set so velocity will ramp starting from current speed

	// check that kick from shockwave is not too large
	if (!(pi->flags & PF_USE_VEL) && (vm_vec_mag_squared(&pi->vel) > MAX_SHIP_SPEED*MAX_SHIP_SPEED)) {
		// Get DaveA
		nprintf(("Physics", "speed reset in physics_apply_shock [speed: %f]\n", vm_vec_mag(&pi->vel)));
		vm_vec_normalize(&pi->vel);
		vm_vec_scale(&pi->vel, (float)RESET_SHIP_SPEED);
	}
}