Merge remote-tracking branch 'origin/master' into gles

This commit is contained in:
Deve
2016-07-11 23:43:10 +02:00
82 changed files with 2572 additions and 1465 deletions

View File

@@ -6,7 +6,7 @@ the game assets from Sourceforge using SVN.
`svn checkout https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets`
Place the `stk-assets` folder next to the source root `stk-code` folder.
See <http://supertuxkart.sourceforge.net/Source_control> for more information
See <https://supertuxkart.net/Source_control> for more information
## Building STK on Linux
@@ -75,8 +75,8 @@ location, specify `CMAKE_INSTALL_PREFIX` when running cmake, e.g.:
## Building STK on OS X
See <http://supertuxkart.sourceforge.net/Building_and_packaging_on_OSX>
See <https://supertuxkart.net/Building_and_packaging_on_OSX>
## Building STK on Windows
See <http://supertuxkart.sourceforge.net/How_to_build_the_Windows_version>
See <https://supertuxkart.net/How_to_build_the_Windows_version>

View File

@@ -3,9 +3,9 @@
SuperTuxKart is a free kart racing game. It focuses on fun and not on realistic kart physics. Instructions can be found on the in-game help page.
The SuperTuxKart homepage can be found at: <http://supertuxkart.sourceforge.net>
The SuperTuxKart homepage can be found at: <https://supertuxkart.net/>
The official SuperTuxKart forum is at <http://supertuxkart.sourceforge.net/forum>. If you need support, this would be the best place to start.
The official SuperTuxKart forum is at <http://forum.freegamedev.net/viewforum.php?f=16>. If you need support, this would be the best place to start.
Hope you enjoy the game.
@@ -22,7 +22,7 @@ Hope you enjoy the game.
### Windows
1. Install VS 2013 (or later). The free express versions work fine.
2. Download and install a source package - either a released package or from our [git/svn repositories](http://supertuxkart.sourceforge.net/Source_control).
2. Download and install a source package - either a released package or from our [git/svn repositories](https://supertuxkart.net/Source_control).
3. Download the latest dependency package from [here](https://sourceforge.net/projects/supertuxkart/files/SuperTuxKart%20Dependencies/Windows/). Unzip it in the root directory, so that the dependencies directory is next to the src and data directories (if you are updating from a previous dependency package, you can delete the .dll files in the root directory, they are not needed anymore).
4. Download cmake and install it. Then start cmake-gui and select the STK root directory as 'Where is the source code', and a new directory in the root directory (next to src, data etc) as the build directory (for now I assume that this directory is called bld).
5. Click on configure. You will be asked to create the directory (yes), then for your VS version. Make sure you select the right version (be aware of the easy to confuse version numbers: VS 2013 = version 12). Click on configure, then generate. This will create the directory 'bld', and a VS solution in that directory.
@@ -30,10 +30,12 @@ Hope you enjoy the game.
7. Right click on the supertuxkart project in the solution explorer, and select "Set as StartUp Project".
8. Select Build->Build Solution (or press F7) to compile.
See <https://supertuxkart.net/How_to_build_the_Windows_version> for more information.
Compilation with cygwin is not officially supported, but this has been done (check with the forum for details).
### Mac OS X
The latest information about compilation on Mac are on our wiki: <http://supertuxkart.sourceforge.net/Building_and_packaging_on_OSX>
The latest information about compilation on Mac are at our site: <https://supertuxkart.net/Building_and_packaging_on_OSX>
### UNIX
See [`INSTALL.md`](INSTALL.md) for details.

31
TODO.md
View File

@@ -4,30 +4,27 @@ SuperTuxKart is looking for additional man power to make this
one of the best free linux games out there :) We need (in
no particular order):
1. Musicians/sound engineers
- Create additional background soundtrack
- Musicians/sound engineers
- Create additional background soundtracks
- Create sound effects
2. Artists and track designer
- Artists and track designer
- Create additional tracks
- Create additional art work for tracks,
background images
3. Developers
- Create additional artwork for tracks and background images
- Developers
- Work on network play support
- Check our bug and enhancement request tracker on
https://github.com/supertuxkart/stk-code/issues
- Extend the current web page, keep it up to date
4. Tester
- For just about everything
- Esp. different platforms and graphics cards
5. Writers
- Write documentation, ranging from man page, to
a description for the web, to a design document, ...
- Extend the current web page and keep it up to date
- Testers
- For just about everything, especially different platforms and graphics cards
- Writers
- Write documentation, ranging from man page, to a description for the web, to a design document, etc...
If you want to help the SuperTuxKart - Project, please
contact us on the email list: [supertuxkart-devel@lists.sourceforge.net](mailto:supertuxkart-devel@lists.sourceforge.net)
If you want to help the SuperTuxKart Project, please contact us on the email list: [supertuxkart-devel@lists.sourceforge.net](mailto:supertuxkart-devel@lists.sourceforge.net)
Thanks in advance!
-- The SuperTuxKart-Team
-- The SuperTuxKart Team
For details, see <http://supertuxkart.sourceforge.net/Get_involved>
For details, see <http://supertuxkart.net/Community>

View File

@@ -7,11 +7,15 @@ uniform sampler2D SpecMap;
flat in sampler2D handle;
flat in sampler2D secondhandle;
#endif
uniform vec2 color_change;
in vec2 uv;
in vec4 color;
out vec4 FragColor;
#stk_include "utils/getLightFactor.frag"
#stk_include "utils/rgb_conversion.frag"
void main(void)
{
@@ -27,6 +31,15 @@ void main(void)
float specmap = texture(SpecMap, uv).g;
float emitmap = texture(SpecMap, uv).b;
#endif
if (color_change.x > 0.0)
{
vec3 old_hsv = rgbToHsv(col.rgb);
old_hsv.y = max(old_hsv.y, color_change.y);
vec3 new_color = hsvToRgb(vec3(color_change.x, old_hsv.y, old_hsv.z));
col = vec4(new_color.r, new_color.g, new_color.b, col.a);
}
col.xyz *= pow(color.xyz, vec3(2.2));
FragColor = vec4(getLightFactor(col.xyz, vec3(1.), specmap, emitmap) , 1.);

View File

@@ -6,11 +6,14 @@ uniform sampler2D Albedo;
uniform sampler2D SpecMap;
#endif
uniform vec2 color_change;
in vec2 uv;
in vec4 color;
out vec4 FragColor;
#stk_include "utils/getLightFactor.frag"
#stk_include "utils/rgb_conversion.frag"
void main(void)
{
@@ -22,6 +25,15 @@ void main(void)
#else
vec4 col = texture(Albedo, uv);
#endif
if (color_change.x > 0.0)
{
vec3 old_hsv = rgbToHsv(col.rgb);
old_hsv.y = max(old_hsv.y, color_change.y);
vec3 new_color = hsvToRgb(vec3(color_change.x, old_hsv.y, old_hsv.z));
col = vec4(new_color.r, new_color.g, new_color.b, col.a);
}
col.xyz *= pow(color.xyz, vec3(2.2));
float specmap = texture(SpecMap, uv).g;
float emitmap = texture(SpecMap, uv).b;

View File

@@ -0,0 +1,17 @@
vec3 rgbToHsv(vec3 c)
{
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsvToRgb(vec3 c)
{
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

View File

@@ -13,6 +13,11 @@ if(NOT USE_GLES2)
include_directories(${OPENGL_INCLUDE_DIR})
endif()
if (UNIX AND NOT APPLE)
find_package(X11 REQUIRED)
include_directories(${X11_INCLUDE_DIR})
endif()
if(APPLE)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht/MacOSX" "${CMAKE_CURRENT_SOURCE_DIR}/source/Irrlicht")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch x86_64")
@@ -27,8 +32,8 @@ elseif(MINGW)
add_definitions(-D_IRR_STATIC_LIB_)
add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Shut up about unsafe stuff
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pipe -O3 -fno-exceptions -fstrict-aliasing -I/usr/X11R6/include")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wall -pipe -O3 -fno-exceptions -fstrict-aliasing -I/usr/X11R6/include")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pipe -O3 -fno-exceptions -fstrict-aliasing")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pipe -O3 -fno-exceptions -fstrict-aliasing")
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fexpensive-optimizations")
endif()

View File

@@ -10,15 +10,6 @@ namespace irr
namespace video
{
//! Flag for mesh (mainly karts in STK) to use specific render type
enum E_RENDER_TYPE
{
ERT_DEFAULT = 0,
ERT_TRANSPARENT,
ERT_RED,
ERT_BLUE
};
//! Abstracted and easy to use fixed function/programmable pipeline material modes.
enum E_MATERIAL_TYPE
{

View File

@@ -23,9 +23,6 @@ namespace scene
class IMesh : public virtual IReferenceCounted
{
public:
IMesh() : m_rt(video::ERT_DEFAULT) {}
virtual ~IMesh() {}
//! Get the amount of mesh buffers.
/** \return Amount of mesh buffers (IMeshBuffer) in this mesh. */
@@ -69,15 +66,6 @@ namespace scene
indices have changed. Otherwise, changes won't be updated
on the GPU in the next render cycle. */
virtual void setDirty(E_BUFFER_TYPE buffer=EBT_VERTEX_AND_INDEX) = 0;
//! Set the mesh to use a specific render type (mainly karts in STK)
/** \param t New render type for the mesh. */
void setRenderType(video::E_RENDER_TYPE t) { m_rt = t; }
//! Get the specific render type for the mesh (mainly karts in STK)
video::E_RENDER_TYPE getRenderType() const { return m_rt; }
private:
video::E_RENDER_TYPE m_rt;
};
} // end namespace scene

View File

@@ -66,7 +66,7 @@ void CImageLoaderJPG::init_source (j_decompress_ptr cinfo)
boolean CImageLoaderJPG::fill_input_buffer (j_decompress_ptr cinfo)
{
// DO NOTHING
return 1;
return TRUE;
}

View File

@@ -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/*")

View File

@@ -72,33 +72,37 @@ MusicInformation *MusicInformation::create(const std::string &filename)
MusicInformation::MusicInformation(const XMLNode *root,
const std::string &filename)
{
m_title = "";
m_mode = SOUND_NORMAL;
m_composer = "";
//m_numLoops = LOOP_FOREVER;
m_normal_filename = "";
m_fast_filename = "";
m_normal_music = NULL;
m_fast_music = NULL;
m_enable_fast = false;
m_music_waiting = false;
m_faster_time = 1.0f;
m_max_pitch = 0.1f;
m_gain = 1.0f;
m_title = "";
m_mode = SOUND_NORMAL;
m_composer = "";
//m_numLoops = LOOP_FOREVER;
m_normal_filename = "";
m_fast_filename = "";
m_normal_music = NULL;
m_fast_music = NULL;
m_normal_loop_start = 0.0f;
m_fast_loop_start = 0.0f;
m_enable_fast = false;
m_music_waiting = false;
m_faster_time = 1.0f;
m_max_pitch = 0.1f;
m_gain = 1.0f;
// Otherwise read config file
// --------------------------
std::string s;
root->get("title", &s );
root->get("title", &s );
m_title = StringUtils::xmlDecode(s);
root->get("composer", &s );
root->get("composer", &s );
m_composer = StringUtils::xmlDecode(s);
root->get("file", &m_normal_filename);
root->get("gain", &m_gain );
root->get("tracks", &m_all_tracks );
root->get("fast", &m_enable_fast );
root->get("fast-filename", &m_fast_filename );
root->get("file", &m_normal_filename );
root->get("gain", &m_gain );
root->get("tracks", &m_all_tracks );
root->get("fast", &m_enable_fast );
root->get("fast-filename", &m_fast_filename );
root->get("loop-start", &m_normal_loop_start);
root->get("fast-loop-start", &m_fast_loop_start );
// Get the path from the filename and add it to the ogg filename
std::string path = StringUtils::getPath(filename);
@@ -155,7 +159,7 @@ void MusicInformation::startMusic()
if (m_normal_music) delete m_normal_music;
#if HAVE_OGGVORBIS
m_normal_music = new MusicOggStream();
m_normal_music = new MusicOggStream(m_normal_loop_start);
#else
m_normal_music = new MusicDummy();
#endif
@@ -190,7 +194,7 @@ void MusicInformation::startMusic()
}
#if HAVE_OGGVORBIS
m_fast_music = new MusicOggStream();
m_fast_music = new MusicOggStream(m_fast_loop_start);
#else
m_fast_music = new MusicDummy();
#endif

View File

@@ -58,6 +58,9 @@ private:
float m_gain;
float m_normal_loop_start;
float m_fast_loop_start;
/** Either time for fading faster music in, or time to change pitch. */
float m_faster_time;
/** Maximum pitch for faster music. */

View File

@@ -32,13 +32,14 @@
#include "utils/constants.hpp"
#include "utils/log.hpp"
MusicOggStream::MusicOggStream()
MusicOggStream::MusicOggStream(float loop_start)
{
//m_oggStream= NULL;
m_soundBuffers[0] = m_soundBuffers[1]= 0;
m_soundSource = -1;
m_pausedMusic = true;
m_playing = false;
m_loop_start = loop_start;
} // MusicOggStream
//-----------------------------------------------------------------------------
@@ -289,8 +290,8 @@ void MusicOggStream::update()
active = streamIntoBuffer(buffer);
if(!active)
{
// no more data. Seek to beginning (causes the sound to loop)
ov_time_seek(&m_oggStream, 0);
// no more data. Seek to loop start (causes the sound to loop)
ov_time_seek(&m_oggStream, m_loop_start);
active = streamIntoBuffer(buffer);//now there really should be data
}

View File

@@ -47,7 +47,7 @@
class MusicOggStream : public Music
{
public:
MusicOggStream();
MusicOggStream(float loop_start);
virtual ~MusicOggStream();
virtual void update();
@@ -71,6 +71,7 @@ private:
bool release();
bool streamIntoBuffer(ALuint buffer);
float m_loop_start;
std::string m_fileName;
FILE* m_oggFile;
OggVorbis_File m_oggStream;

View File

@@ -180,9 +180,9 @@ public:
* \throw out_of_range if there is no data for 'type'.
* \param type Type of kart (e.g. heavy, medium, ...).
*/
const KartProperties& getKartProperties(std::string type)
const KartProperties& getKartProperties(const std::string &type)
{
return *m_kart_properties.at(type);
return *m_kart_properties.at(type);
} // getKartProperties
}
; // STKConfig

View File

@@ -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,78 @@
#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
// ----------------------------------------------------------------------------
void Camera::resetAllCameras()
{
for (unsigned int i = 0; i < Camera::getNumCameras(); i++)
{
changeCamera(i, m_default_type);
getCamera(i)->reset();
}
} // resetAllCameras
// ----------------------------------------------------------------------------
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 +122,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 +138,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 +153,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,22 +237,14 @@ 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(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);
} // mode==CM_FINAL
m_mode = mode;
} // setMode
@@ -303,7 +255,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 +279,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 +292,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 +317,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 +337,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

View File

@@ -35,57 +35,56 @@
#include <vector>
namespace irr
{
namespace scene { class ICameraSceneNode; }
}
using namespace irr;
#include "ICameraSceneNode.h"
class AbstractKart;
/**
* \brief Handles the game camera
* \brief This is the base class for all cameras. It also includes some
* static functios to keep track of all cameras (e.g. a static function to
* create a camera, get a camera with a specified index).
* \ingroup graphics
*/
class Camera : public NoCopy
{
public:
enum Mode {
/** The different camera types that can be used. */
enum CameraType
{
CM_TYPE_NORMAL,
CM_TYPE_DEBUG, //!< A debug camera.
CM_TYPE_FPS, //!< FPS Camera
CM_TYPE_END //!< End camera
}; // CameraType
/* Only used for the normal camera. */
enum Mode
{
CM_NORMAL, //!< Normal camera mode
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
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 +92,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 +109,57 @@ 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();
virtual void reset();
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 resetAllCameras();
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 +169,20 @@ 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 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 +202,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,10 +221,10 @@ 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()); }
}; // class Camera
#endif

View File

@@ -0,0 +1,199 @@
//
// 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 )
{
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;
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;
// 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());
}
// 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);
// 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);
positionCamera(dt, above_kart, cam_angle, side_way, distance);
}
} // 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 )
{
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 (getMode() != CM_FALLING)
m_camera->setPosition(wanted_position.toIrrVector());
m_camera->setTarget(wanted_target.toIrrVector());
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

View File

@@ -0,0 +1,69 @@
//
// 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 );
void positionCamera(float dt, float above_kart, float cam_angle,
float side_way, float distance);
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
View 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
View 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
View 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
View 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 */

View 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

View 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 */

View File

@@ -30,6 +30,7 @@
#include "graphics/per_camera_node.hpp"
#include "graphics/post_processing.hpp"
#include "graphics/referee.hpp"
#include "graphics/render_info.hpp"
#include "graphics/shaders.hpp"
#include "graphics/shadow_matrices.hpp"
#include "graphics/stk_animated_mesh.hpp"
@@ -1047,8 +1048,7 @@ scene::IMesh *IrrDriver::getMesh(const std::string &filename)
* \return Newly created skinned mesh. You should call drop() when you don't
* need it anymore.
*/
scene::IAnimatedMesh *IrrDriver::copyAnimatedMesh(scene::IAnimatedMesh *orig,
video::E_RENDER_TYPE rt)
scene::IAnimatedMesh *IrrDriver::copyAnimatedMesh(scene::IAnimatedMesh *orig)
{
using namespace scene;
CSkinnedMesh *mesh = dynamic_cast<CSkinnedMesh*>(orig);
@@ -1059,7 +1059,6 @@ scene::IAnimatedMesh *IrrDriver::copyAnimatedMesh(scene::IAnimatedMesh *orig,
}
scene::IAnimatedMesh* out = mesh->clone();
out->setRenderType(rt);
return out;
} // copyAnimatedMesh
@@ -1205,7 +1204,9 @@ scene::IParticleSystemSceneNode *IrrDriver::addParticleNode(bool default_emitter
*/
scene::IMeshSceneNode *IrrDriver::addMesh(scene::IMesh *mesh,
const std::string& debug_name,
scene::ISceneNode *parent)
scene::ISceneNode *parent,
RenderInfo* render_info,
bool all_parts_colorized)
{
if (!CVS->isGLSL())
return m_scene_manager->addMeshSceneNode(mesh, parent);
@@ -1215,7 +1216,12 @@ scene::IMeshSceneNode *IrrDriver::addMesh(scene::IMesh *mesh,
scene::IMeshSceneNode* node = new STKMeshSceneNode(mesh, parent,
m_scene_manager, -1,
debug_name);
debug_name,
core::vector3df(0, 0, 0),
core::vector3df(0, 0, 0),
core::vector3df(1.0f, 1.0f, 1.0f),
true, render_info,
all_parts_colorized);
node->drop();
return node;
@@ -1397,7 +1403,8 @@ void IrrDriver::removeTexture(video::ITexture *t)
* \param mesh The animated mesh to add.
*/
scene::IAnimatedMeshSceneNode *IrrDriver::addAnimatedMesh(scene::IAnimatedMesh *mesh,
const std::string& debug_name, scene::ISceneNode* parent)
const std::string& debug_name, scene::ISceneNode* parent,
RenderInfo* render_info, bool all_parts_colorized)
{
if (!CVS->isGLSL())
{
@@ -1412,7 +1419,8 @@ scene::IAnimatedMeshSceneNode *IrrDriver::addAnimatedMesh(scene::IAnimatedMesh *
parent = m_scene_manager->getRootSceneNode();
scene::IAnimatedMeshSceneNode* node =
new STKAnimatedMesh(mesh, parent, m_scene_manager, -1, debug_name,
core::vector3df(0, 0, 0), core::vector3df(0, 0, 0), core::vector3df(1, 1, 1));
core::vector3df(0, 0, 0), core::vector3df(0, 0, 0),
core::vector3df(1, 1, 1), render_info, all_parts_colorized);
node->drop();
return node;
} // addAnimatedMesh

View File

@@ -56,6 +56,7 @@ namespace irr
using namespace irr;
class RTT;
class RenderInfo;
class FrameBuffer;
class ShadowImportanceProvider;
class AbstractKart;
@@ -353,8 +354,7 @@ public:
void setAllMaterialFlags(scene::IMesh *mesh) const;
scene::IAnimatedMesh *getAnimatedMesh(const std::string &name);
scene::IMesh *getMesh(const std::string &name);
scene::IAnimatedMesh *copyAnimatedMesh(scene::IAnimatedMesh *orig,
video::E_RENDER_TYPE rt);
scene::IAnimatedMesh *copyAnimatedMesh(scene::IAnimatedMesh *orig);
video::ITexture *applyMask(video::ITexture* texture,
const std::string& mask_path);
void displayFPS();
@@ -387,7 +387,9 @@ public:
const video::SColor &color=video::SColor(128, 255, 255, 255));
scene::IMeshSceneNode*addMesh(scene::IMesh *mesh,
const std::string& debug_name,
scene::ISceneNode *parent=NULL);
scene::ISceneNode *parent = NULL,
RenderInfo* render_info = NULL,
bool all_parts_colorized = false);
PerCameraNode *addPerCameraNode(scene::ISceneNode* node,
scene::ICameraSceneNode* cam,
scene::ISceneNode *parent = NULL);
@@ -407,7 +409,11 @@ public:
void removeMeshFromCache(scene::IMesh *mesh);
void removeTexture(video::ITexture *t);
scene::IAnimatedMeshSceneNode
*addAnimatedMesh(scene::IAnimatedMesh *mesh, const std::string& debug_name, scene::ISceneNode* parent = NULL);
*addAnimatedMesh(scene::IAnimatedMesh *mesh,
const std::string& debug_name,
scene::ISceneNode* parent = NULL,
RenderInfo* render_info = NULL,
bool all_parts_colorized = false);
scene::ICameraSceneNode
*addCameraSceneNode();
Camera *addCamera(unsigned int index, AbstractKart *kart);

