void update_drop_camera (camera *raw) { entity *en; vec3d pos, v; // // pre-amble // ASSERT (raw); ASSERT (raw->external_view_entity); en = raw->external_view_entity; // // get camera to entity vector // get_local_entity_target_point (en, &pos); v.x = pos.x - raw->position.x; v.y = pos.y - raw->position.y; v.z = pos.z - raw->position.z; // // prevent divide by zero // if (get_3d_vector_magnitude (&v) < 0.001) { v.x = 0.0; v.y = 0.0; v.z = 1.0; } // // get camera attitude // normalise_3d_vector (&v); get_matrix3x3_from_unit_vec3d (raw->attitude, &v); }
void reset_static_camera (camera *raw) { entity *en; vec3d pos, v; matrix3x3 m; float heading, z_min, z_max, radius, length; int fast_airborne; ASSERT (raw); ASSERT (raw->external_view_entity); en = raw->external_view_entity; z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE); z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE); ASSERT (z_min < z_max); radius = -(((z_max - z_min) * CHASE_CAMERA_RESET_ZOOM * CHASE_CAMERA_RESET_ZOOM) + z_min); fast_airborne = FALSE; if (get_local_entity_int_value (en, INT_TYPE_AIRBORNE_AIRCRAFT)) { if (get_local_entity_vec3d_magnitude (en, VEC3D_TYPE_MOTION_VECTOR) >= knots_to_metres_per_second (10.0)) { fast_airborne = TRUE; } } if (fast_airborne) { get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &v); normalise_3d_vector (&v); v.x *= radius; v.y *= radius; v.z *= radius; } else { heading = get_local_entity_float_value (en, FLOAT_TYPE_HEADING); get_3d_transformation_matrix (m, heading, CHASE_CAMERA_RESET_PITCH, 0.0); v.x = 0.0; v.y = 0.0; v.z = radius; multiply_matrix3x3_vec3d (&v, m, &v); } get_local_entity_target_point (en, &pos); raw->position.x = pos.x + v.x; raw->position.y = pos.y + v.y; raw->position.z = pos.z + v.z; // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + CAMERA_MIN_HEIGHT_ABOVE_GROUND); } // // attitude // v.x = pos.x - raw->position.x; v.y = pos.y - raw->position.y; v.z = pos.z - raw->position.z; length = (v.x * v.x) + (v.y * v.y) + (v.z * v.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&v, length); get_matrix3x3_from_unit_vec3d (raw->attitude, &v); } else { get_identity_matrix3x3 (raw->attitude); } // // motion vector // raw->motion_vector.x = 0.0; raw->motion_vector.y = 0.0; raw->motion_vector.z = 0.0; }
void scan_3d_clouds ( void ) { int visual_sector_x, visual_sector_z, current_sector_x, current_sector_z, minimum_sector_x, minimum_sector_z, maximum_sector_x, maximum_sector_z; float initial_sector_x_offset, initial_sector_z_offset, current_sector_x_offset, current_sector_z_offset; weathermodes current_weathermode, target_weathermode; matrix3x3 cloud_matrix; // // Get the vector pointing to the colour blend // get_3d_transformation_matrix ( cloud_matrix, active_3d_environment->cloud_light.heading, active_3d_environment->cloud_light.pitch, 0 ); cloud_colour_blend_vector.x = cloud_matrix[2][0]; cloud_colour_blend_vector.y = 0; cloud_colour_blend_vector.z = cloud_matrix[2][2]; normalise_3d_vector ( &cloud_colour_blend_vector ); // // Adjust the cloud blend factor // if ( ( visual_3d_vp->y > ( cloud_3d_base_height - 100 ) ) && ( visual_3d_vp->y < ( cloud_3d_base_height + 100 ) ) ) { float blend; blend = ( ( fabs ( visual_3d_vp->y - cloud_3d_base_height ) ) / 100 ); if ( blend > 1 ) { blend = 1; } cloud_3d_adjusted_blend_factor = cloud_3d_blend_factor * blend; } else { cloud_3d_adjusted_blend_factor = cloud_3d_blend_factor; } // // Choose the two textures to be blending inbetween // current_weathermode = get_3d_weathermode ( active_3d_environment ); target_weathermode = get_3d_target_weathermode ( active_3d_environment ); if ( !cloud_textures[current_weathermode].valid ) { debug_fatal ( "Unable to draw clouds - no texture set for current weathermode: %d", current_weathermode ); } if ( !cloud_textures[target_weathermode].texture_index ) { debug_fatal ( "Unable to draw clouds - no texture set for target weathermode: %d", target_weathermode ); } cloud_weather_blend_factor = get_3d_target_weathermode_transitional_status ( active_3d_environment ); cloud_weather_one_minus_blend_factor = 1.0 - cloud_weather_blend_factor; if ( current_weathermode != target_weathermode ) { if ( cloud_weather_blend_factor == 1 ) { current_weather_texture = system_textures[ cloud_textures[target_weathermode].texture_index ]; target_weather_texture = NULL; cloud_weather_blend_factor = 0; cloud_weather_one_minus_blend_factor = 1.0; } else if ( cloud_weather_blend_factor == 0 ) { current_weather_texture = system_textures[ cloud_textures[current_weathermode].texture_index ]; target_weather_texture = NULL; cloud_weather_blend_factor = 0; cloud_weather_one_minus_blend_factor = 1.0; } else { current_weather_texture = system_textures[ cloud_textures[current_weathermode].texture_index ]; target_weather_texture = system_textures[ cloud_textures[target_weathermode].texture_index ]; } } else { current_weather_texture = system_textures[ cloud_textures[current_weathermode].texture_index ]; target_weather_texture = NULL; cloud_weather_blend_factor = 0; cloud_weather_one_minus_blend_factor = 1.0; } // // Now bias the blend factors, to take into account the transparency of each texture // cloud_weather_one_minus_blend_factor *= active_3d_environment->cloud_light.light_colour.alpha; cloud_weather_blend_factor *= active_3d_environment->cloud_light.light_colour.alpha; // // Get the sector the visual_3d_vp is currently in // get_cloud_3d_sector ( visual_3d_vp->x, visual_3d_vp->z, &visual_sector_x, &visual_sector_z ); minimum_sector_x = visual_sector_x - cloud_3d_sector_scan_radius; minimum_sector_z = visual_sector_z - cloud_3d_sector_scan_radius; maximum_sector_x = visual_sector_x + cloud_3d_sector_scan_radius; maximum_sector_z = visual_sector_z + cloud_3d_sector_scan_radius; initial_sector_x_offset = minimum_sector_x * CLOUD_3D_SECTOR_SIDE_LENGTH; initial_sector_z_offset = minimum_sector_z * CLOUD_3D_SECTOR_SIDE_LENGTH; current_sector_z_offset = initial_sector_z_offset; for ( current_sector_z = minimum_sector_z; current_sector_z < maximum_sector_z; current_sector_z++ ) { current_sector_x_offset = initial_sector_x_offset; for ( current_sector_x = minimum_sector_x; current_sector_x < maximum_sector_x; current_sector_x++ ) { vec3d sector_centre, sector_relative_centre; scene_slot_drawing_list *sorting_slot; sector_centre.x = current_sector_x_offset + ( CLOUD_3D_SECTOR_SIDE_LENGTH / 2 ); sector_centre.y = cloud_3d_base_height; sector_centre.z = current_sector_z_offset + ( CLOUD_3D_SECTOR_SIDE_LENGTH / 2 ); sector_relative_centre.z = ( ( sector_centre.x - visual_3d_vp->x ) * visual_3d_vp->zv.x + ( sector_centre.y - visual_3d_vp->y ) * visual_3d_vp->zv.y + ( sector_centre.z - visual_3d_vp->z ) * visual_3d_vp->zv.z ); if ( ( sector_relative_centre.z + ( CLOUD_3D_SECTOR_SIDE_LENGTH * 1.4142 ) ) < clip_hither ) { // // Cloud sector is totally behind the view // } else { unsigned int outcode, outcode1, outcode2; float x_minimum_offset, x_maximum_offset, z_minimum_offset, z_maximum_offset; x_minimum_offset = current_sector_x_offset; x_maximum_offset = current_sector_x_offset + CLOUD_3D_SECTOR_SIDE_LENGTH; z_minimum_offset = current_sector_z_offset; z_maximum_offset = current_sector_z_offset + CLOUD_3D_SECTOR_SIDE_LENGTH; outcode = get_3d_point_outcodes ( x_minimum_offset, cloud_3d_base_height, z_minimum_offset ); outcode1 = outcode; outcode2 = outcode; outcode = get_3d_point_outcodes ( x_minimum_offset, cloud_3d_base_height, z_maximum_offset ); outcode1 |= outcode; outcode2 &= outcode; outcode = get_3d_point_outcodes ( x_maximum_offset, cloud_3d_base_height, z_minimum_offset ); outcode1 |= outcode; outcode2 &= outcode; outcode = get_3d_point_outcodes ( x_maximum_offset, cloud_3d_base_height, z_maximum_offset ); outcode1 |= outcode; outcode2 &= outcode; // if ( outcode2 == 0 ) { sorting_slot = get_3d_scene_slot (); if ( sorting_slot ) { sorting_slot->type = OBJECT_3D_DRAW_TYPE_CLOUD_SECTOR; // // Use the integer representation of the float value // sector_relative_centre.z += 32768; sorting_slot->z = *( ( int * ) §or_relative_centre.z ); sorting_slot->cloud_sector.x = current_sector_x; sorting_slot->cloud_sector.z = current_sector_z; insert_middle_scene_slot_into_3d_scene ( sorting_slot ); } else { debug_log ( "Run out of object slots!" ); } } } current_sector_x_offset += CLOUD_3D_SECTOR_SIDE_LENGTH; } current_sector_z_offset += CLOUD_3D_SECTOR_SIDE_LENGTH; } }
int check_position_line_of_sight (entity *source, entity *target, vec3d *source_position, vec3d *target_position, mobile_los_check_criteria criteria) { entity *collision_en; vec3d increment, collision_point, normal, #if LINE_DEBUG_MODULE old_position, #endif check_position, direction; float target_range, collision_distance, number_of_terrain_checks, terrain_elevation; terrain_3d_point_data terrain_info; ASSERT (source); ASSERT (target); ASSERT (source_position); ASSERT (target_position); direction.x = target_position->x - source_position->x; direction.y = target_position->y - source_position->y; direction.z = target_position->z - source_position->z; target_range = sqrt ((direction.x * direction.x) + (direction.z * direction.z)); normalise_3d_vector (&direction); //////////////////////////////////////////////////////////////// // COARSE line of sight check with terrain //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_COURSE_TERRAIN) { number_of_terrain_checks = target_range / LOS_COARSE_CHECK_DISTANCE; increment.x = direction.x * LOS_COARSE_CHECK_DISTANCE; increment.y = direction.y * LOS_COARSE_CHECK_DISTANCE; increment.z = direction.z * LOS_COARSE_CHECK_DISTANCE; check_position = *source_position; memset (&terrain_info, 0, sizeof (terrain_3d_point_data)); while (number_of_terrain_checks > 1.0) { #if LINE_DEBUG_MODULE old_position = check_position; #endif check_position.x += increment.x; check_position.y += increment.y; check_position.z += increment.z; get_3d_terrain_point_data (check_position.x, check_position.z, &terrain_info); terrain_elevation = get_3d_terrain_point_data_elevation (&terrain_info); if (terrain_elevation > check_position.y) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed COURSE terrain LOS", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME)); #endif return FALSE; } #if LINE_DEBUG_MODULE create_debug_3d_line (&old_position, &check_position, sys_col_yellow, 10.0); #endif number_of_terrain_checks --; } } //////////////////////////////////////////////////////////////// // SOURCE END FINE line of sight check with terrain //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_SOURCE_END_TERRAIN) { number_of_terrain_checks = target_range / LOS_FINE_CHECK_DISTANCE_SOURCE_END; number_of_terrain_checks = min (number_of_terrain_checks, LOS_NUMBER_OF_FINE_CHECKS_SOURCE_END); increment.x = direction.x * LOS_FINE_CHECK_DISTANCE_SOURCE_END; increment.y = direction.y * LOS_FINE_CHECK_DISTANCE_SOURCE_END; increment.z = direction.z * LOS_FINE_CHECK_DISTANCE_SOURCE_END; check_position = *source_position; while (number_of_terrain_checks > 1.0) { #if LINE_DEBUG_MODULE old_position = check_position; #endif check_position.x += increment.x; check_position.y += increment.y; check_position.z += increment.z; get_3d_terrain_point_data (check_position.x, check_position.z, &terrain_info); terrain_elevation = get_3d_terrain_point_data_elevation (&terrain_info); if (terrain_elevation > check_position.y) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed FINE terrain LOS (source end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME)); #endif return FALSE; } #if LINE_DEBUG_MODULE create_debug_3d_line (&old_position, &check_position, sys_col_yellow, 10.0); #endif number_of_terrain_checks --; } } //////////////////////////////////////////////////////////////// // TARGET END FINE line of sight check with terrain //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_TARGET_END_TERRAIN) { number_of_terrain_checks = target_range / LOS_FINE_CHECK_DISTANCE_TARGET_END; number_of_terrain_checks = min (number_of_terrain_checks, LOS_NUMBER_OF_FINE_CHECKS_TARGET_END); increment.x = direction.x * LOS_FINE_CHECK_DISTANCE_TARGET_END; increment.y = direction.y * LOS_FINE_CHECK_DISTANCE_TARGET_END; increment.z = direction.z * LOS_FINE_CHECK_DISTANCE_TARGET_END; check_position = *target_position; while (number_of_terrain_checks > 1.0) { #if LINE_DEBUG_MODULE old_position = check_position; #endif check_position.x -= increment.x; check_position.y -= increment.y; check_position.z -= increment.z; get_3d_terrain_point_data (check_position.x, check_position.z, &terrain_info); terrain_elevation = get_3d_terrain_point_data_elevation (&terrain_info); if (terrain_elevation > check_position.y) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed FINE terrain LOS (target end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME)); #endif return FALSE; } #if LINE_DEBUG_MODULE create_debug_3d_line (&old_position, &check_position, sys_col_yellow, 10.0); #endif number_of_terrain_checks --; } } //////////////////////////////////////////////////////////////// // SOURCE END line of sight check with objects //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_SOURCE_END_OBJECTS) { check_position.x = source_position->x + (direction.x * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.y = source_position->y + (direction.y * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.z = source_position->z + (direction.z * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); collision_en = get_line_of_sight_collision_entity ( source, target, source_position, &check_position, &collision_point, &normal ); if (collision_en) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed OBJECT LOS with %s (source end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_type_name (collision_en)); #endif return FALSE; } } //////////////////////////////////////////////////////////////// // TARGET END line of sight check with objects //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_TARGET_END_OBJECTS) { check_position.x = target_position->x - (direction.x * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.y = target_position->y - (direction.y * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.z = target_position->z - (direction.z * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); collision_en = get_line_of_sight_collision_entity ( source, target, target_position, &check_position, &collision_point, &normal ); if (collision_en) { collision_distance = get_sqr_3d_range (&collision_point, target_position); if (collision_distance > (LOS_OBJECT_EXCLUDE_DISTANCE_TARGET_END * LOS_OBJECT_EXCLUDE_DISTANCE_TARGET_END)) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed OBJECT LOS with %s (target end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_type_name (collision_en)); #endif return FALSE; } } } return TRUE; }
void set_reverse_tactical_camera_values (entity *source, entity *target) { camera *raw; int airborne; object_3d_index_numbers object_3d_index; object_3d_bounds *bounding_box; float length, radius, z_min, z_max, rad_alt, dx, dy, dz; vec3d source_position, target_position, direction; ASSERT (source); ASSERT (target); ASSERT (get_camera_entity ()); raw = get_local_entity_data (get_camera_entity ()); // // get camera position // if (get_local_entity_int_value (target, INT_TYPE_IDENTIFY_FIXED)) { object_3d_index = get_local_entity_int_value (target, INT_TYPE_OBJECT_3D_SHAPE); bounding_box = get_object_3d_bounding_box (object_3d_index); dx = bounding_box->xmax - bounding_box->xmin; dy = bounding_box->ymax; dz = bounding_box->zmax - bounding_box->zmin; radius = sqrt ((dx * dx) + (dy * dy) + (dz * dz)) * 2.0; } else { z_min = get_local_entity_float_value (target, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE); z_max = get_local_entity_float_value (target, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE); ASSERT (z_min < z_max); radius = ((z_max - z_min) * 0.05) + z_min; } get_local_entity_target_point (source, &source_position); get_local_entity_target_point (target, &target_position); airborne = FALSE; if (get_local_entity_int_value (target, INT_TYPE_AIRBORNE_AIRCRAFT)) { if (point_inside_map_area (&target_position)) { rad_alt = max (target_position.y - get_3d_terrain_elevation (target_position.x, target_position.z), 0.0); if (rad_alt > z_min) { airborne = TRUE; } } } if (airborne) { direction.x = target_position.x - source_position.x; direction.y = target_position.y - source_position.y; direction.z = target_position.z - source_position.z; length = (direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&direction, length); } else { direction.x = 0.0; direction.y = 0.0; direction.z = -1.0; } } else { direction.x = target_position.x - source_position.x; direction.y = 0.0; direction.z = target_position.z - source_position.z; length = (direction.x * direction.x) + (direction.z * direction.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&direction, length); } else { direction.x = 0.0; direction.z = -1.0; } direction.y = 0.5; normalise_3d_vector (&direction); } raw->position.x = target_position.x + (direction.x * radius); raw->position.y = target_position.y + (direction.y * radius); raw->position.z = target_position.z + (direction.z * radius); // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + CAMERA_MIN_HEIGHT_ABOVE_GROUND); } // // get camera attitude // direction.x = target_position.x - raw->position.x; direction.y = target_position.y - raw->position.y; direction.z = target_position.z - raw->position.z; length = (direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&direction, length); get_matrix3x3_from_unit_vec3d (raw->attitude, &direction); } else { get_identity_matrix3x3 (raw->attitude); } // // motion vector // get_local_entity_vec3d (target, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector); }
void ship_vehicle_movement (entity *en) { ship_vehicle *raw; entity *guide, *current_waypoint; vec3d wp_pos, wp_vec, new_pos; float roll, pitch, heading, sqr_range, turn_rate, required_heading, delta_heading, current_velocity, new_velocity; raw = get_local_entity_data (en); // // abort if mobile is not moving (i.e. landed, or dead) // if (!get_local_entity_int_value (en, INT_TYPE_MOBILE_MOVING)) { return; } // // abort if the mobile has no PRIMARY guide (also stops ships from moving if just engaging) // guide = get_local_entity_primary_guide (en); if (!guide) { return; } current_waypoint = get_local_entity_parent (guide, LIST_TYPE_CURRENT_WAYPOINT); ASSERT (current_waypoint); current_velocity = raw->vh.mob.velocity; // // GET WAYPOINT POSITION // ship_movement_get_waypoint_position (en, &wp_pos); wp_vec.x = wp_pos.x - raw->vh.mob.position.x; wp_vec.y = 0; wp_vec.z = wp_pos.z - raw->vh.mob.position.z; sqr_range = ((wp_vec.x * wp_vec.x) + (wp_vec.z * wp_vec.z)); #if DEBUG_MODULE create_vectored_debug_3d_object (&wp_pos, (vec3d *) &raw->vh.mob.attitude [1], OBJECT_3D_RED_ARROW, 0, 0.20); #endif // ???? if (fabs (sqr_range) < 1 * CENTIMETRE) { wp_vec.z = 0; wp_vec.y = 0; wp_vec.z = 1; } //////////////////////////////////////// // // angles // //////////////////////////////////////// // heading normalise_3d_vector (&wp_vec); heading = get_heading_from_attitude_matrix (raw->vh.mob.attitude); required_heading = atan2 (wp_vec.x, wp_vec.z); { float angle, range, v; range = sqrt (sqr_range); v = sqrt (0.5 * range * vehicle_database [raw->vh.mob.sub_type].g_max); angle = ((raw->vh.mob.attitude [2][0] * wp_vec.x) + (raw->vh.mob.attitude [2][2] * wp_vec.z)); if (angle < 0.707) // 45 degs. { // wp behind ship #if DEBUG_MODULE debug_log ("SH_MOVE: ship cannot reach wp at vel %f m/s (max v %f), range %f, g %f", raw->vh.mob.velocity, v, range, vehicle_database [raw->vh.mob.sub_type].g_max); #endif new_velocity = bound (v, 0.0, get_local_entity_float_value (guide, FLOAT_TYPE_VELOCITY)); } else { #if DEBUG_MODULE debug_log ("SH_MOVE: ship can reach wp at vel %f m/s (max v %f), range %f, g %f", raw->vh.mob.velocity, v, range, vehicle_database [raw->vh.mob.sub_type].g_max); #endif new_velocity = get_local_entity_float_value (guide, FLOAT_TYPE_VELOCITY); } } turn_rate = 0.0; if (raw->vh.mob.velocity != 0.0) { turn_rate = fabs (vehicle_database [raw->vh.mob.sub_type].g_max / raw->vh.mob.velocity); } delta_heading = required_heading - heading; if (delta_heading <= -PI) { delta_heading += PI2; } if (delta_heading >= PI) { delta_heading -= PI2; } delta_heading = bound (delta_heading, -turn_rate, turn_rate); heading += delta_heading * get_entity_movement_delta_time (); pitch = 0.0; roll = 0.0; //////////////////////////////////////// // // attitude // //////////////////////////////////////// get_3d_transformation_matrix (raw->vh.mob.attitude, heading, rad (pitch), rad (roll)); //////////////////////////////////////// // // velocity // //////////////////////////////////////// { float maximum_acceleration, required_acceleration; required_acceleration = (new_velocity - raw->vh.mob.velocity); maximum_acceleration = get_local_entity_float_value (en, FLOAT_TYPE_MAX_ACCELERATION); raw->vh.mob.velocity += min (required_acceleration, maximum_acceleration) * get_entity_movement_delta_time (); } //////////////////////////////////////// // // position // //////////////////////////////////////// new_pos.x = raw->vh.mob.position.x + (raw->vh.mob.velocity * raw->vh.mob.zv.x * get_entity_movement_delta_time ()); new_pos.y = 0.0; new_pos.z = raw->vh.mob.position.z + (raw->vh.mob.velocity * raw->vh.mob.zv.z * get_entity_movement_delta_time ()); bound_position_to_map_volume (&new_pos); // // Calculate motion vector for view system // raw->vh.mob.motion_vector.x = (new_pos.x - raw->vh.mob.position.x) * get_one_over_delta_time (); raw->vh.mob.motion_vector.y = 0.0; raw->vh.mob.motion_vector.z = (new_pos.z - raw->vh.mob.position.z) * get_one_over_delta_time (); new_pos.y = 0.0; set_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &new_pos); }
void draw_3d_terrain_tree ( object_3d_instance *obj ) { int object_number; object_3d_info *this_object_3d_info; light_3d_source *this_light, *prev_light, *light_ptr, *light; vec3d *pos; vec3d object_camera_position, object_pos; // // Set up the object drawing global variables // object_3d_points_current_base = 0; object_3d_object_current_base = 0; object_3d_light_3d_current_base = 0; // // Calculate the object's position relative to the view. // pos = &obj->rel_vp.position; { float fog_intensity; int ifog_intensity; fog_intensity = get_fog_distance_value ( pos->z ); convert_float_to_int ( fog_intensity, &ifog_intensity ); set_d3d_fog_face_intensity ( ifog_intensity ); } // // Set the main objects' scaling values // object_3d_scale.x = obj->relative_scale.x; object_3d_scale.y = obj->relative_scale.y; object_3d_scale.z = obj->relative_scale.z; // // Calculate the object's rotation matrix, to transform its 3d points relative to the view. // rotation_3d[0][0] = ( obj->vp.xv.x * visual_3d_vp->xv.x + obj->vp.xv.y * visual_3d_vp->xv.y + obj->vp.xv.z * visual_3d_vp->xv.z ); rotation_3d[0][1] = ( obj->vp.xv.x * visual_3d_vp->yv.x + obj->vp.xv.y * visual_3d_vp->yv.y + obj->vp.xv.z * visual_3d_vp->yv.z ); rotation_3d[0][2] = ( obj->vp.xv.x * visual_3d_vp->zv.x + obj->vp.xv.y * visual_3d_vp->zv.y + obj->vp.xv.z * visual_3d_vp->zv.z ); rotation_3d[1][0] = ( obj->vp.yv.x * visual_3d_vp->xv.x + obj->vp.yv.y * visual_3d_vp->xv.y + obj->vp.yv.z * visual_3d_vp->xv.z ); rotation_3d[1][1] = ( obj->vp.yv.x * visual_3d_vp->yv.x + obj->vp.yv.y * visual_3d_vp->yv.y + obj->vp.yv.z * visual_3d_vp->yv.z ); rotation_3d[1][2] = ( obj->vp.yv.x * visual_3d_vp->zv.x + obj->vp.yv.y * visual_3d_vp->zv.y + obj->vp.yv.z * visual_3d_vp->zv.z ); rotation_3d[2][0] = ( obj->vp.zv.x * visual_3d_vp->xv.x + obj->vp.zv.y * visual_3d_vp->xv.y + obj->vp.zv.z * visual_3d_vp->xv.z ); rotation_3d[2][1] = ( obj->vp.zv.x * visual_3d_vp->yv.x + obj->vp.zv.y * visual_3d_vp->yv.y + obj->vp.zv.z * visual_3d_vp->yv.z ); rotation_3d[2][2] = ( obj->vp.zv.x * visual_3d_vp->zv.x + obj->vp.zv.y * visual_3d_vp->zv.y + obj->vp.zv.z * visual_3d_vp->zv.z ); rotation_3d[0][0] *= object_3d_scale.x; rotation_3d[1][0] *= object_3d_scale.y; rotation_3d[2][0] *= object_3d_scale.z; rotation_3d[0][1] *= object_3d_scale.x; rotation_3d[1][1] *= object_3d_scale.y; rotation_3d[2][1] *= object_3d_scale.z; rotation_3d[0][2] *= object_3d_scale.x; rotation_3d[1][2] *= object_3d_scale.y; rotation_3d[2][2] *= object_3d_scale.z; // // Calculate the vector from the object to the viewpoint, in the object's view system // { float x, y, z; x = ( ( visual_3d_vp->x - obj->vp.x ) * obj->vp.xv.x ); x += ( ( visual_3d_vp->y - obj->vp.y ) * obj->vp.xv.y ); x += ( ( visual_3d_vp->z - obj->vp.z ) * obj->vp.xv.z ); y = ( ( visual_3d_vp->x - obj->vp.x ) * obj->vp.yv.x ); y += ( ( visual_3d_vp->y - obj->vp.y ) * obj->vp.yv.y ); y += ( ( visual_3d_vp->z - obj->vp.z ) * obj->vp.yv.z ); z = ( ( visual_3d_vp->x - obj->vp.x ) * obj->vp.zv.x ); z += ( ( visual_3d_vp->y - obj->vp.y ) * obj->vp.zv.y ); z += ( ( visual_3d_vp->z - obj->vp.z ) * obj->vp.zv.z ); object_pos.x = x; object_pos.y = y; object_pos.z = z; } // // Get the object number // object_number = get_object_approximation_number ( obj->object_number, pos->z, &object_3d_approximation_level ); // // Rotate the light source vector to be relative to the object. // light_ptr = current_3d_lights; prev_light = NULL; light = NULL; if ( light_ptr ) { light = &light_3d_array[object_3d_light_3d_current_base]; while ( light_ptr ) { float lx, ly, lz; if ( light_ptr->type == LIGHT_3D_TYPE_POINT ) { vec3d vector; float distance; // // Work out the distance from object to light source // vector.x = - light_ptr->light_position.x + obj->vp.x; vector.y = - light_ptr->light_position.y + obj->vp.y; vector.z = - light_ptr->light_position.z + obj->vp.z; lx = vector.x * vector.x; ly = vector.y * vector.y; lz = vector.z * vector.z; distance = ( lx + ly + lz ); if ( distance < light_ptr->radius ) { distance = 1 - ( distance / light_ptr->radius ); this_light = &light_3d_array[object_3d_light_3d_current_base]; object_3d_light_3d_current_base++; if ( prev_light ) { prev_light->succ = this_light; } this_light->pred = prev_light; this_light->succ = NULL; this_light->type = light_ptr->type; this_light->colour.red = light_ptr->colour.red * distance; this_light->colour.green = light_ptr->colour.green * distance; this_light->colour.blue = light_ptr->colour.blue * distance; // this_light->colour.intensity = light_ptr->colour.intensity * distance; normalise_3d_vector ( &vector ); lx = ( vector.x * obj->vp.attitude[0][0] ); lx += ( vector.y * obj->vp.attitude[0][1] ); lx += ( vector.z * obj->vp.attitude[0][2] ); ly = ( vector.x * obj->vp.attitude[1][0] ); ly += ( vector.y * obj->vp.attitude[1][1] ); ly += ( vector.z * obj->vp.attitude[1][2] ); lz = ( vector.x * obj->vp.attitude[2][0] ); lz += ( vector.y * obj->vp.attitude[2][1] ); lz += ( vector.z * obj->vp.attitude[2][2] ); this_light->lx = lx; this_light->ly = ly; this_light->lz = lz; prev_light = this_light; } } else { this_light = &light_3d_array[object_3d_light_3d_current_base]; object_3d_light_3d_current_base++; if ( prev_light ) { prev_light->succ = this_light; } this_light->pred = prev_light; this_light->succ = NULL; this_light->type = light_ptr->type; this_light->colour.red = light_ptr->colour.red; this_light->colour.green = light_ptr->colour.green; this_light->colour.blue = light_ptr->colour.blue; // this_light->colour.intensity = light_ptr->colour.intensity; lx = ( light_ptr->lx * obj->vp.attitude[0][0] ); lx += ( light_ptr->ly * obj->vp.attitude[0][1] ); lx += ( light_ptr->lz * obj->vp.attitude[0][2] ); ly = ( light_ptr->lx * obj->vp.attitude[1][0] ); ly += ( light_ptr->ly * obj->vp.attitude[1][1] ); ly += ( light_ptr->lz * obj->vp.attitude[1][2] ); lz = ( light_ptr->lx * obj->vp.attitude[2][0] ); lz += ( light_ptr->ly * obj->vp.attitude[2][1] ); lz += ( light_ptr->lz * obj->vp.attitude[2][2] ); this_light->lx = lx; this_light->ly = ly; this_light->lz = lz; prev_light = this_light; } light_ptr = light_ptr->succ; } } { vec3d rel_pos; // // Calculate the relative camera position in the object viewspace // rel_pos.x = visual_3d_vp->x - obj->vp.x; rel_pos.y = visual_3d_vp->y - obj->vp.y; rel_pos.z = visual_3d_vp->z - obj->vp.z; object_camera_position.x = ( rel_pos.x * obj->vp.attitude[0][0] + rel_pos.y * obj->vp.attitude[1][0] + rel_pos.z * obj->vp.attitude[2][0] ); object_camera_position.y = ( rel_pos.x * obj->vp.attitude[0][1] + rel_pos.y * obj->vp.attitude[1][1] + rel_pos.z * obj->vp.attitude[2][1] ); object_camera_position.z = ( rel_pos.x * obj->vp.attitude[0][2] + rel_pos.y * obj->vp.attitude[1][2] + rel_pos.z * obj->vp.attitude[2][2] ); } // // Set up this objects' object info structure // object_3d_object_base[object_3d_object_current_base].lights = light; object_3d_object_base[object_3d_object_current_base].camera_position = object_camera_position; object_3d_object_base[object_3d_object_current_base].points_base = object_3d_points_current_base; object_3d_object_base[object_3d_object_current_base].object_number = object_number; this_object_3d_info = &object_3d_object_base[object_3d_object_current_base]; global_object_3d_info = this_object_3d_info; // // Transform the object's shape data // // // Setup the objects scaling information // { float xdistance, ydistance, zdistance; xdistance = ( objects_3d_data[object_number].bounding_box.xmax - objects_3d_data[object_number].bounding_box.xmin ) / 2; ydistance = ( objects_3d_data[object_number].bounding_box.ymax - objects_3d_data[object_number].bounding_box.ymin ) / 2; zdistance = ( objects_3d_data[object_number].bounding_box.zmax - objects_3d_data[object_number].bounding_box.zmin ) / 2; object_3d_x_middle = objects_3d_data[object_number].bounding_box.xmin + xdistance; object_3d_y_middle = objects_3d_data[object_number].bounding_box.ymin + ydistance; object_3d_z_middle = objects_3d_data[object_number].bounding_box.zmin + zdistance; object_3d_x_scale = xdistance / 32767.0; object_3d_y_scale = ydistance / 32767.0; object_3d_z_scale = zdistance / 32767.0; } /* if ( objects_3d_data[object_number].number_of_points ) { int object_outcode; object_outcode = get_object_3d_outcode ( object_number, pos ); if ( object_outcode ) { transform_3d_object ( &objects_3d_data[object_number], pos, light, object_3d_points_current_base); } else { transform_unclipped_3d_object ( &objects_3d_data[object_number], pos, light, object_3d_points_current_base); } polygon_zdistance_bias = POLYGON_ZDISTANCE_NORMAL_BIAS; set_d3d_int_state ( D3DRENDERSTATE_CULLMODE, D3DCULL_CW ); if ( object_outcode ) { draw_3d_terrain_tree_clipped_faces ( object_number, this_object_3d_info ); } else { draw_3d_terrain_tree_unclipped_faces ( object_number, this_object_3d_info ); } set_d3d_int_state ( D3DRENDERSTATE_CULLMODE, D3DCULL_CCW ); if ( object_outcode ) { draw_3d_terrain_tree_clipped_faces ( object_number, this_object_3d_info ); } else { draw_3d_terrain_tree_unclipped_faces ( object_number, this_object_3d_info ); } } */ }