1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2009-2013  Joerg Henrichs
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #include "graphics/shadow.hpp"
20 #include "karts/abstract_kart.hpp"
21 #include "karts/skidding.hpp"
22 #include "graphics/sp/sp_shader_manager.hpp"
23 #include "graphics/sp/sp_dynamic_draw_call.hpp"
24 #include "physics/btKart.hpp"
25 #include "utils/mini_glm.hpp"
26 #include "utils/vec3.hpp"
27 
28 #ifndef SERVER_ONLY
29 
Shadow(Material * shadow_mat,const AbstractKart & kart)30 Shadow::Shadow(Material* shadow_mat, const AbstractKart& kart)
31       : m_dy_dc(NULL), m_shadow_enabled(false), m_kart(kart)
32 {
33     m_dy_dc = std::make_shared<SP::SPDynamicDrawCall>
34         (scene::EPT_TRIANGLE_STRIP,
35         SP::SPShaderManager::get()->getSPShader("alphablend"), shadow_mat);
36 
37     m_dy_dc->getVerticesVector().resize(4);
38     video::S3DVertexSkinnedMesh* v = m_dy_dc->getVerticesVector().data();
39     v[0].m_all_uvs[0] = 0;
40     v[0].m_all_uvs[1] = 0;
41     v[1].m_all_uvs[0] = 15360;
42     v[1].m_all_uvs[1] = 0;
43     v[3].m_all_uvs[0] = 15360;
44     v[3].m_all_uvs[1] = 15360;
45     v[2].m_all_uvs[0] = 0;
46     v[2].m_all_uvs[1] = 15360;
47 
48     m_dy_dc->setVisible(false);
49     SP::addDynamicDrawCall(m_dy_dc);
50 }   // Shadow
51 
52 // ----------------------------------------------------------------------------
~Shadow()53 Shadow::~Shadow()
54 {
55     m_dy_dc->removeFromSP();
56 }   // ~Shadow
57 
58 // ----------------------------------------------------------------------------
59 /** Updates the simulated shadow. It takes the 4 suspension lengths of vehicle
60  *  from ground to position the shadow quad exactly on the ground.
61  *  It also disables the shadow if requested (e.g. if the kart is in the air).
62  *  \param enabled If the shadow should be shown or not.
63  */
update(bool enabled)64 void Shadow::update(bool enabled)
65 {
66     if (enabled != m_shadow_enabled)
67     {
68         m_shadow_enabled = enabled;
69         if (m_shadow_enabled)
70         {
71             m_dy_dc->setVisible(true);
72         }
73         else
74         {
75             m_dy_dc->setVisible(false);
76         }
77     }
78     if (m_shadow_enabled)
79     {
80         video::S3DVertexSkinnedMesh* v = m_dy_dc->getVerticesVector().data();
81         v[0].m_position.X = -1; v[0].m_position.Z =  1; v[0].m_position.Y = 0;
82         v[1].m_position.X =  1; v[1].m_position.Z =  1; v[1].m_position.Y = 0;
83         v[2].m_position.X = -1; v[2].m_position.Z = -1; v[2].m_position.Y = 0;
84         v[3].m_position.X =  1; v[3].m_position.Z = -1; v[3].m_position.Y = 0;
85         btTransform kart_trans = m_kart.getSmoothedTrans();
86         btTransform skidding_rotation;
87         skidding_rotation.setOrigin(Vec3(0, 0, 0));
88         skidding_rotation.setRotation
89             (btQuaternion(m_kart.getSkidding()->getVisualSkidRotation(), 0, 0));
90         kart_trans *= skidding_rotation;
91         for (unsigned i = 0; i < 4; i++)
92         {
93             const btWheelInfo& wi = m_kart.getVehicle()->getWheelInfo(i);
94             Vec3 up_vector = kart_trans.getBasis().getColumn(1);
95             up_vector = up_vector * (wi.m_raycastInfo.m_suspensionLength - 0.02f);
96             Vec3 pos = kart_trans(Vec3(v[i].m_position)) - up_vector;
97             v[i].m_position = pos.toIrrVector();
98             v[i].m_normal = MiniGLM::compressVector3
99                 (Vec3(wi.m_raycastInfo.m_contactNormalWS).toIrrVector());
100         }
101         m_dy_dc->recalculateBoundingBox();
102         m_dy_dc->setUpdateOffset(0);
103     }
104 }   // update
105 
106 #endif
107