View File

@@ -133,20 +133,22 @@ Material::Material(const XMLNode *node, bool deprecated)
// force the reset flag in this case.
if(m_falling_effect)
m_drive_reset=true;
node->get("surface", &m_surface );
node->get("ignore", &m_ignore );
node->get("surface", &m_surface );
node->get("ignore", &m_ignore );
node->get("max-speed", &m_max_speed_fraction);
node->get("slowdown-time", &m_slowdown_time );
node->get("backface-culling", &m_backface_culling );
node->get("disable-z-write", &m_disable_z_write );
node->get("fog", &m_fog );
node->get("max-speed", &m_max_speed_fraction );
node->get("slowdown-time", &m_slowdown_time );
node->get("backface-culling", &m_backface_culling );
node->get("disable-z-write", &m_disable_z_write );
node->get("colorizable", &m_colorizable );
node->get("colorization-factor", &m_colorization_factor);
node->get("fog", &m_fog );
node->get("mask", &m_mask );
node->get("gloss-map", &m_gloss_map );
node->get("water-splash", &m_water_splash );
node->get("jump", &m_is_jump_texture );
node->get("has-gravity", &m_has_gravity );
node->get("mask", &m_mask );
node->get("gloss-map", &m_gloss_map );
node->get("water-splash", &m_water_splash );
node->get("jump", &m_is_jump_texture );
node->get("has-gravity", &m_has_gravity );
if (m_collision_reaction != NORMAL)
{
@@ -434,6 +436,8 @@ void Material::init()
m_mirror_axis_when_reverse = ' ';
m_collision_reaction = NORMAL;
m_disable_z_write = false;
m_colorizable = false;
m_colorization_factor = 0.0f;
m_water_shader_speed_1 = 6.6667f;
m_water_shader_speed_2 = 4.0f;
m_fog = true;

View File

@@ -175,6 +175,12 @@ private:
/** Set to true to disable writing to the Z buffer. Usually to be used with alpha blending */
bool m_disable_z_write;
/** True if this material can be colorized (like red/blue in team game). */
bool m_colorizable;
/** Minimum resulting saturation when colorized (from 0 to 1) */
float m_colorization_factor;
/** Some textures need to be pre-multiplied, some divided to give
* the intended effect. */
//enum {ADJ_NONE, ADJ_PREMUL, ADJ_DIV}
@@ -283,6 +289,14 @@ public:
* is driving on it. */
bool isDriveReset () const { return m_drive_reset; }
// ------------------------------------------------------------------------
/** Returns if this material can be colorized (like red/blue in team game).
*/
bool isColorizable () const { return m_colorizable; }
// ------------------------------------------------------------------------
/** Returns the minimum resulting saturation when colorized.
*/
float getColorizationFactor () const { return m_colorization_factor; }
// ------------------------------------------------------------------------
/** Returns if this material should trigger a rescue if a kart
* crashes against it. */
CollisionReaction getCollisionReaction() const { return m_collision_reaction; }

View File

@@ -23,6 +23,7 @@
#include "graphics/glwrap.hpp"
#include "graphics/post_processing.hpp"
#include "graphics/rtts.hpp"
#include "graphics/render_info.hpp"
#include "graphics/shaders.hpp"
#include "graphics/shadow_matrices.hpp"
#include "graphics/stk_scene_manager.hpp"
@@ -128,11 +129,15 @@ public:
// ============================================================================
class InstancedObjectPass2Shader : public TextureShader<InstancedObjectPass2Shader, 5>
{
private:
GLint m_color_change_location;
public:
InstancedObjectPass2Shader()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "instanced_object_pass.vert",
GL_FRAGMENT_SHADER, "instanced_object_pass2.frag");
m_color_change_location = glGetUniformLocation(m_program, "color_change");
assignUniforms();
assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED,
1, "SpecularMap", ST_NEAREST_FILTERED,
@@ -140,6 +145,12 @@ public:
3, "Albedo", ST_TRILINEAR_ANISOTROPIC_FILTERED,
4, "SpecMap", ST_TRILINEAR_ANISOTROPIC_FILTERED);
} // InstancedObjectPass2Shader
virtual bool changeableColor(float hue = 0.0f, float min_sat = 0.0f) const OVERRIDE
{
glUniform2f(m_color_change_location, hue, min_sat);
return true;
} // changeableColor
}; // InstancedObjectPass2Shader
// ============================================================================
@@ -967,11 +978,26 @@ void draw(const T *Shader, const GLMesh *mesh, uniforms... Args)
GLenum itype = mesh->IndexType;
size_t count = mesh->IndexCount;
const bool support_change_hue = (mesh->m_render_info != NULL &&
mesh->m_material != NULL);
const bool need_change_hue = (support_change_hue &&
mesh->m_render_info->getHue() > 0.0f);
if (need_change_hue)
{
Shader->changeableColor(mesh->m_render_info->getHue(),
mesh->m_material->getColorizationFactor());
}
Shader->setUniforms(Args...);
glDrawRangeElements(ptype, (int)mesh->vaoBaseVertex,
(int)mesh->vaoBaseVertex + count - 1,
count, itype, (GLvoid *)mesh->vaoOffset);
if (need_change_hue)
{
// Reset after changing
Shader->changeableColor();
}
} // draw
// ----------------------------------------------------------------------------
@@ -1260,10 +1286,28 @@ void renderInstancedMeshes2ndPass(const std::vector<GLuint> &Prefilled_tex, Args
TexExpander<typename T::InstancedSecondPassShader>::template
ExpandTex(*mesh, T::SecondPassTextures, Prefilled_tex[0],
Prefilled_tex[1], Prefilled_tex[2]);
const bool support_change_hue = (mesh->m_render_info != NULL &&
mesh->m_material != NULL);
const bool need_change_hue =
(support_change_hue && mesh->m_render_info->getHue() > 0.0f);
if (need_change_hue)
{
T::InstancedSecondPassShader::getInstance()->changeableColor
(mesh->m_render_info->getHue(),
mesh->m_material->getColorizationFactor());
}
T::InstancedSecondPassShader::getInstance()->setUniforms(args...);
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
(const void*)((SolidPassCmd::getInstance()->Offset[T::MaterialType] + i)
* sizeof(DrawElementsIndirectCommand)));
if (need_change_hue)
{
// Reset after changing
T::InstancedSecondPassShader::getInstance()->changeableColor();
}
}
} // renderInstancedMeshes2ndPass

