matrix shadows_start_render(matrix *eye_orient, vec3d *eye_pos, float fov, float aspect, float veryneardist, float neardist, float middist, float fardist) { if(Static_light.empty()) return vmd_identity_matrix; light *lp = *(Static_light.begin()); if ( lp == NULL ) { return vmd_identity_matrix; } vec3d light_dir; matrix light_matrix; vm_vec_copy_normalize(&light_dir, &lp->vec); vm_vector_2_matrix(&light_matrix, &light_dir, &eye_orient->vec.uvec, NULL); shadows_construct_light_frustum(&Shadow_frustums[0], &light_matrix, eye_orient, eye_pos, fov, aspect, 0.0f, veryneardist); shadows_construct_light_frustum(&Shadow_frustums[1], &light_matrix, eye_orient, eye_pos, fov, aspect, veryneardist - (veryneardist - 0.0f)* 0.2f, neardist); shadows_construct_light_frustum(&Shadow_frustums[2], &light_matrix, eye_orient, eye_pos, fov, aspect, neardist - (neardist - veryneardist) * 0.2f, middist); shadows_construct_light_frustum(&Shadow_frustums[3], &light_matrix, eye_orient, eye_pos, fov, aspect, middist - (middist - neardist) * 0.2f, fardist); Shadow_cascade_distances[0] = veryneardist; Shadow_cascade_distances[1] = neardist; Shadow_cascade_distances[2] = middist; Shadow_cascade_distances[3] = fardist; Shadow_proj_matrix[0] = Shadow_frustums[0].proj_matrix; Shadow_proj_matrix[1] = Shadow_frustums[1].proj_matrix; Shadow_proj_matrix[2] = Shadow_frustums[2].proj_matrix; Shadow_proj_matrix[3] = Shadow_frustums[3].proj_matrix; gr_shadow_map_start(&Shadow_view_matrix, &light_matrix); return light_matrix; }
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); } }
// Create a grid // *forward is vector pointing forward // *right is vector pointing right // *center is center point of grid // length is length of grid // width is width of grid // square_size is size of a grid square // For example: // *forward = (0.0, 0.0, 1.0) // *right = (1.0, 0.0, 0.0) // *center = (0.0, 0.0, 0.0) // nrows = 10 // ncols = 50.0 // square_size = 10.0 // will generate a grid of squares 10 long by 5 wide. // Each grid square will be 10.0 x 10.0 units. // The center of the grid will be at the global origin. // The grid will be parallel to the xz plane (because the normal is 0,1,0). // (In fact, it will be the xz plane because it is centered on the origin.) // // Stuffs grid in *gridp. If gridp == NULL, mallocs and returns a grid. grid *create_grid(grid *gridp, vector *forward, vector *right, vector *center, int nrows, int ncols, float square_size) { int i, ncols2, nrows2, d = 1; vector dfvec, drvec, cur, cur2, tvec, uvec, save, save2; Assert(square_size > 0.0); if (double_fine_gridlines) d = 2; if (gridp == NULL) gridp = (grid *) malloc(sizeof(grid)); Assert(gridp); gridp->center = *center; gridp->square_size = square_size; // Create the plane equation. Assert(!IS_VEC_NULL(forward)); Assert(!IS_VEC_NULL(right)); vm_vec_copy_normalize(&dfvec, forward); vm_vec_copy_normalize(&drvec, right); vm_vec_cross(&uvec, &dfvec, &drvec); Assert(!IS_VEC_NULL(&uvec)); gridp->gmatrix.v.uvec = uvec; gridp->planeD = -(center->xyz.x * uvec.xyz.x + center->xyz.y * uvec.xyz.y + center->xyz.z * uvec.xyz.z); Assert(!_isnan(gridp->planeD)); gridp->gmatrix.v.fvec = dfvec; gridp->gmatrix.v.rvec = drvec; vm_vec_scale(&dfvec, square_size); vm_vec_scale(&drvec, square_size); vm_vec_scale_add(&cur, center, &dfvec, (float) -nrows * d / 2); vm_vec_scale_add2(&cur, &drvec, (float) -ncols * d / 2); vm_vec_scale_add(&cur2, center, &dfvec, (float) -nrows * 5 / 2); vm_vec_scale_add2(&cur2, &drvec, (float) -ncols * 5 / 2); save = cur; save2 = cur2; gridp->ncols = ncols; gridp->nrows = nrows; ncols2 = ncols / 2; nrows2 = nrows / 2; Assert(ncols < MAX_GRIDLINE_POINTS && nrows < MAX_GRIDLINE_POINTS); // Create the points along the edges of the grid, so we can just draw lines // between them to form the grid. for (i=0; i<=ncols*d; i++) { gridp->gpoints1[i] = cur; // small, dark gridline points vm_vec_scale_add(&tvec, &cur, &dfvec, (float) nrows * d); gridp->gpoints2[i] = tvec; vm_vec_add2(&cur, &drvec); } for (i=0; i<=ncols2; i++) { gridp->gpoints5[i] = cur2; // large, brighter gridline points vm_vec_scale_add(&tvec, &cur2, &dfvec, (float) nrows2 * 10); gridp->gpoints6[i] = tvec; vm_vec_scale_add2(&cur2, &drvec, 10.0f); } cur = save; cur2 = save2; for (i=0; i<=nrows*d; i++) { gridp->gpoints3[i] = cur; // small, dark gridline points vm_vec_scale_add(&tvec, &cur, &drvec, (float) ncols * d); gridp->gpoints4[i] = tvec; vm_vec_add2(&cur, &dfvec); } for (i=0; i<=nrows2; i++) { gridp->gpoints7[i] = cur2; // large, brighter gridline points vm_vec_scale_add(&tvec, &cur2, &drvec, (float) ncols2 * 10); gridp->gpoints8[i] = tvec; vm_vec_scale_add2(&cur2, &dfvec, 10.0f); } return gridp; }
//compute the corners of a rod. fills in vertbuf. static int calc_rod_corners(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width) { vms_vector delta_vec,top,tempv,rod_norm; ubyte codes_and; int i; //compute vector from one point to other, do cross product with vector //from eye to get perpendiclar vm_vec_sub(&delta_vec,&bot_point->p3_vec,&top_point->p3_vec); //unscale for aspect delta_vec.x = fixdiv(delta_vec.x,Matrix_scale.x); delta_vec.y = fixdiv(delta_vec.y,Matrix_scale.y); //calc perp vector //do lots of normalizing to prevent overflowing. When this code works, //it should be optimized vm_vec_normalize(&delta_vec); vm_vec_copy_normalize(&top,&top_point->p3_vec); vm_vec_cross(&rod_norm,&delta_vec,&top); vm_vec_normalize(&rod_norm); //scale for aspect rod_norm.x = fixmul(rod_norm.x,Matrix_scale.x); rod_norm.y = fixmul(rod_norm.y,Matrix_scale.y); //now we have the usable edge. generate four points //top points vm_vec_copy_scale(&tempv,&rod_norm,top_width); tempv.z = 0; vm_vec_add(&rod_points[0].p3_vec,&top_point->p3_vec,&tempv); vm_vec_sub(&rod_points[1].p3_vec,&top_point->p3_vec,&tempv); vm_vec_copy_scale(&tempv,&rod_norm,bot_width); tempv.z = 0; vm_vec_sub(&rod_points[2].p3_vec,&bot_point->p3_vec,&tempv); vm_vec_add(&rod_points[3].p3_vec,&bot_point->p3_vec,&tempv); //now code the four points for (i=0,codes_and=0xff;i<4;i++) codes_and &= g3_code_point(&rod_points[i]); if (codes_and) return 1; //1 means off screen //clear flags for new points (not projected) for (i=0;i<4;i++) rod_points[i].p3_flags = 0; return 0; }