コード例 #1
0
ファイル: camera.cpp プロジェクト: Esarai/fs2open.github.com
void camera::get_info(vec3d *position, matrix *orientation)
{
	if(position == NULL && orientation == NULL)
		return;
	
	eye* eyep = NULL;
	vec3d host_normal;
	//POSITION
	if(!(flags & CAM_STATIONARY_POS) || object_host.IsValid())
	{
		c_pos = vmd_zero_vector;

		vec3d pt;
		pos_x.get(&pt.xyz.x, NULL);
		pos_y.get(&pt.xyz.y, NULL);
		pos_z.get(&pt.xyz.z, NULL);

		if(object_host.IsValid())
		{
			object *objp = object_host.objp;
			int model_num = object_get_model(objp);
			polymodel *pm = NULL;
			
			if(model_num > -1)
			{
				pm = model_get(model_num);
			}

			if(object_host_submodel < 0 || pm == NULL)
			{
				vm_vec_unrotate(&c_pos, &pt, &object_host.objp->orient);
				vm_vec_add2(&c_pos, &object_host.objp->pos);
			}
			else
			{
				eyep = get_submodel_eye(pm, object_host_submodel);
				if(eyep)
				{
					vec3d c_pos_in;
					find_submodel_instance_point_normal( &c_pos_in, &host_normal, objp, eyep->parent, &eyep->pnt, &eyep->norm);
					vm_vec_unrotate(&c_pos, &c_pos_in, &objp->orient);
					vm_vec_add2(&c_pos, &objp->pos);
				}
				else
				{
					model_find_world_point( &c_pos, &pt, pm->id, object_host_submodel, &objp->orient, &objp->pos );
				}
			}
		}
		else
		{
			c_pos = pt;
		}

		//Do custom position stuff, if needed
		if(func_custom_position != NULL && !eyep)
		{
			func_custom_position(this, &c_pos);
		}
	}

	if(position != NULL)
		*position = c_pos;

	//ORIENTATION
	if(orientation != NULL)
	{
		bool target_set = false;
		if(!(flags & CAM_STATIONARY_ORI) || object_target.IsValid() || object_host.IsValid())
		{
			if(object_target.IsValid())
			{
				object *objp = object_target.objp;
				int model_num = object_get_model(objp);
				polymodel *pm = NULL;
				vec3d target_pos = vmd_zero_vector;
				
				//See if we can get the model
				if(model_num > -1)
				{
					pm = model_get(model_num);
				}

				//If we don't have a submodel or don't have the model use object pos
				//Otherwise, find the submodel pos as it is rotated
				if(object_target_submodel < 0 || pm == NULL)
				{
					target_pos = objp->pos;
				}
				else
				{
					model_find_world_point( &target_pos, &vmd_zero_vector, pm->id, object_target_submodel, &objp->orient, &objp->pos );
				}

				vec3d targetvec;
				vm_vec_normalized_dir(&targetvec, &target_pos, &c_pos);
				vm_vector_2_matrix(&c_ori, &targetvec, NULL, NULL);
				target_set = true;
			}
			else if(object_host.IsValid())
			{
				if(eyep)
				{
					vm_vector_2_matrix(&c_ori, &host_normal, vm_vec_same(&host_normal, &object_host.objp->orient.vec.uvec)?NULL:&object_host.objp->orient.vec.uvec, NULL);
					target_set = true;
				}
				else
				{
					c_ori = object_host.objp->orient;
				}
			}
			else
			{
				c_ori = vmd_identity_matrix;
			}

			matrix mtxA = c_ori;
			matrix mtxB = IDENTITY_MATRIX;
			float pos = 0.0f;
			for(int i = 0; i < 9; i++)
			{
				ori[i].get(&pos, NULL);
				mtxB.a1d[i] = pos;
			}
			vm_matrix_x_matrix(&c_ori, &mtxA, &mtxB);

			vm_orthogonalize_matrix(&c_ori);
		}
		//Do custom orientation stuff, if needed
		if(func_custom_orientation != NULL && !target_set)
		{
			func_custom_orientation(this, &c_ori);
		}
		*orientation = c_ori;
	}
}
コード例 #2
0
// See model.h for usage.   I don't want to put the
// usage here because you need to see the #defines and structures
// this uses while reading the help.   
int model_collide(mc_info *mc_info_obj)
{
	Mc = mc_info_obj;

	MONITOR_INC(NumFVI,1);

	Mc->num_hits = 0;				// How many collisions were found
	Mc->shield_hit_tri = -1;	// Assume we won't hit any shield polygons
	Mc->hit_bitmap = -1;
	Mc->edge_hit = 0;

	if ( (Mc->flags & MC_CHECK_SHIELD) && (Mc->flags & MC_CHECK_MODEL) )	{
		Error( LOCATION, "Checking both shield and model!\n" );
		return 0;
	}

	//Fill in some global variables that all the model collide routines need internally.
	Mc_pm = model_get(Mc->model_num);
	Mc_orient = *Mc->orient;
	Mc_base = *Mc->pos;
	Mc_mag = vm_vec_dist( Mc->p0, Mc->p1 );
	Mc_edge_time = FLT_MAX;

	if ( Mc->model_instance_num >= 0 ) {
		Mc_pmi = model_get_instance(Mc->model_instance_num);
	} else {
		Mc_pmi = NULL;
	}

	// DA 11/19/98 - disable this check for rotating submodels
	// Don't do check if for very small movement
//	if (Mc_mag < 0.01f) {
//		return 0;
//	}

	float model_radius;		// How big is the model we're checking against
	int first_submodel;		// Which submodel gets returned as hit if MC_ONLY_SPHERE specified

	if ( (Mc->flags & MC_SUBMODEL) || (Mc->flags & MC_SUBMODEL_INSTANCE) )	{
		first_submodel = Mc->submodel_num;
		model_radius = Mc_pm->submodel[first_submodel].rad;
	} else {
		first_submodel = Mc_pm->detail[0];
		model_radius = Mc_pm->rad;
	}

	if ( Mc->flags & MC_CHECK_SPHERELINE ) {
		if ( Mc->radius <= 0.0f ) {
			Warning(LOCATION, "Attempting to collide with a sphere, but the sphere's radius is <= 0.0f!\n\n(model file is %s; submodel is %d, mc_flags are %d)", Mc_pm->filename, first_submodel, Mc->flags);
			return 0;
		}

		// Do a quick check on the Bounding Sphere
		if (fvi_segment_sphere(&Mc->hit_point_world, Mc->p0, Mc->p1, Mc->pos, model_radius+Mc->radius) )	{
			if ( Mc->flags & MC_ONLY_SPHERE )	{
				Mc->hit_point = Mc->hit_point_world;
				Mc->hit_submodel = first_submodel;
				Mc->num_hits++;
				return (Mc->num_hits > 0);
			}
			// continue checking polygons.
		} else {
			return 0;
		}
	} else {
		int r;

		// Do a quick check on the Bounding Sphere
		if ( Mc->flags & MC_CHECK_RAY ) {
			r = fvi_ray_sphere(&Mc->hit_point_world, Mc->p0, Mc->p1, Mc->pos, model_radius);
		} else {
			r = fvi_segment_sphere(&Mc->hit_point_world, Mc->p0, Mc->p1, Mc->pos, model_radius);
		}
		if (r) {
			if ( Mc->flags & MC_ONLY_SPHERE ) {
				Mc->hit_point = Mc->hit_point_world;
				Mc->hit_submodel = first_submodel;
				Mc->num_hits++;
				return (Mc->num_hits > 0);
			}
			// continue checking polygons.
		} else {
			return 0;
		}

	}

	if ( Mc->flags & MC_SUBMODEL )	{
		// Check only one subobject
		mc_check_subobj( Mc->submodel_num );
		// Check submodel and any children
	} else if (Mc->flags & MC_SUBMODEL_INSTANCE) {
		mc_check_subobj(Mc->submodel_num);
	} else {
		// Check all the the highest detail model polygons and subobjects for intersections

		// Don't check it or its children if it is destroyed
		if (!Mc_pm->submodel[Mc_pm->detail[0]].blown_off)	{	
			mc_check_subobj( Mc_pm->detail[0] );
		}
	}


	//If we found a hit, then rotate it into world coordinates	
	if ( Mc->num_hits )	{
		if ( Mc->flags & MC_SUBMODEL )	{
			// If we're just checking one submodel, don't use normal instancing to find world points
			vm_vec_unrotate(&Mc->hit_point_world, &Mc->hit_point, Mc->orient);
			vm_vec_add2(&Mc->hit_point_world, Mc->pos);
		} else {
			if ( Mc_pmi ) {
				model_instance_find_world_point(&Mc->hit_point_world, &Mc->hit_point, Mc->model_instance_num, Mc->hit_submodel, Mc->orient, Mc->pos);
			} else {
				model_find_world_point(&Mc->hit_point_world, &Mc->hit_point, Mc->model_num, Mc->hit_submodel, Mc->orient, Mc->pos);
			}
		}
	}


	return Mc->num_hits;

}