View File

@@ -0,0 +1,44 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2016 SuperTuxKart-Team
//
// 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/render_info.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include <ISceneManager.h>
// ----------------------------------------------------------------------------
RenderInfo::RenderInfo(float hue, bool transparent)
{
m_hue = hue;
m_transparent = transparent;
} // RenderInfo
// ----------------------------------------------------------------------------
void RenderInfo::setColorizableParts(irr::scene::IMesh* m)
{
for (int i = 0; i < int(m->getMeshBufferCount()); i++)
{
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
Material* material = material_manager->getMaterialFor(mb
->getMaterial().getTexture(0), mb);
if (material->isColorizable())
m_colorizable_parts.push_back(i);
}
} // setColorizableParts

View File

@@ -0,0 +1,87 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2016 SuperTuxKart-Team
//
// 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_RENDER_INFO_HPP
#define HEADER_RENDER_INFO_HPP
#include <algorithm>
#include <vector>
namespace irr
{
namespace scene { class IMesh; }
}
/**
* \ingroup graphics
*/
class RenderInfo
{
public:
enum KartRenderType
{
KRT_DEFAULT,
KRT_RED,
KRT_BLUE,
KRT_TRANSPARENT,
};
private:
float m_hue;
bool m_transparent;
std::vector<int> m_colorizable_parts;
public:
RenderInfo(float hue = 0.0f, bool transparent = false);
// ------------------------------------------------------------------------
~RenderInfo() {}
// ------------------------------------------------------------------------
void setColorizableParts(irr::scene::IMesh* m);
// ------------------------------------------------------------------------
void setHue(float hue) { m_hue = hue; }
// ------------------------------------------------------------------------
void setTransparent(bool transparent) { m_transparent = transparent; }
// ------------------------------------------------------------------------
float getHue() const { return m_hue; }
// ------------------------------------------------------------------------
bool isTransparent() const { return m_transparent; }
// ------------------------------------------------------------------------
bool isColorizable(int mesh_buffer_index) const
{
return m_colorizable_parts.empty() ||
std::find(m_colorizable_parts.begin(), m_colorizable_parts.end(),
mesh_buffer_index) != m_colorizable_parts.end();
}
// ------------------------------------------------------------------------
void setKartModelRenderInfo(KartRenderType krt)
{
setHue(krt == RenderInfo::KRT_BLUE ? 0.66f :
krt == RenderInfo::KRT_RED ? 1.0f : 0.0f);
setTransparent(krt == RenderInfo::KRT_TRANSPARENT ? true : false);
}
// ------------------------------------------------------------------------
void setRenderInfo(const RenderInfo* other) { *this = *other; }
}; // RenderInfo
#endif
/* EOF */

View File

@@ -350,6 +350,7 @@ Shaders::ObjectPass2Shader::ObjectPass2Shader()
{
loadProgram(OBJECT, GL_VERTEX_SHADER, "object_pass.vert",
GL_FRAGMENT_SHADER, "object_pass2.frag");
m_color_change_location = glGetUniformLocation(m_program, "color_change");
assignUniforms("ModelMatrix", "TextureMatrix");
assignSamplerNames(0, "DiffuseMap", ST_NEAREST_FILTERED,
1, "SpecularMap", ST_NEAREST_FILTERED,

View File

@@ -146,8 +146,15 @@ public:
class ObjectPass2Shader : public TextureShader < ObjectPass2Shader, 5,
core::matrix4, core::matrix4 >
{
private:
GLint m_color_change_location;
public:
ObjectPass2Shader();
virtual bool changeableColor(float hue = 0.0f, float min_sat = 0.0f) const OVERRIDE
{
glUniform2f(m_color_change_location, hue, min_sat);
return true;
} // changeableColor
}; // ObjectPass2Shader
// ========================================================================

View File

@@ -18,36 +18,42 @@
#include "graphics/stars.hpp"
#include <cmath>
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/kart_model.hpp"
#include "utils/constants.hpp"
#include <ISceneNode.h>
#include <IBillboardSceneNode.h>
#include <cmath>
const int STAR_AMOUNT = 7;
const float RADIUS = 0.7f;
const float STAR_SIZE = 0.4f;
Stars::Stars(scene::ISceneNode* parentKart, core::vector3df center)
Stars::Stars(AbstractKart *kart)
{
m_parent_kart_node = parentKart;
m_parent_kart_node = kart->getNode();
m_enabled = false;
video::ITexture* texture = irr_driver->getTexture("starparticle.png");
Material* star_material =
material_manager->getMaterial("starparticle.png");
m_center = center;
m_center = core::vector3df(0.0f,
kart->getKartModel()->getModel()
->getBoundingBox().MaxEdge.Y,
0.0f );
for (int n=0; n<STAR_AMOUNT; n++)
{
scene::ISceneNode* billboard =
irr_driver->addBillboard(core::dimension2df(STAR_SIZE, STAR_SIZE),
texture, parentKart);
texture, kart->getNode());
#ifdef DEBUG
billboard->setName("star");
#endif

View File

@@ -21,9 +21,12 @@
#include "utils/no_copy.hpp"
#include "vector3d.h"
#include <vector>
#include <vector3d.h>
class AbstractKart;
namespace irr
{
namespace scene { class ISceneNode; }
@@ -54,7 +57,7 @@ private:
float m_remaining_time;
public:
Stars (scene::ISceneNode* parentKart, core::vector3df center);
Stars (AbstractKart *kart);
~Stars ();
void showFor(float time);
void reset();

View File

@@ -21,8 +21,9 @@
#include "central_settings.hpp"
#include "graphics/camera.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/stk_animated_mesh.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/render_info.hpp"
#include "graphics/stk_animated_mesh.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
#include "utils/profiler.hpp"
@@ -38,11 +39,13 @@ STKAnimatedMesh::STKAnimatedMesh(irr::scene::IAnimatedMesh* mesh, irr::scene::IS
irr::scene::ISceneManager* mgr, s32 id, const std::string& debug_name,
const core::vector3df& position,
const core::vector3df& rotation,
const core::vector3df& scale) :
const core::vector3df& scale, RenderInfo* render_info, bool all_parts_colorized) :
CAnimatedMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
{
isGLInitialized = false;
isMaterialInitialized = false;
m_mesh_render_info = render_info;
m_all_parts_colorized = all_parts_colorized;
#ifdef DEBUG
m_debug_name = debug_name;
#endif
@@ -100,7 +103,16 @@ void STKAnimatedMesh::updateNoGL()
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name));
bool affected = false;
if (!m_all_parts_colorized && mb && m_mesh_render_info)
{
// Test if material is affected by hue change
affected = m_mesh_render_info->isColorizable(i);
}
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name,
affected || m_all_parts_colorized || (m_mesh_render_info
&& m_mesh_render_info->isTransparent()) ? m_mesh_render_info : NULL));
}
for (u32 i = 0; i < m->getMeshBufferCount(); ++i)
@@ -126,10 +138,17 @@ void STKAnimatedMesh::updateNoGL()
TransparentMaterial TranspMat = getTransparentMaterialFromType(type, MaterialTypeParam, material);
TransparentMesh[TranspMat].push_back(&mesh);
}
else if (m->getRenderType() == video::ERT_TRANSPARENT)
else if (mesh.m_render_info != NULL && mesh.m_render_info->isTransparent())
{
TransparentMesh[TM_ADDITIVE].push_back(&mesh);
}
else if (mesh.m_render_info != NULL)
{
// For now, put all meshes that support custom render info into
// solid (default) material first, this allowing changing fewer
// shaders
MeshSolidMaterial[Material::SHADERTYPE_SOLID].push_back(&mesh);
}
else
{
Material::ShaderType MatType = material->getShaderType();// getMeshMaterialFromType(type, mb->getVertexType(), material);

View File

@@ -25,6 +25,8 @@
#include <IAnimatedMesh.h>
#include <irrTypes.h>
class RenderInfo;
class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode, public STKMeshCommon
{
protected:
@@ -40,12 +42,16 @@ public:
irr::scene::ISceneManager* mgr, irr::s32 id, const std::string& debug_name,
const irr::core::vector3df& position = irr::core::vector3df(0,0,0),
const irr::core::vector3df& rotation = irr::core::vector3df(0,0,0),
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f));
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f),
RenderInfo* render_info = NULL, bool all_parts_colorized = false);
~STKAnimatedMesh();
virtual void render();
virtual void setMesh(irr::scene::IAnimatedMesh* mesh);
virtual bool glow() const { return false; }
private:
RenderInfo* m_mesh_render_info;
bool m_all_parts_colorized;
};
#endif // STKANIMATEDMESH_HPP

View File

@@ -23,6 +23,8 @@
#include "graphics/camera.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/render_info.hpp"
#include "graphics/shaders.hpp"
#include "modes/world.hpp"
#include "tracks/track.hpp"
@@ -163,13 +165,21 @@ GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type)
} // createVAO
// ----------------------------------------------------------------------------
GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb, const std::string& debug_name)
GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb, const std::string& debug_name,
RenderInfo* render_info)
{
GLMesh result = {};
result.m_material = NULL;
result.m_render_info = NULL;
if (!mb)
return result;
result.mb = mb;
if (render_info != NULL)
{
result.m_render_info = render_info;
result.m_material = material_manager->getMaterialFor(mb
->getMaterial().getTexture(0), mb);
}
#ifdef DEBUG
result.debug_name = debug_name;
#endif

View File

@@ -30,7 +30,7 @@
#include <vector>
class Material;
class RenderInfo;
enum TransparentMaterial
{
@@ -56,6 +56,8 @@ struct GLMesh
video::E_VERTEX_TYPE VAOType;
uint64_t TextureHandles[6];
scene::IMeshBuffer *mb;
RenderInfo* m_render_info;
Material* m_material;
#ifdef DEBUG
std::string debug_name;
#endif
@@ -63,7 +65,8 @@ struct GLMesh
// ----------------------------------------------------------------------------
GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb,
const std::string& debug_name);
const std::string& debug_name,
RenderInfo* render_info);
void fillLocalBuffer(GLMesh &, scene::IMeshBuffer* mb);
video::E_VERTEX_TYPE getVTXTYPEFromStride(size_t stride);
GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type);

View File

