void opengl_create_view_matrix(matrix4 *out, const vec3d *pos, const matrix *orient) { vec3d scaled_pos; vec3d inv_pos; matrix scaled_orient = *orient; matrix inv_orient; vm_vec_copy_scale(&scaled_pos, pos, -1.0f); vm_vec_scale(&scaled_orient.vec.fvec, -1.0f); vm_copy_transpose(&inv_orient, &scaled_orient); vm_vec_rotate(&inv_pos, &scaled_pos, &scaled_orient); vm_matrix4_set_transform(out, &inv_orient, &inv_pos); }
static matrix4 create_view_matrix(const vec3d *pos, const matrix *orient) { vec3d scaled_pos; vec3d inv_pos; matrix scaled_orient = *orient; matrix inv_orient; vm_vec_copy_scale(&scaled_pos, pos, -1.0f); vm_vec_scale(&scaled_orient.vec.fvec, -1.0f); vm_copy_transpose(&inv_orient, &scaled_orient); vm_vec_rotate(&inv_pos, &scaled_pos, &scaled_orient); matrix4 out; vm_matrix4_set_transform(&out, &inv_orient, &inv_pos); return out; }
void model_collide_preprocess_subobj(vec3d *pos, matrix *orient, polymodel *pm, polymodel_instance *pmi, int subobj_num) { submodel_instance *smi = &pmi->submodel[subobj_num]; smi->mc_base = *pos; smi->mc_orient = *orient; int i = pm->submodel[subobj_num].first_child; while ( i >= 0 ) { angles angs = pmi->submodel[i].angs; bsp_info * csm = &pm->submodel[i]; matrix tm = IDENTITY_MATRIX; vm_vec_unrotate(pos, &csm->offset, &smi->mc_orient ); vm_vec_add2(pos, &smi->mc_base); if( vm_matrix_same(&tm, &csm->orientation)) { // if submodel orientation matrix is identity matrix then don't bother with matrix ops vm_angles_2_matrix(&tm, &angs); } else { matrix rotation_matrix = csm->orientation; vm_rotate_matrix_by_angles(&rotation_matrix, &angs); matrix inv_orientation; vm_copy_transpose(&inv_orientation, &csm->orientation); vm_matrix_x_matrix(&tm, &rotation_matrix, &inv_orientation); } vm_matrix_x_matrix(orient, &smi->mc_orient, &tm); model_collide_preprocess_subobj(pos, orient, pm, pmi, i); i = csm->next_sibling; } }
/** * nstance at specified point with specified orientation * * if matrix==NULL, don't modify matrix. This will be like doing an offset * if pos==NULL, no position change */ void g3_start_instance_matrix(const vec3d *pos, const matrix *orient, bool set_api) { vec3d tempv; matrix tempm,tempm2; Assert( G3_count == 1 ); Assert(instance_depth<MAX_INSTANCE_DEPTH); instance_stack[instance_depth].m = View_matrix; instance_stack[instance_depth].p = View_position; instance_stack[instance_depth].lm = Light_matrix; instance_stack[instance_depth].lb = Light_base; instance_stack[instance_depth].om = Object_matrix; instance_stack[instance_depth].op = Object_position; instance_depth++; // Make sure orient is valid if (!orient) { orient = &vmd_identity_matrix; // Assume no change in orient } if ( pos ) { //step 1: subtract object position from view position vm_vec_sub2(&View_position,pos); //step 2: rotate view vector through object matrix vm_vec_rotate(&tempv,&View_position,orient); View_position = tempv; vm_vec_unrotate(&tempv,pos,&Object_matrix); vm_vec_add2(&Object_position, &tempv); } else { // No movement, leave View_position alone } //step 3: rotate object matrix through view_matrix (vm = ob * vm) vm_copy_transpose(&tempm2,orient); vm_matrix_x_matrix(&tempm,&tempm2,&View_matrix); View_matrix = tempm; vm_matrix_x_matrix(&Object_matrix,&instance_stack[instance_depth-1].om,orient); // Update the lighting matrix matrix saved_orient = Light_matrix; vec3d saved_base = Light_base; if ( pos ) { vm_vec_unrotate(&Light_base,pos,&saved_orient ); vm_vec_add2(&Light_base, &saved_base ); } else { // No movement, light_base doesn't change. } vm_matrix_x_matrix(&Light_matrix,&saved_orient, orient); if(!Cmdline_nohtl && set_api) gr_start_instance_matrix(pos, orient); }
// This function recursively checks a submodel and its children // for a collision with a vector. void mc_check_subobj( int mn ) { vec3d tempv; vec3d hitpt; // used in bounding box check bsp_info * sm; int i; Assert( mn >= 0 ); Assert( mn < Mc_pm->n_models ); if ( (mn < 0) || (mn>=Mc_pm->n_models) ) return; sm = &Mc_pm->submodel[mn]; if (sm->no_collisions) return; // don't do collisions if (sm->nocollide_this_only) goto NoHit; // Don't collide for this model, but keep checking others // Rotate the world check points into the current subobject's // frame of reference. // After this block, Mc_p0, Mc_p1, Mc_direction, and Mc_mag are correct // and relative to this subobjects' frame of reference. vm_vec_sub(&tempv, Mc->p0, &Mc_base); vm_vec_rotate(&Mc_p0, &tempv, &Mc_orient); vm_vec_sub(&tempv, Mc->p1, &Mc_base); vm_vec_rotate(&Mc_p1, &tempv, &Mc_orient); vm_vec_sub(&Mc_direction, &Mc_p1, &Mc_p0); // bail early if no ray exists if ( IS_VEC_NULL(&Mc_direction) ) { return; } if (Mc_pm->detail[0] == mn) { // Quickly bail if we aren't inside the full model bbox if (!mc_ray_boundingbox( &Mc_pm->mins, &Mc_pm->maxs, &Mc_p0, &Mc_direction, NULL)) { return; } // If we are checking the root submodel, then we might want to check // the shield at this point if ((Mc->flags & MC_CHECK_SHIELD) && (Mc_pm->shield.ntris > 0 )) { mc_check_shield(); return; } } if (!(Mc->flags & MC_CHECK_MODEL)) { return; } Mc_submodel = mn; // Check if the ray intersects this subobject's bounding box if ( mc_ray_boundingbox(&sm->min, &sm->max, &Mc_p0, &Mc_direction, &hitpt) ) { if (Mc->flags & MC_ONLY_BOUND_BOX) { float dist = vm_vec_dist( &Mc_p0, &hitpt ); // If the ray is behind the plane there is no collision if (dist < 0.0f) { goto NoHit; } // The ray isn't long enough to intersect the plane if ( !(Mc->flags & MC_CHECK_RAY) && (dist > Mc_mag) ) { goto NoHit; } // If the ray hits, but a closer intersection has already been found, return if ( Mc->num_hits && (dist >= Mc->hit_dist) ) { goto NoHit; } Mc->hit_dist = dist; Mc->hit_point = hitpt; Mc->hit_submodel = Mc_submodel; Mc->hit_bitmap = -1; Mc->num_hits++; } else { // The ray intersects this bounding box, so we have to check all the // polygons in this submodel. if ( Cmdline_old_collision_sys ) { model_collide_sub(sm->bsp_data); } else { if (Mc->lod > 0 && sm->num_details > 0) { bsp_info *lod_sm = sm; for (i = Mc->lod - 1; i >= 0; i--) { if (sm->details[i] != -1) { lod_sm = &Mc_pm->submodel[sm->details[i]]; //mprintf(("Checking %s collision for %s using %s instead\n", Mc_pm->filename, sm->name, lod_sm->name)); break; } } model_collide_bsp(model_get_bsp_collision_tree(lod_sm->collision_tree_index), 0); } else { model_collide_bsp(model_get_bsp_collision_tree(sm->collision_tree_index), 0); } } } } NoHit: // If we're only checking one submodel, return if (Mc->flags & MC_SUBMODEL) { return; } // If this subobject doesn't have any children, we're done checking it. if ( sm->num_children < 1 ) return; // Save instance (Mc_orient, Mc_base, Mc_point_base) matrix saved_orient = Mc_orient; vec3d saved_base = Mc_base; // Check all of this subobject's children i = sm->first_child; while ( i >= 0 ) { angles angs; bool blown_off; bool collision_checked; bsp_info * csm = &Mc_pm->submodel[i]; if ( Mc_pmi ) { angs = Mc_pmi->submodel[i].angs; blown_off = Mc_pmi->submodel[i].blown_off; collision_checked = Mc_pmi->submodel[i].collision_checked; } else { angs = csm->angs; blown_off = csm->blown_off ? true : false; collision_checked = false; } // Don't check it or its children if it is destroyed // or if it's set to no collision if ( !blown_off && !collision_checked && !csm->no_collisions ) { if ( Mc_pmi ) { Mc_orient = Mc_pmi->submodel[i].mc_orient; Mc_base = Mc_pmi->submodel[i].mc_base; vm_vec_add2(&Mc_base, Mc->pos); } else { //instance for this subobject matrix tm = IDENTITY_MATRIX; vm_vec_unrotate(&Mc_base, &csm->offset, &saved_orient ); vm_vec_add2(&Mc_base, &saved_base ); if( vm_matrix_same(&tm, &csm->orientation)) { // if submodel orientation matrix is identity matrix then don't bother with matrix ops vm_angles_2_matrix(&tm, &angs); } else { matrix rotation_matrix = csm->orientation; vm_rotate_matrix_by_angles(&rotation_matrix, &angs); matrix inv_orientation; vm_copy_transpose(&inv_orientation, &csm->orientation); vm_matrix_x_matrix(&tm, &rotation_matrix, &inv_orientation); } vm_matrix_x_matrix(&Mc_orient, &saved_orient, &tm); } mc_check_subobj( i ); } i = csm->next_sibling; } }
void HudGaugeReticle::getFirepointStatus() { //First, get the player ship ship_info* sip; ship* shipp; polymodel* pm; Assert(Objects[Player->objnum].type == OBJ_SHIP); if (Objects[Player->objnum].type == OBJ_SHIP) { shipp = &Ships[Objects[Player->objnum].instance]; sip = &Ship_info[shipp->ship_info_index]; //Get the player eyepoint pm = model_get(sip->model_num); if (pm->n_view_positions == 0) { mprintf(("Model %s does not have a defined eyepoint. Firepoint display could not be generated\n", pm->filename)); } else { if (pm->n_guns > 0) { eye eyepoint = pm->view_positions[shipp->current_viewpoint]; vec2d ep = { eyepoint.pnt.xyz.x, eyepoint.pnt.xyz.y }; for (int i = 0; i < pm->n_guns; i++) { int bankactive = 0; ship_weapon *swp = &shipp->weapons; if (!timestamp_elapsed(shipp->weapons.next_primary_fire_stamp[i])) bankactive = 1; else if (timestamp_elapsed(shipp->weapons.primary_animation_done_time[i])) bankactive = 1; else if (i == shipp->weapons.current_primary_bank || shipp->flags[Ship::Ship_Flags::Primary_linked]) bankactive = 2; int num_slots = pm->gun_banks[i].num_slots; for (int j = 0; j < num_slots; j++) { int fpactive = bankactive; if (sip->flags[Ship::Info_Flags::Dyn_primary_linking]) { // If this firepoint is not among the next shot(s) to be fired, dim it one step if ( !( (j >= (shipp->last_fired_point[i]+1) % num_slots) && (j <= (shipp->last_fired_point[i]+swp->primary_bank_slot_count[i]) % num_slots) ) ) { fpactive--; } } else if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Cycle]) { // If this firepoint is not the next one to be fired, dim it one step if (j != (shipp->last_fired_point[i]+1) % num_slots) { fpactive--; } } vec3d fpfromeye; matrix eye_orient, player_transpose; vm_copy_transpose(&player_transpose, &Objects[Player->objnum].orient); vm_matrix_x_matrix(&eye_orient, &player_transpose, &Eye_matrix); vm_vec_rotate(&fpfromeye, &pm->gun_banks[i].pnt[j], &eye_orient); firepoint tmp = { { fpfromeye.xyz.x - ep.x, ep.y - fpfromeye.xyz.y }, fpactive }; fp.push_back(tmp); } } } } } }