Started to refactor the camera into different classes. Normal
camera is working atm. but not much more.
This commit is contained in:
parent
caca4b06b2
commit
d65dd6c199
@ -1,5 +1,5 @@
|
||||
# Modify this file to change the last-modified date when you add/remove a file.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
|
||||
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
|
||||
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")
|
||||
|
@ -23,6 +23,10 @@
|
||||
|
||||
#include "audio/sfx_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera_debug.hpp"
|
||||
#include "graphics/camera_end.hpp"
|
||||
#include "graphics/camera_fps.hpp"
|
||||
#include "graphics/camera_normal.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
@ -38,20 +42,68 @@
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/vs.hpp"
|
||||
|
||||
#include "ICameraSceneNode.h"
|
||||
#include "ISceneManager.h"
|
||||
|
||||
AlignedArray<Camera::EndCameraInformation> Camera::m_end_cameras;
|
||||
std::vector<Camera*> Camera::m_all_cameras;
|
||||
std::vector<Camera*> Camera::m_all_cameras;
|
||||
Camera* Camera::s_active_camera = NULL;
|
||||
Camera::CameraType Camera::m_default_type = Camera::CM_TYPE_NORMAL;
|
||||
|
||||
Camera* Camera::s_active_camera = NULL;
|
||||
Camera::DebugMode Camera::m_debug_mode = Camera::CM_DEBUG_NONE;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Creates a new camera and adds it to the list of all cameras. Also the
|
||||
* camera index (which determines which viewport to use in split screen)
|
||||
* is set.
|
||||
*/
|
||||
Camera* Camera::createCamera(AbstractKart* kart)
|
||||
{
|
||||
Camera *camera = createCamera(m_all_cameras.size(), m_default_type, kart);
|
||||
m_all_cameras.push_back(camera);
|
||||
return camera;
|
||||
} // createCamera(kart)
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Creates a camera of the specified type, but does not add it to the list
|
||||
* of all cameras. This is a helper function for other static functions.
|
||||
* \paran index Index this camera has in the list of all cameras.
|
||||
* \param type The camera type of the camera to create.
|
||||
* \param kart To which kart the camera is attached (NULL if a free camera).
|
||||
*/
|
||||
Camera* Camera::createCamera(unsigned int index, CameraType type,
|
||||
AbstractKart* kart)
|
||||
{
|
||||
Camera *camera = NULL;
|
||||
switch (type)
|
||||
{
|
||||
case CM_TYPE_NORMAL: camera = new CameraNormal(index, kart); break;
|
||||
case CM_TYPE_DEBUG: camera = new CameraDebug (index, kart); break;
|
||||
case CM_TYPE_FPS: camera = new CameraFPS (index, kart); break;
|
||||
case CM_TYPE_END: camera = new CameraEnd (index, kart); break;
|
||||
} // switch type
|
||||
|
||||
return camera;
|
||||
} // createCamera
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Camera::changeCamera(unsigned int camera_index, CameraType type)
|
||||
{
|
||||
assert(camera_index<m_all_cameras.size());
|
||||
|
||||
Camera *old_camera = m_all_cameras[camera_index];
|
||||
// Nothing to do if this is already the right type.
|
||||
|
||||
if(old_camera->getType()==type) return;
|
||||
|
||||
Camera *new_camera = createCamera(old_camera->getIndex(), type,
|
||||
old_camera->m_kart );
|
||||
// Replace the previous camera
|
||||
m_all_cameras[camera_index] = new_camera;
|
||||
if(s_active_camera == old_camera)
|
||||
s_active_camera == new_camera;
|
||||
delete old_camera;
|
||||
} // changeCamera
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
|
||||
{
|
||||
m_smooth = false;
|
||||
m_attached = false;
|
||||
m_mode = CM_NORMAL;
|
||||
m_index = camera_index;
|
||||
m_original_kart = kart;
|
||||
@ -60,31 +112,8 @@ Camera::Camera(int camera_index, AbstractKart* kart) : m_kart(NULL)
|
||||
|
||||
setupCamera();
|
||||
setKart(kart);
|
||||
m_distance = kart ? kart->getKartProperties()->getCameraDistance() : 1000.0f;
|
||||
m_ambient_light = World::getWorld()->getTrack()->getDefaultAmbientColor();
|
||||
|
||||
// TODO: Put these values into a config file
|
||||
// Global or per split screen zone?
|
||||
// Either global or per user (for instance, some users may not like
|
||||
// the extra camera rotation so they could set m_rotation_range to
|
||||
// zero to disable it for themselves).
|
||||
m_position_speed = 8.0f;
|
||||
m_target_speed = 10.0f;
|
||||
m_rotation_range = 0.4f;
|
||||
m_rotation_range = 0.0f;
|
||||
m_lin_velocity = core::vector3df(0, 0, 0);
|
||||
m_target_velocity = core::vector3df(0, 0, 0);
|
||||
m_target_direction = core::vector3df(0, 0, 1);
|
||||
m_target_up_vector = core::vector3df(0, 1, 0);
|
||||
m_direction_velocity = core::vector3df(0, 0, 0);
|
||||
|
||||
m_local_position = core::vector3df(0, 0, 0);
|
||||
m_local_direction = core::vector3df(0, 0, 1);
|
||||
m_local_up = core::vector3df(0, 1, 0);
|
||||
|
||||
m_angular_velocity = 0;
|
||||
m_target_angular_velocity = 0;
|
||||
m_max_velocity = 15;
|
||||
reset();
|
||||
} // Camera
|
||||
|
||||
@ -99,53 +128,6 @@ Camera::~Camera()
|
||||
s_active_camera = NULL;
|
||||
} // ~Camera
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Applies mouse movement to the first person camera.
|
||||
* \param x The horizontal difference of the mouse position.
|
||||
* \param y The vertical difference of the mouse position.
|
||||
*/
|
||||
void Camera::applyMouseMovement (float x, float y)
|
||||
{
|
||||
vector3df direction(m_target_direction);
|
||||
vector3df up(m_camera->getUpVector());
|
||||
|
||||
// Set local values if the camera is attached to the kart
|
||||
if (m_attached)
|
||||
up = m_local_up;
|
||||
|
||||
direction.normalize();
|
||||
up.normalize();
|
||||
|
||||
vector3df side(direction.crossProduct(up));
|
||||
side.normalize();
|
||||
core::quaternion quat;
|
||||
quat.fromAngleAxis(y, side);
|
||||
|
||||
core::quaternion quat_x;
|
||||
quat_x.fromAngleAxis(x, up);
|
||||
quat *= quat_x;
|
||||
|
||||
direction = quat * direction;
|
||||
// Try to prevent toppling over
|
||||
// If the camera would topple over with the next movement, the vertical
|
||||
// movement gets reset close to the up vector
|
||||
if ((direction - up).getLengthSQ() + (m_target_direction - up).getLengthSQ()
|
||||
<= (direction - m_target_direction).getLengthSQ())
|
||||
direction = quat_x * ((m_target_direction - up).setLength(0.02f) + up);
|
||||
// Prevent toppling under
|
||||
else if ((direction + up).getLengthSQ() + (m_target_direction + up).getLengthSQ()
|
||||
<= (direction - m_target_direction).getLengthSQ())
|
||||
direction = quat_x * ((m_target_direction + up).setLength(0.02f) - up);
|
||||
m_target_direction = direction;
|
||||
|
||||
// Don't do that because it looks ugly and is bad to handle ;)
|
||||
/*side = direction.crossProduct(up);
|
||||
// Compute new up vector
|
||||
up = side.crossProduct(direction);
|
||||
up.normalize();
|
||||
cam->setUpVector(up);*/
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Changes the owner of this camera to the new kart.
|
||||
* \param new_kart The new kart to use this camera.
|
||||
@ -161,46 +143,14 @@ void Camera::setKart(AbstractKart *new_kart)
|
||||
|
||||
} // setKart
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function clears all end camera data structure. This is necessary
|
||||
* since all end cameras are shared between all camera instances (i.e. are
|
||||
* static), otherwise (if no end camera is defined for a track) the old
|
||||
* end camera structure would be used.
|
||||
*/
|
||||
void Camera::clearEndCameras()
|
||||
{
|
||||
m_end_cameras.clear();
|
||||
} // clearEndCameras
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Reads the information about the end camera. This information is shared
|
||||
* between all cameras, so this is a static function.
|
||||
* \param node The XML node containing all end camera informations
|
||||
*/
|
||||
void Camera::readEndCamera(const XMLNode &root)
|
||||
{
|
||||
m_end_cameras.clear();
|
||||
for(unsigned int i=0; i<root.getNumNodes(); i++)
|
||||
{
|
||||
unsigned int index = i;
|
||||
// In reverse mode, reverse the order in which the
|
||||
// end cameras are read.
|
||||
if(QuadGraph::get()->isReverse())
|
||||
index = root.getNumNodes() - 1 - i;
|
||||
const XMLNode *node = root.getNode(index);
|
||||
EndCameraInformation eci;
|
||||
if(!eci.readXML(*node)) continue;
|
||||
m_end_cameras.push_back(eci);
|
||||
} // for i<getNumNodes()
|
||||
} // readEndCamera
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets up the viewport, aspect ratio, field of view, and scaling for this
|
||||
* camera.
|
||||
*/
|
||||
void Camera::setupCamera()
|
||||
{
|
||||
m_aspect = (float)(irr_driver->getActualScreenSize().Width)/irr_driver->getActualScreenSize().Height;
|
||||
m_aspect = (float)(irr_driver->getActualScreenSize().Width)
|
||||
/ irr_driver->getActualScreenSize().Height;
|
||||
switch(race_manager->getNumLocalPlayers())
|
||||
{
|
||||
case 1: m_viewport = core::recti(0, 0,
|
||||
@ -277,21 +227,18 @@ void Camera::setMode(Mode mode)
|
||||
{
|
||||
// If we switch from reverse view, move the camera immediately to the
|
||||
// correct position.
|
||||
if((m_mode==CM_REVERSE && mode==CM_NORMAL) || (m_mode==CM_FALLING && mode==CM_NORMAL))
|
||||
if( (m_mode==CM_REVERSE && mode==CM_NORMAL) ||
|
||||
(m_mode==CM_FALLING && mode==CM_NORMAL) )
|
||||
{
|
||||
Vec3 start_offset(0, 1.6f, -3);
|
||||
Vec3 current_position = m_kart->getTrans()(start_offset);
|
||||
m_camera->setPosition( current_position.toIrrVector());
|
||||
m_camera->setPosition(current_position.toIrrVector());
|
||||
m_camera->setTarget(m_camera->getPosition());
|
||||
}
|
||||
if(mode==CM_FINAL)
|
||||
|
||||
if(mode==CM_TYPE_END)
|
||||
{
|
||||
if(m_end_cameras.size()>0)
|
||||
m_camera->setPosition(m_end_cameras[0].m_position.toIrrVector());
|
||||
m_next_end_camera = m_end_cameras.size()>1 ? 1 : 0;
|
||||
m_current_end_camera = 0;
|
||||
m_camera->setFOV(m_fov);
|
||||
handleEndCamera(0);
|
||||
printf("");
|
||||
} // mode==CM_FINAL
|
||||
|
||||
m_mode = mode;
|
||||
@ -303,7 +250,7 @@ void Camera::setMode(Mode mode)
|
||||
Camera::Mode Camera::getMode()
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
} // getMode
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Reset is called when a new race starts. Make sure that the camera
|
||||
@ -327,6 +274,9 @@ void Camera::setInitialTransform()
|
||||
if (m_kart == NULL) return;
|
||||
Vec3 start_offset(0, 1.6f, -3);
|
||||
Vec3 current_position = m_kart->getTrans()(start_offset);
|
||||
assert(!std::isnan(current_position.getX()));
|
||||
assert(!std::isnan(current_position.getY()));
|
||||
assert(!std::isnan(current_position.getZ()));
|
||||
m_camera->setPosition( current_position.toIrrVector());
|
||||
// Reset the target from the previous target (in case of a restart
|
||||
// of a race) - otherwise the camera will initially point in the wrong
|
||||
@ -337,179 +287,15 @@ void Camera::setInitialTransform()
|
||||
m_camera->setRotation(core::vector3df(0, 0, 0));
|
||||
m_camera->setRotation( core::vector3df( 0.0f, 0.0f, 0.0f ) );
|
||||
m_camera->setFOV(m_fov);
|
||||
|
||||
assert(!std::isnan(m_camera->getPosition().X));
|
||||
assert(!std::isnan(m_camera->getPosition().Y));
|
||||
assert(!std::isnan(m_camera->getPosition().Z));
|
||||
} // setInitialTransform
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Moves the camera smoothly from the current camera position (and target)
|
||||
* to the new position and target.
|
||||
* \param wanted_position The position the camera wanted to reach.
|
||||
* \param wanted_target The point the camera wants to point to.
|
||||
*/
|
||||
void Camera::smoothMoveCamera(float dt)
|
||||
{
|
||||
Kart *kart = dynamic_cast<Kart*>(m_kart);
|
||||
if (kart->isFlying())
|
||||
{
|
||||
Vec3 vec3 = m_kart->getXYZ() + Vec3(sin(m_kart->getHeading()) * -4.0f, 0.5f, cos(m_kart->getHeading()) * -4.0f);
|
||||
m_camera->setTarget(m_kart->getXYZ().toIrrVector());
|
||||
m_camera->setPosition(vec3.toIrrVector());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
core::vector3df current_position = m_camera->getPosition();
|
||||
// Smoothly interpolate towards the position and target
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
float max_increase_with_zipper = kp->getZipperMaxSpeedIncrease();
|
||||
float max_speed_without_zipper = kp->getEngineMaxSpeed();
|
||||
float current_speed = m_kart->getSpeed();
|
||||
|
||||
const Skidding *ks = m_kart->getSkidding();
|
||||
float skid_factor = ks->getVisualSkidRotation();
|
||||
|
||||
float skid_angle = asin(skid_factor);
|
||||
float ratio = (current_speed - max_speed_without_zipper) / max_increase_with_zipper;
|
||||
ratio = ratio > -0.12f ? ratio : -0.12f;
|
||||
float camera_distance = -3 * (0.5f + ratio);// distance of camera from kart in x and z plane
|
||||
if (camera_distance > -2.0f) camera_distance = -2.0f;
|
||||
Vec3 camera_offset(camera_distance * sin(skid_angle / 2),
|
||||
1.1f * (1 + ratio / 2),
|
||||
camera_distance * cos(skid_angle / 2));// defines how far camera should be from player kart.
|
||||
Vec3 m_kart_camera_position_with_offset = m_kart->getTrans()(camera_offset);
|
||||
|
||||
|
||||
|
||||
core::vector3df current_target = m_kart->getXYZ().toIrrVector();// next target
|
||||
current_target.Y += 0.5f;
|
||||
core::vector3df wanted_position = m_kart_camera_position_with_offset.toIrrVector();// new required position of camera
|
||||
|
||||
if ((m_kart->getSpeed() > 5 ) || (m_kart->getSpeed() < 0 ))
|
||||
{
|
||||
current_position += ((wanted_position - current_position) * dt
|
||||
* (m_kart->getSpeed()>0 ? m_kart->getSpeed()/3 + 1.0f
|
||||
: -1.5f * m_kart->getSpeed() + 2.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
current_position += (wanted_position - current_position) * dt * 5;
|
||||
}
|
||||
|
||||
// Avoid camera crash: if the speed is negative, the current_position
|
||||
// can oscillate between plus and minus, getting bigger and bigger. If
|
||||
// this happens often enough, floating point overflow happens (large
|
||||
// negative speeds can happen when the kart is tumbling/falling)
|
||||
// To avoid this, we just move the camera to the wanted position if
|
||||
// the distance becomes too large (see #1356).
|
||||
if( (current_position - wanted_position).getLengthSQ() > 100)
|
||||
{
|
||||
Log::debug("camera", "Resetting camera position to avoid crash");
|
||||
current_position = wanted_position;
|
||||
}
|
||||
|
||||
if(m_mode!=CM_FALLING)
|
||||
m_camera->setPosition(current_position);
|
||||
m_camera->setTarget(current_target);//set new target
|
||||
|
||||
assert(!std::isnan(m_camera->getPosition().X));
|
||||
assert(!std::isnan(m_camera->getPosition().Y));
|
||||
assert(!std::isnan(m_camera->getPosition().Z));
|
||||
|
||||
} // smoothMoveCamera
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Determine the camera settings for the current frame.
|
||||
* \param above_kart How far above the camera should aim at.
|
||||
* \param cam_angle Angle above the kart plane for the camera.
|
||||
* \param sideway Sideway movement of the camera.
|
||||
* \param distance Distance from kart.
|
||||
*/
|
||||
void Camera::getCameraSettings(float *above_kart, float *cam_angle,
|
||||
float *sideway, float *distance,
|
||||
bool *smoothing)
|
||||
{
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
|
||||
switch(m_mode)
|
||||
{
|
||||
case CM_NORMAL:
|
||||
case CM_FALLING:
|
||||
{
|
||||
if(m_debug_mode==CM_DEBUG_GROUND)
|
||||
{
|
||||
*above_kart = 0;
|
||||
*cam_angle = 0;
|
||||
*distance = -m_kart->getKartModel()->getLength()-1.0f;
|
||||
}
|
||||
else if(m_debug_mode==CM_DEBUG_BEHIND_KART)
|
||||
{
|
||||
*above_kart = 0;
|
||||
*cam_angle = 0;
|
||||
*distance = -0.5f*m_kart->getKartModel()->getLength()-1.0f;
|
||||
*smoothing = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
*above_kart = 0.75f;
|
||||
*cam_angle = kp->getCameraForwardUpAngle() * DEGREE_TO_RAD;
|
||||
*distance = -m_distance;
|
||||
}
|
||||
float steering = m_kart->getSteerPercent()
|
||||
* (1.0f + (m_kart->getSkidding()->getSkidFactor()
|
||||
- 1.0f)/2.3f );
|
||||
// quadratically to dampen small variations (but keep sign)
|
||||
float dampened_steer = fabsf(steering) * steering;
|
||||
*sideway = -m_rotation_range*dampened_steer*0.5f;
|
||||
*smoothing = true;
|
||||
break;
|
||||
} // CM_FALLING
|
||||
case CM_REVERSE: // Same as CM_NORMAL except it looks backwards
|
||||
{
|
||||
*above_kart = 0.75f;
|
||||
*cam_angle = kp->getCameraBackwardUpAngle() * DEGREE_TO_RAD;
|
||||
*sideway = 0;
|
||||
*distance = 2.0f*m_distance;
|
||||
*smoothing = false;
|
||||
break;
|
||||
}
|
||||
case CM_CLOSEUP: // Lower to the ground and closer to the kart
|
||||
{
|
||||
*above_kart = 0.75f;
|
||||
*cam_angle = 20.0f*DEGREE_TO_RAD;
|
||||
*sideway = m_rotation_range
|
||||
* m_kart->getSteerPercent()
|
||||
* m_kart->getSkidding()->getSkidFactor();
|
||||
*distance = -0.5f*m_distance;
|
||||
*smoothing = false;
|
||||
break;
|
||||
}
|
||||
case CM_LEADER_MODE:
|
||||
{
|
||||
*above_kart = 0.0f;
|
||||
*cam_angle = 40*DEGREE_TO_RAD;
|
||||
*sideway = 0;
|
||||
*distance = 2.0f*m_distance;
|
||||
*smoothing = true;
|
||||
break;
|
||||
}
|
||||
case CM_FINAL:
|
||||
case CM_SIMPLE_REPLAY:
|
||||
// TODO: Implement
|
||||
break;
|
||||
}
|
||||
|
||||
} // getCameraSettings
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called once per time frame to move the camera to the right position.
|
||||
* \param dt Time step.
|
||||
*/
|
||||
void Camera::update(float dt)
|
||||
{
|
||||
if (m_kart == NULL)
|
||||
if (!m_kart)
|
||||
{
|
||||
if (race_manager->getNumLocalPlayers() < 2)
|
||||
{
|
||||
@ -526,320 +312,11 @@ void Camera::update(float dt)
|
||||
{
|
||||
Vec3 heading(sin(m_kart->getHeading()), 0.0f, cos(m_kart->getHeading()));
|
||||
SFXManager::get()->positionListener(m_kart->getXYZ(),
|
||||
heading,
|
||||
Vec3(0, 1, 0));
|
||||
}
|
||||
|
||||
float above_kart, cam_angle, side_way, distance;
|
||||
bool smoothing;
|
||||
|
||||
// To view inside tunnels in top mode, increase near value
|
||||
m_camera->setNearValue(m_debug_mode==CM_DEBUG_TOP_OF_KART ? 27.0f : 1.0f);
|
||||
|
||||
// The following settings give a debug camera which shows the track from
|
||||
// high above the kart straight down.
|
||||
if (m_debug_mode==CM_DEBUG_TOP_OF_KART)
|
||||
{
|
||||
core::vector3df xyz = m_kart->getXYZ().toIrrVector();
|
||||
m_camera->setTarget(xyz);
|
||||
xyz.Y = xyz.Y+55;
|
||||
xyz.Z -= 5.0f;
|
||||
m_camera->setPosition(xyz);
|
||||
}
|
||||
else if (m_debug_mode==CM_DEBUG_SIDE_OF_KART)
|
||||
{
|
||||
core::vector3df xyz = m_kart->getXYZ().toIrrVector();
|
||||
Vec3 offset(3, 0, 0);
|
||||
offset = m_kart->getTrans()(offset);
|
||||
m_camera->setTarget(xyz);
|
||||
m_camera->setPosition(offset.toIrrVector());
|
||||
}
|
||||
// Update the first person camera
|
||||
else if (m_debug_mode == CM_DEBUG_FPS)
|
||||
{
|
||||
vector3df direction(m_camera->getTarget() - m_camera->getPosition());
|
||||
vector3df up(m_camera->getUpVector());
|
||||
vector3df side(direction.crossProduct(up));
|
||||
vector3df pos = m_camera->getPosition();
|
||||
|
||||
// Set local values if the camera is attached to the kart
|
||||
if (m_attached)
|
||||
{
|
||||
direction = m_local_direction;
|
||||
up = m_local_up;
|
||||
pos = m_local_position;
|
||||
}
|
||||
|
||||
// Update smooth movement
|
||||
if (m_smooth)
|
||||
{
|
||||
// Angular velocity
|
||||
if (m_angular_velocity < m_target_angular_velocity)
|
||||
{
|
||||
m_angular_velocity += UserConfigParams::m_fpscam_angular_velocity;
|
||||
if (m_angular_velocity > m_target_angular_velocity)
|
||||
m_angular_velocity = m_target_angular_velocity;
|
||||
}
|
||||
else if (m_angular_velocity > m_target_angular_velocity)
|
||||
{
|
||||
m_angular_velocity -= UserConfigParams::m_fpscam_angular_velocity;
|
||||
if (m_angular_velocity < m_target_angular_velocity)
|
||||
m_angular_velocity = m_target_angular_velocity;
|
||||
}
|
||||
|
||||
// Linear velocity
|
||||
core::vector3df diff(m_target_velocity - m_lin_velocity);
|
||||
if (diff.X != 0 || diff.Y != 0 || diff.Z != 0)
|
||||
{
|
||||
if (diff.getLengthSQ() > 1)
|
||||
diff.setLength(1);
|
||||
m_lin_velocity += diff;
|
||||
}
|
||||
|
||||
// Camera direction
|
||||
diff = m_target_direction - direction;
|
||||
if (diff.X != 0 || diff.Y != 0 || diff.Z != 0)
|
||||
{
|
||||
diff.setLength(UserConfigParams::m_fpscam_direction_speed);
|
||||
m_direction_velocity += diff;
|
||||
if (m_direction_velocity.getLengthSQ() >
|
||||
UserConfigParams::m_fpscam_smooth_direction_max_speed *
|
||||
UserConfigParams::m_fpscam_smooth_direction_max_speed)
|
||||
m_direction_velocity.setLength(
|
||||
UserConfigParams::m_fpscam_smooth_direction_max_speed);
|
||||
direction += m_direction_velocity;
|
||||
m_target_direction = direction;
|
||||
}
|
||||
|
||||
// Camera rotation
|
||||
diff = m_target_up_vector - up;
|
||||
if (diff.X != 0 || diff.Y != 0 || diff.Z != 0)
|
||||
{
|
||||
if (diff.getLengthSQ() >
|
||||
UserConfigParams::m_fpscam_angular_velocity *
|
||||
UserConfigParams::m_fpscam_angular_velocity)
|
||||
diff.setLength(UserConfigParams::m_fpscam_angular_velocity);
|
||||
up += diff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
direction = m_target_direction;
|
||||
up = m_target_up_vector;
|
||||
side = direction.crossProduct(up);
|
||||
}
|
||||
|
||||
// Rotate camera
|
||||
core::quaternion quat;
|
||||
quat.fromAngleAxis(m_angular_velocity * dt, direction);
|
||||
up = quat * up;
|
||||
m_target_up_vector = quat * up;
|
||||
direction.normalize();
|
||||
up.normalize();
|
||||
side.normalize();
|
||||
|
||||
// Top vector is the real up vector, not the one used by the camera
|
||||
vector3df top(side.crossProduct(direction));
|
||||
|
||||
// Move camera
|
||||
vector3df movement(direction * m_lin_velocity.Z +
|
||||
top * m_lin_velocity.Y + side * m_lin_velocity.X);
|
||||
pos = pos + movement * dt;
|
||||
|
||||
if (m_attached)
|
||||
{
|
||||
// Save current values
|
||||
m_local_position = pos;
|
||||
m_local_direction = direction;
|
||||
m_local_up = up;
|
||||
|
||||
// Move the camera with the kart
|
||||
btTransform t = m_kart->getTrans();
|
||||
if (stk_config->m_camera_follow_skid &&
|
||||
m_kart->getSkidding()->getVisualSkidRotation() != 0)
|
||||
{
|
||||
// If the camera should follow the graphical skid, add the
|
||||
// visual rotation to the relative vector:
|
||||
btQuaternion q(m_kart->getSkidding()->getVisualSkidRotation(), 0, 0);
|
||||
t.setBasis(t.getBasis() * btMatrix3x3(q));
|
||||
}
|
||||
pos = Vec3(t(Vec3(pos))).toIrrVector();
|
||||
|
||||
btQuaternion q = t.getRotation();
|
||||
btMatrix3x3 mat(q);
|
||||
direction = Vec3(mat * Vec3(direction)).toIrrVector();
|
||||
up = Vec3(mat * Vec3(up)).toIrrVector();
|
||||
}
|
||||
|
||||
// Set camera attributes
|
||||
m_camera->setPosition(pos);
|
||||
m_camera->setTarget(pos + direction);
|
||||
m_camera->setUpVector(up);
|
||||
}
|
||||
else if (m_mode==CM_FINAL)
|
||||
{
|
||||
handleEndCamera(dt);
|
||||
}
|
||||
// If an explosion is happening, stop moving the camera,
|
||||
// but keep it target on the kart.
|
||||
else if (dynamic_cast<ExplosionAnimation*>(m_kart->getKartAnimation()))
|
||||
{
|
||||
getCameraSettings(&above_kart, &cam_angle, &side_way, &distance, &smoothing);
|
||||
// The camera target needs to be 'smooth moved', otherwise
|
||||
// there will be a noticable jump in the first frame
|
||||
|
||||
// Aim at the usual same position of the kart (i.e. slightly
|
||||
// above the kart).
|
||||
// Note: this code is replicated from smoothMoveCamera so that
|
||||
// the camera keeps on pointing to the same spot.
|
||||
core::vector3df current_target = (m_kart->getXYZ().toIrrVector()+core::vector3df(0, above_kart, 0));
|
||||
m_camera->setTarget(current_target);
|
||||
}
|
||||
else
|
||||
{
|
||||
getCameraSettings(&above_kart, &cam_angle, &side_way, &distance, &smoothing);
|
||||
positionCamera(dt, above_kart, cam_angle, side_way, distance, smoothing);
|
||||
heading,
|
||||
Vec3(0, 1, 0));
|
||||
}
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Actually sets the camera based on the given parameter.
|
||||
* \param above_kart How far above the camera should aim at.
|
||||
* \param cam_angle Angle above the kart plane for the camera.
|
||||
* \param sideway Sideway movement of the camera.
|
||||
* \param distance Distance from kart.
|
||||
*/
|
||||
void Camera::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
float side_way, float distance, float smoothing)
|
||||
{
|
||||
Vec3 wanted_position;
|
||||
Vec3 wanted_target = m_kart->getXYZ();
|
||||
if(m_debug_mode==CM_DEBUG_GROUND)
|
||||
{
|
||||
const btWheelInfo &w = m_kart->getVehicle()->getWheelInfo(2);
|
||||
wanted_target.setY(w.m_raycastInfo.m_contactPointWS.getY());
|
||||
}
|
||||
else
|
||||
wanted_target.setY(wanted_target.getY()+above_kart);
|
||||
float tan_up = tan(cam_angle);
|
||||
Vec3 relative_position(side_way,
|
||||
fabsf(distance)*tan_up+above_kart,
|
||||
distance);
|
||||
btTransform t=m_kart->getTrans();
|
||||
if(stk_config->m_camera_follow_skid &&
|
||||
m_kart->getSkidding()->getVisualSkidRotation()!=0)
|
||||
{
|
||||
// If the camera should follow the graphical skid, add the
|
||||
// visual rotation to the relative vector:
|
||||
btQuaternion q(m_kart->getSkidding()->getVisualSkidRotation(), 0, 0);
|
||||
t.setBasis(t.getBasis() * btMatrix3x3(q));
|
||||
}
|
||||
if (m_debug_mode == CM_DEBUG_GROUND)
|
||||
{
|
||||
wanted_position = t(relative_position);
|
||||
// Make sure that the Y position is a the same height as the wheel.
|
||||
wanted_position.setY(wanted_target.getY());
|
||||
}
|
||||
else
|
||||
wanted_position = t(relative_position);
|
||||
|
||||
if (smoothing && !isDebug())
|
||||
{
|
||||
smoothMoveCamera(dt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_mode!=CM_FALLING)
|
||||
m_camera->setPosition(wanted_position.toIrrVector());
|
||||
m_camera->setTarget(wanted_target.toIrrVector());
|
||||
|
||||
if (race_manager->getNumLocalPlayers() < 2)
|
||||
{
|
||||
SFXManager::get()->positionListener(m_camera->getPosition(),
|
||||
wanted_target - m_camera->getPosition(),
|
||||
Vec3(0, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
Kart *kart = dynamic_cast<Kart*>(m_kart);
|
||||
if (kart && !kart->isFlying())
|
||||
{
|
||||
// Rotate the up vector (0,1,0) by the rotation ... which is just column 1
|
||||
Vec3 up = m_kart->getTrans().getBasis().getColumn(1);
|
||||
float f = 0.04f; // weight for new up vector to reduce shaking
|
||||
m_camera->setUpVector( f * up.toIrrVector() +
|
||||
(1.0f - f) * m_camera->getUpVector());
|
||||
} // kart && !flying
|
||||
else
|
||||
m_camera->setUpVector(core::vector3df(0, 1, 0));
|
||||
} // positionCamera
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** This function handles the end camera. It adjusts the camera position
|
||||
* according to the current camera type, and checks if a switch to the
|
||||
* next camera should be made.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void Camera::handleEndCamera(float dt)
|
||||
{
|
||||
// First test if the kart is close enough to the next end camera, and
|
||||
// if so activate it.
|
||||
if( m_end_cameras.size()>0 &&
|
||||
m_end_cameras[m_next_end_camera].isReached(m_kart->getXYZ()))
|
||||
{
|
||||
m_current_end_camera = m_next_end_camera;
|
||||
if(m_end_cameras[m_current_end_camera].m_type
|
||||
==EndCameraInformation::EC_STATIC_FOLLOW_KART)
|
||||
{
|
||||
m_camera->setPosition(
|
||||
m_end_cameras[m_current_end_camera].m_position.toIrrVector()
|
||||
);
|
||||
}
|
||||
m_camera->setFOV(m_fov);
|
||||
m_next_end_camera++;
|
||||
if(m_next_end_camera>=(unsigned)m_end_cameras.size())
|
||||
m_next_end_camera = 0;
|
||||
}
|
||||
|
||||
EndCameraInformation::EndCameraType info
|
||||
= m_end_cameras.size()==0 ? EndCameraInformation::EC_AHEAD_OF_KART
|
||||
: m_end_cameras[m_current_end_camera].m_type;
|
||||
|
||||
switch(info)
|
||||
{
|
||||
case EndCameraInformation::EC_STATIC_FOLLOW_KART:
|
||||
{
|
||||
// Since the camera has no parents, we can use the relative
|
||||
// position here (otherwise we need to call updateAbsolutePosition
|
||||
// after changing the relative position in order to get the right
|
||||
// position here).
|
||||
const core::vector3df &cp = m_camera->getPosition();
|
||||
const Vec3 &kp = m_kart->getXYZ();
|
||||
// Estimate the fov, assuming that the vector from the camera to
|
||||
// the kart and the kart length are orthogonal to each other
|
||||
// --> tan (fov) = kart_length / camera_kart_distance
|
||||
// In order to show a little bit of the surrounding of the kart
|
||||
// the kart length is multiplied by 6 (experimentally found)
|
||||
float fov = 6*atan2(m_kart->getKartLength(),
|
||||
(cp-kp.toIrrVector()).getLength());
|
||||
m_camera->setFOV(fov);
|
||||
m_camera->setTarget(m_kart->getXYZ().toIrrVector());
|
||||
break;
|
||||
}
|
||||
case EndCameraInformation::EC_AHEAD_OF_KART:
|
||||
{
|
||||
float cam_angle = m_kart->getKartProperties()->getCameraBackwardUpAngle() * DEGREE_TO_RAD;
|
||||
|
||||
positionCamera(dt, /*above_kart*/0.75f,
|
||||
cam_angle, /*side_way*/0,
|
||||
2.0f*m_distance, /*smoothing*/false);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
} // switch
|
||||
|
||||
} // handleEndCamera
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sets viewport etc. for this camera. Called from irr_driver just before
|
||||
* rendering the view for this kart.
|
||||
@ -855,43 +332,3 @@ void Camera::activate(bool alsoActivateInIrrlicht)
|
||||
}
|
||||
} // activate
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sets the angular velocity for this camera. */
|
||||
void Camera::setAngularVelocity(float vel)
|
||||
{
|
||||
if (m_smooth)
|
||||
m_target_angular_velocity = vel;
|
||||
else
|
||||
m_angular_velocity = vel;
|
||||
} // setAngularVelocity
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the current target angular velocity. */
|
||||
float Camera::getAngularVelocity()
|
||||
{
|
||||
if (m_smooth)
|
||||
return m_target_angular_velocity;
|
||||
else
|
||||
return m_angular_velocity;
|
||||
} // getAngularVelocity
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sets the linear velocity for this camera. */
|
||||
void Camera::setLinearVelocity(core::vector3df vel)
|
||||
{
|
||||
if (m_smooth)
|
||||
m_target_velocity = vel;
|
||||
else
|
||||
m_lin_velocity = vel;
|
||||
} // setLinearVelocity
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the current linear velocity. */
|
||||
const core::vector3df &Camera::getLinearVelocity()
|
||||
{
|
||||
if (m_smooth)
|
||||
return m_target_velocity;
|
||||
else
|
||||
return m_lin_velocity;
|
||||
} // getLinearVelocity
|
||||
|
||||
|
@ -35,11 +35,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene { class ICameraSceneNode; }
|
||||
}
|
||||
using namespace irr;
|
||||
#include "ICameraSceneNode.h"
|
||||
|
||||
class AbstractKart;
|
||||
|
||||
@ -55,37 +51,34 @@ public:
|
||||
CM_CLOSEUP, //!< Closer to kart
|
||||
CM_REVERSE, //!< Looking backwards
|
||||
CM_LEADER_MODE, //!< for deleted player karts in follow the leader
|
||||
CM_FINAL, //!< Final camera
|
||||
CM_SIMPLE_REPLAY,
|
||||
CM_FALLING
|
||||
}; // Mode
|
||||
|
||||
enum DebugMode {
|
||||
CM_DEBUG_NONE,
|
||||
CM_DEBUG_TOP_OF_KART, //!< Camera hovering over kart
|
||||
CM_DEBUG_GROUND, //!< Camera at ground level, wheel debugging
|
||||
CM_DEBUG_FPS, //!< FPS Camera
|
||||
CM_DEBUG_BEHIND_KART, //!< Camera straight behind kart
|
||||
CM_DEBUG_SIDE_OF_KART,//!< Camera to the right of the kart
|
||||
}; // DebugMode
|
||||
enum CameraType {
|
||||
CM_TYPE_NORMAL,
|
||||
CM_TYPE_DEBUG, //!< A debug camera.
|
||||
CM_TYPE_FPS, //!< FPS Camera
|
||||
CM_TYPE_END //!< End camera
|
||||
}; // CameraType
|
||||
|
||||
|
||||
private:
|
||||
static Camera* s_active_camera;
|
||||
|
||||
/** Special debug camera: 0: normal camera; 1: being high over the kart;
|
||||
2: on ground level; 3: free first person camera;
|
||||
4: straight behind kart */
|
||||
static DebugMode m_debug_mode;
|
||||
|
||||
/** The camera scene node. */
|
||||
scene::ICameraSceneNode *m_camera;
|
||||
/** The project-view matrix of the previous frame, used for the blur shader. */
|
||||
core::matrix4 m_previous_pv_matrix;
|
||||
|
||||
/** Camera's mode. */
|
||||
Mode m_mode;
|
||||
|
||||
/** The type of the camera. */
|
||||
CameraType m_type;
|
||||
|
||||
/** The default type for any newly created camera. Used to store command
|
||||
* line parameters. */
|
||||
static CameraType m_default_type;
|
||||
|
||||
/** The index of this camera which is the index of the kart it is
|
||||
* attached to. */
|
||||
unsigned int m_index;
|
||||
@ -93,24 +86,6 @@ private:
|
||||
/** Current ambient light for this camera. */
|
||||
video::SColor m_ambient_light;
|
||||
|
||||
/** Distance between the camera and the kart. */
|
||||
float m_distance;
|
||||
|
||||
/** The speed at which the camera changes position. */
|
||||
float m_position_speed;
|
||||
|
||||
/** The speed at which the camera target changes position. */
|
||||
float m_target_speed;
|
||||
|
||||
/** Factor of the effects of steering in camera aim. */
|
||||
float m_rotation_range;
|
||||
|
||||
/** The kart that the camera follows. It can't be const,
|
||||
* since in profile mode the camera might change its owner.
|
||||
* May be NULL (example: cutscene camera)
|
||||
*/
|
||||
AbstractKart *m_kart;
|
||||
|
||||
/** A pointer to the original kart the camera was pointing at when it
|
||||
* was created. Used when restarting a race (since the camera might
|
||||
* get attached to another kart if a kart is elimiated). */
|
||||
@ -128,136 +103,55 @@ private:
|
||||
/** Aspect ratio for camera. */
|
||||
float m_aspect;
|
||||
|
||||
/** Smooth acceleration with the first person camera. */
|
||||
bool m_smooth;
|
||||
|
||||
/** Attache the first person camera to a kart.
|
||||
That means moving the kart also moves the camera. */
|
||||
bool m_attached;
|
||||
|
||||
/** The speed at which the up-vector rotates, only used for the first person camera. */
|
||||
float m_angular_velocity;
|
||||
|
||||
/** Target angular velocity. Used for smooth movement in fps perpective. */
|
||||
float m_target_angular_velocity;
|
||||
|
||||
/** Maximum velocity for fps camera. */
|
||||
float m_max_velocity;
|
||||
|
||||
/** Linear velocity of the camera, used for end and first person camera.
|
||||
It's stored relative to the camera direction for the first person view. */
|
||||
core::vector3df m_lin_velocity;
|
||||
|
||||
/** Velocity of the target of the camera, used for end and first person camera. */
|
||||
core::vector3df m_target_velocity;
|
||||
|
||||
/** The target direction for the camera, only used for the first person camera. */
|
||||
core::vector3df m_target_direction;
|
||||
|
||||
/** The speed at which the direction changes, only used for the first person camera. */
|
||||
core::vector3df m_direction_velocity;
|
||||
|
||||
/** The up vector the camera should have, only used for the first person camera. */
|
||||
core::vector3df m_target_up_vector;
|
||||
|
||||
/** Save the local position if the first person camera is attached to the kart. */
|
||||
core::vector3df m_local_position;
|
||||
|
||||
/** Save the local direction if the first person camera is attached to the kart. */
|
||||
core::vector3df m_local_direction;
|
||||
|
||||
/** Save the local up vector if the first person camera is attached to the kart. */
|
||||
core::vector3df m_local_up;
|
||||
|
||||
/** List of all cameras. */
|
||||
static std::vector<Camera*> m_all_cameras;
|
||||
|
||||
/** A class that stores information about the different end cameras
|
||||
* which can be specified in the scene.xml file. */
|
||||
class EndCameraInformation
|
||||
{
|
||||
public:
|
||||
/** The camera type:
|
||||
EC_STATIC_FOLLOW_KART A static camera that always points at the
|
||||
kart.
|
||||
EC_AHEAD_OF_KART A camera that flies ahead of the kart
|
||||
always pointing at the kart.
|
||||
*/
|
||||
typedef enum {EC_STATIC_FOLLOW_KART,
|
||||
EC_AHEAD_OF_KART} EndCameraType;
|
||||
EndCameraType m_type;
|
||||
|
||||
/** Position of the end camera. */
|
||||
Vec3 m_position;
|
||||
|
||||
/** Distance to kart by which this camera is activated. */
|
||||
float m_distance2;
|
||||
|
||||
/** Reads end camera information from XML. Returns false if an
|
||||
* error occurred.
|
||||
* \param node XML Node with the end camera information. */
|
||||
bool readXML(const XMLNode &node)
|
||||
{
|
||||
std::string s;
|
||||
node.get("type", &s);
|
||||
if(s=="static_follow_kart")
|
||||
m_type = EC_STATIC_FOLLOW_KART;
|
||||
else if(s=="ahead_of_kart")
|
||||
m_type = EC_AHEAD_OF_KART;
|
||||
else
|
||||
{
|
||||
Log::warn("Camera", "Invalid camera type '%s' - camera is ignored.",
|
||||
s.c_str());
|
||||
return false;
|
||||
}
|
||||
node.get("xyz", &m_position);
|
||||
node.get("distance", &m_distance2);
|
||||
// Store the squared value
|
||||
m_distance2 *= m_distance2;
|
||||
return true;
|
||||
} // readXML
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns true if the specified position is close enough to this
|
||||
* camera, so that this camera should become the next end camera.
|
||||
* \param xyz Position to test for distance.
|
||||
* \returns True if xyz is close enough to this camera.
|
||||
*/
|
||||
bool isReached(const Vec3 &xyz)
|
||||
{ return (xyz-m_position).length2() < m_distance2; }
|
||||
}; // EndCameraInformation
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** List of all end camera information. This information is shared
|
||||
* between all cameras, so it's static. */
|
||||
static AlignedArray<EndCameraInformation> m_end_cameras;
|
||||
|
||||
/** Index of the current end camera. */
|
||||
unsigned int m_current_end_camera;
|
||||
|
||||
/** The next end camera to be activated. */
|
||||
unsigned int m_next_end_camera;
|
||||
|
||||
void setupCamera();
|
||||
void smoothMoveCamera(float dt);
|
||||
void handleEndCamera(float dt);
|
||||
void getCameraSettings(float *above_kart, float *cam_angle,
|
||||
float *side_way, float *distance,
|
||||
bool *smoothing);
|
||||
void positionCamera(float dt, float above_kart, float cam_angle,
|
||||
float side_way, float distance, float smoothing);
|
||||
|
||||
Camera(int camera_index, AbstractKart* kart);
|
||||
~Camera();
|
||||
protected:
|
||||
/** The camera scene node. */
|
||||
scene::ICameraSceneNode *m_camera;
|
||||
|
||||
/** The kart that the camera follows. It can't be const,
|
||||
* since in profile mode the camera might change its owner.
|
||||
* May be NULL (example: cutscene camera)
|
||||
*/
|
||||
AbstractKart *m_kart;
|
||||
|
||||
static Camera* createCamera(unsigned int index, CameraType type,
|
||||
AbstractKart* kart);
|
||||
|
||||
Camera(int camera_index, AbstractKart* kart);
|
||||
virtual ~Camera();
|
||||
public:
|
||||
LEAK_CHECK()
|
||||
|
||||
/** Returns the number of cameras used. */
|
||||
static unsigned int getNumCameras() { return (unsigned int)m_all_cameras.size(); }
|
||||
// ========================================================================
|
||||
// Static functions
|
||||
static Camera* createCamera(AbstractKart* kart);
|
||||
static void changeCamera(unsigned int camera_index, CameraType type);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the default type for each camera that will be created. Used for
|
||||
* command line parameters to select a debug etc camera. */
|
||||
static void setDefaultCameraType(CameraType type) { m_default_type = type;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the default type for each camera that will be created. Used
|
||||
* for command line parameters to select a debug etc camera. */
|
||||
static CameraType getDefaultCameraType() { return m_default_type;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of cameras used. */
|
||||
static unsigned int getNumCameras()
|
||||
{
|
||||
return (unsigned int)m_all_cameras.size();
|
||||
} // getNumCameras
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a camera. */
|
||||
static Camera *getCamera(unsigned int n) { return m_all_cameras[n]; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the currently active camera. */
|
||||
static Camera* getActiveCamera() { return s_active_camera; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Remove all cameras. */
|
||||
static void removeAllCameras()
|
||||
@ -267,37 +161,21 @@ public:
|
||||
m_all_cameras.clear();
|
||||
} // removeAllCameras
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Creates a camera and adds it to the list of all cameras. Also the
|
||||
* camera index (which determines which viewport to use in split screen)
|
||||
* is set.
|
||||
*/
|
||||
static Camera* createCamera(AbstractKart* kart)
|
||||
{
|
||||
Camera *c = new Camera((int)m_all_cameras.size(), kart);
|
||||
m_all_cameras.push_back(c);
|
||||
return c;
|
||||
} // createCamera
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
static void readEndCamera(const XMLNode &root);
|
||||
static void clearEndCameras();
|
||||
// ------------------------------------------------------------------------
|
||||
static void setDebugMode(DebugMode debug_mode) { m_debug_mode = debug_mode;}
|
||||
// ------------------------------------------------------------------------
|
||||
static bool isDebug() { return m_debug_mode != CM_DEBUG_NONE; }
|
||||
// ------------------------------------------------------------------------
|
||||
static bool isFPS() { return m_debug_mode == CM_DEBUG_FPS; }
|
||||
// ------------------------------------------------------------------------
|
||||
// ========================================================================
|
||||
|
||||
void setMode(Mode mode); /** Set the camera to the given mode */
|
||||
Mode getMode();
|
||||
void reset();
|
||||
void setInitialTransform();
|
||||
void activate(bool alsoActivateInIrrlicht=true);
|
||||
void update(float dt);
|
||||
void setKart(AbstractKart *new_kart);
|
||||
|
||||
virtual void reset();
|
||||
virtual void setInitialTransform();
|
||||
virtual void activate(bool alsoActivateInIrrlicht=true);
|
||||
virtual void update(float dt);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the type of this camera. */
|
||||
CameraType getType() { return m_type; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the field of view for the irrlicht camera. */
|
||||
void setFoV() { m_camera->setFOV(m_fov); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the camera index (or player kart index, which is the same). */
|
||||
int getIndex() const {return m_index;}
|
||||
@ -317,66 +195,6 @@ public:
|
||||
/** Returns the kart to which this camera is attached. */
|
||||
AbstractKart* getKart() { return m_kart; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Applies mouse movement to the first person camera. */
|
||||
void applyMouseMovement (float x, float y);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets if the first person camera should be moved smooth. */
|
||||
void setSmoothMovement (bool value) { m_smooth = value; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** If the first person camera should be moved smooth. */
|
||||
bool getSmoothMovement () { return m_smooth; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets if the first person camera should be moved with the kart. */
|
||||
void setAttachedFpsCam (bool value) { m_attached = value; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** If the first person camera should be moved with the kart. */
|
||||
bool getAttachedFpsCam () { return m_attached; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the angular velocity for this camera. */
|
||||
void setMaximumVelocity (float vel) { m_max_velocity = vel; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current angular velocity. */
|
||||
float getMaximumVelocity () { return m_max_velocity; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the vector, the first person camera should look at. */
|
||||
void setDirection (core::vector3df target) { m_target_direction = target; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Gets the vector, the first person camera should look at. */
|
||||
const core::vector3df &getDirection () { return m_target_direction; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the up vector, the first person camera should use. */
|
||||
void setUpVector (core::vector3df target) { m_target_up_vector = target; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Gets the up vector, the first person camera should use. */
|
||||
const core::vector3df &getUpVector () { return m_target_up_vector; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the angular velocity for this camera. */
|
||||
void setAngularVelocity (float vel);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current target angular velocity. */
|
||||
float getAngularVelocity ();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the linear velocity for this camera. */
|
||||
void setLinearVelocity (core::vector3df vel);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current linear velocity. */
|
||||
const core::vector3df &getLinearVelocity ();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the ambient light for this camera. */
|
||||
void setAmbientLight(const video::SColor &color) { m_ambient_light=color; }
|
||||
@ -396,9 +214,9 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the camera scene node. */
|
||||
scene::ICameraSceneNode *getCameraSceneNode() { return m_camera; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
static Camera* getActiveCamera() { return s_active_camera; }
|
||||
/** Returs the absolute position of the camera. */
|
||||
Vec3 getXYZ() { return Vec3(m_camera->getPosition()); }
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
217
src/graphics/camera_debug.cpp
Normal file
217
src/graphics/camera_debug.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2004-2015 Steve Baker <sjbaker1@airmail.net>
|
||||
// Copyright (C) 2006-2015 SuperTuxKart-Team, Steve Baker
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "graphics/camera_debug.hpp"
|
||||
|
||||
#include "config/stk_config.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/explosion_animation.hpp"
|
||||
#include "karts/kart.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/skidding.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
|
||||
CameraDebug::CameraDebugType CameraDebug::m_default_debug_Type =
|
||||
CameraDebug::CM_DEBUG_TOP_OF_KART;
|
||||
|
||||
// ============================================================================
|
||||
CameraDebug::CameraDebug(int camera_index, AbstractKart* kart)
|
||||
: CameraNormal(camera_index, kart)
|
||||
{
|
||||
reset();
|
||||
} // Camera
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Removes the camera scene node from the scene.
|
||||
*/
|
||||
CameraDebug::~CameraDebug()
|
||||
{
|
||||
} // ~CameraDebug
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Determine the camera settings for the current frame.
|
||||
* \param above_kart How far above the camera should aim at.
|
||||
* \param cam_angle Angle above the kart plane for the camera.
|
||||
* \param sideway Sideway movement of the camera.
|
||||
* \param distance Distance from kart.
|
||||
*/
|
||||
void CameraDebug::getCameraSettings(float *above_kart, float *cam_angle,
|
||||
float *sideway, float *distance,
|
||||
bool *smoothing)
|
||||
{
|
||||
const KartProperties *kp = getKart()->getKartProperties();
|
||||
|
||||
// Set some default values
|
||||
float steering = m_kart->getSteerPercent()
|
||||
* (1.0f + (m_kart->getSkidding()->getSkidFactor()
|
||||
- 1.0f) / 2.3f);
|
||||
// quadratically to dampen small variations (but keep sign)
|
||||
float dampened_steer = fabsf(steering) * steering;
|
||||
*sideway = -m_rotation_range*dampened_steer*0.5f;
|
||||
*above_kart = 0;
|
||||
*cam_angle = 0;
|
||||
*smoothing = true;
|
||||
|
||||
switch(m_default_debug_Type)
|
||||
{
|
||||
case CM_DEBUG_BEHIND_KART:
|
||||
*distance = -0.5f*m_kart->getKartModel()->getLength()-1.0f;
|
||||
break;
|
||||
case CM_DEBUG_GROUND:
|
||||
*distance = -m_kart->getKartModel()->getLength()-1.0f;
|
||||
break;
|
||||
case CM_DEBUG_SIDE_OF_KART:
|
||||
case CM_DEBUG_TOP_OF_KART:
|
||||
*above_kart = 0.75f;
|
||||
*cam_angle = kp->getCameraForwardUpAngle() * DEGREE_TO_RAD;
|
||||
*distance = -m_distance;
|
||||
break;
|
||||
} // switch
|
||||
|
||||
} // getCameraSettings
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called once per time frame to move the camera to the right position.
|
||||
* \param dt Time step.
|
||||
*/
|
||||
void CameraDebug::update(float dt)
|
||||
{
|
||||
Camera::update(dt);
|
||||
|
||||
// To view inside tunnels in top mode, increase near value
|
||||
m_camera->setNearValue(m_default_debug_Type==CM_DEBUG_TOP_OF_KART
|
||||
? 27.0f : 1.0f);
|
||||
|
||||
float above_kart, cam_angle, side_way, distance;
|
||||
bool smoothing;
|
||||
|
||||
// The following settings give a debug camera which shows the track from
|
||||
// high above the kart straight down.
|
||||
if (m_default_debug_Type==CM_DEBUG_TOP_OF_KART)
|
||||
{
|
||||
core::vector3df xyz = m_kart->getXYZ().toIrrVector();
|
||||
m_camera->setTarget(xyz);
|
||||
xyz.Y = xyz.Y+55;
|
||||
xyz.Z -= 5.0f;
|
||||
m_camera->setPosition(xyz);
|
||||
}
|
||||
else if (m_default_debug_Type==CM_DEBUG_SIDE_OF_KART)
|
||||
{
|
||||
core::vector3df xyz = m_kart->getXYZ().toIrrVector();
|
||||
Vec3 offset(3, 0, 0);
|
||||
offset = m_kart->getTrans()(offset);
|
||||
m_camera->setTarget(xyz);
|
||||
m_camera->setPosition(offset.toIrrVector());
|
||||
}
|
||||
// Update the first person camera
|
||||
// If an explosion is happening, stop moving the camera,
|
||||
// but keep it target on the kart.
|
||||
else if (dynamic_cast<ExplosionAnimation*>(m_kart->getKartAnimation()))
|
||||
{
|
||||
getCameraSettings(&above_kart, &cam_angle, &side_way, &distance, &smoothing);
|
||||
// The camera target needs to be 'smooth moved', otherwise
|
||||
// there will be a noticable jump in the first frame
|
||||
|
||||
// Aim at the usual same position of the kart (i.e. slightly
|
||||
// above the kart).
|
||||
// Note: this code is replicated from smoothMoveCamera so that
|
||||
// the camera keeps on pointing to the same spot.
|
||||
core::vector3df current_target = (m_kart->getXYZ().toIrrVector()+core::vector3df(0, above_kart, 0));
|
||||
m_camera->setTarget(current_target);
|
||||
}
|
||||
else
|
||||
{
|
||||
getCameraSettings(&above_kart, &cam_angle, &side_way, &distance, &smoothing);
|
||||
positionCamera(dt, above_kart, cam_angle, side_way, distance, smoothing);
|
||||
}
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Actually sets the camera based on the given parameter.
|
||||
* \param above_kart How far above the camera should aim at.
|
||||
* \param cam_angle Angle above the kart plane for the camera.
|
||||
* \param sideway Sideway movement of the camera.
|
||||
* \param distance Distance from kart.
|
||||
*/
|
||||
void CameraDebug::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
float side_way, float distance,
|
||||
float smoothing)
|
||||
{
|
||||
Vec3 wanted_position;
|
||||
Vec3 wanted_target = m_kart->getXYZ();
|
||||
if(m_default_debug_Type==CM_DEBUG_GROUND)
|
||||
{
|
||||
const btWheelInfo &w = m_kart->getVehicle()->getWheelInfo(2);
|
||||
wanted_target.setY(w.m_raycastInfo.m_contactPointWS.getY());
|
||||
}
|
||||
else
|
||||
wanted_target.setY(wanted_target.getY()+above_kart);
|
||||
float tan_up = tan(cam_angle);
|
||||
Vec3 relative_position(side_way,
|
||||
fabsf(distance)*tan_up+above_kart,
|
||||
distance);
|
||||
btTransform t=m_kart->getTrans();
|
||||
if(stk_config->m_camera_follow_skid &&
|
||||
m_kart->getSkidding()->getVisualSkidRotation()!=0)
|
||||
{
|
||||
// If the camera should follow the graphical skid, add the
|
||||
// visual rotation to the relative vector:
|
||||
btQuaternion q(m_kart->getSkidding()->getVisualSkidRotation(), 0, 0);
|
||||
t.setBasis(t.getBasis() * btMatrix3x3(q));
|
||||
}
|
||||
if (m_default_debug_Type == CM_DEBUG_GROUND)
|
||||
{
|
||||
wanted_position = t(relative_position);
|
||||
// Make sure that the Y position is a the same height as the wheel.
|
||||
wanted_position.setY(wanted_target.getY());
|
||||
}
|
||||
else
|
||||
wanted_position = t(relative_position);
|
||||
|
||||
if (smoothing && !isDebug())
|
||||
{
|
||||
smoothMoveCamera(dt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (getMode()!=CM_FALLING)
|
||||
m_camera->setPosition(wanted_position.toIrrVector());
|
||||
m_camera->setTarget(wanted_target.toIrrVector());
|
||||
|
||||
if (race_manager->getNumLocalPlayers() < 2)
|
||||
{
|
||||
SFXManager::get()->positionListener(m_camera->getPosition(),
|
||||
wanted_target - m_camera->getPosition(),
|
||||
Vec3(0, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
Kart *kart = dynamic_cast<Kart*>(m_kart);
|
||||
if (kart && !kart->isFlying())
|
||||
{
|
||||
// Rotate the up vector (0,1,0) by the rotation ... which is just column 1
|
||||
Vec3 up = m_kart->getTrans().getBasis().getColumn(1);
|
||||
float f = 0.04f; // weight for new up vector to reduce shaking
|
||||
m_camera->setUpVector( f * up.toIrrVector() +
|
||||
(1.0f - f) * m_camera->getUpVector());
|
||||
} // kart && !flying
|
||||
else
|
||||
m_camera->setUpVector(core::vector3df(0, 1, 0));
|
||||
} // positionCamera
|
||||
|
70
src/graphics/camera_debug.hpp
Normal file
70
src/graphics/camera_debug.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2004-2015 Steve Baker <sjbaker1@airmail.net>
|
||||
// Copyright (C) 2006-2015 SuperTuxKart-Team, Steve Baker
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_CAMERA_DEBUG_HPP
|
||||
#define HEADER_CAMERA_DEBUG_HPP
|
||||
|
||||
#include "graphics/camera_normal.hpp"
|
||||
|
||||
class AbstractKart;
|
||||
|
||||
/**
|
||||
* Handles the debug camera. Inherits from CameraNormal to make use
|
||||
* of the smoothing function.
|
||||
* \ingroup graphics
|
||||
*/
|
||||
class CameraDebug : public CameraNormal
|
||||
{
|
||||
public:
|
||||
enum CameraDebugType {
|
||||
CM_DEBUG_TOP_OF_KART, //!< Camera hovering over kart
|
||||
CM_DEBUG_GROUND, //!< Camera at ground level, wheel debugging
|
||||
CM_DEBUG_BEHIND_KART, //!< Camera straight behind kart
|
||||
CM_DEBUG_SIDE_OF_KART, //!< Camera to the right of the kart
|
||||
}; // CameraDebugType
|
||||
|
||||
private:
|
||||
|
||||
static CameraDebugType m_default_debug_Type;
|
||||
|
||||
void getCameraSettings(float *above_kart, float *cam_angle,
|
||||
float *side_way, float *distance,
|
||||
bool *smoothing);
|
||||
void positionCamera(float dt, float above_kart, float cam_angle,
|
||||
float side_way, float distance, float smoothing);
|
||||
|
||||
friend class Camera;
|
||||
CameraDebug(int camera_index, AbstractKart* kart);
|
||||
virtual ~CameraDebug();
|
||||
public:
|
||||
|
||||
void update(float dt);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the debug type for all cameras. */
|
||||
static void setDebugType(CameraDebugType type)
|
||||
{
|
||||
m_default_debug_Type = type;
|
||||
} // setDebugType
|
||||
|
||||
}; // CameraDebug
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
144
src/graphics/camera_end.cpp
Normal file
144
src/graphics/camera_end.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2006-2016 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "graphics/camera_end.hpp"
|
||||
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
|
||||
#include "ICameraSceneNode.h"
|
||||
|
||||
AlignedArray<CameraEnd::EndCameraInformation> CameraEnd::m_end_cameras;
|
||||
// ============================================================================
|
||||
CameraEnd::CameraEnd(int camera_index, AbstractKart* kart)
|
||||
: CameraNormal(camera_index, kart)
|
||||
{
|
||||
reset();
|
||||
if(m_end_cameras.size()>0)
|
||||
m_camera->setPosition(m_end_cameras[0].m_position.toIrrVector());
|
||||
m_next_end_camera = m_end_cameras.size()>1 ? 1 : 0;
|
||||
m_current_end_camera = 0;
|
||||
setFoV();
|
||||
update(0);
|
||||
} // Camera
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This function clears all end camera data structure. This is necessary
|
||||
* since all end cameras are shared between all camera instances (i.e. are
|
||||
* static), otherwise (if no end camera is defined for a track) the old
|
||||
* end camera structure would be used.
|
||||
*/
|
||||
void CameraEnd::clearEndCameras()
|
||||
{
|
||||
m_end_cameras.clear();
|
||||
} // clearEndCameras
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Reads the information about the end camera. This information is shared
|
||||
* between all cameras, so this is a static function.
|
||||
* \param node The XML node containing all end camera informations
|
||||
*/
|
||||
void CameraEnd::readEndCamera(const XMLNode &root)
|
||||
{
|
||||
m_end_cameras.clear();
|
||||
for(unsigned int i=0; i<root.getNumNodes(); i++)
|
||||
{
|
||||
unsigned int index = i;
|
||||
// In reverse mode, reverse the order in which the
|
||||
// end cameras are read.
|
||||
if(QuadGraph::get()->isReverse())
|
||||
index = root.getNumNodes() - 1 - i;
|
||||
const XMLNode *node = root.getNode(index);
|
||||
EndCameraInformation eci;
|
||||
if(!eci.readXML(*node)) continue;
|
||||
m_end_cameras.push_back(eci);
|
||||
} // for i<getNumNodes()
|
||||
} // readEndCamera
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called once per time frame to move the camera to the right position.
|
||||
* This function handles the end camera. It adjusts the camera position
|
||||
* according to the current camera type, and checks if a switch to the
|
||||
* next camera should be made.
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void CameraEnd::update(float dt)
|
||||
{
|
||||
Camera::update(dt);
|
||||
m_camera->setNearValue(1.0f);
|
||||
|
||||
// First test if the kart is close enough to the next end camera, and
|
||||
// if so activate it.
|
||||
if( m_end_cameras.size()>0 &&
|
||||
m_end_cameras[m_next_end_camera].isReached(m_kart->getXYZ()))
|
||||
{
|
||||
m_current_end_camera = m_next_end_camera;
|
||||
if(m_end_cameras[m_current_end_camera].m_type
|
||||
==EndCameraInformation::EC_STATIC_FOLLOW_KART)
|
||||
{
|
||||
m_camera->setPosition(
|
||||
m_end_cameras[m_current_end_camera].m_position.toIrrVector()
|
||||
);
|
||||
}
|
||||
setFoV();
|
||||
m_next_end_camera++;
|
||||
if(m_next_end_camera>=(unsigned)m_end_cameras.size())
|
||||
m_next_end_camera = 0;
|
||||
}
|
||||
|
||||
EndCameraInformation::EndCameraType info
|
||||
= m_end_cameras.size()==0 ? EndCameraInformation::EC_AHEAD_OF_KART
|
||||
: m_end_cameras[m_current_end_camera].m_type;
|
||||
|
||||
switch(info)
|
||||
{
|
||||
case EndCameraInformation::EC_STATIC_FOLLOW_KART:
|
||||
{
|
||||
// Since the camera has no parents, we can use the relative
|
||||
// position here (otherwise we need to call updateAbsolutePosition
|
||||
// after changing the relative position in order to get the right
|
||||
// position here).
|
||||
const core::vector3df &cp = m_camera->getPosition();
|
||||
const Vec3 &kp = m_kart->getXYZ();
|
||||
// Estimate the fov, assuming that the vector from the camera to
|
||||
// the kart and the kart length are orthogonal to each other
|
||||
// --> tan (fov) = kart_length / camera_kart_distance
|
||||
// In order to show a little bit of the surrounding of the kart
|
||||
// the kart length is multiplied by 6 (experimentally found)
|
||||
float fov = 6*atan2(m_kart->getKartLength(),
|
||||
(cp-kp.toIrrVector()).getLength());
|
||||
m_camera->setFOV(fov);
|
||||
m_camera->setTarget(m_kart->getXYZ().toIrrVector());
|
||||
break;
|
||||
}
|
||||
case EndCameraInformation::EC_AHEAD_OF_KART:
|
||||
{
|
||||
float cam_angle = m_kart->getKartProperties()->getCameraBackwardUpAngle()
|
||||
* DEGREE_TO_RAD;
|
||||
|
||||
positionCamera(dt, /*above_kart*/0.75f,
|
||||
cam_angle, /*side_way*/0,
|
||||
2.0f*getDistanceToKart(), /*smoothing*/false);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
} // switch
|
||||
|
||||
} // update
|
115
src/graphics/camera_end.hpp
Normal file
115
src/graphics/camera_end.hpp
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2004-2015 Steve Baker <sjbaker1@airmail.net>
|
||||
// Copyright (C) 2006-2015 SuperTuxKart-Team, Steve Baker
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_CAMERA_END_HPP
|
||||
#define HEADER_CAMERA_END_HPP
|
||||
|
||||
#include "graphics/camera_normal.hpp"
|
||||
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
/**
|
||||
* Handles the end race camera. It inherits from CameraNormal to make
|
||||
* use of the normal camera implementation of a reverse camera.
|
||||
* \ingroup graphics
|
||||
*/
|
||||
class CameraEnd : public CameraNormal
|
||||
{
|
||||
private:
|
||||
/** A class that stores information about the different end cameras
|
||||
* which can be specified in the scene.xml file. */
|
||||
class EndCameraInformation
|
||||
{
|
||||
public:
|
||||
/** The camera type:
|
||||
EC_STATIC_FOLLOW_KART A static camera that always points at the
|
||||
kart.
|
||||
EC_AHEAD_OF_KART A camera that flies ahead of the kart
|
||||
always pointing at the kart.
|
||||
*/
|
||||
typedef enum {EC_STATIC_FOLLOW_KART,
|
||||
EC_AHEAD_OF_KART} EndCameraType;
|
||||
EndCameraType m_type;
|
||||
|
||||
/** Position of the end camera. */
|
||||
Vec3 m_position;
|
||||
|
||||
/** Distance to kart by which this camera is activated. */
|
||||
float m_distance2;
|
||||
|
||||
/** Reads end camera information from XML. Returns false if an
|
||||
* error occurred.
|
||||
* \param node XML Node with the end camera information. */
|
||||
bool readXML(const XMLNode &node)
|
||||
{
|
||||
std::string s;
|
||||
node.get("type", &s);
|
||||
if(s=="static_follow_kart")
|
||||
m_type = EC_STATIC_FOLLOW_KART;
|
||||
else if(s=="ahead_of_kart")
|
||||
m_type = EC_AHEAD_OF_KART;
|
||||
else
|
||||
{
|
||||
Log::warn("Camera", "Invalid camera type '%s' - camera is ignored.",
|
||||
s.c_str());
|
||||
return false;
|
||||
}
|
||||
node.get("xyz", &m_position);
|
||||
node.get("distance", &m_distance2);
|
||||
// Store the squared value
|
||||
m_distance2 *= m_distance2;
|
||||
return true;
|
||||
} // readXML
|
||||
// --------------------------------------------------------------------
|
||||
/** Returns true if the specified position is close enough to this
|
||||
* camera, so that this camera should become the next end camera.
|
||||
* \param xyz Position to test for distance.
|
||||
* \returns True if xyz is close enough to this camera.
|
||||
*/
|
||||
bool isReached(const Vec3 &xyz)
|
||||
{ return (xyz-m_position).length2() < m_distance2; }
|
||||
}; // EndCameraInformation
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/** List of all end camera information. This information is shared
|
||||
* between all cameras, so it's static. */
|
||||
static AlignedArray<EndCameraInformation> m_end_cameras;
|
||||
|
||||
/** Index of the current end camera. */
|
||||
unsigned int m_current_end_camera;
|
||||
|
||||
/** The next end camera to be activated. */
|
||||
unsigned int m_next_end_camera;
|
||||
|
||||
void handleEndCamera(float dt);
|
||||
|
||||
friend class Camera; // Give Camera access to constructor
|
||||
CameraEnd(int camera_index, AbstractKart* kart);
|
||||
virtual ~CameraEnd() {}
|
||||
public:
|
||||
|
||||
static void readEndCamera(const XMLNode &root);
|
||||
static void clearEndCameras();
|
||||
virtual void update(float dt) OVERRIDE;
|
||||
}; // class CameraEnd
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
289
src/graphics/camera_fps.cpp
Normal file
289
src/graphics/camera_fps.cpp
Normal file
@ -0,0 +1,289 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2004-2015 Steve Baker <sjbaker1@airmail.net>
|
||||
// Copyright (C) 2006-2015 SuperTuxKart-Team, Steve Baker
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "graphics/camera_fps.hpp"
|
||||
|
||||
#include "config/stk_config.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/skidding.hpp"
|
||||
|
||||
#include "vector3d.h"
|
||||
|
||||
using namespace irr;
|
||||
|
||||
// ============================================================================
|
||||
CameraFPS::CameraFPS(int camera_index, AbstractKart* kart)
|
||||
: Camera(camera_index, kart)
|
||||
{
|
||||
m_attached = false;
|
||||
|
||||
// TODO: Put these values into a config file
|
||||
// Global or per split screen zone?
|
||||
// Either global or per user (for instance, some users may not like
|
||||
// the extra camera rotation so they could set m_rotation_range to
|
||||
// zero to disable it for themselves).
|
||||
m_position_speed = 8.0f;
|
||||
m_target_speed = 10.0f;
|
||||
m_rotation_range = 0.4f;
|
||||
m_rotation_range = 0.0f;
|
||||
m_lin_velocity = core::vector3df(0, 0, 0);
|
||||
m_target_velocity = core::vector3df(0, 0, 0);
|
||||
m_target_direction = core::vector3df(0, 0, 1);
|
||||
m_target_up_vector = core::vector3df(0, 1, 0);
|
||||
m_direction_velocity = core::vector3df(0, 0, 0);
|
||||
|
||||
m_local_position = core::vector3df(0, 0, 0);
|
||||
m_local_direction = core::vector3df(0, 0, 1);
|
||||
m_local_up = core::vector3df(0, 1, 0);
|
||||
|
||||
m_angular_velocity = 0;
|
||||
m_target_angular_velocity = 0;
|
||||
m_max_velocity = 15;
|
||||
reset();
|
||||
} // Camera
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Removes the camera scene node from the scene.
|
||||
*/
|
||||
CameraFPS::~CameraFPS()
|
||||
{
|
||||
} // ~Camera
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Applies mouse movement to the first person camera.
|
||||
* \param x The horizontal difference of the mouse position.
|
||||
* \param y The vertical difference of the mouse position.
|
||||
*/
|
||||
void CameraFPS::applyMouseMovement (float x, float y)
|
||||
{
|
||||
core::vector3df direction(m_target_direction);
|
||||
core::vector3df up(m_camera->getUpVector());
|
||||
|
||||
// Set local values if the camera is attached to the kart
|
||||
if (m_attached)
|
||||
up = m_local_up;
|
||||
|
||||
direction.normalize();
|
||||
up.normalize();
|
||||
|
||||
core::vector3df side(direction.crossProduct(up));
|
||||
side.normalize();
|
||||
core::quaternion quat;
|
||||
quat.fromAngleAxis(y, side);
|
||||
|
||||
core::quaternion quat_x;
|
||||
quat_x.fromAngleAxis(x, up);
|
||||
quat *= quat_x;
|
||||
|
||||
direction = quat * direction;
|
||||
// Try to prevent toppling over
|
||||
// If the camera would topple over with the next movement, the vertical
|
||||
// movement gets reset close to the up vector
|
||||
if ((direction - up).getLengthSQ() + (m_target_direction - up).getLengthSQ()
|
||||
<= (direction - m_target_direction).getLengthSQ())
|
||||
direction = quat_x * ((m_target_direction - up).setLength(0.02f) + up);
|
||||
// Prevent toppling under
|
||||
else if ((direction + up).getLengthSQ() + (m_target_direction + up).getLengthSQ()
|
||||
<= (direction - m_target_direction).getLengthSQ())
|
||||
direction = quat_x * ((m_target_direction + up).setLength(0.02f) - up);
|
||||
m_target_direction = direction;
|
||||
|
||||
// Don't do that because it looks ugly and is bad to handle ;)
|
||||
/*side = direction.crossProduct(up);
|
||||
// Compute new up vector
|
||||
up = side.crossProduct(direction);
|
||||
up.normalize();
|
||||
cam->setUpVector(up);*/
|
||||
} // applyMouseMovement
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called once per time frame to move the camera to the right position.
|
||||
* \param dt Time step.
|
||||
*/
|
||||
void CameraFPS::update(float dt)
|
||||
{
|
||||
Camera::update(dt);
|
||||
|
||||
// To view inside tunnels in top mode, increase near value
|
||||
m_camera->setNearValue(1.0f);
|
||||
|
||||
core::vector3df direction(m_camera->getTarget() - m_camera->getPosition());
|
||||
core::vector3df up(m_camera->getUpVector());
|
||||
core::vector3df side(direction.crossProduct(up));
|
||||
core::vector3df pos = m_camera->getPosition();
|
||||
|
||||
// Set local values if the camera is attached to the kart
|
||||
if (m_attached)
|
||||
{
|
||||
direction = m_local_direction;
|
||||
up = m_local_up;
|
||||
pos = m_local_position;
|
||||
}
|
||||
|
||||
// Update smooth movement
|
||||
if (m_smooth)
|
||||
{
|
||||
// Angular velocity
|
||||
if (m_angular_velocity < m_target_angular_velocity)
|
||||
{
|
||||
m_angular_velocity += UserConfigParams::m_fpscam_angular_velocity;
|
||||
if (m_angular_velocity > m_target_angular_velocity)
|
||||
m_angular_velocity = m_target_angular_velocity;
|
||||
}
|
||||
else if (m_angular_velocity > m_target_angular_velocity)
|
||||
{
|
||||
m_angular_velocity -= UserConfigParams::m_fpscam_angular_velocity;
|
||||
if (m_angular_velocity < m_target_angular_velocity)
|
||||
m_angular_velocity = m_target_angular_velocity;
|
||||
}
|
||||
|
||||
// Linear velocity
|
||||
core::vector3df diff(m_target_velocity - m_lin_velocity);
|
||||
if (diff.X != 0 || diff.Y != 0 || diff.Z != 0)
|
||||
{
|
||||
if (diff.getLengthSQ() > 1) diff.setLength(1);
|
||||
m_lin_velocity += diff;
|
||||
}
|
||||
|
||||
// Camera direction
|
||||
diff = m_target_direction - direction;
|
||||
if (diff.X != 0 || diff.Y != 0 || diff.Z != 0)
|
||||
{
|
||||
diff.setLength(UserConfigParams::m_fpscam_direction_speed);
|
||||
m_direction_velocity += diff;
|
||||
if (m_direction_velocity.getLengthSQ() >
|
||||
UserConfigParams::m_fpscam_smooth_direction_max_speed *
|
||||
UserConfigParams::m_fpscam_smooth_direction_max_speed)
|
||||
{
|
||||
m_direction_velocity.setLength(
|
||||
UserConfigParams::m_fpscam_smooth_direction_max_speed);
|
||||
}
|
||||
direction += m_direction_velocity;
|
||||
m_target_direction = direction;
|
||||
} // if diff is no 0
|
||||
|
||||
// Camera rotation
|
||||
diff = m_target_up_vector - up;
|
||||
if (diff.X != 0 || diff.Y != 0 || diff.Z != 0)
|
||||
{
|
||||
if (diff.getLengthSQ() >
|
||||
UserConfigParams::m_fpscam_angular_velocity *
|
||||
UserConfigParams::m_fpscam_angular_velocity)
|
||||
{
|
||||
diff.setLength(UserConfigParams::m_fpscam_angular_velocity);
|
||||
}
|
||||
up += diff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
direction = m_target_direction;
|
||||
up = m_target_up_vector;
|
||||
side = direction.crossProduct(up);
|
||||
}
|
||||
|
||||
// Rotate camera
|
||||
core::quaternion quat;
|
||||
quat.fromAngleAxis(m_angular_velocity * dt, direction);
|
||||
up = quat * up;
|
||||
m_target_up_vector = quat * up;
|
||||
direction.normalize();
|
||||
up.normalize();
|
||||
side.normalize();
|
||||
|
||||
// Top vector is the real up vector, not the one used by the camera
|
||||
core::vector3df top(side.crossProduct(direction));
|
||||
|
||||
// Move camera
|
||||
core::vector3df movement(direction * m_lin_velocity.Z +
|
||||
top * m_lin_velocity.Y + side * m_lin_velocity.X);
|
||||
pos = pos + movement * dt;
|
||||
|
||||
if (m_attached)
|
||||
{
|
||||
// Save current values
|
||||
m_local_position = pos;
|
||||
m_local_direction = direction;
|
||||
m_local_up = up;
|
||||
|
||||
// Move the camera with the kart
|
||||
btTransform t = m_kart->getTrans();
|
||||
if (stk_config->m_camera_follow_skid &&
|
||||
m_kart->getSkidding()->getVisualSkidRotation() != 0)
|
||||
{
|
||||
// If the camera should follow the graphical skid, add the
|
||||
// visual rotation to the relative vector:
|
||||
btQuaternion q(m_kart->getSkidding()->getVisualSkidRotation(), 0, 0);
|
||||
t.setBasis(t.getBasis() * btMatrix3x3(q));
|
||||
}
|
||||
pos = Vec3(t(Vec3(pos))).toIrrVector();
|
||||
|
||||
btQuaternion q = t.getRotation();
|
||||
btMatrix3x3 mat(q);
|
||||
direction = Vec3(mat * Vec3(direction)).toIrrVector();
|
||||
up = Vec3(mat * Vec3(up)).toIrrVector();
|
||||
}
|
||||
|
||||
// Set camera attributes
|
||||
m_camera->setPosition(pos);
|
||||
m_camera->setTarget(pos + direction);
|
||||
m_camera->setUpVector(up);
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sets the angular velocity for this camera. */
|
||||
void CameraFPS::setAngularVelocity(float vel)
|
||||
{
|
||||
if (m_smooth)
|
||||
m_target_angular_velocity = vel;
|
||||
else
|
||||
m_angular_velocity = vel;
|
||||
} // setAngularVelocity
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the current target angular velocity. */
|
||||
float CameraFPS::getAngularVelocity()
|
||||
{
|
||||
if (m_smooth)
|
||||
return m_target_angular_velocity;
|
||||
else
|
||||
return m_angular_velocity;
|
||||
} // getAngularVelocity
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Sets the linear velocity for this camera. */
|
||||
void CameraFPS::setLinearVelocity(core::vector3df vel)
|
||||
{
|
||||
if (m_smooth)
|
||||
m_target_velocity = vel;
|
||||
else
|
||||
m_lin_velocity = vel;
|
||||
} // setLinearVelocity
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns the current linear velocity. */
|
||||
const core::vector3df &CameraFPS::getLinearVelocity()
|
||||
{
|
||||
if (m_smooth)
|
||||
return m_target_velocity;
|
||||
else
|
||||
return m_lin_velocity;
|
||||
} // getLinearVelocity
|
||||
|
165
src/graphics/camera_fps.hpp
Normal file
165
src/graphics/camera_fps.hpp
Normal file
@ -0,0 +1,165 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2004-2015 Steve Baker <sjbaker1@airmail.net>
|
||||
// Copyright (C) 2006-2015 SuperTuxKart-Team, Steve Baker
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_CAMERA_FPS_HPP
|
||||
#define HEADER_CAMERA_FPS_HPP
|
||||
|
||||
#include "graphics/camera.hpp"
|
||||
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
class AbstractKart;
|
||||
|
||||
/**
|
||||
* \brief Handles the game camera
|
||||
* \ingroup graphics
|
||||
*/
|
||||
class CameraFPS : public Camera
|
||||
{
|
||||
private:
|
||||
/** The speed at which the camera changes position. */
|
||||
float m_position_speed;
|
||||
|
||||
/** The speed at which the camera target changes position. */
|
||||
float m_target_speed;
|
||||
|
||||
/** Factor of the effects of steering in camera aim. */
|
||||
float m_rotation_range;
|
||||
|
||||
/** Smooth acceleration with the first person camera. */
|
||||
bool m_smooth;
|
||||
|
||||
/** Attache the first person camera to a kart.
|
||||
That means moving the kart also moves the camera. */
|
||||
bool m_attached;
|
||||
|
||||
/** The speed at which the up-vector rotates, only used for the first person camera. */
|
||||
float m_angular_velocity;
|
||||
|
||||
/** Target angular velocity. Used for smooth movement in fps perpective. */
|
||||
float m_target_angular_velocity;
|
||||
|
||||
/** Maximum velocity for fps camera. */
|
||||
float m_max_velocity;
|
||||
|
||||
/** Linear velocity of the camera, used for end and first person camera.
|
||||
It's stored relative to the camera direction for the first person view. */
|
||||
core::vector3df m_lin_velocity;
|
||||
|
||||
/** Velocity of the target of the camera, used for end and first person camera. */
|
||||
core::vector3df m_target_velocity;
|
||||
|
||||
/** The target direction for the camera, only used for the first person camera. */
|
||||
core::vector3df m_target_direction;
|
||||
|
||||
/** The speed at which the direction changes, only used for the first person camera. */
|
||||
core::vector3df m_direction_velocity;
|
||||
|
||||
/** The up vector the camera should have, only used for the first person camera. */
|
||||
core::vector3df m_target_up_vector;
|
||||
|
||||
/** Save the local position if the first person camera is attached to the kart. */
|
||||
core::vector3df m_local_position;
|
||||
|
||||
/** Save the local direction if the first person camera is attached to the kart. */
|
||||
core::vector3df m_local_direction;
|
||||
|
||||
/** Save the local up vector if the first person camera is attached to the kart. */
|
||||
core::vector3df m_local_up;
|
||||
|
||||
|
||||
|
||||
void positionCamera(float dt, float above_kart, float cam_angle,
|
||||
float side_way, float distance, float smoothing);
|
||||
|
||||
friend class Camera;
|
||||
CameraFPS(int camera_index, AbstractKart* kart);
|
||||
virtual ~CameraFPS();
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
static bool isFPS() { return true; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
virtual void update(float dt) OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Applies mouse movement to the first person camera. */
|
||||
void applyMouseMovement (float x, float y);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets if the first person camera should be moved smooth. */
|
||||
void setSmoothMovement (bool value) { m_smooth = value; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** If the first person camera should be moved smooth. */
|
||||
bool getSmoothMovement () { return m_smooth; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets if the first person camera should be moved with the kart. */
|
||||
void setAttachedFpsCam (bool value) { m_attached = value; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** If the first person camera should be moved with the kart. */
|
||||
bool getAttachedFpsCam () { return m_attached; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the angular velocity for this camera. */
|
||||
void setMaximumVelocity (float vel) { m_max_velocity = vel; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current angular velocity. */
|
||||
float getMaximumVelocity () { return m_max_velocity; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the vector, the first person camera should look at. */
|
||||
void setDirection (core::vector3df target) { m_target_direction = target; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Gets the vector, the first person camera should look at. */
|
||||
const core::vector3df &getDirection () { return m_target_direction; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the up vector, the first person camera should use. */
|
||||
void setUpVector (core::vector3df target) { m_target_up_vector = target; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Gets the up vector, the first person camera should use. */
|
||||
const core::vector3df &getUpVector () { return m_target_up_vector; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the angular velocity for this camera. */
|
||||
void setAngularVelocity (float vel);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current target angular velocity. */
|
||||
float getAngularVelocity ();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the linear velocity for this camera. */
|
||||
void setLinearVelocity (core::vector3df vel);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current linear velocity. */
|
||||
const core::vector3df &getLinearVelocity ();
|
||||
|
||||
}; // class CameraFPS
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
293
src/graphics/camera_normal.cpp
Normal file
293
src/graphics/camera_normal.cpp
Normal file
@ -0,0 +1,293 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2004-2015 Steve Baker <sjbaker1@airmail.net>
|
||||
// Copyright (C) 2006-2015 SuperTuxKart-Team, Steve Baker
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "graphics/camera_normal.hpp"
|
||||
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/explosion_animation.hpp"
|
||||
#include "karts/kart.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/skidding.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
|
||||
// ============================================================================
|
||||
CameraNormal::CameraNormal(int camera_index, AbstractKart* kart)
|
||||
: Camera(camera_index, kart)
|
||||
{
|
||||
m_distance = kart ? kart->getKartProperties()->getCameraDistance() : 1000.0f;
|
||||
m_ambient_light = World::getWorld()->getTrack()->getDefaultAmbientColor();
|
||||
|
||||
// TODO: Put these values into a config file
|
||||
// Global or per split screen zone?
|
||||
// Either global or per user (for instance, some users may not like
|
||||
// the extra camera rotation so they could set m_rotation_range to
|
||||
// zero to disable it for themselves).
|
||||
m_position_speed = 8.0f;
|
||||
m_target_speed = 10.0f;
|
||||
m_rotation_range = 0.4f;
|
||||
m_rotation_range = 0.0f;
|
||||
reset();
|
||||
m_camera->setNearValue(1.0f);
|
||||
} // Camera
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Moves the camera smoothly from the current camera position (and target)
|
||||
* to the new position and target.
|
||||
* \param wanted_position The position the camera wanted to reach.
|
||||
* \param wanted_target The point the camera wants to point to.
|
||||
*/
|
||||
void CameraNormal::smoothMoveCamera(float dt)
|
||||
{
|
||||
Kart *kart = dynamic_cast<Kart*>(m_kart);
|
||||
if (kart->isFlying())
|
||||
{
|
||||
Vec3 vec3 = m_kart->getXYZ() + Vec3(sin(m_kart->getHeading()) * -4.0f,
|
||||
0.5f,
|
||||
cos(m_kart->getHeading()) * -4.0f);
|
||||
m_camera->setTarget(m_kart->getXYZ().toIrrVector());
|
||||
m_camera->setPosition(vec3.toIrrVector());
|
||||
return;
|
||||
} // kart is flying
|
||||
|
||||
|
||||
core::vector3df current_position = m_camera->getPosition();
|
||||
// Smoothly interpolate towards the position and target
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
float max_increase_with_zipper = kp->getZipperMaxSpeedIncrease();
|
||||
float max_speed_without_zipper = kp->getEngineMaxSpeed();
|
||||
float current_speed = m_kart->getSpeed();
|
||||
|
||||
const Skidding *ks = m_kart->getSkidding();
|
||||
float skid_factor = ks->getVisualSkidRotation();
|
||||
|
||||
float skid_angle = asin(skid_factor);
|
||||
float ratio = (current_speed - max_speed_without_zipper) / max_increase_with_zipper;
|
||||
ratio = ratio > -0.12f ? ratio : -0.12f;
|
||||
|
||||
// distance of camera from kart in x and z plane
|
||||
float camera_distance = -3 * (0.5f + ratio);
|
||||
if (camera_distance > -2.0f) camera_distance = -2.0f;
|
||||
|
||||
// Defines how far camera should be from player kart.
|
||||
Vec3 camera_offset(camera_distance * sin(skid_angle / 2),
|
||||
1.1f * (1 + ratio / 2),
|
||||
camera_distance * cos(skid_angle / 2));
|
||||
Vec3 m_kart_camera_position_with_offset = m_kart->getTrans()(camera_offset);
|
||||
|
||||
// next target
|
||||
core::vector3df current_target = m_kart->getXYZ().toIrrVector();
|
||||
current_target.Y += 0.5f;
|
||||
// new required position of camera
|
||||
core::vector3df wanted_position = m_kart_camera_position_with_offset.toIrrVector();
|
||||
|
||||
float f = 5.0f;
|
||||
if ((m_kart->getSpeed() > 5 ) || (m_kart->getSpeed() < 0 ))
|
||||
{
|
||||
f = m_kart->getSpeed()>0 ? m_kart->getSpeed()/3 + 1.0f
|
||||
: -1.5f * m_kart->getSpeed() + 2.0f;
|
||||
}
|
||||
current_position += (wanted_position - current_position) * (dt *f);
|
||||
|
||||
// Avoid camera crash: if the speed is negative, the current_position
|
||||
// can oscillate between plus and minus, getting bigger and bigger. If
|
||||
// this happens often enough, floating point overflow happens (large
|
||||
// negative speeds can happen when the kart is tumbling/falling)
|
||||
// To avoid this, we just move the camera to the wanted position if
|
||||
// the distance becomes too large (see #1356).
|
||||
if( (current_position - wanted_position).getLengthSQ() > 100)
|
||||
{
|
||||
Log::debug("camera", "Resetting camera position to avoid crash");
|
||||
current_position = wanted_position;
|
||||
}
|
||||
|
||||
if(getMode()!=CM_FALLING)
|
||||
m_camera->setPosition(current_position);
|
||||
m_camera->setTarget(current_target);//set new target
|
||||
|
||||
assert(!std::isnan(m_camera->getPosition().X));
|
||||
assert(!std::isnan(m_camera->getPosition().Y));
|
||||
assert(!std::isnan(m_camera->getPosition().Z));
|
||||
|
||||
} // smoothMoveCamera
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Determine the camera settings for the current frame.
|
||||
* \param above_kart How far above the camera should aim at.
|
||||
* \param cam_angle Angle above the kart plane for the camera.
|
||||
* \param sideway Sideway movement of the camera.
|
||||
* \param distance Distance from kart.
|
||||
*/
|
||||
void CameraNormal::getCameraSettings(float *above_kart, float *cam_angle,
|
||||
float *sideway, float *distance,
|
||||
bool *smoothing)
|
||||
{
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
|
||||
switch(getMode())
|
||||
{
|
||||
case CM_NORMAL:
|
||||
case CM_FALLING:
|
||||
{
|
||||
*above_kart = 0.75f;
|
||||
*cam_angle = kp->getCameraForwardUpAngle() * DEGREE_TO_RAD;
|
||||
*distance = -m_distance;
|
||||
float steering = m_kart->getSteerPercent()
|
||||
* (1.0f + (m_kart->getSkidding()->getSkidFactor()
|
||||
- 1.0f)/2.3f );
|
||||
// quadratically to dampen small variations (but keep sign)
|
||||
float dampened_steer = fabsf(steering) * steering;
|
||||
*sideway = -m_rotation_range*dampened_steer*0.5f;
|
||||
*smoothing = true;
|
||||
break;
|
||||
} // CM_FALLING
|
||||
case CM_REVERSE: // Same as CM_NORMAL except it looks backwards
|
||||
{
|
||||
*above_kart = 0.75f;
|
||||
*cam_angle = kp->getCameraBackwardUpAngle() * DEGREE_TO_RAD;
|
||||
*sideway = 0;
|
||||
*distance = 2.0f*m_distance;
|
||||
*smoothing = false;
|
||||
break;
|
||||
}
|
||||
case CM_CLOSEUP: // Lower to the ground and closer to the kart
|
||||
{
|
||||
*above_kart = 0.75f;
|
||||
*cam_angle = 20.0f*DEGREE_TO_RAD;
|
||||
*sideway = m_rotation_range
|
||||
* m_kart->getSteerPercent()
|
||||
* m_kart->getSkidding()->getSkidFactor();
|
||||
*distance = -0.5f*m_distance;
|
||||
*smoothing = false;
|
||||
break;
|
||||
}
|
||||
case CM_LEADER_MODE:
|
||||
{
|
||||
*above_kart = 0.0f;
|
||||
*cam_angle = 40*DEGREE_TO_RAD;
|
||||
*sideway = 0;
|
||||
*distance = 2.0f*m_distance;
|
||||
*smoothing = true;
|
||||
break;
|
||||
}
|
||||
case CM_SIMPLE_REPLAY:
|
||||
// TODO: Implement
|
||||
break;
|
||||
}
|
||||
|
||||
} // getCameraSettings
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called once per time frame to move the camera to the right position.
|
||||
* \param dt Time step.
|
||||
*/
|
||||
void CameraNormal::update(float dt)
|
||||
{
|
||||
Camera::update(dt);
|
||||
if(!m_kart) return;
|
||||
|
||||
m_camera->setNearValue(1.0f);
|
||||
|
||||
// If an explosion is happening, stop moving the camera,
|
||||
// but keep it target on the kart.
|
||||
if (dynamic_cast<ExplosionAnimation*>(m_kart->getKartAnimation()))
|
||||
{
|
||||
float above_kart, cam_angle, side_way, distance;
|
||||
bool smoothing;
|
||||
|
||||
getCameraSettings(&above_kart, &cam_angle, &side_way, &distance, &smoothing);
|
||||
// The camera target needs to be 'smooth moved', otherwise
|
||||
// there will be a noticable jump in the first frame
|
||||
|
||||
// Aim at the usual same position of the kart (i.e. slightly
|
||||
// above the kart).
|
||||
// Note: this code is replicated from smoothMoveCamera so that
|
||||
// the camera keeps on pointing to the same spot.
|
||||
core::vector3df current_target = (m_kart->getXYZ().toIrrVector()
|
||||
+ core::vector3df(0, above_kart, 0));
|
||||
m_camera->setTarget(current_target);
|
||||
}
|
||||
else // no kart animation
|
||||
{
|
||||
float above_kart, cam_angle, side_way, distance;
|
||||
bool smoothing;
|
||||
getCameraSettings(&above_kart, &cam_angle, &side_way, &distance, &smoothing);
|
||||
positionCamera(dt, above_kart, cam_angle, side_way, distance, smoothing);
|
||||
}
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Actually sets the camera based on the given parameter.
|
||||
* \param above_kart How far above the camera should aim at.
|
||||
* \param cam_angle Angle above the kart plane for the camera.
|
||||
* \param sideway Sideway movement of the camera.
|
||||
* \param distance Distance from kart.
|
||||
*/
|
||||
void CameraNormal::positionCamera(float dt, float above_kart, float cam_angle,
|
||||
float side_way, float distance, float smoothing)
|
||||
{
|
||||
Vec3 wanted_position;
|
||||
Vec3 wanted_target = m_kart->getXYZ();
|
||||
wanted_target.setY(wanted_target.getY() + above_kart);
|
||||
|
||||
float tan_up = tan(cam_angle);
|
||||
Vec3 relative_position(side_way,
|
||||
fabsf(distance)*tan_up+above_kart,
|
||||
distance);
|
||||
btTransform t=m_kart->getTrans();
|
||||
if(stk_config->m_camera_follow_skid &&
|
||||
m_kart->getSkidding()->getVisualSkidRotation()!=0)
|
||||
{
|
||||
// If the camera should follow the graphical skid, add the
|
||||
// visual rotation to the relative vector:
|
||||
btQuaternion q(m_kart->getSkidding()->getVisualSkidRotation(), 0, 0);
|
||||
t.setBasis(t.getBasis() * btMatrix3x3(q));
|
||||
}
|
||||
wanted_position = t(relative_position);
|
||||
|
||||
if (smoothing)
|
||||
{
|
||||
smoothMoveCamera(dt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (getMode()!=CM_FALLING)
|
||||
m_camera->setPosition(wanted_position.toIrrVector());
|
||||
m_camera->setTarget(wanted_target.toIrrVector());
|
||||
|
||||
if (race_manager->getNumLocalPlayers() < 2)
|
||||
{
|
||||
SFXManager::get()->positionListener(m_camera->getPosition(),
|
||||
wanted_target - m_camera->getPosition(),
|
||||
Vec3(0, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
Kart *kart = dynamic_cast<Kart*>(m_kart);
|
||||
if (kart && !kart->isFlying())
|
||||
{
|
||||
// Rotate the up vector (0,1,0) by the rotation ... which is just column 1
|
||||
Vec3 up = m_kart->getTrans().getBasis().getColumn(1);
|
||||
float f = 0.04f; // weight for new up vector to reduce shaking
|
||||
m_camera->setUpVector( f * up.toIrrVector() +
|
||||
(1.0f - f) * m_camera->getUpVector());
|
||||
} // kart && !flying
|
||||
else
|
||||
m_camera->setUpVector(core::vector3df(0, 1, 0));
|
||||
} // positionCamera
|
85
src/graphics/camera_normal.hpp
Normal file
85
src/graphics/camera_normal.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2004-2015 Steve Baker <sjbaker1@airmail.net>
|
||||
// Copyright (C) 2006-2015 SuperTuxKart-Team, Steve Baker
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_CAMERA_NORMAL_HPP
|
||||
#define HEADER_CAMERA_NORMAL_HPP
|
||||
|
||||
#include "graphics/camera.hpp"
|
||||
|
||||
#include "utils/cpp2011.hpp"
|
||||
|
||||
/**
|
||||
* \brief Handles the normal racing camera
|
||||
* \ingroup graphics
|
||||
*/
|
||||
class CameraNormal : public Camera
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
/** Current ambient light for this camera. */
|
||||
video::SColor m_ambient_light;
|
||||
|
||||
/** Distance between the camera and the kart. */
|
||||
float m_distance;
|
||||
|
||||
/** The speed at which the camera changes position. */
|
||||
float m_position_speed;
|
||||
|
||||
/** The speed at which the camera target changes position. */
|
||||
float m_target_speed;
|
||||
|
||||
/** Factor of the effects of steering in camera aim. */
|
||||
float m_rotation_range;
|
||||
|
||||
void smoothMoveCamera(float dt);
|
||||
void handleEndCamera(float dt);
|
||||
void getCameraSettings(float *above_kart, float *cam_angle,
|
||||
float *side_way, float *distance,
|
||||
bool *smoothing);
|
||||
void positionCamera(float dt, float above_kart, float cam_angle,
|
||||
float side_way, float distance, float smoothing);
|
||||
|
||||
// Give a few classes access to the constructor (mostly for inheritance)
|
||||
friend class Camera;
|
||||
friend class CameraDebug;
|
||||
friend class CameraEnd;
|
||||
CameraNormal(int camera_index, AbstractKart* kart);
|
||||
virtual ~CameraNormal() {}
|
||||
public:
|
||||
bool isDebug() { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool isFPS() { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void update(float dt) OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the ambient light for this camera. */
|
||||
void setAmbientLight(const video::SColor &color) { m_ambient_light=color; }
|
||||
// ------------------------------------------------------------------------
|
||||
float getDistanceToKart() const { return m_distance; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the current ambient light. */
|
||||
const video::SColor &getAmbientLight() const {return m_ambient_light; }
|
||||
|
||||
}; // class CameraNormal
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
@ -19,7 +19,7 @@
|
||||
#include "input/input_manager.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/camera_fps.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/event_handler.hpp"
|
||||
@ -174,10 +174,9 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
// Moving the first person camera
|
||||
case KEY_KEY_W:
|
||||
{
|
||||
if (world && UserConfigParams::m_artist_debug_mode &&
|
||||
Camera::isFPS() )
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if (world && UserConfigParams::m_artist_debug_mode && cam )
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
core::vector3df vel(cam->getLinearVelocity());
|
||||
vel.Z = value ? cam->getMaximumVelocity() : 0;
|
||||
cam->setLinearVelocity(vel);
|
||||
@ -186,10 +185,9 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
}
|
||||
case KEY_KEY_S:
|
||||
{
|
||||
if (world && UserConfigParams::m_artist_debug_mode &&
|
||||
Camera::isFPS() )
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if (world && UserConfigParams::m_artist_debug_mode && cam)
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
core::vector3df vel(cam->getLinearVelocity());
|
||||
vel.Z = value ? -cam->getMaximumVelocity() : 0;
|
||||
cam->setLinearVelocity(vel);
|
||||
@ -198,10 +196,9 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
}
|
||||
case KEY_KEY_D:
|
||||
{
|
||||
if (world && !UserConfigParams::m_artist_debug_mode &&
|
||||
Camera::isFPS() )
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if (world && !UserConfigParams::m_artist_debug_mode && cam)
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
core::vector3df vel(cam->getLinearVelocity());
|
||||
vel.X = value ? -cam->getMaximumVelocity() : 0;
|
||||
cam->setLinearVelocity(vel);
|
||||
@ -210,10 +207,9 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
}
|
||||
case KEY_KEY_A:
|
||||
{
|
||||
if (world && UserConfigParams::m_artist_debug_mode &&
|
||||
Camera::isFPS() )
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if (world && UserConfigParams::m_artist_debug_mode && cam)
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
core::vector3df vel(cam->getLinearVelocity());
|
||||
vel.X = value ? cam->getMaximumVelocity() : 0;
|
||||
cam->setLinearVelocity(vel);
|
||||
@ -222,10 +218,9 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
}
|
||||
case KEY_KEY_R:
|
||||
{
|
||||
if (world && UserConfigParams::m_artist_debug_mode &&
|
||||
Camera::isFPS() )
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if (world && UserConfigParams::m_artist_debug_mode && cam)
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
core::vector3df vel(cam->getLinearVelocity());
|
||||
vel.Y = value ? cam->getMaximumVelocity() : 0;
|
||||
cam->setLinearVelocity(vel);
|
||||
@ -234,10 +229,9 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
}
|
||||
case KEY_KEY_F:
|
||||
{
|
||||
if (world && UserConfigParams::m_artist_debug_mode &&
|
||||
Camera::isFPS() )
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if (world && UserConfigParams::m_artist_debug_mode && cam)
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
core::vector3df vel(cam->getLinearVelocity());
|
||||
vel.Y = value ? -cam->getMaximumVelocity() : 0;
|
||||
cam->setLinearVelocity(vel);
|
||||
@ -247,22 +241,20 @@ void InputManager::handleStaticAction(int key, int value)
|
||||
// Rotating the first person camera
|
||||
case KEY_KEY_Q:
|
||||
{
|
||||
if (world && UserConfigParams::m_artist_debug_mode &&
|
||||
Camera::isFPS() )
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if (world && UserConfigParams::m_artist_debug_mode && cam )
|
||||
{
|
||||
Camera *active_cam = Camera::getActiveCamera();
|
||||
active_cam->setAngularVelocity(value ?
|
||||
cam->setAngularVelocity(value ?
|
||||
UserConfigParams::m_fpscam_max_angular_velocity : 0.0f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEY_KEY_E:
|
||||
{
|
||||
if (world && UserConfigParams::m_artist_debug_mode &&
|
||||
Camera::isFPS() )
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if (world && UserConfigParams::m_artist_debug_mode && cam)
|
||||
{
|
||||
Camera *active_cam = Camera::getActiveCamera();
|
||||
active_cam->setAngularVelocity(value ?
|
||||
cam->setAngularVelocity(value ?
|
||||
-UserConfigParams::m_fpscam_max_angular_velocity : 0);
|
||||
}
|
||||
break;
|
||||
@ -1009,9 +1001,9 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
|
||||
if (type == EMIE_MOUSE_MOVED)
|
||||
{
|
||||
if (Camera::isFPS())
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if (cam)
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
// Center of the screen
|
||||
core::vector2df screen_size = irr_driver->getCurrentScreenSize();
|
||||
int mid_x = (int) screen_size.X / 2;
|
||||
@ -1064,12 +1056,12 @@ EventPropagation InputManager::input(const SEvent& event)
|
||||
}
|
||||
else if (type == EMIE_MOUSE_WHEEL)
|
||||
{
|
||||
if (Camera::isFPS())
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if (cam)
|
||||
{
|
||||
// Use scrolling to change the maximum speed
|
||||
// Only test if it's more or less than 0 as it seems to be not
|
||||
// reliable accross more platforms.
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
if (event.MouseInput.Wheel < 0)
|
||||
{
|
||||
float vel = cam->getMaximumVelocity() - 3;
|
||||
|
@ -66,7 +66,7 @@ void AIBaseController::update(float dt)
|
||||
void AIBaseController::setControllerName(const std::string &name)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if(m_ai_debug && !Camera::isDebug())
|
||||
if(m_ai_debug && Camera::getActiveCamera()->getType()==Camera::CM_NORMAL)
|
||||
m_kart->setOnScreenText(core::stringw(name.c_str()).c_str());
|
||||
#endif
|
||||
Controller::setControllerName(name);
|
||||
|
@ -16,7 +16,7 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/camera_fps.hpp"
|
||||
#include "karts/controller/ghost_controller.hpp"
|
||||
#include "karts/controller/kart_control.hpp"
|
||||
#include "modes/world.hpp"
|
||||
@ -48,19 +48,23 @@ void GhostController::update(float dt)
|
||||
}
|
||||
|
||||
// Watching replay use only
|
||||
Camera *camera = Camera::getActiveCamera();
|
||||
if (camera != NULL && camera->getMode() != Camera::CM_FINAL)
|
||||
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
|
||||
{
|
||||
if (m_controls->m_look_back)
|
||||
Camera *camera = Camera::getCamera(i);
|
||||
if(camera->getKart()!=m_kart) continue;
|
||||
if (camera->getType() != Camera::CM_TYPE_END)
|
||||
{
|
||||
camera->setMode(Camera::CM_REVERSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (camera->getMode() == Camera::CM_REVERSE)
|
||||
camera->setMode(Camera::CM_NORMAL);
|
||||
}
|
||||
}
|
||||
if (m_controls->m_look_back)
|
||||
{
|
||||
camera->setMode(Camera::CM_REVERSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (camera->getMode() == Camera::CM_REVERSE)
|
||||
camera->setMode(Camera::CM_NORMAL);
|
||||
}
|
||||
} // if camera mode != END
|
||||
} // for i in all cameras
|
||||
|
||||
} // update
|
||||
|
||||
|
@ -61,7 +61,8 @@ LocalPlayerController::LocalPlayerController(AbstractKart *kart,
|
||||
|
||||
// Keep a pointer to the camera to remove the need to search for
|
||||
// the right camera once per frame later.
|
||||
m_camera = Camera::createCamera(kart);
|
||||
Camera *camera = Camera::createCamera(kart);
|
||||
m_camera_index = camera->getIndex();
|
||||
m_bzzt_sound = SFXManager::get()->createSoundSource("bzzt");
|
||||
m_wee_sound = SFXManager::get()->createSoundSource("wee");
|
||||
m_ugh_sound = SFXManager::get()->createSoundSource("ugh");
|
||||
@ -166,17 +167,18 @@ void LocalPlayerController::update(float dt)
|
||||
|
||||
// look backward when the player requests or
|
||||
// if automatic reverse camera is active
|
||||
if (m_camera->getMode() != Camera::CM_FINAL)
|
||||
Camera *camera = Camera::getCamera(m_camera_index);
|
||||
if (camera->getType() != Camera::CM_TYPE_END)
|
||||
{
|
||||
if (m_controls->m_look_back || (UserConfigParams::m_reverse_look_threshold > 0 &&
|
||||
m_kart->getSpeed() < -UserConfigParams::m_reverse_look_threshold))
|
||||
{
|
||||
m_camera->setMode(Camera::CM_REVERSE);
|
||||
camera->setMode(Camera::CM_REVERSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_camera->getMode() == Camera::CM_REVERSE)
|
||||
m_camera->setMode(Camera::CM_NORMAL);
|
||||
if (camera->getMode() == Camera::CM_REVERSE)
|
||||
camera->setMode(Camera::CM_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,8 +244,7 @@ void LocalPlayerController::setPosition(int p)
|
||||
void LocalPlayerController::finishedRace(float time)
|
||||
{
|
||||
// This will implicitely trigger setting the first end camera to be active
|
||||
m_camera->setMode(Camera::CM_FINAL);
|
||||
|
||||
Camera::changeCamera(m_camera_index, Camera::CM_TYPE_END);
|
||||
} // finishedRace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -263,7 +264,7 @@ void LocalPlayerController::handleZipper(bool play_sound)
|
||||
}
|
||||
|
||||
// Apply the motion blur according to the speed of the kart
|
||||
irr_driver->getPostProcessing()->giveBoost(m_camera->getIndex());
|
||||
irr_driver->getPostProcessing()->giveBoost(m_camera_index);
|
||||
|
||||
} // handleZipper
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "karts/controller/player_controller.hpp"
|
||||
|
||||
class AbstractKart;
|
||||
class Camera;
|
||||
class Player;
|
||||
class SFXBase;
|
||||
|
||||
@ -42,9 +41,10 @@ private:
|
||||
|
||||
bool m_sound_schedule;
|
||||
|
||||
/** The camera attached to the kart for this controller. The camera
|
||||
* object is managed in the Camera class, so no need to free it. */
|
||||
Camera *m_camera;
|
||||
|
||||
/** The index of the camera attached to the kart for this controller. The
|
||||
* camera object is managed in the Camera class, so no need to free it. */
|
||||
int m_camera_index;
|
||||
|
||||
SFXBase *m_bzzt_sound;
|
||||
SFXBase *m_wee_sound;
|
||||
|
@ -127,7 +127,7 @@ ExplosionAnimation::~ExplosionAnimation()
|
||||
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
|
||||
{
|
||||
Camera *camera = Camera::getCamera(i);
|
||||
if(camera->getMode() != Camera::CM_FINAL)
|
||||
if(camera->getType() != Camera::CM_TYPE_END)
|
||||
camera->setMode(Camera::CM_NORMAL);
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ RescueAnimation::~RescueAnimation()
|
||||
{
|
||||
Camera *camera = Camera::getCamera(i);
|
||||
if(camera && camera->getKart()==m_kart &&
|
||||
camera->getMode() != Camera::CM_FINAL)
|
||||
camera->getType() != Camera::CM_TYPE_END)
|
||||
camera->setMode(Camera::CM_NORMAL);
|
||||
}
|
||||
}
|
||||
|
20
src/main.cpp
20
src/main.cpp
@ -151,6 +151,7 @@
|
||||
#include "config/stk_config.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/camera_debug.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/graphics_restrictions.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
@ -761,14 +762,23 @@ int handleCmdLine()
|
||||
if (CommandLine::has("--fps-debug"))
|
||||
UserConfigParams::m_fps_debug = true;
|
||||
|
||||
if(UserConfigParams::m_artist_debug_mode)
|
||||
if (UserConfigParams::m_artist_debug_mode)
|
||||
{
|
||||
if(CommandLine::has("--camera-wheel-debug"))
|
||||
Camera::setDebugMode(Camera::CM_DEBUG_GROUND);
|
||||
if (CommandLine::has("--camera-wheel-debug"))
|
||||
{
|
||||
Camera::setDefaultCameraType(Camera::CM_TYPE_DEBUG);
|
||||
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_GROUND);
|
||||
}
|
||||
if(CommandLine::has("--camera-debug"))
|
||||
Camera::setDebugMode(Camera::CM_DEBUG_TOP_OF_KART);
|
||||
{
|
||||
Camera::setDefaultCameraType(Camera::CM_TYPE_DEBUG);
|
||||
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_TOP_OF_KART);
|
||||
}
|
||||
if(CommandLine::has("--camera-kart-debug"))
|
||||
Camera::setDebugMode(Camera::CM_DEBUG_BEHIND_KART);
|
||||
{
|
||||
Camera::setDefaultCameraType(Camera::CM_TYPE_DEBUG);
|
||||
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_BEHIND_KART);
|
||||
}
|
||||
if(CommandLine::has("--physics-debug"))
|
||||
UserConfigParams::m_physics_debug=1;
|
||||
if(CommandLine::has("--check-debug"))
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/stk_config.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/camera_end.hpp"
|
||||
#include "graphics/CBatchingMesh.hpp"
|
||||
#include "graphics/central_settings.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
@ -1606,7 +1606,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
#endif
|
||||
}
|
||||
|
||||
Camera::clearEndCameras();
|
||||
CameraEnd::clearEndCameras();
|
||||
m_sky_type = SKY_NONE;
|
||||
m_track_object_manager = new TrackObjectManager();
|
||||
|
||||
@ -1761,7 +1761,8 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
// It's important to execute this BEFORE the code that creates the skycube,
|
||||
// otherwise the skycube node could be modified to have fog enabled, which
|
||||
// we don't want
|
||||
if (m_use_fog && !Camera::isDebug() && !CVS->isGLSL())
|
||||
if (m_use_fog && Camera::getDefaultCameraType()!=Camera::CM_TYPE_DEBUG &&
|
||||
!CVS->isGLSL())
|
||||
{
|
||||
/* NOTE: if LINEAR type, density does not matter, if EXP or EXP2, start
|
||||
and end do not matter */
|
||||
@ -2003,7 +2004,7 @@ void Track::loadObjects(const XMLNode* root, const std::string& path, ModelDefin
|
||||
}
|
||||
else if (name == "end-cameras")
|
||||
{
|
||||
Camera::readEndCamera(*node);
|
||||
CameraEnd::readEndCamera(*node);
|
||||
}
|
||||
else if (name == "light")
|
||||
{
|
||||
|
@ -19,7 +19,8 @@
|
||||
#include "debug.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/camera_debug.hpp"
|
||||
#include "graphics/camera_fps.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/light.hpp"
|
||||
#include "graphics/shaders.hpp"
|
||||
@ -440,47 +441,58 @@ bool handleContextMenuAction(s32 cmdID)
|
||||
}
|
||||
else if (cmdID == DEBUG_GUI_CAM_TOP)
|
||||
{
|
||||
Camera::setDebugMode(Camera::CM_DEBUG_TOP_OF_KART);
|
||||
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_TOP_OF_KART);
|
||||
irr_driver->getDevice()->getCursorControl()->setVisible(true);
|
||||
}
|
||||
else if (cmdID == DEBUG_GUI_CAM_WHEEL)
|
||||
{
|
||||
Camera::setDebugMode(Camera::CM_DEBUG_GROUND);
|
||||
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_GROUND);
|
||||
irr_driver->getDevice()->getCursorControl()->setVisible(true);
|
||||
}
|
||||
else if (cmdID == DEBUG_GUI_CAM_BEHIND_KART)
|
||||
{
|
||||
Camera::setDebugMode(Camera::CM_DEBUG_BEHIND_KART);
|
||||
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_BEHIND_KART);
|
||||
irr_driver->getDevice()->getCursorControl()->setVisible(true);
|
||||
}
|
||||
else if (cmdID == DEBUG_GUI_CAM_SIDE_OF_KART)
|
||||
{
|
||||
Camera::setDebugMode(Camera::CM_DEBUG_SIDE_OF_KART);
|
||||
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_SIDE_OF_KART);
|
||||
irr_driver->getDevice()->getCursorControl()->setVisible(true);
|
||||
}
|
||||
else if (cmdID == DEBUG_GUI_CAM_FREE)
|
||||
{
|
||||
Camera::setDebugMode(Camera::CM_DEBUG_FPS);
|
||||
Camera *camera = Camera::getActiveCamera();
|
||||
Camera::changeCamera(camera->getIndex(), Camera::CM_TYPE_FPS);
|
||||
irr_driver->getDevice()->getCursorControl()->setVisible(false);
|
||||
// Reset camera rotation
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
cam->setDirection(vector3df(0, 0, 1));
|
||||
cam->setUpVector(vector3df(0, 1, 0));
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if(cam)
|
||||
{
|
||||
cam->setDirection(vector3df(0, 0, 1));
|
||||
cam->setUpVector(vector3df(0, 1, 0));
|
||||
}
|
||||
}
|
||||
else if (cmdID == DEBUG_GUI_CAM_NORMAL)
|
||||
{
|
||||
Camera::setDebugMode(Camera::CM_DEBUG_NONE);
|
||||
Camera *camera = Camera::getActiveCamera();
|
||||
Camera::changeCamera(camera->getIndex(), Camera::CM_TYPE_NORMAL);
|
||||
irr_driver->getDevice()->getCursorControl()->setVisible(true);
|
||||
}
|
||||
else if (cmdID == DEBUG_GUI_CAM_SMOOTH)
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
cam->setSmoothMovement(!cam->getSmoothMovement());
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if(cam)
|
||||
{
|
||||
cam->setSmoothMovement(!cam->getSmoothMovement());
|
||||
}
|
||||
}
|
||||
else if (cmdID == DEBUG_GUI_CAM_ATTACH)
|
||||
{
|
||||
Camera *cam = Camera::getActiveCamera();
|
||||
cam->setAttachedFpsCam(!cam->getAttachedFpsCam());
|
||||
CameraFPS *cam = dynamic_cast<CameraFPS*>(Camera::getActiveCamera());
|
||||
if(cam)
|
||||
{
|
||||
cam->setAttachedFpsCam(!cam->getAttachedFpsCam());
|
||||
}
|
||||
}
|
||||
else if (cmdID == DEBUG_VIEW_KART_ONE)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user