@@ -24,6 +24,7 @@
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/render_info.hpp"
#include "graphics/stk_mesh.hpp"
#include "tracks/track.hpp"
#include "modes/world.hpp"
@@ -34,7 +35,6 @@
#include <ISceneManager.h>
#include <IMaterialRenderer.h>
// ============================================================================
class ColorizeShader : public Shader<ColorizeShader, core::matrix4,
video::SColorf>
@@ -54,7 +54,7 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent,
irr::s32 id, const std::string& debug_name,
const irr::core::vector3df& position,
const irr::core::vector3df& rotation,
const irr::core::vector3df& scale, bool createGLMeshes) :
const irr::core::vector3df& scale, bool createGLMeshes, RenderInfo* render_info, bool all_parts_colorized) :
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
{
isDisplacement = false;
@@ -65,7 +65,7 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent,
m_debug_name = debug_name;
if (createGLMeshes)
this->createGLMeshes();
this->createGLMeshes(render_info, all_parts_colorized);
}
void STKMeshSceneNode::setReloadEachFrame(bool val)
@@ -75,12 +75,21 @@ void STKMeshSceneNode::setReloadEachFrame(bool val)
immediate_draw = true;
}
void STKMeshSceneNode::createGLMeshes()
void STKMeshSceneNode::createGLMeshes(RenderInfo* render_info, bool all_parts_colorized)
{
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name));
bool affected = false;
if (!all_parts_colorized && mb && render_info)
{
// Test if material is affected by hue change
affected = render_info->isColorizable(i);
}
GLmeshes.push_back(allocateMeshBuffer(mb, m_debug_name,
affected || all_parts_colorized || (render_info &&
render_info->isTransparent()) ? render_info : NULL));
}
isMaterialInitialized = false;
isGLInitialized = false;
@@ -175,7 +184,7 @@ void STKMeshSceneNode::updateNoGL()
GLMesh &mesh = GLmeshes[i];
Material* material = material_manager->getMaterialFor(mb->getMaterial().getTexture(0), mb);
if (Mesh->getRenderType() == video::ERT_TRANSPARENT)
if (mesh.m_render_info != NULL && mesh.m_render_info->isTransparent())
{
if (!immediate_draw)
TransparentMesh[TM_ADDITIVE].push_back(&mesh);
@@ -190,6 +199,14 @@ void STKMeshSceneNode::updateNoGL()
else
additive = (TranspMat == TM_ADDITIVE);
}
else if (mesh.m_render_info != NULL)
{
// For now, put all meshes that support custom render info into
// solid (default) material first, this allowing changing fewer
// shaders
if (!immediate_draw)
MeshSolidMaterial[Material::SHADERTYPE_SOLID].push_back(&mesh);
}
else
{
assert(!isDisplacement);

View File

@@ -23,6 +23,8 @@
#include "graphics/shaders.hpp"
#include "utils/ptr_vector.hpp"
class RenderInfo;
class STKMeshSceneNode : public irr::scene::CMeshSceneNode, public STKMeshCommon
{
protected:
@@ -33,7 +35,7 @@ protected:
// Misc passes shaders (glow, displace...)
void drawGlow(const GLMesh &mesh);
void createGLMeshes();
void createGLMeshes(RenderInfo* render_info = NULL, bool all_parts_colorized = false);
void cleanGLMeshes();
void setFirstTimeMaterial();
void updatevbo();
@@ -54,7 +56,8 @@ public:
const irr::core::vector3df& position = irr::core::vector3df(0, 0, 0),
const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0),
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f),
bool createGLMeshes = true);
bool createGLMeshes = true,
RenderInfo* render_info = NULL, bool all_parts_colorized = false);
virtual void render();
virtual void setMesh(irr::scene::IMesh* mesh);
virtual void OnRegisterSceneNode();

View File

@@ -22,6 +22,7 @@
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/lod_node.hpp"
#include "graphics/render_info.hpp"
#include "graphics/shadow_matrices.hpp"
#include "graphics/stk_animated_mesh.hpp"
#include "graphics/stk_mesh.hpp"
@@ -155,6 +156,42 @@ FillInstances_impl(std::vector<std::pair<GLMesh *, scene::ISceneNode *> > Instan
PolyCount += (InstanceBufferOffset - InitialOffset) * mesh->IndexCount / 3;
}
class MeshRenderInfoHash
{
public:
size_t operator() (const std::pair<scene::IMeshBuffer*, RenderInfo*> &p) const
{
return (std::hash<scene::IMeshBuffer*>()(p.first) ^
(std::hash<RenderInfo*>()(p.second) << 1));
}
};
struct MeshRenderInfoEquals : std::binary_function
<const std::pair<scene::IMeshBuffer*, RenderInfo*>&,
const std::pair<scene::IMeshBuffer*, RenderInfo*>&, bool>
{
result_type operator() (first_argument_type lhs,
second_argument_type rhs) const
{
return (lhs.first == rhs.first) &&
(lhs.second == rhs.second);
}
};
template<typename T>
static
void FillInstances(const std::unordered_map<std::pair<scene::IMeshBuffer*, RenderInfo*>, std::vector<std::pair<GLMesh *, scene::ISceneNode*> >, MeshRenderInfoHash, MeshRenderInfoEquals> &GatheredGLMesh, std::vector<GLMesh *> &InstancedList,
T *InstanceBuffer, DrawElementsIndirectCommand *CommandBuffer, size_t &InstanceBufferOffset, size_t &CommandBufferOffset, size_t &Polycount)
{
auto It = GatheredGLMesh.begin(), E = GatheredGLMesh.end();
for (; It != E; ++It)
{
FillInstances_impl<T>(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, Polycount);
if (!CVS->isAZDOEnabled())
InstancedList.push_back(It->second.front().first);
}
}
template<typename T>
static
void FillInstances(const std::unordered_map<scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > &GatheredGLMesh, std::vector<GLMesh *> &InstancedList,
@@ -169,7 +206,8 @@ void FillInstances(const std::unordered_map<scene::IMeshBuffer *, std::vector<st
}
}
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForSolidPass[Material::SHADERTYPE_COUNT], MeshForShadowPass[Material::SHADERTYPE_COUNT][4], MeshForRSM[Material::SHADERTYPE_COUNT];
static std::unordered_map <std::pair<scene::IMeshBuffer*, RenderInfo*>, std::vector<std::pair<GLMesh *, scene::ISceneNode*> >, MeshRenderInfoHash, MeshRenderInfoEquals> MeshForSolidPass[Material::SHADERTYPE_COUNT];
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForShadowPass[Material::SHADERTYPE_COUNT][4], MeshForRSM[Material::SHADERTYPE_COUNT];
static std::unordered_map <scene::IMeshBuffer *, std::vector<std::pair<GLMesh *, scene::ISceneNode*> > > MeshForGlowPass;
static std::vector <STKMeshCommon *> DeferredUpdate;
@@ -321,7 +359,7 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector<scene::ISceneNode *> *Immed
MeshForGlowPass[mesh->mb].emplace_back(mesh, Node);
if (Mat != Material::SHADERTYPE_SPLATTING && mesh->TextureMatrix.isIdentity())
MeshForSolidPass[Mat][mesh->mb].emplace_back(mesh, Node);
MeshForSolidPass[Mat][std::pair<scene::IMeshBuffer*, RenderInfo*>(mesh->mb, mesh->m_render_info)].emplace_back(mesh, Node);
else
{
core::matrix4 ModelMatrix = Node->getAbsoluteTransformation(), InvModelMatrix;

View File

@@ -21,6 +21,7 @@
#include "graphics/central_settings.hpp"
#include "graphics/gl_headers.hpp"
#include "graphics/shader.hpp"
#include "utils/cpp2011.hpp"
#include <assert.h>
#include <functional>
@@ -243,6 +244,12 @@ public:
glDeleteSamplers(1, &m_sampler_ids[i]);
} // ~TextureShader
/** Override this class and return true if a shader has changeable color.
*/
virtual bool changeableColor(float hue = 0.0f, float min_sat = 0.0f) const
{
return false;
} // changeableColor
}; // class TextureShader

View File

