void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, f32 tool_reload_ratio) { // Get player position // Smooth the movement when walking up stairs v3f old_player_position = m_playernode->getPosition(); v3f player_position = player->getPosition(); if (player->isAttached && player->parent) player_position = player->parent->getPosition(); //if(player->touching_ground && player_position.Y > old_player_position.Y) if(player->touching_ground && player_position.Y > old_player_position.Y) { f32 oldy = old_player_position.Y; f32 newy = player_position.Y; f32 t = exp(-23*frametime); player_position.Y = oldy * t + newy * (1-t); } // Set player node transformation m_playernode->setPosition(player_position); m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0)); m_playernode->updateAbsolutePosition(); // Get camera tilt timer (hurt animation) float cameratilt = fabs(fabs(player->hurt_tilt_timer-0.75)-0.75); // Fall bobbing animation float fall_bobbing = 0; if(player->camera_impact >= 1 && m_camera_mode < CAMERA_MODE_THIRD) { if(m_view_bobbing_fall == -1) // Effect took place and has finished player->camera_impact = m_view_bobbing_fall = 0; else if(m_view_bobbing_fall == 0) // Initialize effect m_view_bobbing_fall = 1; // Convert 0 -> 1 to 0 -> 1 -> 0 fall_bobbing = m_view_bobbing_fall < 0.5 ? m_view_bobbing_fall * 2 : -(m_view_bobbing_fall - 0.5) * 2 + 1; // Smoothen and invert the above fall_bobbing = sin(fall_bobbing * 0.5 * M_PI) * -1; // Amplify according to the intensity of the impact fall_bobbing *= (1 - rangelim(50 / player->camera_impact, 0, 1)) * 5; fall_bobbing *= m_cache_fall_bobbing_amount; } // Calculate players eye offset for different camera modes v3f PlayerEyeOffset = player->getEyeOffset(); if (m_camera_mode == CAMERA_MODE_FIRST) PlayerEyeOffset += player->eye_offset_first; else PlayerEyeOffset += player->eye_offset_third; // Set head node transformation m_headnode->setPosition(PlayerEyeOffset+v3f(0,cameratilt*-player->hurt_tilt_strength+fall_bobbing,0)); m_headnode->setRotation(v3f(player->getPitch(), 0, cameratilt*player->hurt_tilt_strength)); m_headnode->updateAbsolutePosition(); // Compute relative camera position and target v3f rel_cam_pos = v3f(0,0,0); v3f rel_cam_target = v3f(0,0,1); v3f rel_cam_up = v3f(0,1,0); if (m_cache_view_bobbing_amount != 0.0f && m_view_bobbing_anim != 0.0f && m_camera_mode < CAMERA_MODE_THIRD) { f32 bobfrac = my_modf(m_view_bobbing_anim * 2); f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0; #if 1 f32 bobknob = 1.2; f32 bobtmp = sin(pow(bobfrac, bobknob) * M_PI); //f32 bobtmp2 = cos(pow(bobfrac, bobknob) * M_PI); v3f bobvec = v3f( 0.3 * bobdir * sin(bobfrac * M_PI), -0.28 * bobtmp * bobtmp, 0.); //rel_cam_pos += 0.2 * bobvec; //rel_cam_target += 0.03 * bobvec; //rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * M_PI); float f = 1.0; f *= m_cache_view_bobbing_amount; rel_cam_pos += bobvec * f; //rel_cam_target += 0.995 * bobvec * f; rel_cam_target += bobvec * f; rel_cam_target.Z -= 0.005 * bobvec.Z * f; //rel_cam_target.X -= 0.005 * bobvec.X * f; //rel_cam_target.Y -= 0.005 * bobvec.Y * f; rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * M_PI * f); #else f32 angle_deg = 1 * bobdir * sin(bobfrac * M_PI); f32 angle_rad = angle_deg * M_PI / 180; f32 r = 0.05; v3f off = v3f( r * sin(angle_rad), r * (cos(angle_rad) - 1), 0); rel_cam_pos += off; //rel_cam_target += off; rel_cam_up.rotateXYBy(angle_deg); #endif } // Compute absolute camera position and target m_headnode->getAbsoluteTransformation().transformVect(m_camera_position, rel_cam_pos); m_headnode->getAbsoluteTransformation().rotateVect(m_camera_direction, rel_cam_target - rel_cam_pos); v3f abs_cam_up; m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up); // Seperate camera position for calculation v3f my_cp = m_camera_position; // Reposition the camera for third person view if (m_camera_mode > CAMERA_MODE_FIRST) { if (m_camera_mode == CAMERA_MODE_THIRD_FRONT) m_camera_direction *= -1; my_cp.Y += 2; // Calculate new position bool abort = false; for (int i = BS; i <= BS * 2.75; i++) { my_cp.X = m_camera_position.X + m_camera_direction.X * -i; my_cp.Z = m_camera_position.Z + m_camera_direction.Z * -i; if (i > 12) my_cp.Y = m_camera_position.Y + (m_camera_direction.Y * -i); // Prevent camera positioned inside nodes INodeDefManager *nodemgr = m_client->ndef(); MapNode n = m_client->getEnv().getClientMap() .getNodeNoEx(floatToInt(my_cp, BS)); const ContentFeatures& features = nodemgr->get(n); if (features.walkable) { my_cp.X += m_camera_direction.X*-1*-BS/2; my_cp.Z += m_camera_direction.Z*-1*-BS/2; my_cp.Y += m_camera_direction.Y*-1*-BS/2; abort = true; break; } } // If node blocks camera position don't move y to heigh if (abort && my_cp.Y > player_position.Y+BS*2) my_cp.Y = player_position.Y+BS*2; } // Update offset if too far away from the center of the map m_camera_offset.X += CAMERA_OFFSET_STEP* (((s16)(my_cp.X/BS) - m_camera_offset.X)/CAMERA_OFFSET_STEP); m_camera_offset.Y += CAMERA_OFFSET_STEP* (((s16)(my_cp.Y/BS) - m_camera_offset.Y)/CAMERA_OFFSET_STEP); m_camera_offset.Z += CAMERA_OFFSET_STEP* (((s16)(my_cp.Z/BS) - m_camera_offset.Z)/CAMERA_OFFSET_STEP); // Set camera node transformation m_cameranode->setPosition(my_cp-intToFloat(m_camera_offset, BS)); m_cameranode->setUpVector(abs_cam_up); // *100.0 helps in large map coordinates m_cameranode->setTarget(my_cp-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction); // update the camera position in front-view mode to render blocks behind player if (m_camera_mode == CAMERA_MODE_THIRD_FRONT) m_camera_position = my_cp; // Get FOV f32 fov_degrees; if (player->getPlayerControl().zoom && player->getCanZoom()) { fov_degrees = m_cache_zoom_fov; } else { fov_degrees = m_cache_fov; } fov_degrees = rangelim(fov_degrees, 7.0, 160.0); // FOV and aspect ratio const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize(); m_aspect = (f32) window_size.X / (f32) window_size.Y; m_fov_y = fov_degrees * M_PI / 180.0; // Increase vertical FOV on lower aspect ratios (<16:10) m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect))); m_fov_x = 2 * atan(m_aspect * tan(0.5 * m_fov_y)); m_cameranode->setAspectRatio(m_aspect); m_cameranode->setFOV(m_fov_y); if (m_arm_inertia) addArmInertia(player->getYaw()); // Position the wielded item //v3f wield_position = v3f(45, -35, 65); v3f wield_position = v3f(m_wieldmesh_offset.X, m_wieldmesh_offset.Y, 65); //v3f wield_rotation = v3f(-100, 120, -100); v3f wield_rotation = v3f(-100, 120, -100); wield_position.Y += fabs(m_wield_change_timer)*320 - 40; if(m_digging_anim < 0.05 || m_digging_anim > 0.5) { f32 frac = 1.0; if(m_digging_anim > 0.5) frac = 2.0 * (m_digging_anim - 0.5); // This value starts from 1 and settles to 0 f32 ratiothing = pow((1.0f - tool_reload_ratio), 0.5f); //f32 ratiothing2 = pow(ratiothing, 0.5f); f32 ratiothing2 = (easeCurve(ratiothing*0.5))*2.0; wield_position.Y -= frac * 25.0 * pow(ratiothing2, 1.7f); //wield_position.Z += frac * 5.0 * ratiothing2; wield_position.X -= frac * 35.0 * pow(ratiothing2, 1.1f); wield_rotation.Y += frac * 70.0 * pow(ratiothing2, 1.4f); //wield_rotation.X -= frac * 15.0 * pow(ratiothing2, 1.4f); //wield_rotation.Z += frac * 15.0 * pow(ratiothing2, 1.0f); } if (m_digging_button != -1) { f32 digfrac = m_digging_anim; wield_position.X -= 50 * sin(pow(digfrac, 0.8f) * M_PI); wield_position.Y += 24 * sin(digfrac * 1.8 * M_PI); wield_position.Z += 25 * 0.5; // Euler angles are PURE EVIL, so why not use quaternions? core::quaternion quat_begin(wield_rotation * core::DEGTORAD); core::quaternion quat_end(v3f(80, 30, 100) * core::DEGTORAD); core::quaternion quat_slerp; quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * M_PI)); quat_slerp.toEuler(wield_rotation); wield_rotation *= core::RADTODEG; } else { f32 bobfrac = my_modf(m_view_bobbing_anim); wield_position.X -= sin(bobfrac*M_PI*2.0) * 3.0; wield_position.Y += sin(my_modf(bobfrac*2.0)*M_PI) * 3.0; } m_wieldnode->setPosition(wield_position); m_wieldnode->setRotation(wield_rotation); m_wieldnode->setColor(player->light_color); // Set render distance updateViewingRange(); // If the player is walking, swimming, or climbing, // view bobbing is enabled and free_move is off, // start (or continue) the view bobbing animation. const v3f &speed = player->getSpeed(); const bool movement_XZ = hypot(speed.X, speed.Z) > BS; const bool movement_Y = fabs(speed.Y) > BS; const bool walking = movement_XZ && player->touching_ground; const bool swimming = (movement_XZ || player->swimming_vertical) && player->in_liquid; const bool climbing = movement_Y && player->is_climbing; if ((walking || swimming || climbing) && (!g_settings->getBool("free_move") || !m_client->checkLocalPrivilege("fly"))) { // Start animation m_view_bobbing_state = 1; m_view_bobbing_speed = MYMIN(speed.getLength(), 70); } else if (m_view_bobbing_state == 1) { // Stop animation m_view_bobbing_state = 2; m_view_bobbing_speed = 60; } }
void Camera::update(LocalPlayer* player, f32 frametime, f32 busytime, v2u32 screensize, f32 tool_reload_ratio) { // Get player position // Smooth the movement when walking up stairs v3f old_player_position = m_playernode->getPosition(); v3f player_position = player->getPosition(); if (player->isAttached && player->parent) player_position = player->parent->getPosition(); //if(player->touching_ground && player_position.Y > old_player_position.Y) if(player->touching_ground && player_position.Y > old_player_position.Y) { f32 oldy = old_player_position.Y; f32 newy = player_position.Y; f32 t = exp(-23*frametime); player_position.Y = oldy * t + newy * (1-t); } // Set player node transformation m_playernode->setPosition(player_position); m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0)); m_playernode->updateAbsolutePosition(); // Get camera tilt timer (hurt animation) float cameratilt = fabs(fabs(player->hurt_tilt_timer-0.75)-0.75); // Fall bobbing animation float fall_bobbing = 0; if(player->camera_impact >= 1) { if(m_view_bobbing_fall == -1) // Effect took place and has finished player->camera_impact = m_view_bobbing_fall = 0; else if(m_view_bobbing_fall == 0) // Initialize effect m_view_bobbing_fall = 1; // Convert 0 -> 1 to 0 -> 1 -> 0 fall_bobbing = m_view_bobbing_fall < 0.5 ? m_view_bobbing_fall * 2 : -(m_view_bobbing_fall - 0.5) * 2 + 1; // Smoothen and invert the above fall_bobbing = sin(fall_bobbing * 0.5 * M_PI) * -1; // Amplify according to the intensity of the impact fall_bobbing *= (1 - rangelim(50 / player->camera_impact, 0, 1)) * 5; fall_bobbing *= g_settings->getFloat("fall_bobbing_amount"); } // Set head node transformation m_headnode->setPosition(player->getEyeOffset()+v3f(0,cameratilt*-player->hurt_tilt_strength+fall_bobbing,0)); m_headnode->setRotation(v3f(player->getPitch(), 0, cameratilt*player->hurt_tilt_strength)); m_headnode->updateAbsolutePosition(); // Compute relative camera position and target v3f rel_cam_pos = v3f(0,0,0); v3f rel_cam_target = v3f(0,0,1); v3f rel_cam_up = v3f(0,1,0); if (m_view_bobbing_anim != 0) { f32 bobfrac = my_modf(m_view_bobbing_anim * 2); f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0; #if 1 f32 bobknob = 1.2; f32 bobtmp = sin(pow(bobfrac, bobknob) * M_PI); //f32 bobtmp2 = cos(pow(bobfrac, bobknob) * M_PI); v3f bobvec = v3f( 0.3 * bobdir * sin(bobfrac * M_PI), -0.28 * bobtmp * bobtmp, 0.); //rel_cam_pos += 0.2 * bobvec; //rel_cam_target += 0.03 * bobvec; //rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * M_PI); float f = 1.0; f *= g_settings->getFloat("view_bobbing_amount"); rel_cam_pos += bobvec * f; //rel_cam_target += 0.995 * bobvec * f; rel_cam_target += bobvec * f; rel_cam_target.Z -= 0.005 * bobvec.Z * f; //rel_cam_target.X -= 0.005 * bobvec.X * f; //rel_cam_target.Y -= 0.005 * bobvec.Y * f; rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * M_PI * f); #else f32 angle_deg = 1 * bobdir * sin(bobfrac * M_PI); f32 angle_rad = angle_deg * M_PI / 180; f32 r = 0.05; v3f off = v3f( r * sin(angle_rad), r * (cos(angle_rad) - 1), 0); rel_cam_pos += off; //rel_cam_target += off; rel_cam_up.rotateXYBy(angle_deg); #endif } // Compute absolute camera position and target m_headnode->getAbsoluteTransformation().transformVect(m_camera_position, rel_cam_pos); m_headnode->getAbsoluteTransformation().rotateVect(m_camera_direction, rel_cam_target - rel_cam_pos); v3f abs_cam_up; m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up); // Set camera node transformation m_cameranode->setPosition(m_camera_position); m_cameranode->setUpVector(abs_cam_up); // *100.0 helps in large map coordinates m_cameranode->setTarget(m_camera_position + 100 * m_camera_direction); // Get FOV setting f32 fov_degrees = g_settings->getFloat("fov"); fov_degrees = MYMAX(fov_degrees, 10.0); fov_degrees = MYMIN(fov_degrees, 170.0); // FOV and aspect ratio m_aspect = (f32)screensize.X / (f32) screensize.Y; m_fov_y = fov_degrees * M_PI / 180.0; // Increase vertical FOV on lower aspect ratios (<16:10) m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect))); m_fov_x = 2 * atan(m_aspect * tan(0.5 * m_fov_y)); m_cameranode->setAspectRatio(m_aspect); m_cameranode->setFOV(m_fov_y); // Position the wielded item //v3f wield_position = v3f(45, -35, 65); v3f wield_position = v3f(55, -35, 65); //v3f wield_rotation = v3f(-100, 120, -100); v3f wield_rotation = v3f(-100, 120, -100); if(m_wield_change_timer < 0) wield_position.Y -= 40 + m_wield_change_timer*320; else wield_position.Y -= 40 - m_wield_change_timer*320; if(m_digging_anim < 0.05 || m_digging_anim > 0.5){ f32 frac = 1.0; if(m_digging_anim > 0.5) frac = 2.0 * (m_digging_anim - 0.5); // This value starts from 1 and settles to 0 f32 ratiothing = pow((1.0f - tool_reload_ratio), 0.5f); //f32 ratiothing2 = pow(ratiothing, 0.5f); f32 ratiothing2 = (easeCurve(ratiothing*0.5))*2.0; wield_position.Y -= frac * 25.0 * pow(ratiothing2, 1.7f); //wield_position.Z += frac * 5.0 * ratiothing2; wield_position.X -= frac * 35.0 * pow(ratiothing2, 1.1f); wield_rotation.Y += frac * 70.0 * pow(ratiothing2, 1.4f); //wield_rotation.X -= frac * 15.0 * pow(ratiothing2, 1.4f); //wield_rotation.Z += frac * 15.0 * pow(ratiothing2, 1.0f); } if (m_digging_button != -1) { f32 digfrac = m_digging_anim; wield_position.X -= 50 * sin(pow(digfrac, 0.8f) * M_PI); wield_position.Y += 24 * sin(digfrac * 1.8 * M_PI); wield_position.Z += 25 * 0.5; // Euler angles are PURE EVIL, so why not use quaternions? core::quaternion quat_begin(wield_rotation * core::DEGTORAD); core::quaternion quat_end(v3f(80, 30, 100) * core::DEGTORAD); core::quaternion quat_slerp; quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * M_PI)); quat_slerp.toEuler(wield_rotation); wield_rotation *= core::RADTODEG; } else { f32 bobfrac = my_modf(m_view_bobbing_anim); wield_position.X -= sin(bobfrac*M_PI*2.0) * 3.0; wield_position.Y += sin(my_modf(bobfrac*2.0)*M_PI) * 3.0; } m_wieldnode->setPosition(wield_position); m_wieldnode->setRotation(wield_rotation); m_wieldlight = player->light; // Render distance feedback loop updateViewingRange(frametime, busytime); // If the player seems to be walking on solid ground, // view bobbing is enabled and free_move is off, // start (or continue) the view bobbing animation. v3f speed = player->getSpeed(); if ((hypot(speed.X, speed.Z) > BS) && (player->touching_ground) && (g_settings->getBool("view_bobbing") == true) && (g_settings->getBool("free_move") == false || !m_gamedef->checkLocalPrivilege("fly"))) { // Start animation m_view_bobbing_state = 1; m_view_bobbing_speed = MYMIN(speed.getLength(), 40); } else if (m_view_bobbing_state == 1) { // Stop animation m_view_bobbing_state = 2; m_view_bobbing_speed = 60; } }
void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize) { // Set player node transformation m_playernode->setPosition(player->getPosition()); m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0)); m_playernode->updateAbsolutePosition(); // Set head node transformation m_headnode->setPosition(player->getEyeOffset()); m_headnode->setRotation(v3f(player->getPitch(), 0, 0)); m_headnode->updateAbsolutePosition(); // Compute relative camera position and target v3f rel_cam_pos = v3f(0,0,0); v3f rel_cam_target = v3f(0,0,1); v3f rel_cam_up = v3f(0,1,0); if (m_view_bobbing_state != 0 && m_view_bobbing_anim != 0) { f32 bobfrac = my_modf(m_view_bobbing_anim * 2); f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0; f32 bobknob = 1.2; f32 bobtmp = sin(pow(bobfrac, bobknob) * PI); v3f bobvec = v3f( 0.3 * bobdir * sin(bobfrac * PI), -0.28 * bobtmp * bobtmp, 0.); float f = 1.0; f *= m_view_bobbing_amount; rel_cam_pos += bobvec * f; rel_cam_target += bobvec * f; rel_cam_target.Z -= 0.005 * bobvec.Z * f; rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * PI * f); } // Compute absolute camera position and target m_headnode->getAbsoluteTransformation().transformVect(m_camera_position, rel_cam_pos); m_headnode->getAbsoluteTransformation().rotateVect(m_camera_direction, rel_cam_target - rel_cam_pos); v3f abs_cam_up; m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up); // Update offset if too far away from the center of the map m_camera_offset.X += CAMERA_OFFSET_STEP* (((s16)(m_camera_position.X/BS) - m_camera_offset.X)/CAMERA_OFFSET_STEP); m_camera_offset.Y += CAMERA_OFFSET_STEP* (((s16)(m_camera_position.Y/BS) - m_camera_offset.Y)/CAMERA_OFFSET_STEP); m_camera_offset.Z += CAMERA_OFFSET_STEP* (((s16)(m_camera_position.Z/BS) - m_camera_offset.Z)/CAMERA_OFFSET_STEP); // Set camera node transformation m_cameranode->setPosition(m_camera_position-intToFloat(m_camera_offset, BS)); m_cameranode->setUpVector(abs_cam_up); // *100.0 helps in large map coordinates m_cameranode->setTarget(m_camera_position-intToFloat(m_camera_offset, BS) + 100 * m_camera_direction); // FOV and aspect ratio m_aspect = (f32)screensize.X / (f32) screensize.Y; m_fov_y = m_fov * PI / 180.0; m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y)); m_cameranode->setAspectRatio(m_aspect); m_cameranode->setFOV(m_fov_y); // Position the wielded item v3f wield_position = m_wieldnode_baseposition; v3f wield_rotation = m_wieldnode_baserotation; if (m_digging_button != -1) { f32 digfrac = m_digging_anim; wield_position.X -= 30 * sin(pow(digfrac, 0.8f) * PI); wield_position.Y += 15 * sin(digfrac * 2 * PI); wield_position.Z += 5 * digfrac; // Euler angles are PURE EVIL, so why not use quaternions? core::quaternion quat_begin(wield_rotation * core::DEGTORAD); core::quaternion quat_end(v3f(90, -10, -130) * core::DEGTORAD); core::quaternion quat_slerp; quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * PI)); quat_slerp.toEuler(wield_rotation); wield_rotation *= core::RADTODEG; }else{ f32 bobfrac = my_modf(m_view_bobbing_anim); wield_position.X -= sin(bobfrac*PI*2.0) * 3.0; wield_position.Y += sin(my_modf(bobfrac*2.0)*PI) * 3.0; } m_wieldnode->setPosition(wield_position); m_wieldnode->setRotation(wield_rotation); u8 li = decode_light(player->light); // Set brightness one lower than incoming light diminish_light(li); m_wieldnode->updateLight(li); // Render distance feedback loop updateViewingRange(frametime); // If the player seems to be walking on solid ground, // view bobbing is enabled and free_move is off, // start (or continue) the view bobbing animation. v3f speed = player->getSpeed(); if ( (hypot(speed.X, speed.Z) > BS) && (player->touching_ground) && m_view_bobbing == true && player->control.free == false ) { // Start animation m_view_bobbing_state = 1; m_view_bobbing_speed = MYMIN(speed.getLength(), 60)*1.2; }else if (m_view_bobbing_state == 1) { // Stop animation m_view_bobbing_state = 2; m_view_bobbing_speed = 60; } }
void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize, f32 tool_reload_ratio) { // Set player node transformation m_playernode->setPosition(player->getPosition()); m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0)); m_playernode->updateAbsolutePosition(); // Set head node transformation m_headnode->setPosition(player->getEyeOffset()); m_headnode->setRotation(v3f(player->getPitch(), 0, 0)); m_headnode->updateAbsolutePosition(); // Compute relative camera position and target v3f rel_cam_pos = v3f(0,0,0); v3f rel_cam_target = v3f(0,0,1); v3f rel_cam_up = v3f(0,1,0); if (m_view_bobbing_anim != 0) { f32 bobfrac = my_modf(m_view_bobbing_anim * 2); f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0; #if 1 f32 bobknob = 1.2; f32 bobtmp = sin(pow(bobfrac, bobknob) * PI); //f32 bobtmp2 = cos(pow(bobfrac, bobknob) * PI); v3f bobvec = v3f( 0.3 * bobdir * sin(bobfrac * PI), -0.28 * bobtmp * bobtmp, 0.); //rel_cam_pos += 0.2 * bobvec; //rel_cam_target += 0.03 * bobvec; //rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * PI); float f = 1.0; f *= g_settings->getFloat("view_bobbing_amount"); rel_cam_pos += bobvec * f; //rel_cam_target += 0.995 * bobvec * f; rel_cam_target += bobvec * f; rel_cam_target.Z -= 0.005 * bobvec.Z * f; //rel_cam_target.X -= 0.005 * bobvec.X * f; //rel_cam_target.Y -= 0.005 * bobvec.Y * f; rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * PI * f); #else f32 angle_deg = 1 * bobdir * sin(bobfrac * PI); f32 angle_rad = angle_deg * PI / 180; f32 r = 0.05; v3f off = v3f( r * sin(angle_rad), r * (cos(angle_rad) - 1), 0); rel_cam_pos += off; //rel_cam_target += off; rel_cam_up.rotateXYBy(angle_deg); #endif } // Compute absolute camera position and target m_headnode->getAbsoluteTransformation().transformVect(m_camera_position, rel_cam_pos); m_headnode->getAbsoluteTransformation().rotateVect(m_camera_direction, rel_cam_target - rel_cam_pos); v3f abs_cam_up; m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up); // Set camera node transformation m_cameranode->setPosition(m_camera_position); m_cameranode->setUpVector(abs_cam_up); // *100.0 helps in large map coordinates m_cameranode->setTarget(m_camera_position + 100 * m_camera_direction); // Get FOV setting f32 fov_degrees = g_settings->getFloat("fov"); fov_degrees = MYMAX(fov_degrees, 10.0); fov_degrees = MYMIN(fov_degrees, 170.0); // FOV and aspect ratio m_aspect = (f32)screensize.X / (f32) screensize.Y; m_fov_y = fov_degrees * PI / 180.0; m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y)); m_cameranode->setAspectRatio(m_aspect); m_cameranode->setFOV(m_fov_y); // Position the wielded item //v3f wield_position = v3f(45, -35, 65); v3f wield_position = v3f(55, -35, 65); //v3f wield_rotation = v3f(-100, 120, -100); v3f wield_rotation = v3f(-100, 120, -100); if(m_digging_anim < 0.05 || m_digging_anim > 0.5){ f32 frac = 1.0; if(m_digging_anim > 0.5) frac = 2.0 * (m_digging_anim - 0.5); // This value starts from 1 and settles to 0 f32 ratiothing = pow((1.0f - tool_reload_ratio), 0.5f); //f32 ratiothing2 = pow(ratiothing, 0.5f); f32 ratiothing2 = (easeCurve(ratiothing*0.5))*2.0; wield_position.Y -= frac * 25.0 * pow(ratiothing2, 1.7f); //wield_position.Z += frac * 5.0 * ratiothing2; wield_position.X -= frac * 35.0 * pow(ratiothing2, 1.1f); wield_rotation.Y += frac * 70.0 * pow(ratiothing2, 1.4f); //wield_rotation.X -= frac * 15.0 * pow(ratiothing2, 1.4f); //wield_rotation.Z += frac * 15.0 * pow(ratiothing2, 1.0f); } if (m_digging_button != -1) { f32 digfrac = m_digging_anim; wield_position.X -= 30 * sin(pow(digfrac, 0.8f) * PI); wield_position.Y += 15 * sin(digfrac * 2 * PI); wield_position.Z += 5 * digfrac; // Euler angles are PURE EVIL, so why not use quaternions? core::quaternion quat_begin(wield_rotation * core::DEGTORAD); core::quaternion quat_end(v3f(90, -10, -130) * core::DEGTORAD); core::quaternion quat_slerp; quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * PI)); quat_slerp.toEuler(wield_rotation); wield_rotation *= core::RADTODEG; } else { f32 bobfrac = my_modf(m_view_bobbing_anim); wield_position.X -= sin(bobfrac*PI*2.0) * 3.0; wield_position.Y += sin(my_modf(bobfrac*2.0)*PI) * 3.0; } m_wieldnode->setPosition(wield_position); m_wieldnode->setRotation(wield_rotation); m_wieldlight = player->light; // Render distance feedback loop updateViewingRange(frametime); // If the player seems to be walking on solid ground, // view bobbing is enabled and free_move is off, // start (or continue) the view bobbing animation. v3f speed = player->getSpeed(); if ((hypot(speed.X, speed.Z) > BS) && (player->touching_ground) && (g_settings->getBool("view_bobbing") == true) && (g_settings->getBool("free_move") == false)) { // Start animation m_view_bobbing_state = 1; m_view_bobbing_speed = MYMIN(speed.getLength(), 40); } else if (m_view_bobbing_state == 1) { // Stop animation m_view_bobbing_state = 2; m_view_bobbing_speed = 60; } }
void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize, f32 tool_reload_ratio) { // Get player position // Smooth the movement when walking up stairs v3f old_player_position = m_playernode->getPosition(); v3f player_position = player->getPosition(); //if(player->touching_ground && player_position.Y > old_player_position.Y) if(player->touching_ground && player_position.Y > old_player_position.Y) { f32 oldy = old_player_position.Y; f32 newy = player_position.Y; f32 t = exp(-23*frametime); player_position.Y = oldy * t + newy * (1-t); } // Set player node transformation m_playernode->setPosition(player_position); m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0)); m_playernode->updateAbsolutePosition(); // Get camera tilt timer (hurt animation) float cameratilt = fabs(fabs(-(player->hurt_tilt_timer_max/2)+player->hurt_tilt_timer)-player->hurt_tilt_timer_max/2)/5; v3f campos(player->getEyeOffset()); v3f camrot(player->getPitch(), 0, 0); //f32 incr = 0.3/m_sprinting_fov_states; /*if(m_sprinting_fov_state <= 0) { m_sprinting_fov_state = incr; } else if(m_sprinting_fov_state < 0.3) { m_sprinting_fov_state += incr; }*/ if(player->sprinting_timer != -10 && player->sprinting_timer != -20 && player->sprinting_timer != -30) { m_sprinting_fov_state = 0.3-player->sprinting_timer; } m_headnode->updateAbsolutePosition(); if(cameratilt > 0) { campos += v3f(0, cameratilt * -13, 0); camrot += v3f(0, 0, cameratilt * 13 * BS); } if(player->control.sneak) { campos += v3f(0, -player->camera_sneak_state*BS, 0); if (player->camera_sneak_state < 0.18) player->camera_sneak_state += 0.02; } else if (player->camera_sneak_state > 0) { player->camera_sneak_state -= 0.02; } campos += v3f(0, 0, m_sprinting_fov_state * BS); // Set head node transformation m_headnode->setPosition(campos); m_headnode->setRotation(camrot); m_headnode->updateAbsolutePosition(); // Compute relative camera position and target v3f rel_cam_pos = v3f(0,0,0); v3f rel_cam_target = v3f(0,0,1); v3f rel_cam_up = v3f(0,1,0); if (m_view_bobbing_anim != 0) { f32 bobfrac = my_modf(m_view_bobbing_anim * 2); f32 bobdir = (m_view_bobbing_anim < 0.5) ? 1.0 : -1.0; #if 1 f32 bobknob = 1.2; f32 bobtmp = sin(pow(bobfrac, bobknob) * PI); //f32 bobtmp2 = cos(pow(bobfrac, bobknob) * PI); v3f bobvec = v3f( 0.3 * bobdir * sin(bobfrac * PI), -0.28 * bobtmp * bobtmp, 0.); //rel_cam_pos += 0.2 * bobvec; //rel_cam_target += 0.03 * bobvec; //rel_cam_up.rotateXYBy(0.02 * bobdir * bobtmp * PI); float f = 1.0; f *= g_settings->getFloat("view_bobbing_amount"); rel_cam_pos += bobvec * f; //rel_cam_target += 0.995 * bobvec * f; rel_cam_target += bobvec * f; rel_cam_target.Z -= 0.005 * bobvec.Z * f; //rel_cam_target.X -= 0.005 * bobvec.X * f; //rel_cam_target.Y -= 0.005 * bobvec.Y * f; rel_cam_up.rotateXYBy(-0.03 * bobdir * bobtmp * PI * f); #else f32 angle_deg = 1 * bobdir * sin(bobfrac * PI); f32 angle_rad = angle_deg * PI / 180; f32 r = 0.05; v3f off = v3f( r * sin(angle_rad), r * (cos(angle_rad) - 1), 0); rel_cam_pos += off; //rel_cam_target += off; rel_cam_up.rotateXYBy(angle_deg); #endif } // Compute absolute camera position and target m_headnode->getAbsoluteTransformation().transformVect(m_camera_position, rel_cam_pos); m_headnode->getAbsoluteTransformation().rotateVect(m_camera_direction, rel_cam_target - rel_cam_pos); v3f abs_cam_up; m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up); // Set camera node transformation m_cameranode->setPosition(m_camera_position); m_cameranode->setUpVector(abs_cam_up); // *100.0 helps in large map coordinates m_cameranode->setTarget(m_camera_position + 100 * m_camera_direction); // Get FOV setting f32 fov_degrees = g_settings->getFloat("fov"); fov_degrees = MYMAX(fov_degrees, 10.0); fov_degrees = MYMIN(fov_degrees, 170.0); // FOV and aspect ratio m_aspect = (f32)screensize.X / (f32) screensize.Y; m_fov_y = fov_degrees * PI / 180.0; // Increase vertical FOV on lower aspect ratios (<16:10) m_fov_y *= MYMAX(1.0, MYMIN(1.4, sqrt(16./10. / m_aspect))); // WTF is this? It can't be right m_fov_x = 2 * atan(0.5 * m_aspect * tan(m_fov_y)); m_fov_x += m_sprinting_fov_state; m_fov_y += m_sprinting_fov_state; m_cameranode->setAspectRatio(m_aspect); m_cameranode->setFOV(m_fov_y); // Position the wielded item //v3f wield_position = v3f(45, -35, 65); v3f wield_position = v3f(55, -35, 65); //v3f wield_rotation = v3f(-100, 120, -100); v3f wield_rotation = v3f(-100, 120, -100); if(m_digging_anim < 0.05 || m_digging_anim > 0.5) { f32 frac = 1.0; if(m_digging_anim > 0.5) frac = 2.0 * (m_digging_anim - 0.5); // This value starts from 1 and settles to 0 f32 ratiothing = pow((1.0f - tool_reload_ratio), 0.5f); //f32 ratiothing2 = pow(ratiothing, 0.5f); f32 ratiothing2 = (easeCurve(ratiothing*0.5))*2.0; wield_position.Y -= frac * 25.0 * pow(ratiothing2, 1.7f); //wield_position.Z += frac * 5.0 * ratiothing2; wield_position.X -= frac * 35.0 * pow(ratiothing2, 1.1f); wield_rotation.Y += frac * 70.0 * pow(ratiothing2, 1.4f); //wield_rotation.X -= frac * 15.0 * pow(ratiothing2, 1.4f); //wield_rotation.Z += frac * 15.0 * pow(ratiothing2, 1.0f); } if(m_digging_button != -1) { if(m_digging_button == 0 && m_eatable) { m_is_eating = true; wield_position.X = 0; wield_position.Y = -20 + m_eating_anim; wield_position.Z = 65; wield_rotation.X = 0; wield_rotation.Y = 0; wield_rotation.Z = 0; } else { m_is_eating = false; f32 digfrac = m_digging_anim; wield_position.X -= 50 * sin(pow(digfrac, 0.7f) * PI); wield_position.Y += 24 * sin(digfrac * 1.8 * PI); wield_position.Z += 25 * 0.5; // Euler angles are PURE EVIL, so why not use quaternions? core::quaternion quat_begin(wield_rotation * core::DEGTORAD); core::quaternion quat_end(v3f(80, 30, 100) * core::DEGTORAD); core::quaternion quat_slerp; quat_slerp.slerp(quat_begin, quat_end, sin(digfrac * PI)); quat_slerp.toEuler(wield_rotation); wield_rotation *= core::RADTODEG; } } else { f32 bobfrac = my_modf(m_view_bobbing_anim); wield_position.X -= sin(bobfrac*PI*2.0) * 3.0; wield_position.Y += sin(my_modf(bobfrac*2.0)*PI) * 3.0; } m_wieldnode->setPosition(wield_position); m_wieldnode->setRotation(wield_rotation); m_wieldlight = player->light; // Render distance feedback loop updateViewingRange(frametime); // If the player seems to be walking on solid ground, // view bobbing is enabled and the player is not flying, // start (or continue) the view bobbing animation. v3f speed = player->getSpeed(); if ((hypot(speed.X, speed.Z) > BS) && (player->touching_ground) && (g_settings->getBool("view_bobbing") == true) && (!player->is_flying || !m_gamedef->checkLocalPrivilege("fly"))) { // Start animation m_view_bobbing_state = 1; //m_view_bobbing_speed = MYMIN(speed.getLength(), 40); m_view_bobbing_speed = speed.getLength()*0.7; } else if (m_view_bobbing_state == 1) { // Stop animation m_view_bobbing_state = 2; m_view_bobbing_speed = 60; } }