Draw kart shadow with dynamic draw call
This commit is contained in:
@@ -17,75 +17,90 @@
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "graphics/shadow.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/skidding.hpp"
|
||||
#include "graphics/sp/sp_base.hpp"
|
||||
#include "graphics/sp/sp_dynamic_draw_call.hpp"
|
||||
#include "physics/btKart.hpp"
|
||||
#include "utils/mini_glm.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
#include <IMesh.h>
|
||||
#include <IMeshSceneNode.h>
|
||||
#include <ISceneNode.h>
|
||||
#ifndef SERVER_ONLY
|
||||
|
||||
Shadow::Shadow(const KartProperties *kart_properties,
|
||||
scene::ISceneNode *node,
|
||||
float y_offset = 0.0)
|
||||
Shadow::Shadow(Material* shadow_mat, const AbstractKart& kart)
|
||||
: m_dy_dc(NULL), m_shadow_enabled(false), m_kart(kart)
|
||||
{
|
||||
m_shadow_enabled = false;
|
||||
video::SMaterial m;
|
||||
m.setTexture(0, kart_properties->getShadowTexture());
|
||||
m.BackfaceCulling = false;
|
||||
m.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||
m.setFlag(video::EMF_ZWRITE_ENABLE , false);
|
||||
m_mesh = irr_driver->createQuadMesh(&m, /*create_one_quad*/true);
|
||||
scene::IMeshBuffer *buffer = m_mesh->getMeshBuffer(0);
|
||||
irr::video::S3DVertex* v=(video::S3DVertex*)buffer->getVertices();
|
||||
float scale = kart_properties->getShadowScale();
|
||||
float x_offset = kart_properties->getShadowXOffset();
|
||||
float z_offset = kart_properties->getShadowXOffset();
|
||||
v[0].Pos.X = -scale+x_offset; v[0].Pos.Z = scale+z_offset; v[0].Pos.Y = 0.01f-y_offset;
|
||||
v[1].Pos.X = scale+x_offset; v[1].Pos.Z = scale+z_offset; v[1].Pos.Y = 0.01f-y_offset;
|
||||
v[2].Pos.X = scale+x_offset; v[2].Pos.Z = -scale+z_offset; v[2].Pos.Y = 0.01f-y_offset;
|
||||
v[3].Pos.X = -scale+x_offset; v[3].Pos.Z = -scale+z_offset; v[3].Pos.Y = 0.01f-y_offset;
|
||||
v[0].TCoords = core::vector2df(0,0);
|
||||
v[1].TCoords = core::vector2df(1,0);
|
||||
v[2].TCoords = core::vector2df(1,1);
|
||||
v[3].TCoords = core::vector2df(0,1);
|
||||
core::vector3df normal(0, 0, 1.0f);
|
||||
v[0].Normal = normal;
|
||||
v[1].Normal = normal;
|
||||
v[2].Normal = normal;
|
||||
v[3].Normal = normal;
|
||||
buffer->recalculateBoundingBox();
|
||||
m_dy_dc = new SP::SPDynamicDrawCall(scene::EPT_TRIANGLE_STRIP,
|
||||
SP::getSPShader("alphablend"), shadow_mat);
|
||||
|
||||
m_node = irr_driver->addMesh(m_mesh, "shadow");
|
||||
#ifdef DEBUG
|
||||
m_node->setName("shadow");
|
||||
#endif
|
||||
|
||||
m_mesh->drop(); // the node grabs the mesh, so we can drop this reference
|
||||
m_node->setAutomaticCulling(scene::EAC_OFF);
|
||||
m_parent_kart_node = node;
|
||||
m_parent_kart_node->addChild(m_node);
|
||||
m_dy_dc->getVerticesVector().resize(4);
|
||||
video::S3DVertexSkinnedMesh* v = m_dy_dc->getVerticesVector().data();
|
||||
v[0].m_all_uvs[0] = 0;
|
||||
v[0].m_all_uvs[1] = 0;
|
||||
v[1].m_all_uvs[0] = 15360;
|
||||
v[1].m_all_uvs[1] = 0;
|
||||
v[3].m_all_uvs[0] = 15360;
|
||||
v[3].m_all_uvs[1] = 15360;
|
||||
v[2].m_all_uvs[0] = 0;
|
||||
v[2].m_all_uvs[1] = 15360;
|
||||
} // Shadow
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Shadow::~Shadow()
|
||||
{
|
||||
// Note: the mesh was not loaded from disk, so it is not cached,
|
||||
// and does not need to be removed. It's clean up when removing the node
|
||||
m_parent_kart_node->removeChild(m_node);
|
||||
if (m_shadow_enabled)
|
||||
{
|
||||
SP::removeDynamicDrawCall(m_dy_dc);
|
||||
}
|
||||
delete m_dy_dc;
|
||||
} // ~Shadow
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Updates the simulated shadow. It takes the offset (distance from visual
|
||||
* chassis to ground) to position the shadow quad exactly on the ground.
|
||||
/** Updates the simulated shadow. It takes the 4 suspension lengths of vehicle
|
||||
* from ground to position the shadow quad exactly on the ground.
|
||||
* It also disables the shadow if requested (e.g. if the kart is in the air).
|
||||
* \param enabled If the shadow should be shown or not.
|
||||
* \param offset Distance from visual chassis to ground = position of the
|
||||
* shadow to make sure it is exactly on the ground.
|
||||
*/
|
||||
void Shadow::update(bool enabled, float offset)
|
||||
void Shadow::update(bool enabled)
|
||||
{
|
||||
m_node->setVisible(enabled);
|
||||
core::vector3df pos = m_node->getPosition();
|
||||
pos.Y = offset;
|
||||
m_node->setPosition(pos);
|
||||
} // update
|
||||
if (enabled != m_shadow_enabled)
|
||||
{
|
||||
m_shadow_enabled = enabled;
|
||||
if (m_shadow_enabled)
|
||||
{
|
||||
SP::addDynamicDrawCall(m_dy_dc);
|
||||
}
|
||||
else
|
||||
{
|
||||
SP::removeDynamicDrawCall(m_dy_dc);
|
||||
}
|
||||
}
|
||||
if (m_shadow_enabled)
|
||||
{
|
||||
video::S3DVertexSkinnedMesh* v = m_dy_dc->getVerticesVector().data();
|
||||
v[0].m_position.X = -1; v[0].m_position.Z = 1; v[0].m_position.Y = 0;
|
||||
v[1].m_position.X = 1; v[1].m_position.Z = 1; v[1].m_position.Y = 0;
|
||||
v[2].m_position.X = -1; v[2].m_position.Z = -1; v[2].m_position.Y = 0;
|
||||
v[3].m_position.X = 1; v[3].m_position.Z = -1; v[3].m_position.Y = 0;
|
||||
btTransform kart_trans = m_kart.getTrans();
|
||||
btTransform skidding_rotation;
|
||||
skidding_rotation.setOrigin(Vec3(0, 0, 0));
|
||||
skidding_rotation.setRotation
|
||||
(btQuaternion(m_kart.getSkidding()->getVisualSkidRotation(), 0, 0));
|
||||
kart_trans *= skidding_rotation;
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
const btWheelInfo& wi = m_kart.getVehicle()->getWheelInfo(i);
|
||||
Vec3 up_vector = kart_trans.getBasis().getColumn(1);
|
||||
up_vector = up_vector * (wi.m_raycastInfo.m_suspensionLength - 0.02f);
|
||||
v[i].m_position =
|
||||
Vec3(kart_trans(Vec3(v[i].m_position)) - up_vector).toIrrVector();
|
||||
v[i].m_normal = MiniGLM::compressVector3
|
||||
(Vec3(wi.m_raycastInfo.m_contactNormalWS).toIrrVector());
|
||||
}
|
||||
m_dy_dc->recalculateBoundingBox();
|
||||
m_dy_dc->setUpdateOffset(0);
|
||||
}
|
||||
} // update
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,14 +21,13 @@
|
||||
|
||||
#include "utils/no_copy.hpp"
|
||||
|
||||
class KartProperties;
|
||||
class AbstractKart;
|
||||
class Material;
|
||||
|
||||
namespace irr
|
||||
namespace SP
|
||||
{
|
||||
namespace scene { class ISceneNode; class IMesh; }
|
||||
namespace video { class ITexture; }
|
||||
class SPDynamicDrawCall;
|
||||
}
|
||||
using namespace irr;
|
||||
|
||||
/**
|
||||
* \brief This class is used to enable a shadow for a kart.
|
||||
@@ -39,24 +38,20 @@ using namespace irr;
|
||||
class Shadow : public NoCopy
|
||||
{
|
||||
private:
|
||||
/** The scene node for the shadow. */
|
||||
scene::ISceneNode *m_node;
|
||||
|
||||
/** The mesh of the shadow. */
|
||||
scene::IMesh *m_mesh;
|
||||
|
||||
/** The scene node of the kart to which this shadow belongs. */
|
||||
scene::ISceneNode *m_parent_kart_node;
|
||||
/** The dynamic draw call of the shadow. */
|
||||
SP::SPDynamicDrawCall* m_dy_dc;
|
||||
|
||||
/** If a kart is flying, the shadow is disabled (since it is
|
||||
* stuck to the kart, i.e. the shadow would be flying, too). */
|
||||
bool m_shadow_enabled;
|
||||
|
||||
/** A read-only kart object for accessing suspension length. */
|
||||
const AbstractKart& m_kart;
|
||||
|
||||
public:
|
||||
Shadow(const KartProperties *kart_properties,
|
||||
scene::ISceneNode *node, float y_offset);
|
||||
Shadow(Material* shadow_mat, const AbstractKart& kart);
|
||||
~Shadow();
|
||||
void update(bool enabled, float hot);
|
||||
void update(bool enabled);
|
||||
}; // Shadow
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1348,7 +1348,7 @@ void handleDynamicDrawCall()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dydc->resetCullingResult();
|
||||
|
||||
SPShader* shader = dydc->getShader();
|
||||
core::aabbox3df bb = dydc->getBoundingBox();
|
||||
dydc->getAbsoluteTransformation().transformBoxEx(bb);
|
||||
@@ -1419,7 +1419,6 @@ void handleDynamicDrawCall()
|
||||
ret[p.first].insert(dydc);
|
||||
}
|
||||
}
|
||||
dydc->setCullingResult(DCT_TRANSPARENT, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1428,7 +1427,6 @@ void handleDynamicDrawCall()
|
||||
}
|
||||
else
|
||||
{
|
||||
dydc->setCullingResult((DrawCallType)dc_type, false);
|
||||
// Check if shader for render pass uses mesh samplers
|
||||
const RenderPass check_pass =
|
||||
dc_type == DCT_NORMAL ? RP_1ST : RP_SHADOW;
|
||||
|
||||
@@ -46,7 +46,6 @@ SPDynamicDrawCall::SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt,
|
||||
}
|
||||
m_tex_cmp[m_textures[0][0]->getPath() + m_textures[0][1]->getPath()] = 0;
|
||||
m_pitch = 48;
|
||||
resetCullingResult();
|
||||
|
||||
// Rerserve 4 vertices, and use m_ibo buffer for instance array
|
||||
glGenBuffers(1, &m_vbo);
|
||||
|
||||
@@ -55,8 +55,6 @@ private:
|
||||
|
||||
int m_update_offset = -1;
|
||||
|
||||
std::vector<bool> m_culling_result;
|
||||
|
||||
bool m_visible = true;
|
||||
|
||||
bool m_update_trans = false;
|
||||
@@ -76,10 +74,6 @@ public:
|
||||
bool bindless_texture = false) const
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
if (m_culling_result[dct])
|
||||
{
|
||||
return;
|
||||
}
|
||||
glBindVertexArray(m_vao[0]);
|
||||
glDrawArraysInstanced(
|
||||
m_primitive_type == EPT_TRIANGLES ? GL_TRIANGLES :
|
||||
@@ -137,15 +131,6 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
void setUpdateOffset(int offset) { m_update_offset = offset; }
|
||||
// ------------------------------------------------------------------------
|
||||
void resetCullingResult()
|
||||
{
|
||||
m_culling_result.clear();
|
||||
m_culling_result.resize(DCT_FOR_VAO, true);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void setCullingResult(DrawCallType dct, bool ret)
|
||||
{ m_culling_result[dct] = ret; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool isVisible() const { return m_visible; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setVisible(bool val) { m_visible = val; }
|
||||
|
||||
@@ -2647,19 +2647,9 @@ void Kart::loadData(RaceManager::KartType type, bool is_animated_model)
|
||||
m_skidmarks = new SkidMarks(*this);
|
||||
}
|
||||
|
||||
bool create_shadow = m_kart_properties->getShadowTexture() != NULL &&
|
||||
!CVS->supportsShadows();
|
||||
|
||||
#ifdef USE_GLES2
|
||||
// Disable kart shadow for legacy pipeline in GLES renderer because it's
|
||||
// broken
|
||||
create_shadow = create_shadow && CVS->isGLSL();
|
||||
#endif
|
||||
|
||||
if (create_shadow)
|
||||
if (CVS->isGLSL() && !CVS->isShadowEnabled())
|
||||
{
|
||||
m_shadow = new Shadow(m_kart_properties.get(), m_node,
|
||||
-m_kart_model->getLowestPoint());
|
||||
m_shadow = new Shadow(m_kart_properties->getShadowMaterial(), *this);
|
||||
}
|
||||
#endif
|
||||
World::getWorld()->kartAdded(this, m_node);
|
||||
@@ -2929,11 +2919,7 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
|
||||
if (m_shadow)
|
||||
{
|
||||
const bool emergency = getKartAnimation() != NULL;
|
||||
m_shadow->update(isOnGround() && !emergency,
|
||||
getTrans().inverse()(m_terrain_info->getHitPoint()).getY()
|
||||
- m_skidding->getGraphicalJumpOffset()
|
||||
- m_graphical_y_offset
|
||||
- m_kart_model->getLowestPoint());
|
||||
m_shadow->update(isOnGround() && !emergency);
|
||||
}
|
||||
#ifdef XX
|
||||
// cheap wheelie effect
|
||||
|
||||
@@ -252,13 +252,6 @@ void KartProperties::load(const std::string &filename, const std::string &node)
|
||||
else
|
||||
m_minimap_icon = NULL;
|
||||
|
||||
#ifndef SERVER_ONLY
|
||||
if (m_minimap_icon == NULL)
|
||||
{
|
||||
m_minimap_icon = STKTexManager::getInstance()->getUnicolorTexture(m_color);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Only load the model if the .kart file has the appropriate version,
|
||||
// otherwise warnings are printed.
|
||||
if (m_version >= 1)
|
||||
@@ -298,7 +291,8 @@ void KartProperties::load(const std::string &filename, const std::string &node)
|
||||
// used.
|
||||
m_wheel_base = fabsf(m_kart_model->getLength() - 2*0.25f);
|
||||
|
||||
m_shadow_texture = STKTexManager::getInstance()->getTexture(m_shadow_file);
|
||||
m_shadow_material = material_manager->getMaterialSPM(m_shadow_file, "",
|
||||
"alphablend");
|
||||
|
||||
STKTexManager::getInstance()->unsetTextureErrorMessage();
|
||||
file_manager->popTextureSearchPath();
|
||||
@@ -369,11 +363,6 @@ void KartProperties::getAllData(const XMLNode * root)
|
||||
m_color.set(255, (int)(255*c.getX()), (int)(255*c.getY()), (int)(255*c.getZ()));
|
||||
|
||||
root->get("groups", &m_groups );
|
||||
|
||||
root->get("shadow-scale", &m_shadow_scale );
|
||||
root->get("shadow-x-offset", &m_shadow_x_offset );
|
||||
root->get("shadow-z-offset", &m_shadow_z_offset );
|
||||
|
||||
root->get("type", &m_kart_type );
|
||||
|
||||
if(const XMLNode *dimensions_node = root->getNode("center"))
|
||||
|
||||
@@ -114,7 +114,7 @@ private:
|
||||
* for this kart.*/
|
||||
float m_shadow_z_offset; /**< Z offset of the shadow plane
|
||||
* for this kart.*/
|
||||
video::ITexture *m_shadow_texture;/**< The texture with the shadow. */
|
||||
Material* m_shadow_material; /**< The texture with the shadow. */
|
||||
video::SColor m_color; /**< Color the represents the kart in the
|
||||
* status bar and on the track-view. */
|
||||
int m_shape; /**< Number of vertices in polygon when
|
||||
@@ -270,7 +270,7 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the shadow texture to use. */
|
||||
video::ITexture *getShadowTexture() const {return m_shadow_texture; }
|
||||
Material* getShadowMaterial() const { return m_shadow_material; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the absolute path of the icon file of this kart. */
|
||||
@@ -341,21 +341,6 @@ public:
|
||||
/** Returns the restitution factor for this kart. */
|
||||
float getRestitution () const { return m_restitution; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the scale factor by which the shadow plane
|
||||
* had to be set. */
|
||||
float getShadowScale () const {return m_shadow_scale; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the scale factor by which the shadow plane
|
||||
* had to be set. */
|
||||
float getShadowXOffset () const {return m_shadow_x_offset; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the scale factor by which the shadow plane
|
||||
* had to be set. */
|
||||
float getShadowZOffset () const {return m_shadow_z_offset; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns a pointer to the AI properties. */
|
||||
const AIProperties *getAIPropertiesForDifficulty() const
|
||||
@@ -367,7 +352,6 @@ public:
|
||||
/** Returns the full path where the files for this kart are stored. */
|
||||
const std::string& getKartDir () const {return m_root; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns minimum time during which nitro is consumed when pressing nitro
|
||||
* key, to prevent using nitro in very short bursts
|
||||
|
||||
@@ -416,7 +416,10 @@ void RaceGUI::drawGlobalMiniMap()
|
||||
video::ITexture* icon = sta ?
|
||||
irr_driver->getTexture(FileManager::GUI, "heart.png") :
|
||||
kart->getKartProperties()->getMinimapIcon();
|
||||
|
||||
if (icon == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// int marker_height = m_marker->getSize().Height;
|
||||
core::rect<s32> source(core::position2di(0, 0), icon->getSize());
|
||||
int marker_half_size = (kart->getController()->isLocalPlayerController()
|
||||
|
||||
@@ -403,8 +403,12 @@ void RaceGUIOverworld::drawGlobalMiniMap()
|
||||
kart_xyz= kart->getXYZ();
|
||||
Vec3 draw_at;
|
||||
track->mapPoint2MiniMap(kart_xyz, &draw_at);
|
||||
|
||||
|
||||
video::ITexture* icon = kart->getKartProperties()->getMinimapIcon();
|
||||
if (icon == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
core::rect<s32> source(core::position2di(0, 0), icon->getSize());
|
||||
int marker_half_size = (kart->getController()->isLocalPlayerController()
|
||||
? m_minimap_player_size
|
||||
|
||||
Reference in New Issue
Block a user