@@ -48,20 +48,20 @@ IconButtonWidget(IconButtonWidget::SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO, false,
m_rtt_provider = NULL;
m_old_rtt_provider = NULL;
m_rotation_mode = ROTATE_OFF;
// so that the base class doesn't complain there is no icon defined
m_properties[PROP_ICON]="gui/main_help.png";
m_rtt_unsupported = false;
}
// -----------------------------------------------------------------------------
ModelViewWidget::~ModelViewWidget()
{
GUIEngine::needsUpdate.remove(this);
delete m_rtt_provider;
m_rtt_provider = NULL;
delete m_old_rtt_provider;
m_old_rtt_provider = NULL;
m_texture = NULL;
@@ -71,18 +71,18 @@ void ModelViewWidget::add()
{
// so that the base class doesn't complain there is no icon defined
m_properties[PROP_ICON]="gui/main_help.png";
IconButtonWidget::add();
/*
FIXME: remove this unclean thing, I think irrlicht provides this feature:
virtual void IGUIElement::OnPostRender (u32 timeMs)
\brief animate the element and its children.
*/
GUIEngine::needsUpdate.push_back(this);
angle = 0;
} // add
// -----------------------------------------------------------------------------
@@ -92,11 +92,12 @@ void ModelViewWidget::clearModels()
m_model_location.clear();
m_model_scale.clear();
m_model_frames.clear();
m_model_render_info_affected.clear();
if (m_rtt_main_node != NULL) m_rtt_main_node->remove();
if (m_light != NULL) m_light->remove();
if (m_camera != NULL) m_camera->remove();
m_rtt_main_node = NULL;
m_camera = NULL;
m_light = NULL;
@@ -105,15 +106,17 @@ void ModelViewWidget::clearModels()
// -----------------------------------------------------------------------------
void ModelViewWidget::addModel(irr::scene::IMesh* mesh, const Vec3& location,
const Vec3& scale, const int frame)
const Vec3& scale, const int frame,
bool all_parts_colorized)
{
if(!mesh) return;
m_models.push_back(mesh);
m_model_location.push_back(location);
m_model_scale.push_back(scale);
m_model_frames.push_back(frame);
m_model_render_info_affected.push_back(all_parts_colorized);
delete m_old_rtt_provider;
m_old_rtt_provider = NULL;
m_texture = NULL;
@@ -123,7 +126,7 @@ void ModelViewWidget::addModel(irr::scene::IMesh* mesh, const Vec3& location,
void ModelViewWidget::update(float delta)
{
if (m_rtt_unsupported) return;
if (m_rotation_mode == ROTATE_CONTINUOUSLY)
{
angle += delta*m_rotation_speed;
@@ -135,10 +138,10 @@ void ModelViewWidget::update(float delta)
// (taking wrap-arounds into account)
const int angle_distance_from_end = (int)(360 - angle);
const int target_distance_from_end = (int)(360 - angle);
int distance_with_positive_rotation;
int distance_with_negative_rotation;
if (angle < m_rotation_target)
{
distance_with_positive_rotation = (int)(m_rotation_target - angle);
@@ -149,11 +152,11 @@ void ModelViewWidget::update(float delta)
distance_with_positive_rotation = (int)(angle_distance_from_end + m_rotation_target);
distance_with_negative_rotation = (int)(angle - m_rotation_target);
}
//Log::info("ModelViewWidget", "distance_with_positive_rotation = %d; "
// "distance_with_negative_rotation = %d; angle = %f", distance_with_positive_rotation,
// distance_with_negative_rotation, angle);
if (distance_with_positive_rotation < distance_with_negative_rotation)
{
angle += m_rotation_speed * delta*(3.0f + std::min(distance_with_positive_rotation, distance_with_negative_rotation)*2.0f);
@@ -164,29 +167,29 @@ void ModelViewWidget::update(float delta)
}
if (angle > 360) angle -= 360;
if (angle < 0) angle += 360;
// stop rotating when target reached
if (fabsf(angle - m_rotation_target) < 2.0f) m_rotation_mode = ROTATE_OFF;
}
if (CVS->isGLSL())
{
if (m_rtt_provider == NULL)
{
m_rtt_provider = new RTT(512, 512);
}
if (m_rtt_main_node == NULL)
{
setupRTTScene(m_models, m_model_location, m_model_scale, m_model_frames);
setupRTTScene();
}
m_rtt_main_node->setRotation(core::vector3df(0.0f, angle, 0.0f));
m_rtt_main_node->setVisible(true);
m_frame_buffer = m_rtt_provider->render(m_camera, GUIEngine::getLatestDt());
m_rtt_main_node->setVisible(false);
}
else
@@ -198,9 +201,9 @@ void ModelViewWidget::update(float delta)
m_old_rtt_provider = new IrrDriver::RTTProvider(core::dimension2d<u32>(512, 512), name, false);
m_old_rtt_provider->setupRTTScene(m_models, m_model_location, m_model_scale, m_model_frames);
}
m_texture = m_old_rtt_provider->renderToTexture(angle);
if (m_texture == NULL)
{
m_rtt_unsupported = true;
@@ -208,98 +211,100 @@ void ModelViewWidget::update(float delta)
}
}
void ModelViewWidget::setupRTTScene(PtrVector<scene::IMesh, REF>& mesh,
AlignedArray<Vec3>& mesh_location,
AlignedArray<Vec3>& mesh_scale,
const std::vector<int>& model_frames)
void ModelViewWidget::setupRTTScene()
{
irr_driver->suppressSkyBox();
if (m_rtt_main_node != NULL) m_rtt_main_node->remove();
if (m_light != NULL) m_light->remove();
if (m_camera != NULL) m_camera->remove();
m_rtt_main_node = NULL;
m_camera = NULL;
m_light = NULL;
irr_driver->clearLights();
if (model_frames[0] == -1)
if (m_model_frames[0] == -1)
{
scene::ISceneNode* node = irr_driver->addMesh(mesh.get(0), "rtt_mesh", NULL);
node->setPosition(mesh_location[0].toIrrVector());
node->setScale(mesh_scale[0].toIrrVector());
scene::ISceneNode* node = irr_driver->addMesh(m_models.get(0), "rtt_mesh",
NULL, &m_render_info, m_model_render_info_affected[0]);
node->setPosition(m_model_location[0].toIrrVector());
node->setScale(m_model_scale[0].toIrrVector());
node->setMaterialFlag(video::EMF_FOG_ENABLE, false);
m_rtt_main_node = node;
}
else
{
scene::IAnimatedMeshSceneNode* node =
irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)mesh.get(0), "rtt_mesh", NULL);
node->setPosition(mesh_location[0].toIrrVector());
node->setFrameLoop(model_frames[0], model_frames[0]);
irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)m_models.get(0), "rtt_mesh",
NULL, &m_render_info, m_model_render_info_affected[0]);
node->setPosition(m_model_location[0].toIrrVector());
node->setFrameLoop(m_model_frames[0], m_model_frames[0]);
node->setAnimationSpeed(0);
node->setScale(mesh_scale[0].toIrrVector());
node->setScale(m_model_scale[0].toIrrVector());
node->setMaterialFlag(video::EMF_FOG_ENABLE, false);
m_rtt_main_node = node;
}
assert(m_rtt_main_node != NULL);
assert(mesh.size() == mesh_location.size());
assert(mesh.size() == model_frames.size());
const int mesh_amount = mesh.size();
assert(m_models.size() == m_model_location.size());
assert(m_models.size() == m_model_frames.size());
assert(m_models.size() == m_model_scale.size());
assert(m_models.size() == m_model_render_info_affected.size());
const int mesh_amount = m_models.size();
for (int n = 1; n<mesh_amount; n++)
{
if (model_frames[n] == -1)
if (m_model_frames[n] == -1)
{
scene::ISceneNode* node =
irr_driver->addMesh(mesh.get(n), "rtt_node", m_rtt_main_node);
node->setPosition(mesh_location[n].toIrrVector());
irr_driver->addMesh(m_models.get(n), "rtt_node", m_rtt_main_node,
&m_render_info, m_model_render_info_affected[n]);
node->setPosition(m_model_location[n].toIrrVector());
node->updateAbsolutePosition();
node->setScale(mesh_scale[n].toIrrVector());
node->setScale(m_model_scale[n].toIrrVector());
}
else
{
scene::IAnimatedMeshSceneNode* node =
irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)mesh.get(n),
"modelviewrtt", m_rtt_main_node);
node->setPosition(mesh_location[n].toIrrVector());
node->setFrameLoop(model_frames[n], model_frames[n]);
irr_driver->addAnimatedMesh((scene::IAnimatedMesh*)m_models.get(n),
"modelviewrtt", m_rtt_main_node, &m_render_info,
m_model_render_info_affected[n]);
node->setPosition(m_model_location[n].toIrrVector());
node->setFrameLoop(m_model_frames[n], m_model_frames[n]);
node->setAnimationSpeed(0);
node->updateAbsolutePosition();
node->setScale(mesh_scale[n].toIrrVector());
//Log::info("ModelViewWidget", "Set frame %d", model_frames[n]);
node->setScale(m_model_scale[n].toIrrVector());
//Log::info("ModelViewWidget", "Set frame %d", m_model_frames[n]);
}
}
irr_driver->setAmbientLight(video::SColor(255, 35, 35, 35));
const core::vector3df &spot_pos = core::vector3df(0, 30, 40);
m_light = irr_driver->addLight(spot_pos, 0.3f /* energy */, 10 /* distance */, 1.0f /* r */, 1.0f /* g */, 1.0f /* g*/, true, NULL);
m_rtt_main_node->setMaterialFlag(video::EMF_GOURAUD_SHADING, true);
m_rtt_main_node->setMaterialFlag(video::EMF_LIGHTING, true);
const int materials = m_rtt_main_node->getMaterialCount();
for (int n = 0; n<materials; n++)
{
m_rtt_main_node->getMaterial(n).setFlag(video::EMF_LIGHTING, true);
// set size of specular highlights
m_rtt_main_node->getMaterial(n).Shininess = 100.0f;
m_rtt_main_node->getMaterial(n).SpecularColor.set(255, 50, 50, 50);
m_rtt_main_node->getMaterial(n).DiffuseColor.set(255, 150, 150, 150);
m_rtt_main_node->getMaterial(n).setFlag(video::EMF_GOURAUD_SHADING,
true);
}
m_camera = irr_driver->getSceneManager()->addCameraSceneNode();
m_camera->setAspectRatio(1.0f);
m_camera->setPosition(core::vector3df(0.0, 20.0f, 70.0f));
m_camera->setUpVector(core::vector3df(0.0, 1.0, 0.0));
m_camera->setTarget(core::vector3df(0, 10, 0.0f));
@@ -334,11 +339,11 @@ void ModelViewWidget::elementRemoved()
{
delete m_rtt_provider;
m_rtt_provider = NULL;
delete m_old_rtt_provider;
m_old_rtt_provider = NULL;
m_texture = NULL;
IconButtonWidget::elementRemoved();
}
@@ -346,7 +351,7 @@ void ModelViewWidget::clearRttProvider()
{
delete m_rtt_provider;
m_rtt_provider = NULL;
delete m_old_rtt_provider;
m_old_rtt_provider = NULL;
m_texture = NULL;

View File

@@ -23,6 +23,7 @@
#include <IMesh.h>
#include "graphics/irr_driver.hpp"
#include "graphics/render_info.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "utils/aligned_array.hpp"
#include "utils/leak_check.hpp"
@@ -44,19 +45,20 @@ namespace GUIEngine
RotationMode m_rotation_mode;
float m_rotation_speed;
float m_rotation_target;
PtrVector<scene::IMesh, REF> m_models;
AlignedArray<Vec3> m_model_location;
AlignedArray<Vec3> m_model_scale;
std::vector<int> m_model_frames;
std::vector<bool> m_model_render_info_affected;
RTT* m_rtt_provider;
IrrDriver::RTTProvider* m_old_rtt_provider;
float angle;
bool m_rtt_unsupported;
scene::ISceneNode *m_rtt_main_node;
scene::ICameraSceneNode *m_camera;
@@ -66,47 +68,48 @@ namespace GUIEngine
FrameBuffer *m_frame_buffer;
video::ITexture *m_texture;
RenderInfo m_render_info;
public:
LEAK_CHECK()
ModelViewWidget();
virtual ~ModelViewWidget();
void add();
void clearModels();
void addModel(irr::scene::IMesh* mesh,
const Vec3& location = Vec3(0,0,0),
const Vec3& scale = Vec3(1,1,1),
const int frame=-1);
const int frame=-1,
bool all_parts_colorized = false);
void update(float delta);
virtual void elementRemoved();
/** Disables any model rotation */
void setRotateOff();
/** Makes the model rotate at given speed (in degrees per second) */
void setRotateContinuously(float speed);
/** Rotate to 'targetAngle' in degrees at given speed (in degrees per second) */
void setRotateTo(float targetAngle, float speed);
/** Returns information if currently kart is rotating */
bool isRotating();
void clearRttProvider();
void setupRTTScene(PtrVector<scene::IMesh, REF>& mesh,
AlignedArray<Vec3>& mesh_location,
AlignedArray<Vec3>& mesh_scale,
const std::vector<int>& model_frames);
void setupRTTScene();
FrameBuffer* getFrameBuffer() { return m_frame_buffer; }
video::ITexture* getTexture() { return m_texture; }
FrameBuffer* getFrameBuffer() { return m_frame_buffer; }
video::ITexture* getTexture() { return m_texture; }
RenderInfo& getModelViewRenderInfo() { return m_render_info; }
};
}
#endif

View File

@@ -490,6 +490,7 @@ bool DeviceManager::load()
if(input->getName()!="input")
{
Log::warn("DeviceManager", "Invalid input.xml file - no input node.");
delete input;
return false;
}
@@ -500,6 +501,7 @@ bool DeviceManager::load()
GUIEngine::showMessage(_("Please re-configure your key bindings."));
GUIEngine::showMessage(_("Your input config file is not compatible "
"with this version of STK."));
delete input;
return false;
}

View File

@@ -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;

View File

@@ -386,11 +386,11 @@ int WiimoteManager::askUserToConnectWiimotes()
{
new MessageDialog(
#ifdef WIN32
_("Connect your wiimote to the Bluetooth manager, then click on Ok."
_("Connect your wiimote to the Bluetooth manager, then click on Ok. "
"Detailed instructions at supertuxkart.net/Wiimote"),
#else
_("Press the buttons 1+2 simultaneously on your wiimote to put "
"it in discovery mode, then click on Ok."
"it in discovery mode, then click on Ok. "
"Detailed instructions at supertuxkart.net/Wiimote"),
#endif
MessageDialog::MESSAGE_DIALOG_OK_CANCEL,

View File

@@ -227,6 +227,7 @@ public:
public:
AbstractCharacteristic();
virtual ~AbstractCharacteristic() {}
virtual void copyFrom(const AbstractCharacteristic *other) = 0;
/**
* The process function is the core of this characteristics system.

View File

@@ -21,7 +21,6 @@
#include "items/powerup.hpp"
#include "karts/abstract_kart_animation.hpp"
#include "karts/kart_model.hpp"
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
#include "utils/log.hpp"
@@ -36,7 +35,7 @@ AbstractKart::AbstractKart(const std::string& ident,
int world_kart_id, int position,
const btTransform& init_transform,
PerPlayerDifficulty difficulty,
video::E_RENDER_TYPE rt)
RenderInfo::KartRenderType krt)
: Moveable()
{
m_world_kart_id = world_kart_id;
@@ -60,7 +59,7 @@ AbstractKart::AbstractKart(const std::string& ident,
// released when the kart is deleted, but since the original
// kart_model is stored in the kart_properties all the time,
// there is no risk of a mesh being deleted to early.
m_kart_model = m_kart_properties->getKartModelCopy(rt);
m_kart_model = m_kart_properties->getKartModelCopy(krt);
m_kart_width = m_kart_model->getWidth();
m_kart_height = m_kart_model->getHeight();
m_kart_length = m_kart_model->getLength();

View File

@@ -19,10 +19,10 @@
#ifndef HEADER_ABSTRACT_KART_HPP
#define HEADER_ABSTRACT_KART_HPP
#include <EMaterialTypes.h>
#include <memory>
#include "items/powerup_manager.hpp"
#include "graphics/render_info.hpp"
#include "karts/moveable.hpp"
#include "karts/controller/kart_control.hpp"
#include "race/race_manager.hpp"
@@ -100,7 +100,7 @@ public:
int world_kart_id,
int position, const btTransform& init_transform,
PerPlayerDifficulty difficulty,
video::E_RENDER_TYPE rt);
RenderInfo::KartRenderType krt);
virtual ~AbstractKart();
virtual core::stringw getName() const;
virtual void reset();

View File

@@ -21,6 +21,8 @@
#include "karts/abstract_characteristic.hpp"
#include <assert.h>
class CachedCharacteristic : public AbstractCharacteristic
{
private:
@@ -46,7 +48,7 @@ public:
/** Fetches all cached values from the original source. */
void updateSource();
virtual void copyFrom(const AbstractCharacteristic *other) { assert(false); }
virtual void process(CharacteristicType type, Value value, bool *is_set) const;
};

View File

@@ -18,10 +18,15 @@
#include "karts/combined_characteristic.hpp"
#include "io/file_manager.hpp"
#include "karts/xml_characteristic.hpp"
#include <assert.h>
void CombinedCharacteristic::addCharacteristic(
const AbstractCharacteristic *characteristic)
{
m_childs.push_back(characteristic);
m_children.push_back(characteristic);
} // addCharacteristic
// ----------------------------------------------------------------------------
@@ -29,7 +34,59 @@ void CombinedCharacteristic::addCharacteristic(
void CombinedCharacteristic::process(CharacteristicType type, Value value,
bool *is_set) const
{
for (const AbstractCharacteristic *characteristic : m_childs)
for (const AbstractCharacteristic *characteristic : m_children)
characteristic->process(type, value, is_set);
} // process
// ============================================================================
void CombinedCharacteristic::unitTesting()
{
// We need to use really existing xml attributes, all characteristics
// were designed to work with those names.
std::string s1=
"<?xml version=\"1.0\"?>"
" <characteristic name=\"base\">"
" <suspension stiffness=\"4.5\" rest=\"-0.3\" travel=\"1+2\"/>"
" <stability roll-influence=\"1+2*3\" chassis-linear-damping=\"2*3+1\""
" chassis-angular-damping=\"0\" downward-impulse-factor=\"5\""
" track-connection-accel=\"2\" smooth-flying-impulse=\"250\" />"
" </characteristic>"
"</characteristics>";
XMLNode *xml1= file_manager->createXMLTreeFromString(s1);
XmlCharacteristic *c1 = new XmlCharacteristic(xml1);
delete xml1;
CombinedCharacteristic *cc = new CombinedCharacteristic();
cc->addCharacteristic(c1);
assert( cc->getSuspensionStiffness() == 4.5f );
assert( cc->getSuspensionRest() == -0.3f );
assert( cc->getSuspensionTravel() == 3.0f );
// Note: no operator precedence supported, so 1+2*3 = 9
assert( cc->getStabilityRollInfluence() == 9.0f );
assert( cc->getStabilityChassisLinearDamping() == 7.0f );
std::string s2=
"<?xml version=\"1.0\"?>"
" <characteristic name=\"base\">"
" <suspension stiffness=\"+1\" rest=\"-1\" travel=\"*2\"/>"
" <stability roll-influence=\"/3\" chassis-linear-damping=\"*1\"/>"
" </characteristic>"
"</characteristics>";
XMLNode *xml2= file_manager->createXMLTreeFromString(s2);
XmlCharacteristic *c2 = new XmlCharacteristic(xml2);
delete xml2;
cc->addCharacteristic(c2);
assert( cc->getSuspensionStiffness() == 5.5f );
assert( cc->getSuspensionRest() == -1.3f );
assert( cc->getSuspensionTravel() == 6.0f );
// Note: no operator precedence supported, so (1+2*3) / 3 = 3
assert( cc->getStabilityRollInfluence() == 3.0f );
assert( cc->getStabilityChassisLinearDamping() == 7.0f );
} // unitTesting

View File

@@ -21,15 +21,23 @@
#include "karts/abstract_characteristic.hpp"
#include <assert.h>
class CombinedCharacteristic : public AbstractCharacteristic
{
private:
std::vector<const AbstractCharacteristic*> m_childs;
std::vector<const AbstractCharacteristic*> m_children;
public:
static void unitTesting();
void addCharacteristic(const AbstractCharacteristic *characteristic);
virtual void process(CharacteristicType type, Value value, bool *is_set) const;
virtual void copyFrom(const AbstractCharacteristic *other)
{
assert(false);
}
};
#endif

View File

@@ -67,7 +67,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_TYPE_NORMAL)
m_kart->setOnScreenText(core::stringw(name.c_str()).c_str());
#endif
Controller::setControllerName(name);

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -28,7 +28,7 @@ GhostKart::GhostKart(const std::string& ident, unsigned int world_kart_id,
int position)
: Kart(ident, world_kart_id,
position, btTransform(btQuaternion(0, 0, 0, 1)),
PLAYER_DIFFICULTY_NORMAL, video::ERT_TRANSPARENT)
PLAYER_DIFFICULTY_NORMAL, RenderInfo::KRT_TRANSPARENT)
{
} // GhostKart

View File

@@ -38,8 +38,6 @@
#include "graphics/stk_text_billboard.hpp"
#include "graphics/stars.hpp"
#include "guiengine/scalable_font.hpp"
#include "karts/abstract_characteristic.hpp"
#include "karts/cached_characteristic.hpp"
#include "karts/explosion_animation.hpp"
#include "karts/kart_gfx.hpp"
#include "karts/rescue_animation.hpp"
@@ -93,9 +91,9 @@
Kart::Kart (const std::string& ident, unsigned int world_kart_id,
int position, const btTransform& init_transform,
PerPlayerDifficulty difficulty,
video::E_RENDER_TYPE rt)
RenderInfo::KartRenderType krt)
: AbstractKart(ident, world_kart_id, position, init_transform,
difficulty, rt)
difficulty, krt)
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
# pragma warning(1:4355)
@@ -181,27 +179,18 @@ void Kart::init(RaceManager::KartType type)
// In multiplayer mode, sounds are NOT positional
if (race_manager->getNumLocalPlayers() > 1)
{
float factor = 1.0f / race_manager->getNumberOfKarts();
// players have louder sounds than AIs
if (type == RaceManager::KT_PLAYER)
{
// players have louder sounds than AIs
const float factor = std::min(1.0f, race_manager->getNumLocalPlayers()/2.0f);
m_goo_sound->setVolume( 1.0f / factor );
m_skid_sound->setVolume( 1.0f / factor );
m_crash_sound->setVolume( 1.0f / factor );
m_boing_sound->setVolume( 1.0f / factor );
m_beep_sound->setVolume( 1.0f / factor );
m_nitro_sound->setVolume( 1.0f / factor );
}
else
{
m_goo_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_skid_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_crash_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_beep_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_boing_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_nitro_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
}
}
factor = std::min(1.0f, race_manager->getNumLocalPlayers()/2.0f);
m_goo_sound->setVolume(factor);
m_skid_sound->setVolume(factor);
m_crash_sound->setVolume(factor);
m_boing_sound->setVolume(factor);
m_beep_sound->setVolume(factor);
m_nitro_sound->setVolume(factor);
} // if getNumLocalPlayers > 1
if(!m_engine_sound)
{
@@ -224,12 +213,7 @@ void Kart::init(RaceManager::KartType type)
m_kart_gfx = new KartGFX(this);
m_skidding = new Skidding(this);
// Create the stars effect
m_stars_effect =
new Stars(getNode(),
core::vector3df(0.0f,
getKartModel()->getModel()
->getBoundingBox().MaxEdge.Y,
0.0f) );
m_stars_effect = new Stars(this);
reset();
} // init

