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; } }
// 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; }