/* 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 ); }
void HudGaugeRadarDradis::drawOutlinesHtl() { matrix base_tilt = vmd_identity_matrix; vec3d base_tilt_norm; if ((xy_plane == -1) || (xz_yz_plane == -1)) return; g3_start_instance_matrix(&vmd_zero_vector, /*&Player_obj->orient*/&vmd_identity_matrix, true); // Tilt the base disc component of DRADIS-style radar 30 degrees down vm_angle_2_matrix(&base_tilt, PI/6, 0); vm_vec_rotate(&base_tilt_norm, &vmd_y_vector, &base_tilt); //gr_set_bitmap(xy_plane, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f); // base //g3_draw_polygon(&vmd_zero_vector, &base_tilt_norm, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); material mat_params; material_set_unlit(&mat_params, xy_plane, 1.0f, true, false); g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &base_tilt_norm, scale, scale); //gr_set_bitmap(xz_yz_plane, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f); //g3_draw_polygon(&vmd_zero_vector, &vmd_x_vector, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); // forward facing ring //g3_draw_polygon(&vmd_zero_vector, &vmd_z_vector, scale, scale, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); // side facing ring material_set_unlit(&mat_params, xz_yz_plane, 1.0f, true, false); g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &vmd_x_vector, scale, scale); // forward facing ring g3_render_rect_oriented(&mat_params, &vmd_zero_vector, &vmd_z_vector, scale, scale); // side facing ring g3_done_instance(true); }
//instance at specified point with specified orientation //if matrix==NULL, don't modify matrix. This will be like doing an offset void g3_start_instance_matrix(vms_vector *pos, vms_matrix *orient) { vms_vector tempv; vms_matrix tempm, tempm2; Assert(instance_depth<MAX_INSTANCE_DEPTH); instance_stack[instance_depth].m = View_matrix; instance_stack[instance_depth].p = View_position; instance_depth++; //step 1: subtract object position from view position vm_vec_sub(&tempv, &View_position, pos); if (orient) { //step 2: rotate view vector through object matrix vm_vec_rotate(&View_position, &tempv, orient); //step 3: rotate object matrix through view_matrix (vm = ob * vm) vm_copy_transpose_matrix(&tempm2, orient); vm_matrix_x_matrix(&tempm, &tempm2, &View_matrix); View_matrix = tempm; } }
// Create a wing. // wing_type is the type of wing from the Wing_formations array to create. // leader_index is the index in Objects of the leader object. This object must // have a position and an orientation. // *wingmen is a list of indices of existing ships to be added to the wing. // The wingmen list is terminated by -1. // max_size is the maximum number of ships to add to the wing // fill_flag is set if more ships are to be added to fill out the wing to max_size void create_wing(int wing_type, int leader_index, int *wingmen, int max_size, int fill_flag) { int num_placed, num_vectors, cur_vec_index; object *lobjp = &Objects[leader_index]; formation *wingp; object *parent; int wing_list[MAX_OBJECTS]; matrix rotmat; initialize_wings(); Assert((wing_type >= 0) && (wing_type < MAX_WING_FORMATIONS)); Assert(Wing_formations[wing_type].num_vectors > 0); Assert(Wing_formations[wing_type].num_vectors < MAX_WING_VECTORS); Assert(Objects[leader_index].type != OBJ_NONE); Assert(max_size < MAX_SHIPS_PER_WING); num_placed = 0; wingp = &Wing_formations[wing_type]; num_vectors = wingp->num_vectors; cur_vec_index = 0; parent = lobjp; vm_copy_transpose_matrix(&rotmat, &lobjp->orient); while (num_placed < max_size) { vector wvec; int curobj; if (*wingmen == -1) { if (!fill_flag) break; else { curobj = get_free_objnum(); Assert(curobj != -1); Objects[curobj].type = lobjp->type; Assert(Wings[cur_wing].wave_count < MAX_SHIPS_PER_WING); // JEH Wings[cur_wing].ship_list[Wings[cur_wing].count] = curobj; Wings[cur_wing].wave_count++; } } else curobj = *wingmen++; Objects[curobj] = *lobjp; vm_vec_rotate(&wvec, &wingp->offsets[cur_vec_index], &rotmat); cur_vec_index = (cur_vec_index + 1) % num_vectors; if (num_placed < num_vectors) parent = lobjp; else parent = &Objects[wing_list[num_placed - num_vectors]]; wing_list[num_placed] = curobj; vm_vec_add(&Objects[curobj].pos, &parent->pos, &wvec); num_placed++; } }
ubyte g3_rotate_vertex(vertex *dest,vector *src) { #if 0 vector tempv; Assert( G3_count == 1 ); vm_vec_sub(&tempv,src,&View_position); vm_vec_rotate( (vector *)&dest->x, &tempv, &View_matrix ); dest->flags = 0; //not projected return g3_code_vertex(dest); #else float tx, ty, tz, x,y,z; ubyte codes; MONITOR_INC( NumRotations, 1 ); tx = src->xyz.x - View_position.xyz.x; ty = src->xyz.y - View_position.xyz.y; tz = src->xyz.z - View_position.xyz.z; x = tx * View_matrix.vec.rvec.xyz.x; x += ty * View_matrix.vec.rvec.xyz.y; x += tz * View_matrix.vec.rvec.xyz.z; y = tx * View_matrix.vec.uvec.xyz.x; y += ty * View_matrix.vec.uvec.xyz.y; y += tz * View_matrix.vec.uvec.xyz.z; z = tx * View_matrix.vec.fvec.xyz.x; z += ty * View_matrix.vec.fvec.xyz.y; z += tz * View_matrix.vec.fvec.xyz.z; codes = 0; if (x > z) codes |= CC_OFF_RIGHT; if (x < -z) codes |= CC_OFF_LEFT; if (y > z) codes |= CC_OFF_TOP; if (y < -z) codes |= CC_OFF_BOT; if (z < MIN_Z ) codes |= CC_BEHIND; dest->x = x; dest->y = y; dest->z = z; if ( G3_user_clip ) { // Check if behind user plane if ( g3_point_behind_user_plane((vector *)&dest->x)) { codes |= CC_OFF_USER; } } dest->codes = codes; dest->flags = 0; // not projected vm_vec_copy_scale(&dest->real_pos, src,1); return codes; #endif }
void opengl_post_lightshafts() { opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_LIGHTSHAFTS, 0)); float x, y; // should we even be here? if ( !Game_subspace_effect && ls_on && !ls_force_off ) { int n_lights = light_get_global_count(); for ( int idx = 0; idx<n_lights; idx++ ) { vec3d light_dir; vec3d local_light_dir; light_get_global_dir(&light_dir, idx); vm_vec_rotate(&local_light_dir, &light_dir, &Eye_matrix); if ( !stars_sun_has_glare(idx) ) { continue; } float dot; if ( (dot = vm_vec_dot(&light_dir, &Eye_matrix.vec.fvec)) > 0.7f ) { x = asinf(vm_vec_dot(&light_dir, &Eye_matrix.vec.rvec)) / PI*1.5f + 0.5f; //cant get the coordinates right but this works for the limited glare fov y = asinf(vm_vec_dot(&light_dir, &Eye_matrix.vec.uvec)) / PI*1.5f*gr_screen.clip_aspect + 0.5f; Current_shader->program->Uniforms.setUniform2f("sun_pos", x, y); Current_shader->program->Uniforms.setUniformi("scene", 0); Current_shader->program->Uniforms.setUniformi("cockpit", 1); Current_shader->program->Uniforms.setUniformf("density", ls_density); Current_shader->program->Uniforms.setUniformf("falloff", ls_falloff); Current_shader->program->Uniforms.setUniformf("weight", ls_weight); Current_shader->program->Uniforms.setUniformf("intensity", Sun_spot * ls_intensity); Current_shader->program->Uniforms.setUniformf("cp_intensity", Sun_spot * ls_cpintensity); GL_state.Texture.SetActiveUnit(0); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Scene_depth_texture); GL_state.Texture.SetActiveUnit(1); GL_state.Texture.SetTarget(GL_TEXTURE_2D); GL_state.Texture.Enable(Cockpit_depth_texture); GL_state.Blend(GL_TRUE); GL_state.SetAlphaBlendMode(ALPHA_BLEND_ADDITIVE); opengl_draw_textured_quad(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, Scene_texture_u_scale, Scene_texture_u_scale); GL_state.Blend(GL_FALSE); break; } } } if ( zbuffer_saved ) { zbuffer_saved = false; gr_zbuffer_set(GR_ZBUFF_FULL); glClear(GL_DEPTH_BUFFER_BIT); gr_zbuffer_set(GR_ZBUFF_NONE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, Scene_depth_texture, 0); } }
//given an object and a gun number, return position in 3-space of gun //fills in gun_point void calc_gun_point(vms_vector *gun_point,object *obj,int gun_num) { polymodel *pm; robot_info *r; vms_vector pnt; vms_matrix m; int mn; //submodel number Assert(obj->render_type==RT_POLYOBJ || obj->render_type==RT_MORPH); Assert(obj->id < N_robot_types); r = &Robot_info[obj->id]; pm =&Polygon_models[r->model_num]; if (gun_num >= r->n_guns) { mprintf((1, "Bashing gun num %d to 0.\n", gun_num)); //Int3(); gun_num = 0; } // Assert(gun_num < r->n_guns); pnt = r->gun_points[gun_num]; mn = r->gun_submodels[gun_num]; //instance up the tree for this gun while (mn != 0) { vms_vector tpnt; vm_angles_2_matrix(&m,&obj->rtype.pobj_info.anim_angles[mn]); vm_transpose_matrix(&m); vm_vec_rotate(&tpnt,&pnt,&m); vm_vec_add(&pnt,&tpnt,&pm->submodel_offsets[mn]); mn = pm->submodel_parents[mn]; } //now instance for the entire object vm_copy_transpose_matrix(&m,&obj->orient); vm_vec_rotate(gun_point,&pnt,&m); vm_vec_add2(gun_point,&obj->pos); }
// ----------------------------------------------------------------------------- //return the position & orientation of a gun on the control center object void calc_controlcen_gun_point(vms_vector *gun_point,vms_vector *gun_dir,object *obj,int gun_num) { vms_matrix m; Assert(obj->type == OBJ_CNTRLCEN); Assert(obj->render_type==RT_POLYOBJ); Assert(gun_num < N_controlcen_guns); //instance gun position & orientation vm_copy_transpose_matrix(&m,&obj->orient); vm_vec_rotate(gun_point,&controlcen_gun_points[gun_num],&m); vm_vec_add2(gun_point,&obj->pos); vm_vec_rotate(gun_dir,&controlcen_gun_dirs[gun_num],&m); }
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 }
ubyte g3_rotate_faraway_vertex(vertex *dest,vector *src) { Assert( G3_count == 1 ); MONITOR_INC( NumRotations, 1 ); vm_vec_rotate( (vector *)&dest->x, src, &View_matrix ); dest->flags = 0; //not projected return g3_code_vertex(dest); }
// Given a global point and an object, get the quadrant number the point belongs to. int shield_get_quadrant_global(object* objp, vec3d* global_pos) { vec3d tpos; vec3d rotpos; vm_vec_sub(&tpos, global_pos, &objp->pos); vm_vec_rotate(&rotpos, &tpos, &objp->orient); return shield_get_quadrant(&rotpos); }
//rotates a point. returns codes. does not check if already rotated ubyte g3_rotate_point(g3s_point *dest, vms_vector *src) { vms_vector tempv; vm_vec_sub(&tempv, src, &View_position); vm_vec_rotate(&dest->p3_vec, &tempv, &View_matrix); dest->p3_flags = 0; //no projected return g3_code_point(dest); }
//rotates a point. returns codes. does not check if already rotated ubyte g3_rotate_vector(vector *dest,vector *src) { vector tempv; Assert( G3_count == 1 ); MONITOR_INC( NumRotations, 1 ); vm_vec_sub(&tempv,src,&View_position); vm_vec_rotate(dest,&tempv,&View_matrix); return g3_code_vector(dest); }
ubyte g3_rotate_vertex_popped(vertex *dest, const vec3d *src) { vec3d tempv; Assert( G3_count == 1 ); Assert( instance_depth > 0 ); vm_vec_sub(&tempv,src,&instance_stack[0].p); vm_vec_rotate( &dest->world, &tempv, &instance_stack[0].m ); dest->flags = 0; //not projected return g3_code_vertex(dest); }
float dock_calc_max_semilatus_rectum_parallel_to_axis(object *objp, axis_type axis) { Assert(objp != NULL); vec3d local_line_end; vec3d *world_line_start, world_line_end; dock_function_info dfi; // to calculate the semilatus rectum, we need a directrix that will be parallel to the axis // the first endpoint is simply the position of the object world_line_start = &objp->pos; // the second endpoint extends in the axis direction vm_vec_zero(&local_line_end); switch(axis) { case X_AXIS: local_line_end.xyz.x = 1.0f; break; case Y_AXIS: local_line_end.xyz.y = 1.0f; break; case Z_AXIS: local_line_end.xyz.z = 1.0f; break; default: Int3(); return 0.0f; } // rotate and move the endpoint to go through the axis of the actual object vm_vec_rotate(&world_line_end, &local_line_end, &objp->orient); vm_vec_add2(&world_line_end, &objp->pos); // now we have a unit vector starting at the object's position and pointing along the chosen axis // (although the length doesn't matter, as it's calculated as an endless line) // now determine the semilatus rectum // set parameters and call function for the semilatus rectum squared dfi.parameter_variables.vecp_value = world_line_start; dfi.parameter_variables.vecp_value2 = &world_line_end; dock_evaluate_all_docked_objects(objp, &dfi, dock_calc_max_semilatus_rectum_squared_parallel_to_directrix_helper); // the semilatus rectum is the square root of our result return fl_sqrt(dfi.maintained_variables.float_value); }
// Returns which octant point pnt is in. This might return // -1 if the point isn't in any octant. // If model_orient and/or model_pos are NULL, pnt is assumed to already // be rotated into the model's local coordinates. // If oct is not null, it will be filled in with a pointer to the octant // data. Or NULL if the pnt isn't in the octant. int model_which_octant(vec3d* pnt, int model_num, matrix* model_orient, vec3d* model_pos, model_octant** oct) { polymodel* pm; vec3d tempv, rotpnt; pm = model_get(model_num); if (model_orient && model_pos) { // First, rotate pnt into the model's frame of reference. vm_vec_sub(&tempv, pnt, model_pos); vm_vec_rotate(&rotpnt, &tempv, model_orient); } else { rotpnt = *pnt; } vec3d center; vm_vec_avg(¢er, &pm->mins, &pm->maxs); int i, x, y, z; if (rotpnt.xyz.x > center.xyz.x) x = 1; else x = 0; if (rotpnt.xyz.y > center.xyz.y) y = 1; else y = 0; if (rotpnt.xyz.z > center.xyz.z) z = 1; else z = 0; i = (x << 2) | (y << 1) | z; if (point_in_octant(pm, &pm->octants[i], &rotpnt)) { if (oct) *oct = &pm->octants[i]; return i; } if (oct) *oct = NULL; return -1; }
void HudGaugeRadarDradis::drawContact(vec3d *pnt, int idx, int clr_idx, float /*dist*/, float alpha, float scale_factor) { vec3d p; int h, w; vertex vert; float aspect_mp; if ((sub_y_clip && (pnt->xyz.y > 0)) || ((!sub_y_clip) && (pnt->xyz.y <= 0))) return; memset(&vert, 0, sizeof(vert)); vm_vec_rotate(&p, pnt, &vmd_identity_matrix); g3_transfer_vertex(&vert, &p); float sizef = fl_sqrt(vm_vec_dist(&Orb_eye_position, pnt) * 8.0f) * scale_factor; if ( clr_idx >= 0 ) { bm_get_info(clr_idx, &w, &h); if (h == w) { aspect_mp = 1.0f; } else { aspect_mp = (((float) h) / ((float) w)); } //gr_set_bitmap(clr_idx, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha); //g3_draw_polygon(&p, &vmd_identity_matrix, sizef/35.0f, aspect_mp*sizef/35.0f, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); material mat_params; material_set_unlit_color(&mat_params, clr_idx, &Color_bright_white, alpha, true, false); g3_render_rect_oriented(&mat_params, &p, &vmd_identity_matrix, sizef/35.0f, aspect_mp*sizef/35.0f); } if ( idx >= 0 ) { bm_get_info(idx, &w, &h); if (h == w) { aspect_mp = 1.0f; } else { aspect_mp = (((float) h) / ((float) w)); } //gr_set_bitmap(idx, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha); //g3_draw_polygon(&p, &vmd_identity_matrix, sizef/35.0f, aspect_mp*sizef/35.0f, TMAP_FLAG_TEXTURED | TMAP_FLAG_BW_TEXTURE | TMAP_HTL_3D_UNLIT); material mat_params; material_set_unlit_color(&mat_params, idx, &gr_screen.current_color, alpha, true, false); g3_render_rect_oriented(&mat_params, &p, &vmd_identity_matrix, sizef/35.0f, aspect_mp*sizef/35.0f); } }
//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); }
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); }
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) }
// What we're doing here is projecting each object extent onto the directrix, calculating the distance between the // projected point and the origin, and then taking the maximum distance as the semilatus rectum. We're actually // maintaining the square of the distance rather than the actual distance, as it's faster to calculate and it gives // the same result in a greater-than or less-than comparison. When we're done calculating everything for all // objects (i.e. when we return to the parent function) we take the square root of the final value. void dock_calc_max_semilatus_rectum_squared_parallel_to_directrix_helper(object *objp, dock_function_info *infop) { vec3d world_point, local_point[6], nearest; polymodel *pm; int i; float temp, dist_squared; // line parameters vec3d *line_start = infop->parameter_variables.vecp_value; vec3d *line_end = infop->parameter_variables.vecp_value2; // We must find world coordinates for each of the six endpoints on the three axes of the object. I looked up // which axis is front/back, left/right, and up/down, as well as which endpoint is which. It doesn't really // matter, though, as all we need are the distances. // grab our model Assert(objp->type == OBJ_SHIP); pm = model_get(Ship_info[Ships[objp->instance].ship_info_index].model_num); // set up the points we want to check memset(local_point, 0, sizeof(vec3d) * 6); local_point[0].xyz.x = pm->maxs.xyz.x; // right point (max x) local_point[1].xyz.x = pm->mins.xyz.x; // left point (min x) local_point[2].xyz.y = pm->maxs.xyz.y; // top point (max y) local_point[3].xyz.y = pm->mins.xyz.y; // bottom point (min y) local_point[4].xyz.z = pm->maxs.xyz.z; // front point (max z) local_point[5].xyz.z = pm->mins.xyz.z; // rear point (min z) // check points for (i = 0; i < 6; i++) { // calculate position of point vm_vec_rotate(&world_point, &local_point[i], &objp->orient); vm_vec_add2(&world_point, &objp->pos); // find the nearest point along the line vm_vec_dist_squared_to_line(&world_point, line_start, line_end, &nearest, &temp); // find the distance squared between the origin of the line and the point on the line dist_squared = vm_vec_dist_squared(line_start, &nearest); // update with farthest distance squared if (dist_squared > infop->maintained_variables.float_value) infop->maintained_variables.float_value = dist_squared; } }
bool shadows_obj_in_frustum(object *objp, matrix *light_orient, vec3d *min, vec3d *max) { vec3d pos, pos_rot; vm_vec_sub(&pos, &objp->pos, &Eye_position); vm_vec_rotate(&pos_rot, &pos, light_orient); if ( (pos_rot.xyz.x - objp->radius) > max->xyz.x || (pos_rot.xyz.x + objp->radius) < min->xyz.x || (pos_rot.xyz.y - objp->radius) > max->xyz.y || (pos_rot.xyz.y + objp->radius) < min->xyz.y || (pos_rot.xyz.z - objp->radius) > max->xyz.z ) { return false; } return true; }
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; }
// Returns which octant point pnt is closet to. This will always return // a valid octant (0-7) since the point doesn't have to be in an octant. // If model_orient and/or model_pos are NULL, pnt is assumed to already // be rotated into the model's local coordinates. // If oct is not null, it will be filled in with a pointer to the octant // data. int model_which_octant_distant_many(vec3d* pnt, int model_num, matrix* model_orient, vec3d* model_pos, polymodel** pm, int* octs) { vec3d tempv, rotpnt; *pm = model_get(model_num); if (model_orient && model_pos) { // First, rotate pnt into the model's frame of reference. vm_vec_sub(&tempv, pnt, model_pos); vm_vec_rotate(&rotpnt, &tempv, model_orient); } else { rotpnt = *pnt; } vec3d center; vm_vec_avg(¢er, &((*pm)->mins), &((*pm)->maxs)); int i, x, y, z; if (rotpnt.xyz.x > center.xyz.x) x = 1; else x = 0; if (rotpnt.xyz.y > center.xyz.y) y = 1; else y = 0; if (rotpnt.xyz.z > center.xyz.z) z = 1; else z = 0; i = ((x << 2) | (y << 1) | z); octs[0] = i; octs[1] = i ^ 4; // Adjacent octant in x dimension octs[2] = i ^ 2; // Adjacent octant in y dimension octs[3] = i ^ 1; // Adjacent octant in z dimension return i; }
void HudGaugeRadarDradis::drawContact(vec3d *pnt, int idx, int clr_idx, float dist, float alpha, float scale_factor) { vec3d p; int h, w; vertex vert; float aspect_mp; if ((sub_y_clip && (pnt->xyz.y > 0)) || ((!sub_y_clip) && (pnt->xyz.y <= 0))) return; memset(&vert, 0, sizeof(vert)); vm_vec_rotate(&p, pnt, &vmd_identity_matrix); g3_transfer_vertex(&vert, &p); float sizef = fl_sqrt(vm_vec_dist(&Orb_eye_position, pnt) * 8.0f) * scale_factor; if ( clr_idx >= 0 ) { bm_get_info(clr_idx, &w, &h); if (h == w) { aspect_mp = 1.0f; } else { aspect_mp = (((float) h) / ((float) w)); } gr_set_bitmap(clr_idx, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha); g3_draw_polygon(&p, &vmd_identity_matrix, sizef/35.0f, aspect_mp*sizef/35.0f, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT); } if ( idx >= 0 ) { bm_get_info(idx, &w, &h); if (h == w) { aspect_mp = 1.0f; } else { aspect_mp = (((float) h) / ((float) w)); } gr_set_bitmap(idx, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha); g3_draw_polygon(&p, &vmd_identity_matrix, sizef/35.0f, aspect_mp*sizef/35.0f, TMAP_FLAG_TEXTURED | TMAP_FLAG_BW_TEXTURE | TMAP_HTL_3D_UNLIT); } }
void Tactile_apply_force (vms_vector *force_vec,vms_matrix *orient) { int feedforce; fix feedmag,tempfix=0; vms_angvec feedang; vms_vector feedvec; unsigned short tempangle; int realangle; if (TactileStick==TACTILE_IMMERSION) { vm_vec_rotate (&feedvec,force_vec,orient); vm_extract_angles_vector(&feedang,&feedvec); feedmag=vm_vec_mag_quick (force_vec); feedforce=f2i(fixmuldiv (feedmag,i2f(100),MAX_FORCE)); mprintf ((0,"feedforce=%d\n",feedforce)); if (feedforce<0) feedforce=0; if (feedforce>100) feedforce=100; tempangle=(unsigned short)feedang.h; tempfix=tempangle; realangle=f2i(fixmul(tempfix,i2f(360))); realangle-=180; if (realangle<0) realangle+=360; Jolt (feedforce,realangle,feedforce*7); } }
//called for each level to load & setup the exit sequence load_endlevel_data(int level_num) { char filename[13]; char line[LINE_LEN],*p; CFILE *ifile; int var,segnum,sidenum; int exit_side, i; int have_binary = 0; endlevel_data_loaded = 0; //not loaded yet try_again: ; if (level_num<0) //secret level strcpy(filename,Secret_level_names[-level_num-1]); else //normal level strcpy(filename,Level_names[level_num-1]); if (!convert_ext(filename,"END")) return; ifile = cfopen(filename,"rb"); if (!ifile) { convert_ext(filename,"TXB"); ifile = cfopen(filename,"rb"); if (!ifile) if (level_num==1) { return; //abort //Error("Cannot load file text of binary version of <%s>",filename); } else { level_num = 1; goto try_again; } have_binary = 1; } //ok...this parser is pretty simple. It ignores comments, but //everything else must be in the right place var = 0; while (cfgets(line,LINE_LEN,ifile)) { if (have_binary) { for (i = 0; i < strlen(line) - 1; i++) { encode_rotate_left(&(line[i])); line[i] = line[i] ^ BITMAP_TBL_XOR; encode_rotate_left(&(line[i])); } p = line; } if ((p=strchr(line,';'))!=NULL) *p = 0; //cut off comment for (p=line+strlen(line)-1;p>line && isspace(*p);*p--=0); for (p=line;isspace(*p);p++); if (!*p) //empty line continue; switch (var) { case 0: { //ground terrain int iff_error; ubyte pal[768]; if (terrain_bm_instance.bm_data) free(terrain_bm_instance.bm_data); iff_error = iff_read_bitmap(p,&terrain_bm_instance,BM_LINEAR,pal); if (iff_error != IFF_NO_ERROR) { mprintf((1, "File %s - IFF error: %s",p,iff_errormsg(iff_error))); Error("File %s - IFF error: %s",p,iff_errormsg(iff_error)); } terrain_bitmap = &terrain_bm_instance; gr_remap_bitmap_good( terrain_bitmap, pal, iff_transparent_color, -1); break; } case 1: //height map load_terrain(p); break; case 2: sscanf(p,"%d,%d",&exit_point_bmx,&exit_point_bmy); break; case 3: //exit heading exit_angles.h = i2f(atoi(p))/360; break; case 4: { //planet bitmap int iff_error; ubyte pal[768]; if (satellite_bm_instance.bm_data) free(satellite_bm_instance.bm_data); iff_error = iff_read_bitmap(p,&satellite_bm_instance,BM_LINEAR,pal); if (iff_error != IFF_NO_ERROR) { mprintf((1, "File %s - IFF error: %s",p,iff_errormsg(iff_error))); Error("File %s - IFF error: %s",p,iff_errormsg(iff_error)); } satellite_bitmap = &satellite_bm_instance; gr_remap_bitmap_good( satellite_bitmap, pal, iff_transparent_color, -1); break; } case 5: //earth pos case 7: { //station pos vms_matrix tm; vms_angvec ta; int pitch,head; sscanf(p,"%d,%d",&head,&pitch); ta.h = i2f(head)/360; ta.p = -i2f(pitch)/360; ta.b = 0; vm_angles_2_matrix(&tm,&ta); if (var==5) satellite_pos = tm.fvec; //vm_vec_copy_scale(&satellite_pos,&tm.fvec,SATELLITE_DIST); else station_pos = tm.fvec; break; } case 6: //planet size satellite_size = i2f(atoi(p)); break; } var++; } Assert(var == NUM_VARS); // OK, now the data is loaded. Initialize everything //find the exit sequence by searching all segments for a side with //children == -2 for (segnum=0,exit_segnum=-1;exit_segnum==-1 && segnum<=Highest_segment_index;segnum++) for (sidenum=0;sidenum<6;sidenum++) if (Segments[segnum].children[sidenum] == -2) { exit_segnum = segnum; exit_side = sidenum; break; } Assert(exit_segnum!=-1); compute_segment_center(&mine_exit_point,&Segments[exit_segnum]); extract_orient_from_segment(&mine_exit_orient,&Segments[exit_segnum]); compute_center_point_on_side(&mine_side_exit_point,&Segments[exit_segnum],exit_side); vm_vec_scale_add(&mine_ground_exit_point,&mine_exit_point,&mine_exit_orient.uvec,-i2f(20)); //compute orientation of surface { vms_vector tv; vms_matrix exit_orient,tm; vm_angles_2_matrix(&exit_orient,&exit_angles); vm_transpose_matrix(&exit_orient); vm_matrix_x_matrix(&surface_orient,&mine_exit_orient,&exit_orient); vm_copy_transpose_matrix(&tm,&surface_orient); vm_vec_rotate(&tv,&station_pos,&tm); vm_vec_scale_add(&station_pos,&mine_exit_point,&tv,STATION_DIST); vm_vec_rotate(&tv,&satellite_pos,&tm); vm_vec_scale_add(&satellite_pos,&mine_exit_point,&tv,SATELLITE_DIST); vm_vector_2_matrix(&tm,&tv,&surface_orient.uvec,NULL); vm_vec_copy_scale(&satellite_upvec,&tm.uvec,SATELLITE_HEIGHT); } cfclose(ifile); endlevel_data_loaded = 1; }
int _do_slew_movement(object *obj, int check_keys, int check_joy ) { int moved = 0; vms_vector svel, movement; //scaled velocity (per this frame) vms_matrix rotmat,new_pm; int joy_x,joy_y,btns; int joyx_moved,joyy_moved; vms_angvec rotang; if (keyd_pressed[KEY_PAD5]) vm_vec_zero(&obj->phys_info.velocity); if (check_keys) { obj->phys_info.velocity.x += VEL_SPEED * (key_down_time(KEY_PAD9) - key_down_time(KEY_PAD7)); obj->phys_info.velocity.y += VEL_SPEED * (key_down_time(KEY_PADMINUS) - key_down_time(KEY_PADPLUS)); obj->phys_info.velocity.z += VEL_SPEED * (key_down_time(KEY_PAD8) - key_down_time(KEY_PAD2)); rotang.pitch = (key_down_time(KEY_LBRACKET) - key_down_time(KEY_RBRACKET))/ROT_SPEED; rotang.bank = (key_down_time(KEY_PAD1) - key_down_time(KEY_PAD3))/ROT_SPEED; rotang.head = (key_down_time(KEY_PAD6) - key_down_time(KEY_PAD4))/ROT_SPEED; } else rotang.pitch = rotang.bank = rotang.head = 0; //check for joystick movement if (check_joy && joy_present) { joy_get_pos(&joy_x,&joy_y); btns=joy_get_btns(); joyx_moved = (abs(joy_x - old_joy_x)>JOY_NULL); joyy_moved = (abs(joy_y - old_joy_y)>JOY_NULL); if (abs(joy_x) < JOY_NULL) joy_x = 0; if (abs(joy_y) < JOY_NULL) joy_y = 0; if (btns) if (!rotang.pitch) rotang.pitch = fixmul(-joy_y * 512,FrameTime); else; else if (joyy_moved) obj->phys_info.velocity.z = -joy_y * 8192; if (!rotang.head) rotang.head = fixmul(joy_x * 512,FrameTime); if (joyx_moved) old_joy_x = joy_x; if (joyy_moved) old_joy_y = joy_y; } moved = rotang.pitch | rotang.bank | rotang.head; vm_angles_2_matrix(&rotmat,&rotang); vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat); obj->orient = new_pm; vm_transpose_matrix(&new_pm); //make those columns rows moved |= obj->phys_info.velocity.x | obj->phys_info.velocity.y | obj->phys_info.velocity.z; svel = obj->phys_info.velocity; vm_vec_scale(&svel,FrameTime); //movement in this frame vm_vec_rotate(&movement,&svel,&new_pm); vm_vec_add2(&obj->pos,&movement); moved |= (movement.x || movement.y || movement.z); return moved; }
vms_vector *g3_rotate_delta_vec(vms_vector *dest,const vms_vector *src) { return vm_vec_rotate(dest,src,&View_matrix); }
void radar_plot_object( object *objp ) { vector pos, tempv; float dist, rscale, zdist, max_radar_dist; int xpos, ypos, color=0; vector *world_pos = &objp->pos; float awacs_level; // don't process anything here. Somehow, a jumpnode object caused this function // to get entered on server side. if( Game_mode & GM_STANDALONE_SERVER ){ return; } // multiplayer clients ingame joining should skip this function if ( MULTIPLAYER_CLIENT && (Net_player->flags & NETINFO_FLAG_INGAME_JOIN) ){ return; } // get team-wide awacs level for the object if not ship int ship_is_visible = 0; if (objp->type == OBJ_SHIP) { if (Player_ship != NULL) { if (ship_is_visible_by_team(objp->instance, Player_ship->team)) { ship_is_visible = 1; } } } // only check awacs level if ship is not visible by team awacs_level = 1.5f; if (Player_ship != NULL && !ship_is_visible) { awacs_level = awacs_get_level(objp, Player_ship); } // if the awacs level is unviewable - bail if(awacs_level < 0.0f && !See_all){ return; } // Apply object type filters switch ( objp->type ) { case OBJ_SHIP: // Place to cull ships, such as NavBuoys break; case OBJ_JUMP_NODE: // filter jump nodes here if required break; case OBJ_WEAPON: { // if not a bomb, return if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_BOMB) ) { return; } // if bomb is on same team as player, return if ( (obj_team(objp) == Player_ship->team) && (Player_ship->team != TEAM_TRAITOR) ) { return; } break; } default: return; // if any other kind of object, don't want to show on radar break; } // end switch // JAS -- new way of getting the rotated point that doesn't require this to be // in a g3_start_frame/end_frame block. vm_vec_sub(&tempv,world_pos,&Player_obj->pos); vm_vec_rotate( &pos, &tempv, &Player_obj->orient ); // Apply range filter dist = vm_vec_dist(world_pos, &Player_obj->pos); max_radar_dist = Radar_ranges[HUD_config.rp_dist]; if ( dist > max_radar_dist ){ return; } if ( dist < pos.xyz.z ) { rscale = 0.0f; } else { rscale = (float) acos( pos.xyz.z/dist ) / 3.14159f; //2.0f; } zdist = fl_sqrt( (pos.xyz.x*pos.xyz.x)+(pos.xyz.y*pos.xyz.y) ); float new_x_dist, clipped_x_dist; float new_y_dist, clipped_y_dist; if (zdist < 0.01f ) { new_x_dist = 0.0f; new_y_dist = 0.0f; } else { new_x_dist = (pos.xyz.x/zdist) * rscale * radx; new_y_dist = (pos.xyz.y/zdist) * rscale * rady; // force new_x_dist and new_y_dist to be inside the radar float hypotenuse; float max_radius; hypotenuse = (float)_hypot(new_x_dist, new_y_dist); max_radius = i2fl(Radar_radius[gr_screen.res][0] - 5); if (hypotenuse >= (max_radius) ) { clipped_x_dist = max_radius * (new_x_dist / hypotenuse); clipped_y_dist = max_radius * (new_y_dist / hypotenuse); new_x_dist = clipped_x_dist; new_y_dist = clipped_y_dist; } } xpos = fl2i( Radar_center[gr_screen.res][0] + new_x_dist ); ypos = fl2i( Radar_center[gr_screen.res][1] - new_y_dist ); color = radar_blip_color(objp); // Determine the distance at which we will dim the radar blip if ( timestamp_elapsed(Radar_calc_dim_dist_timer) ) { Radar_calc_dim_dist_timer=timestamp(1000); Radar_dim_range = player_farthest_weapon_range(); if ( Radar_dim_range <= 0 ) { Radar_dim_range=1500.0f; } } blip *b; int blip_dim=0; if ( dist > Radar_dim_range ) { blip_dim=1; } if ( N_blips >= MAX_BLIPS ) { // out of blips, don't plot Int3(); return; } b = &Blips[N_blips]; b->flags=0; // flag the blip as a current target if it is if (OBJ_INDEX(objp) == Player_ai->target_objnum) { b->flags |= BLIP_CURRENT_TARGET; blip_dim = 0; } if ( blip_dim ) { list_append( &Blip_dim_list[color], b ); } else { list_append( &Blip_bright_list[color], b ); } b->x = xpos; b->y = ypos; // see if blip should be drawn distorted if (objp->type == OBJ_SHIP) { // ships specifically hidden from sensors if ( Ships[objp->instance].flags & SF_HIDDEN_FROM_SENSORS ) { b->flags |= BLIP_DRAW_DISTORTED; } // determine if its AWACS distorted if ( awacs_level < 1.0f ){ b->flags |= BLIP_DRAW_DISTORTED; } } N_blips++; }