View File

@@ -232,7 +232,7 @@ public:
Kart(const std::string& ident, unsigned int world_kart_id,
int position, const btTransform& init_transform,
PerPlayerDifficulty difficulty,
video::E_RENDER_TYPE rt = video::ERT_DEFAULT);
RenderInfo::KartRenderType krt = RenderInfo::KRT_DEFAULT);
virtual ~Kart();
virtual void init(RaceManager::KartType type);
virtual void kartIsInRestNow();

View File

@@ -134,12 +134,13 @@ KartModel::KartModel(bool is_master)
m_wheel_filename[3] = "";
m_speed_weighted_objects.clear();
m_animated_node = NULL;
m_mesh = NULL;
for(unsigned int i=AF_BEGIN; i<=AF_END; i++)
m_animation_frame[i]=-1;
m_animation_speed = 25;
m_current_animation = AF_DEFAULT;
m_play_non_loop = false;
m_krt = RenderInfo::KRT_DEFAULT;
m_render_info = RenderInfo();
} // KartModel
// ----------------------------------------------------------------------------
@@ -226,17 +227,6 @@ KartModel::~KartModel()
{
// Master KartModels should never have a wheel attached.
assert(!m_is_master);
// Drop the cloned transparent mesh wheel if created
if (m_wheel_model[i])
{
// m_wheel_model[i] can be NULL
if (m_wheel_model[i]
->getRenderType() == video::ERT_TRANSPARENT)
{
m_wheel_model[i]->drop();
}
}
m_wheel_node[i]->drop();
}
if(m_is_master && m_wheel_model[i])
@@ -253,9 +243,8 @@ KartModel::~KartModel()
// Master KartModels should never have a speed weighted object attached.
assert(!m_is_master);
// Drop the cloned model if created
if (m_speed_weighted_objects[i].m_model
->getRenderType() != video::ERT_DEFAULT)
// Drop the cloned transparent model if created
if (m_krt == RenderInfo::KRT_TRANSPARENT)
{
m_speed_weighted_objects[i].m_model->drop();
}
@@ -298,7 +287,7 @@ KartModel::~KartModel()
* It is also marked not to be a master copy, so attachModel can be called
* for this instance.
*/
KartModel* KartModel::makeCopy(video::E_RENDER_TYPE rt)
KartModel* KartModel::makeCopy(RenderInfo::KartRenderType krt)
{
// Make sure that we are copying from a master objects, and
// that there is indeed no animated node defined here ...
@@ -311,34 +300,25 @@ KartModel* KartModel::makeCopy(video::E_RENDER_TYPE rt)
km->m_kart_height = m_kart_height;
km->m_kart_highest_point= m_kart_highest_point;
km->m_kart_lowest_point = m_kart_lowest_point;
km->m_mesh = irr_driver->copyAnimatedMesh(m_mesh, rt);
km->m_mesh = irr_driver->copyAnimatedMesh(m_mesh);
km->m_model_filename = m_model_filename;
km->m_animation_speed = m_animation_speed;
km->m_current_animation = AF_DEFAULT;
km->m_animated_node = NULL;
km->m_hat_offset = m_hat_offset;
km->m_hat_name = m_hat_name;
km->m_krt = krt;
km->m_render_info = m_render_info;
km->m_nitro_emitter_position[0] = m_nitro_emitter_position[0];
km->m_nitro_emitter_position[1] = m_nitro_emitter_position[1];
km->m_has_nitro_emitter = m_has_nitro_emitter;
scene::IMeshManipulator *mani =
irr_driver->getVideoDriver()->getMeshManipulator();
for(unsigned int i=0; i<4; i++)
{
// Master should not have any wheel nodes.
assert(!m_wheel_node[i]);
if (m_wheel_model[i] && rt == video::ERT_TRANSPARENT)
{
// Only clone the mesh if transparence is used
scene::SMesh* clone = mani->createMeshCopy(m_wheel_model[i]);
clone->setRenderType(rt);
km->m_wheel_model[i] = dynamic_cast<scene::IMesh*>(clone);
}
else
km->m_wheel_model[i] = m_wheel_model[i];
km->m_wheel_model[i] = m_wheel_model[i];
km->m_wheel_filename[i] = m_wheel_filename[i];
km->m_wheel_graphics_position[i] = m_wheel_graphics_position[i];
km->m_wheel_graphics_radius[i] = m_wheel_graphics_radius[i];
@@ -346,18 +326,18 @@ KartModel* KartModel::makeCopy(video::E_RENDER_TYPE rt)
km->m_max_suspension[i] = m_max_suspension[i];
km->m_dampen_suspension_amplitude[i]= m_dampen_suspension_amplitude[i];
}
km->m_speed_weighted_objects.resize(m_speed_weighted_objects.size());
for(size_t i=0; i<m_speed_weighted_objects.size(); i++)
{
// Master should not have any speed weighted nodes.
assert(!m_speed_weighted_objects[i].m_node);
km->m_speed_weighted_objects[i] = m_speed_weighted_objects[i];
if (rt != video::ERT_DEFAULT)
if (krt == RenderInfo::KRT_TRANSPARENT)
{
// Only clone the mesh if default type is not used
// Only clone the mesh if transparent type is used, see #2445
km->m_speed_weighted_objects[i].m_model = irr_driver
->copyAnimatedMesh(m_speed_weighted_objects[i].m_model, rt);
->copyAnimatedMesh(m_speed_weighted_objects[i].m_model);
}
}
@@ -376,7 +356,8 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim
{
assert(!m_is_master);
scene::ISceneNode* node;
scene::ISceneNode* node = NULL;
m_render_info.setKartModelRenderInfo(m_krt);
if (animated_models)
{
@@ -385,7 +366,8 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim
irr_driver->getSceneManager() );
node = irr_driver->addAnimatedMesh(m_mesh, "kartmesh");
node = irr_driver->addAnimatedMesh(m_mesh, "kartmesh",
NULL/*parent*/, getRenderInfo());
// as animated mesh are not cheap to render use frustum box culling
if (CVS->isGLSL())
node->setAutomaticCulling(scene::EAC_OFF);
@@ -462,7 +444,8 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim
debug_name = m_model_filename + " (kart-model)";
#endif
node = irr_driver->addMesh(main_frame, debug_name);
node = irr_driver->addMesh(main_frame, debug_name,
NULL /*parent*/, getRenderInfo());
#ifdef DEBUG
node->setName(debug_name.c_str());
@@ -473,7 +456,8 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim
for(unsigned int i=0; i<4; i++)
{
if(!m_wheel_model[i]) continue;
m_wheel_node[i] = irr_driver->addMesh(m_wheel_model[i], "wheel", node);
m_wheel_node[i] = irr_driver->addMesh(m_wheel_model[i], "wheel",
node, getRenderInfo(), true/*all_parts_colorized*/);
Vec3 wheel_min, wheel_max;
MeshTools::minMax3D(m_wheel_model[i], &wheel_min, &wheel_max);
m_wheel_graphics_radius[i] = 0.5f*(wheel_max.getY() - wheel_min.getY());
@@ -495,7 +479,8 @@ scene::ISceneNode* KartModel::attachModel(bool animated_models, bool always_anim
if(obj.m_model)
{
obj.m_node = irr_driver->addAnimatedMesh(obj.m_model,
"speedweighted", node);
"speedweighted", node, getRenderInfo(),
true/*all_parts_colorized*/);
obj.m_node->grab();
obj.m_node->setFrameLoop(m_animation_frame[AF_SPEED_WEIGHTED_START],
@@ -535,6 +520,9 @@ bool KartModel::loadModels(const KartProperties &kart_properties)
MeshTools::minMax3D(m_mesh->getMesh(m_animation_frame[AF_STRAIGHT]),
&kart_min, &kart_max);
// Enable colorization for karts later when attachModel
m_render_info.setColorizableParts(m_mesh);
#undef MOVE_KART_MESHES
#ifdef MOVE_KART_MESHES
// Kart models are not exactly centered. The following code would
@@ -984,6 +972,7 @@ void KartModel::update(float dt, float distance, float steer, float speed,
m_animated_node->setCurrentFrame(frame);
} // update
//-----------------------------------------------------------------------------
void KartModel::attachHat()
{
@@ -1018,4 +1007,4 @@ void KartModel::attachHat()
m_hat_node->setRotation(inv.getRotationDegrees());
} // if bone
} // if(m_hat_name)
}
} // attachHat

View File

@@ -30,6 +30,7 @@ namespace irr
}
using namespace irr;
#include "graphics/render_info.hpp"
#include "utils/no_copy.hpp"
#include "utils/vec3.hpp"
@@ -115,6 +116,7 @@ public:
AF_SPEED_WEIGHTED_END, // End of speed-weighted animation
AF_END=AF_SPEED_WEIGHTED_END, // Last animation frame
AF_COUNT}; // Number of entries here
private:
/** Which frame number starts/end which animation. */
int m_animation_frame[AF_COUNT];
@@ -229,10 +231,14 @@ private:
/** Pointer to the kart object belonging to this kart model. */
AbstractKart* m_kart;
RenderInfo::KartRenderType m_krt;
RenderInfo m_render_info;
public:
KartModel(bool is_master);
~KartModel();
KartModel* makeCopy(video::E_RENDER_TYPE rt);
KartModel* makeCopy(RenderInfo::KartRenderType krt);
void reset();
void loadInfo(const XMLNode &node);
bool loadModels(const KartProperties &kart_properties);
@@ -328,6 +334,10 @@ public:
scene::IAnimatedMeshSceneNode* getAnimatedNode(){ return m_animated_node; }
// ------------------------------------------------------------------------
core::vector3df getHatOffset() { return m_hat_offset; }
// ------------------------------------------------------------------------
RenderInfo* getRenderInfo() { return &m_render_info; }
// ------------------------------------------------------------------------
const RenderInfo* getRenderInfo() const { return &m_render_info; }
}; // KartModel
#endif

View File

@@ -125,8 +125,10 @@ void KartProperties::copyForPlayer(const KartProperties *source)
// So all pointer variables need to be separately allocated and assigned.
if (source->m_characteristic)
{
// Remove the shared reference by creating a new pointer
m_characteristic.reset(new XmlCharacteristic());
*m_characteristic = *source->m_characteristic;
m_characteristic->copyFrom(source->getCharacteristic());
// Combine the characteristics for this object. We can't copy it because
// this object has other pointers (to m_characteristic).
combineCharacteristics();

View File

@@ -244,8 +244,8 @@ public:
// ------------------------------------------------------------------------
/** Returns a pointer to the KartModel object. */
KartModel* getKartModelCopy
(video::E_RENDER_TYPE rt = video::ERT_DEFAULT) const
{return m_kart_model->makeCopy(rt); }
(RenderInfo::KartRenderType krt = RenderInfo::KRT_DEFAULT) const
{return m_kart_model->makeCopy(krt); }
// ------------------------------------------------------------------------
/** Returns a pointer to the main KartModel object. This copy

View File

@@ -85,7 +85,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);
}
}

View File

@@ -31,6 +31,17 @@ XmlCharacteristic::XmlCharacteristic(const XMLNode *node) :
load(node);
} // XmlCharacteristic constructor
// ----------------------------------------------------------------------------
/** Copies the characteristics from the specified other characteristic class
* into this class.
*/
void XmlCharacteristic::copyFrom(const AbstractCharacteristic *other)
{
const XmlCharacteristic *xc = dynamic_cast<const XmlCharacteristic*>(other);
assert(xc!=NULL);
m_values = xc->m_values;
} // operator=
// ----------------------------------------------------------------------------
/** process will execute the operation that is specified in the saved string.
* The format of the operations is specified in kart_characteristics.xml.
@@ -212,8 +223,9 @@ void XmlCharacteristic::processFloat(const std::string &processor, float *value,
std::size_t pos2;
while ((pos2 = processor.find_first_of(operators, pos)) != std::string::npos)
{
parts.push_back(processor.substr(pos, pos2));
operations.push_back(processor.substr(pos2, pos2 + 1));
std::string s = processor.substr(pos, pos2);
parts.push_back(processor.substr(pos, pos2-pos));
operations.push_back(processor.substr(pos2, 1));
pos = pos2 + 1;
}
parts.push_back(processor.substr(pos));
@@ -224,15 +236,15 @@ void XmlCharacteristic::processFloat(const std::string &processor, float *value,
// If nothing preceeds the first operator, insert x
if (parts[index].empty())
{
if (!*is_set)
// - is a special case: We don't take e.g. "-5" as relative, it
// describes a negative number. So
if (!*is_set && operations[index] == "-")
*value = 0;
else if (!*is_set)
{
Log::error("XmlCharacteristic::processFloat", "x is unknown");
return;
}
// - is a special case: We don't take e.g. "-5" as relative, it
// describes a negative number
else if (operations[index] == "-")
*value = 0;
else
*value = x;
}

View File

@@ -37,6 +37,7 @@ public:
virtual void process(CharacteristicType type, Value value, bool *is_set) const;
void load(const XMLNode *node);
virtual void copyFrom(const AbstractCharacteristic *other);
private:
static void processFloat(const std::string &processor, float *value, bool *is_set);

View File

@@ -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"
@@ -168,6 +169,7 @@
#include "items/attachment_manager.hpp"
#include "items/item_manager.hpp"
#include "items/projectile_manager.hpp"
#include "karts/combined_characteristic.hpp"
#include "karts/controller/ai_base_lap_controller.hpp"
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
@@ -910,14 +912,23 @@ int handleCmdLine()
UserConfigParams::m_music = false;
}
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"))
@@ -1863,6 +1874,11 @@ void runUnitTests()
assert( isEasterMode(22, 3, 2016, 5));
assert(!isEasterMode(21, 3, 2016, 5));
UserConfigParams::m_easter_ear_mode = saved_easter_mode;
Log::info("UnitTest", " - Kart characteristics");
CombinedCharacteristic::unitTesting();
Log::info("UnitTest", "=====================");
Log::info("UnitTest", "Testing successful ");
Log::info("UnitTest", "=====================");

View File

@@ -22,7 +22,9 @@
#include "audio/sfx_base.hpp"
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/render_info.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/kart.hpp"
#include "karts/kart_model.hpp"
@@ -303,6 +305,9 @@ void SoccerWorld::countdownReachedZero()
//-----------------------------------------------------------------------------
void SoccerWorld::initKartList()
{
// Color of karts can be changed using shaders
if (CVS->isGLSL()) return;
const unsigned int kart_amount = (unsigned int)m_karts.size();
//Loading the indicator textures
@@ -388,9 +393,8 @@ AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index,
m_kart_position_map[index] = (unsigned)(pos_index - 1);
AbstractKart *new_kart = new Kart(kart_ident, index, position, init_pos,
difficulty);
//difficulty, team == SOCCER_TEAM_BLUE ?
//video::ERT_BLUE : video::ERT_RED);
difficulty, team == SOCCER_TEAM_BLUE ?
RenderInfo::KRT_BLUE : RenderInfo::KRT_RED);
new_kart->init(race_manager->getKartType(index));
Controller *controller = NULL;

View File

@@ -260,10 +260,7 @@ void World::reset()
(*i)->reset();
}
for(unsigned int i=0; i<Camera::getNumCameras(); i++)
{
Camera::getCamera(i)->reset();
}
Camera::resetAllCameras();
if(race_manager->hasGhostKarts())
ReplayPlay::get()->reset();

View File

@@ -47,6 +47,8 @@ void NetworkString::unitTesting()
s.addUInt16(12345);
s.addFloat(1.2345f);
// Since this string was not received, we need to skip the type and token explicitly.
s.skip(5);
assert(s.getUInt16() == 12345);
float f = s.getFloat();
assert(f==1.2345f);

View File

@@ -191,8 +191,10 @@ Online::XMLRequest* ServersManager::getLANRefreshRequest() const
m_success = true;
} // if received_data
} // while still waiting
if (!m_success)
m_info = _("No LAN server detected");
delete broadcast;
if (!m_success)
m_info = _("No LAN server detected");
} // operation
// --------------------------------------------------------------------
/** This function is necessary, otherwise the XML- and HTTP-Request

View File

@@ -131,37 +131,72 @@ void SoccerSetupScreen::beforeAddingWidget()
// Add the view
ModelViewWidget* kart_view = new ModelViewWidget();
// These values will be overriden by updateKartViewsLayout() anyway
kart_view->m_x = 0;
kart_view->m_y = 0;
kart_view->m_w = 200;
kart_view->m_h = 200; // these values will be overriden by updateKartViewsLayout() anyway
kart_view->m_h = 200;
kart_view->clearModels();
// Add the kart model
// Record info about it for further update
KartViewInfo info;
int single_team = UserConfigParams::m_soccer_default_team;
info.team = (nb_players == 1 ? (SoccerTeam)single_team :
(i&1 ? SOCCER_TEAM_BLUE : SOCCER_TEAM_RED));
// addModel requires loading the RenderInfo first
kart_view->getModelViewRenderInfo().setRenderInfo
(kart_model.getRenderInfo());
kart_view->getModelViewRenderInfo().setKartModelRenderInfo
(info.team == SOCCER_TEAM_BLUE ?
RenderInfo::KRT_BLUE : RenderInfo::KRT_RED);
// Add the kart model (including wheels and speed weight objects)
kart_view->addModel( kart_model.getModel(), Vec3(0,0,0),
Vec3(35.0f, 35.0f, 35.0f),
kart_model.getBaseFrame() );
kart_view->addModel( kart_model.getWheelModel(0),
kart_model.getWheelGraphicsPosition(0) );
kart_view->addModel( kart_model.getWheelModel(1),
kart_model.getWheelGraphicsPosition(1) );
kart_view->addModel( kart_model.getWheelModel(2),
kart_model.getWheelGraphicsPosition(2) );
kart_view->addModel( kart_model.getWheelModel(3),
kart_model.getWheelGraphicsPosition(3) );
kart_view->setRotateContinuously( KART_CONTINUOUS_ROTATION_SPEED );
kart_view->addModel( kart_model.getWheelModel(0),
kart_model.getWheelGraphicsPosition(0),
Vec3(1, 1, 1), /*scale*/
-1, /*frame*/
true /*all_parts_colorized*/);
kart_view->addModel( kart_model.getWheelModel(1),
kart_model.getWheelGraphicsPosition(1),
Vec3(1, 1, 1), /*scale*/
-1, /*frame*/
true /*all_parts_colorized*/);
kart_view->addModel( kart_model.getWheelModel(2),
kart_model.getWheelGraphicsPosition(2),
Vec3(1, 1, 1), /*scale*/
-1, /*frame*/
true /*all_parts_colorized*/);
kart_view->addModel( kart_model.getWheelModel(3),
kart_model.getWheelGraphicsPosition(3),
Vec3(1, 1, 1), /*scale*/
-1, /*frame*/
true /*all_parts_colorized*/);
for (size_t i = 0; i < kart_model.getSpeedWeightedObjectsCount(); i++)
{
const SpeedWeightedObject& obj = kart_model.getSpeedWeightedObject((int)i);
kart_view->addModel(obj.m_model, obj.m_position,
Vec3(1, 1, 1), /*scale*/
-1, /*frame*/
true /*all_parts_colorized*/);
}
kart_view->setRotateContinuously( KART_CONTINUOUS_ROTATION_SPEED );
kart_view->update(0);
central_div->getChildren().push_back(kart_view);
// Record info about it for further update
KartViewInfo info;
info.view = kart_view;
info.confirmed = false;
int single_team = UserConfigParams::m_soccer_default_team;
info.team = nb_players == 1 ? (SoccerTeam)single_team :
(i&1 ? SOCCER_TEAM_BLUE : SOCCER_TEAM_RED);
info.view = kart_view;
info.confirmed = false;
m_kart_view_info.push_back(info);
race_manager->setKartSoccerTeam(i, info.team);
}
@@ -255,6 +290,10 @@ GUIEngine::EventPropagation SoccerSetupScreen::filterActions(PlayerAction action
{
team_switch = SOCCER_TEAM_RED;
// Change the kart color
m_kart_view_info[playerId].view->getModelViewRenderInfo()
.setKartModelRenderInfo(RenderInfo::KRT_RED);
for(int i=0 ; i < nb_players ; i++)
{
m_kart_view_info[i].view->unsetBadge(BAD_BADGE);
@@ -268,6 +307,10 @@ GUIEngine::EventPropagation SoccerSetupScreen::filterActions(PlayerAction action
{
team_switch = SOCCER_TEAM_BLUE;
// Change the kart color
m_kart_view_info[playerId].view->getModelViewRenderInfo()
.setKartModelRenderInfo(RenderInfo::KRT_BLUE);
for(int i=0 ; i < nb_players ; i++)
{
m_kart_view_info[i].view->unsetBadge(BAD_BADGE);

View File

@@ -18,6 +18,7 @@
#ifndef HEADER_SOCCER_SETUP_SCREEN_HPP
#define HEADER_SOCCER_SETUP_SCREEN_HPP
#include "graphics/render_info.hpp"
#include "guiengine/screen.hpp"
#include "network/remote_kart_info.hpp"
@@ -38,8 +39,9 @@ class SoccerSetupScreen : public GUIEngine::Screen, public GUIEngine::ScreenSing
GUIEngine::ModelViewWidget* view;
bool confirmed;
SoccerTeam team;
RenderInfo render_info;
KartViewInfo() : view(NULL), confirmed(false), team(SOCCER_TEAM_NONE) {}
KartViewInfo() : view(), confirmed(false), team(SOCCER_TEAM_NONE) {}
};
AlignedArray<KartViewInfo> m_kart_view_info;

View File

@@ -46,6 +46,7 @@ NavMesh::NavMesh(const std::string &filename)
if(xml->getName()!="navmesh")
{
Log::error("NavMesh", "NavMesh is invalid. \n");
delete xml;
return;
}

View File

@@ -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"
@@ -1595,7 +1595,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();
@@ -1751,7 +1751,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 */
@@ -1993,7 +1994,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")
{

View File

@@ -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"
@@ -220,186 +221,160 @@ LightNode* findNearestLight()
// ----------------------------------------------------------------------------
bool handleContextMenuAction(s32 cmdID)
bool handleContextMenuAction(s32 cmd_id)
{
World *world = World::getWorld();
Physics *physics = world ? world->getPhysics() : NULL;
if (cmdID == DEBUG_GRAPHICS_RELOAD_SHADERS)
{
Log::info("Debug", "Reloading shaders...");
ShaderBase::updateShaders();
}
else if (cmdID == DEBUG_GRAPHICS_RESET)
switch(cmd_id)
{
case DEBUG_GRAPHICS_RELOAD_SHADERS:
Log::info("Debug", "Reloading shaders...");
ShaderBase::updateShaders();
break;
case DEBUG_GRAPHICS_RESET:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
}
else if (cmdID == DEBUG_GRAPHICS_WIREFRAME)
{
break;
case DEBUG_GRAPHICS_WIREFRAME:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleWireframe();
}
else if (cmdID == DEBUG_GRAPHICS_MIPMAP_VIZ)
{
break;
case DEBUG_GRAPHICS_MIPMAP_VIZ:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleMipVisualization();
}
else if (cmdID == DEBUG_GRAPHICS_NORMALS_VIZ)
{
break;
case DEBUG_GRAPHICS_NORMALS_VIZ:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleNormals();
}
else if (cmdID == DEBUG_GRAPHICS_SSAO_VIZ)
{
break;
case DEBUG_GRAPHICS_SSAO_VIZ:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleSSAOViz();
}
else if (cmdID == DEBUG_GRAPHICS_RSM_VIZ)
{
break;
case DEBUG_GRAPHICS_RSM_VIZ:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleRSM();
}
else if (cmdID == DEBUG_GRAPHICS_RH_VIZ)
{
break;
case DEBUG_GRAPHICS_RH_VIZ:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleRH();
}
else if (cmdID == DEBUG_GRAPHICS_GI_VIZ)
{
break;
case DEBUG_GRAPHICS_GI_VIZ:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleGI();
}
else if (cmdID == DEBUG_GRAPHICS_SHADOW_VIZ)
{
break;
case DEBUG_GRAPHICS_SHADOW_VIZ:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleShadowViz();
}
else if (cmdID == DEBUG_GRAPHICS_LIGHT_VIZ)
{
break;
case DEBUG_GRAPHICS_LIGHT_VIZ:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleLightViz();
}
else if (cmdID == DEBUG_GRAPHICS_DISTORT_VIZ)
{
break;
case DEBUG_GRAPHICS_DISTORT_VIZ:
if (physics)
physics->setDebugMode(IrrDebugDrawer::DM_NONE);
irr_driver->resetDebugModes();
irr_driver->toggleDistortViz();
}
else if (cmdID == DEBUG_GRAPHICS_BULLET_1)
{
break;
case DEBUG_GRAPHICS_BULLET_1:
irr_driver->resetDebugModes();
if (!world) return false;
physics->setDebugMode(IrrDebugDrawer::DM_KARTS_PHYSICS);
}
else if (cmdID == DEBUG_GRAPHICS_BULLET_2)
break;
case DEBUG_GRAPHICS_BULLET_2:
{
irr_driver->resetDebugModes();
if (!world) return false;
Physics *physics = world->getPhysics();
physics->setDebugMode(IrrDebugDrawer::DM_NO_KARTS_GRAPHICS);
break;
}
else if (cmdID == DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ)
{
case DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ:
irr_driver->resetDebugModes();
irr_driver->toggleBoundingBoxesViz();
}
else if (cmdID == DEBUG_PROFILER)
{
break;
case DEBUG_PROFILER:
UserConfigParams::m_profiler_enabled =
!UserConfigParams::m_profiler_enabled;
}
else if (cmdID == DEBUG_PROFILER_GENERATE_REPORT)
{
break;
case DEBUG_PROFILER_GENERATE_REPORT:
profiler.setCaptureReport(!profiler.getCaptureReport());
}
else if (cmdID == DEBUG_THROTTLE_FPS)
{
break;
case DEBUG_THROTTLE_FPS:
main_loop->setThrottleFPS(false);
}
else if (cmdID == DEBUG_FPS)
{
break;
case DEBUG_FPS:
UserConfigParams::m_display_fps =
!UserConfigParams::m_display_fps;
}
else if (cmdID == DEBUG_SAVE_REPLAY)
{
break;
case DEBUG_SAVE_REPLAY:
ReplayRecorder::get()->save();
}
else if (cmdID == DEBUG_SAVE_HISTORY)
{
break;
case DEBUG_SAVE_HISTORY:
history->Save();
}
else if (cmdID == DEBUG_POWERUP_BOWLING)
{
break;
case DEBUG_POWERUP_BOWLING:
addPowerup(PowerupManager::POWERUP_BOWLING);
}
else if (cmdID == DEBUG_POWERUP_BUBBLEGUM)
{
break;
case DEBUG_POWERUP_BUBBLEGUM:
addPowerup(PowerupManager::POWERUP_BUBBLEGUM);
}
else if (cmdID == DEBUG_POWERUP_CAKE)
{
break;
case DEBUG_POWERUP_CAKE:
addPowerup(PowerupManager::POWERUP_CAKE);
}
else if (cmdID == DEBUG_POWERUP_PARACHUTE)
{
break;
case DEBUG_POWERUP_PARACHUTE:
addPowerup(PowerupManager::POWERUP_PARACHUTE);
}
else if (cmdID == DEBUG_POWERUP_PLUNGER)
{
break;
case DEBUG_POWERUP_PLUNGER:
addPowerup(PowerupManager::POWERUP_PLUNGER);
}
else if (cmdID == DEBUG_POWERUP_RUBBERBALL)
{
break;
case DEBUG_POWERUP_RUBBERBALL:
addPowerup(PowerupManager::POWERUP_RUBBERBALL);
}
else if (cmdID == DEBUG_POWERUP_SWATTER)
{
break;
case DEBUG_POWERUP_SWATTER:
addPowerup(PowerupManager::POWERUP_SWATTER);
}
else if (cmdID == DEBUG_POWERUP_SWITCH)
{
break;
case DEBUG_POWERUP_SWITCH:
addPowerup(PowerupManager::POWERUP_SWITCH);
}
else if (cmdID == DEBUG_POWERUP_ZIPPER)
{
break;
case DEBUG_POWERUP_ZIPPER:
addPowerup(PowerupManager::POWERUP_ZIPPER);
}
else if (cmdID == DEBUG_POWERUP_NITRO)
break;
case DEBUG_POWERUP_NITRO:
{
if (!world) return false;
const unsigned int num_local_players =
@@ -409,27 +384,25 @@ bool handleContextMenuAction(s32 cmdID)
AbstractKart* kart = world->getLocalPlayerKart(i);
kart->setEnergy(100.0f);
}
break;
}
else if (cmdID == DEBUG_ATTACHMENT_ANVIL)
{
case DEBUG_ATTACHMENT_ANVIL:
addAttachment(Attachment::ATTACH_ANVIL);
}
else if (cmdID == DEBUG_ATTACHMENT_BOMB)
{
break;
case DEBUG_ATTACHMENT_BOMB:
addAttachment(Attachment::ATTACH_BOMB);
}
else if (cmdID == DEBUG_ATTACHMENT_PARACHUTE)
{
break;
case DEBUG_ATTACHMENT_PARACHUTE:
addAttachment(Attachment::ATTACH_PARACHUTE);
}
else if (cmdID == DEBUG_GUI_TOGGLE)
break;
case DEBUG_GUI_TOGGLE:
{
if (!world) return false;
RaceGUIBase* gui = world->getRaceGUI();
if (gui != NULL) gui->m_enabled = !gui->m_enabled;
break;
}
else if (cmdID == DEBUG_GUI_HIDE_KARTS)
{
case DEBUG_GUI_HIDE_KARTS:
if (!world) return false;
for (unsigned int n = 0; n<world->getNumKarts(); n++)
{
@@ -437,85 +410,91 @@ bool handleContextMenuAction(s32 cmdID)
if (kart->getController()->isPlayerController())
kart->getNode()->setVisible(false);
}
}
else if (cmdID == DEBUG_GUI_CAM_TOP)
{
Camera::setDebugMode(Camera::CM_DEBUG_TOP_OF_KART);
break;
case DEBUG_GUI_CAM_TOP:
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_TOP_OF_KART);
Camera::changeCamera(0, Camera::CM_TYPE_DEBUG);
irr_driver->getDevice()->getCursorControl()->setVisible(true);
}
else if (cmdID == DEBUG_GUI_CAM_WHEEL)
{
Camera::setDebugMode(Camera::CM_DEBUG_GROUND);
break;
case DEBUG_GUI_CAM_WHEEL:
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_GROUND);
Camera::changeCamera(0, Camera::CM_TYPE_DEBUG);
irr_driver->getDevice()->getCursorControl()->setVisible(true);
}
else if (cmdID == DEBUG_GUI_CAM_BEHIND_KART)
{
Camera::setDebugMode(Camera::CM_DEBUG_BEHIND_KART);
break;
case DEBUG_GUI_CAM_BEHIND_KART:
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_BEHIND_KART);
Camera::changeCamera(0, Camera::CM_TYPE_DEBUG);
irr_driver->getDevice()->getCursorControl()->setVisible(true);
}
else if (cmdID == DEBUG_GUI_CAM_SIDE_OF_KART)
{
Camera::setDebugMode(Camera::CM_DEBUG_SIDE_OF_KART);
break;
case DEBUG_GUI_CAM_SIDE_OF_KART:
CameraDebug::setDebugType(CameraDebug::CM_DEBUG_SIDE_OF_KART);
Camera::changeCamera(0, Camera::CM_TYPE_DEBUG);
irr_driver->getDevice()->getCursorControl()->setVisible(true);
}
else if (cmdID == DEBUG_GUI_CAM_FREE)
break;
case 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));
}
break;
}
else if (cmdID == DEBUG_GUI_CAM_NORMAL)
case 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);
break;
}
else if (cmdID == DEBUG_GUI_CAM_SMOOTH)
case 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());
}
break;
}
else if (cmdID == DEBUG_GUI_CAM_ATTACH)
case 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());
}
break;
}
else if (cmdID == DEBUG_VIEW_KART_ONE)
{
case DEBUG_VIEW_KART_ONE:
changeCameraTarget(1);
}
else if (cmdID == DEBUG_VIEW_KART_TWO)
{
break;
case DEBUG_VIEW_KART_TWO:
changeCameraTarget(2);
}
else if (cmdID == DEBUG_VIEW_KART_THREE)
{
break;
case DEBUG_VIEW_KART_THREE:
changeCameraTarget(3);
}
else if (cmdID == DEBUG_VIEW_KART_FOUR)
{
break;
case DEBUG_VIEW_KART_FOUR:
changeCameraTarget(4);
}
else if (cmdID == DEBUG_VIEW_KART_FIVE)
{
break;
case DEBUG_VIEW_KART_FIVE:
changeCameraTarget(5);
}
else if (cmdID == DEBUG_VIEW_KART_SIX)
{
break;
case DEBUG_VIEW_KART_SIX:
changeCameraTarget(6);
}
else if (cmdID == DEBUG_VIEW_KART_SEVEN)
{
break;
case DEBUG_VIEW_KART_SEVEN:
changeCameraTarget(7);
}
else if (cmdID == DEBUG_VIEW_KART_EIGHT)
{
break;
case DEBUG_VIEW_KART_EIGHT:
changeCameraTarget(8);
}
else if (cmdID == DEBUG_PRINT_START_POS)
{
break;
case DEBUG_PRINT_START_POS:
if (!world) return false;
for (unsigned int i = 0; i<world->getNumKarts(); i++)
{
@@ -526,8 +505,8 @@ bool handleContextMenuAction(s32 cmdID)
kart->getXYZ().getZ(), kart->getHeading()*RAD_TO_DEGREE
);
}
}
else if (cmdID == DEBUG_VISUAL_VALUES)
break;
case DEBUG_VISUAL_VALUES:
{
#if !defined(__APPLE__)
DebugSliderDialog *dsd = new DebugSliderDialog();
@@ -566,7 +545,8 @@ bool handleContextMenuAction(s32 cmdID)
);
#endif
}
else if (cmdID == DEBUG_ADJUST_LIGHTS)
break;
case DEBUG_ADJUST_LIGHTS:
{
#if !defined(__APPLE__)
// Some sliders use multipliers because the spinner widget
@@ -623,12 +603,12 @@ bool handleContextMenuAction(s32 cmdID)
);
dsd->changeLabel("SSAO Sigma", "[None]");
#endif
break;
}
else if (cmdID == DEBUG_SCRIPT_CONSOLE)
{
case DEBUG_SCRIPT_CONSOLE:
ScriptingConsole* console = new ScriptingConsole();
}
break;
} // switch
return false;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 151 KiB