Merge remote-tracking branch 'origin/skinned_mesh_normal_map'

This commit is contained in:
Benau
2016-10-15 15:25:20 +08:00
21 changed files with 242 additions and 89 deletions

View File

@@ -899,7 +899,7 @@ bool CIrrDeviceLinux::createWindow()
WMCheck, 0L, 1L, False, XA_WINDOW,
&type, &form, &len, &remain,
(unsigned char **)&list);
XFree(list);
bool netWM = (s == Success) && len;
attributes.override_redirect = !netWM && CreationParams.Fullscreen;

View File

@@ -245,8 +245,11 @@ void Camera::setMode(Mode mode)
{
Vec3 start_offset(0, 1.6f, -3);
Vec3 current_position = m_kart->getTrans()(start_offset);
Vec3 target_position = m_kart->getTrans()(Vec3(0, 0, 1));
// Don't set position and target the same, otherwise
// nan values will be calculated in ViewArea of camera
m_camera->setPosition(current_position.toIrrVector());
m_camera->setTarget(m_camera->getPosition());
m_camera->setTarget(target_position.toIrrVector());
}
m_mode = mode;
@@ -291,9 +294,9 @@ void Camera::setInitialTransform()
// direction till smoothMoveCamera has corrected this. Setting target
// to position doesn't make sense, but smoothMoves will adjust the
// value before the first frame is rendered
m_camera->setTarget(m_camera->getPosition());
Vec3 target_position = m_kart->getTrans()(Vec3(0, 0, 1));
m_camera->setTarget(target_position.toIrrVector());
m_camera->setRotation(core::vector3df(0, 0, 0));
m_camera->setRotation( core::vector3df( 0.0f, 0.0f, 0.0f ) );
m_camera->setFOV(m_fov);
} // setInitialTransform

View File

@@ -160,6 +160,7 @@ IrrDriver::~IrrDriver()
}
assert(m_device != NULL);
cleanUnicolorTextures();
m_device->drop();
m_device = NULL;
m_modes.clear();
@@ -869,11 +870,11 @@ void IrrDriver::applyResolutionSettings()
UserConfigParams::m_prev_height) );
m_video_driver->endScene();
track_manager->removeAllCachedData();
attachment_manager->removeTextures();
delete attachment_manager;
projectile_manager->removeTextures();
ItemManager::removeTextures();
kart_properties_manager->unloadAllKarts();
powerup_manager->unloadPowerups();
delete powerup_manager;
Referee::cleanup();
ParticleKindManager::get()->cleanup();
delete input_manager;
@@ -900,11 +901,23 @@ void IrrDriver::applyResolutionSettings()
RSMPassCmd::getInstance()->kill();
GlowPassCmd::getInstance()->kill();
resetTextureTable();
// initDevice will drop the current device.
if (m_post_processing)
{
// check if we createad the OpenGL device by calling initDevice()
m_post_processing->drop();
}
cleanUnicolorTextures();
delete m_shadow_matrices;
if (CVS->isGLSL())
{
Shaders::destroy();
}
delete m_spherical_harmonics;
// initDevice will drop the current device.
initDevice();
font_manager = new FontManager();
@@ -917,6 +930,8 @@ void IrrDriver::applyResolutionSettings()
material_manager->loadMaterial();
input_manager = new InputManager ();
input_manager->setMode(InputManager::MENU);
powerup_manager = new PowerupManager();
attachment_manager = new AttachmentManager();
GUIEngine::addLoadingIcon(
irr_driver->getTexture(file_manager
@@ -2649,8 +2664,6 @@ scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos,
else
light = new SunNode(m_scene_manager, parent, r, g, b);
light->grab();
light->setPosition(pos);
light->updateAbsolutePosition();
@@ -2680,9 +2693,7 @@ scene::ISceneNode *IrrDriver::addLight(const core::vector3df &pos,
void IrrDriver::clearLights()
{
u32 i;
const u32 max = (int)m_lights.size();
for (i = 0; i < max; i++)
for (unsigned int i = 0; i < m_lights.size(); i++)
{
m_lights[i]->drop();
}

View File

@@ -28,6 +28,7 @@
#include <irrlicht.h>
#include <IMesh.h>
#include <IMeshBuffer.h>
#include <SSkinMeshBuffer.h>
void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) {
@@ -444,29 +445,86 @@ scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh,
clone->recalculateBoundingBox();
if (calculate_tangents)
recalculateTangents(clone, recalculate_normals, smooth, angle_weighted);
int mbcount = clone->getMeshBufferCount();
for (int i = 0; i < mbcount; i++)
{
scene::IMeshBuffer* mb = clone->getMeshBuffer(i);
for (u32 t = 0; t < video::MATERIAL_MAX_TEXTURES; t++)
{
video::ITexture* texture = mb->getMaterial().TextureLayer[t].Texture;
if (texture != NULL)
texture->grab();
}
}
scene::IMeshCache* meshCache = irr_driver->getSceneManager()->getMeshCache();
io::SNamedPath path = meshCache->getMeshName(mesh);
irr_driver->removeMeshFromCache(mesh);
if (path.getPath() == "")
{
// This mesh is not in irrlicht cache, drop it directly
assert(mesh->getReferenceCount() == 1);
mesh->drop();
return clone;
}
else
{
// Cache the calcuated tangent mesh with path
irr_driver->removeMeshFromCache(mesh);
scene::SAnimatedMesh* amesh = new scene::SAnimatedMesh(clone);
clone->drop();
meshCache->addMesh(path, amesh);
if (World::getWorld())
{
irr_driver->grabAllTextures(amesh);
World::getWorld()->getTrack()->addCachedMesh(amesh);
return amesh;
}
amesh->drop();
return amesh;
}
scene::SAnimatedMesh* amesh = new scene::SAnimatedMesh(clone);
meshCache->addMesh(path, amesh);
World::getWorld()->getTrack()->addCachedMesh(amesh);
return clone;
}
void MeshTools::createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
bool(*predicate)(scene::IMeshBuffer*))
{
core::array<scene::SSkinMeshBuffer*>& all_mb = mesh->getMeshBuffers();
const int all_mb_size = all_mb.size();
for (int i = 0; i < all_mb_size; i++)
{
scene::SSkinMeshBuffer* mb = all_mb[i];
if (mb && predicate(mb))
{
mb->convertToTangents();
const int index_count = mb->getIndexCount();
uint16_t* idx = mb->getIndices();
video::S3DVertexTangents* v =
(video::S3DVertexTangents*)mb->getVertices();
for (int i = 0; i < index_count; i += 3)
{
calculateTangents(
v[idx[i+0]].Normal,
v[idx[i+0]].Tangent,
v[idx[i+0]].Binormal,
v[idx[i+0]].Pos,
v[idx[i+1]].Pos,
v[idx[i+2]].Pos,
v[idx[i+0]].TCoords,
v[idx[i+1]].TCoords,
v[idx[i+2]].TCoords);
calculateTangents(
v[idx[i+1]].Normal,
v[idx[i+1]].Tangent,
v[idx[i+1]].Binormal,
v[idx[i+1]].Pos,
v[idx[i+2]].Pos,
v[idx[i+0]].Pos,
v[idx[i+1]].TCoords,
v[idx[i+2]].TCoords,
v[idx[i+0]].TCoords);
calculateTangents(
v[idx[i+2]].Normal,
v[idx[i+2]].Tangent,
v[idx[i+2]].Binormal,
v[idx[i+2]].Pos,
v[idx[i+0]].Pos,
v[idx[i+1]].Pos,
v[idx[i+2]].TCoords,
v[idx[i+0]].TCoords,
v[idx[i+1]].TCoords);
}
}
}
}

View File

@@ -21,7 +21,7 @@
namespace irr
{
namespace scene { class IMesh; class IMeshBuffer; }
namespace scene { class IMesh; class IMeshBuffer; class ISkinnedMesh; }
}
using namespace irr;
@@ -37,8 +37,14 @@ namespace MeshTools
bool isNormalMap(scene::IMeshBuffer* mb);
// Copied from irrlicht
scene::IMesh* createMeshWithTangents(scene::IMesh* mesh, bool(*predicate)(scene::IMeshBuffer*),
bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false, bool calculateTangents = true);
scene::IMesh* createMeshWithTangents(scene::IMesh* mesh,
bool(*predicate)(scene::IMeshBuffer*), bool recalculateNormals = false,
bool smooth = false, bool angleWeighted = false,
bool calculateTangents = true);
void createSkinnedMeshWithTangents(scene::ISkinnedMesh* mesh,
bool(*predicate)(scene::IMeshBuffer*));
} // MeshTools
#endif

View File

@@ -126,15 +126,34 @@ ShadowMatrices::ShadowMatrices()
m_shadow_cam_nodes[1] = NULL;
m_shadow_cam_nodes[2] = NULL;
m_shadow_cam_nodes[3] = NULL;
m_rsm_map_available = false;
m_rsm_matrix_initialized = false;
} // ShadowMatrices
// ----------------------------------------------------------------------------
ShadowMatrices::~ShadowMatrices()
{
resetShadowCamNodes();
m_sun_cam->drop();
} // ~ShadowMatrices
// ----------------------------------------------------------------------------
void ShadowMatrices::resetShadowCamNodes()
{
for (unsigned i = 0; i < 4; i++)
{
if (m_shadow_cam_nodes[i])
{
m_shadow_cam_nodes[i]->drop();
m_shadow_cam_nodes[i] = NULL;
}
}
} // resetShadowCamNodes
// ----------------------------------------------------------------------------
void ShadowMatrices::addLight(const core::vector3df &pos)
{
m_sun_cam->setPosition(pos);
m_sun_cam->updateAbsolutePosition();
m_rsm_matrix_initialized = false;
} // addLight
// ----------------------------------------------------------------------------
@@ -334,17 +353,6 @@ void ShadowMatrices::computeMatrixesAndCameras(scene::ICameraSceneNode *const ca
if (World::getWorld() && World::getWorld()->getTrack())
{
// Compute track extent
btVector3 btmin, btmax;
if (World::getWorld()->getTrack()->getPtrTriangleMesh())
{
World::getWorld()->getTrack()->getTriangleMesh().getCollisionShape()
.getAabb(btTransform::getIdentity(), btmin, btmax);
}
const Vec3 vmin = btmin, vmax = btmax;
core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
core::vector3df(0, 30, 0));
float FarValues[] =
{
ShadowMatrices::m_shadow_split[1],
@@ -411,8 +419,16 @@ void ShadowMatrices::computeMatrixesAndCameras(scene::ICameraSceneNode *const ca
}
// Rsm Matrix and camera
if (!m_rsm_matrix_initialized)
if (!m_rsm_matrix_initialized &&
World::getWorld()->getTrack()->getPtrTriangleMesh())
{
// Compute track extent
Vec3 vmin, vmax;
World::getWorld()->getTrack()->getTriangleMesh().getCollisionShape()
.getAabb(btTransform::getIdentity(), vmin, vmax);
core::aabbox3df trackbox(vmin.toIrrVector(), vmax.toIrrVector() -
core::vector3df(0, 30, 0));
if (trackbox.MinEdge.X != trackbox.MaxEdge.X &&
trackbox.MinEdge.Y != trackbox.MaxEdge.Y &&
// Cover the case where sun_cam_view_matrix is null

View File

@@ -61,6 +61,7 @@ private:
public:
ShadowMatrices();
~ShadowMatrices();
void computeMatrixesAndCameras(scene::ICameraSceneNode *const camnode,
unsigned int width, unsigned int height);
@@ -69,10 +70,7 @@ public:
void renderShadowsDebug();
// ------------------------------------------------------------------------
void resetShadowCamNodes()
{
memset(m_shadow_cam_nodes, 0, 4 * sizeof(void*));
} // resetShadowCamNodes
void resetShadowCamNodes();
// ------------------------------------------------------------------------
scene::ICameraSceneNode** getShadowCamNodes()
{

View File

@@ -169,7 +169,7 @@ void STKAnimatedMesh::updateNoGL()
}
else
{
Material::ShaderType MatType = material->getShaderType();// getMeshMaterialFromType(type, mb->getVertexType(), material);
Material::ShaderType MatType = getMeshMaterialFromType(type, mb->getVertexType(), material, NULL);
MeshSolidMaterial[MatType].push_back(&mesh);
}
}

View File

@@ -59,6 +59,14 @@ static std::map<int, video::ITexture*> unicolor_cache;
void resetTextureTable()
{
AlreadyTransformedTexture.clear();
}
void cleanUnicolorTextures()
{
for (std::pair<const int, video::ITexture*>& uc : unicolor_cache)
{
uc.second->drop();
}
unicolor_cache.clear();
}
@@ -228,7 +236,6 @@ video::ITexture* getUnicolorTexture(const video::SColor &c)
std::map<int, video::ITexture*>::iterator it = unicolor_cache.find(c.color);
if (it != unicolor_cache.end())
{
it->second->grab();
return it->second;
}
else
@@ -240,10 +247,12 @@ video::ITexture* getUnicolorTexture(const video::SColor &c)
c.color
};
video::IImage *img = irr_driver->getVideoDriver()->createImageFromData(video::ECF_A8R8G8B8, core::dimension2d<u32>(2, 2), tmp);
img->grab();
std::stringstream name;
name << "color" << c.color;
video::ITexture* tex = irr_driver->getVideoDriver()->addTexture(name.str().c_str(), img);
tex->grab();
// Only let our map hold the unicolor texture
irr_driver->getVideoDriver()->removeTexture(tex);
unicolor_cache[c.color] = tex;
img->drop();
return tex;

View File

@@ -26,6 +26,7 @@
GLuint getTextureGLuint(irr::video::ITexture *tex);
GLuint getDepthTexture(irr::video::ITexture *tex);
void resetTextureTable();
void cleanUnicolorTextures();
void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = false);
bool loadCompressedTexture(const std::string& compressed_tex);
void saveCompressedTexture(const std::string& compressed_tex);

View File

@@ -50,6 +50,7 @@ IconButtonWidget(IconButtonWidget::SCALE_MODE_KEEP_TEXTURE_ASPECT_RATIO, false,
m_old_rtt_provider = NULL;
m_rotation_mode = ROTATE_OFF;
m_render_info = new RenderInfo();
m_angle = 0;
// so that the base class doesn't complain there is no icon defined
m_properties[PROP_ICON]="gui/main_help.png";
@@ -85,8 +86,6 @@ void ModelViewWidget::add()
*/
GUIEngine::needsUpdate.push_back(this);
angle = 0;
} // add
// -----------------------------------------------------------------------------
@@ -133,28 +132,28 @@ void ModelViewWidget::update(float delta)
if (m_rotation_mode == ROTATE_CONTINUOUSLY)
{
angle += delta*m_rotation_speed;
if (angle > 360) angle -= 360;
m_angle += delta*m_rotation_speed;
if (m_angle > 360) m_angle -= 360;
}
else if (m_rotation_mode == ROTATE_TO)
{
// check if we should rotate clockwise or counter-clockwise to reach the target faster
// (taking wrap-arounds into account)
const int angle_distance_from_end = (int)(360 - angle);
const int target_distance_from_end = (int)(360 - angle);
const int angle_distance_from_end = (int)(360 - m_angle);
const int target_distance_from_end = (int)(360 - m_angle);
int distance_with_positive_rotation;
int distance_with_negative_rotation;
if (angle < m_rotation_target)
if (m_angle < m_rotation_target)
{
distance_with_positive_rotation = (int)(m_rotation_target - angle);
distance_with_negative_rotation = (int)(angle + target_distance_from_end);
distance_with_positive_rotation = (int)(m_rotation_target - m_angle);
distance_with_negative_rotation = (int)(m_angle + target_distance_from_end);
}
else
{
distance_with_positive_rotation = (int)(angle_distance_from_end + m_rotation_target);
distance_with_negative_rotation = (int)(angle - m_rotation_target);
distance_with_negative_rotation = (int)(m_angle - m_rotation_target);
}
//Log::info("ModelViewWidget", "distance_with_positive_rotation = %d; "
@@ -163,17 +162,17 @@ void ModelViewWidget::update(float delta)
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);
m_angle += m_rotation_speed * delta*(3.0f + std::min(distance_with_positive_rotation, distance_with_negative_rotation)*2.0f);
}
else
{
angle -= m_rotation_speed * delta*(3.0f + std::min(distance_with_positive_rotation, distance_with_negative_rotation)*2.0f);
m_angle -= m_rotation_speed * delta*(3.0f + std::min(distance_with_positive_rotation, distance_with_negative_rotation)*2.0f);
}
if (angle > 360) angle -= 360;
if (angle < 0) angle += 360;
if (m_angle > 360) m_angle -= 360;
if (m_angle < 0) m_angle += 360;
// stop rotating when target reached
if (fabsf(angle - m_rotation_target) < 2.0f) m_rotation_mode = ROTATE_OFF;
if (fabsf(m_angle - m_rotation_target) < 2.0f) m_rotation_mode = ROTATE_OFF;
}
if (CVS->isGLSL())
@@ -188,7 +187,7 @@ void ModelViewWidget::update(float delta)
setupRTTScene();
}
m_rtt_main_node->setRotation(core::vector3df(0.0f, angle, 0.0f));
m_rtt_main_node->setRotation(core::vector3df(0.0f, m_angle, 0.0f));
m_rtt_main_node->setVisible(true);
@@ -206,7 +205,7 @@ void ModelViewWidget::update(float delta)
m_old_rtt_provider->setupRTTScene(m_models, m_model_location, m_model_scale, m_model_frames);
}
m_texture = m_old_rtt_provider->renderToTexture(angle);
m_texture = m_old_rtt_provider->renderToTexture(m_angle);
if (m_texture == NULL)
{

View File

@@ -56,7 +56,7 @@ namespace GUIEngine
RTT* m_rtt_provider;
IrrDriver::RTTProvider* m_old_rtt_provider;
float angle;
float m_angle;
bool m_rtt_unsupported;

View File

@@ -332,6 +332,7 @@ void Kart::reset()
// restore the original controller.
if(m_saved_controller)
{
delete m_controller;
m_controller = m_saved_controller;
m_saved_controller = NULL;
}
@@ -2888,12 +2889,14 @@ void Kart::setOnScreenText(const wchar_t *text)
if (CVS->isGLSL())
{
new STKTextBillboard(text, bold_face,
scene::ISceneNode* tb =
new STKTextBillboard(text, bold_face,
GUIEngine::getSkin()->getColor("font::bottom"),
GUIEngine::getSkin()->getColor("font::top"),
getNode(), irr_driver->getSceneManager(), -1,
core::vector3df(0.0f, 1.5f, 0.0f),
core::vector3df(1.0f, 1.0f, 1.0f));
tb->drop();
}
else
{

View File

@@ -80,6 +80,13 @@ KartGFX::KartGFX(const AbstractKart *kart)
m_skidding_light_2->setName( ("skidding emitter 2 (" + m_kart->getIdent()
+ ")").c_str() );
if (CVS->isGLSL())
{
m_nitro_light->grab();
m_skidding_light_1->grab();
m_skidding_light_2->grab();
}
// Create particle effects
Vec3 rear_left(kart->getWheelGraphicsPosition(3).getX(), 0.05f,
kart->getWheelGraphicsPosition(3).getZ()-0.1f );

View File

@@ -131,6 +131,7 @@ KartModel::KartModel(bool is_master)
m_min_suspension[i] = -0.07f;
m_max_suspension[i] = 0.20f;
m_dampen_suspension_amplitude[i] = 2.5f;
m_default_physics_suspension[i] = 0.25f;
}
m_wheel_filename[0] = "";
m_wheel_filename[1] = "";
@@ -521,6 +522,13 @@ bool KartModel::loadModels(const KartProperties &kart_properties)
full_path.c_str(), kart_properties.getIdent().c_str());
return false;
}
scene::ISkinnedMesh* sm = dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
if (sm)
{
MeshTools::createSkinnedMeshWithTangents(sm, &MeshTools::isNormalMap);
}
m_mesh->grab();
irr_driver->grabAllTextures(m_mesh);
@@ -569,6 +577,14 @@ bool KartModel::loadModels(const KartProperties &kart_properties)
// Grab all textures. This is done for the master only, so
// the destructor will only free the textures if a master
// copy is freed.
scene::ISkinnedMesh* sm =
dynamic_cast<scene::ISkinnedMesh*>(obj.m_model);
if (sm)
{
MeshTools::createSkinnedMeshWithTangents(sm,
&MeshTools::isNormalMap);
}
irr_driver->grabAllTextures(obj.m_model);
// Update min/max
@@ -611,6 +627,8 @@ bool KartModel::loadModels(const KartProperties &kart_properties)
std::string full_wheel =
kart_properties.getKartDir()+m_wheel_filename[i];
m_wheel_model[i] = irr_driver->getMesh(full_wheel);
m_wheel_model[i] = MeshTools::createMeshWithTangents(m_wheel_model[i],
&MeshTools::isNormalMap);
// Grab all textures. This is done for the master only, so
// the destructor will only free the textures if a master
// copy is freed.
@@ -861,17 +879,18 @@ void KartModel::update(float dt, float distance, float steer, float speed,
float suspension_length = 0.0f;
GhostKart* gk = dynamic_cast<GhostKart*>(m_kart);
// Prevent using m_default_physics_suspension uninitialized
if (gk && gt_replay_index == -1) break;
if (gk)
// Prevent using suspension length uninitialized
if (dt != 0.0f && !(gk && gt_replay_index == -1))
{
suspension_length = gk->getSuspensionLength(gt_replay_index, i);
}
else
{
suspension_length = m_kart->getVehicle()->getWheelInfo(i).
m_raycastInfo.m_suspensionLength;
if (gk)
{
suspension_length = gk->getSuspensionLength(gt_replay_index, i);
}
else
{
suspension_length = m_kart->getVehicle()->getWheelInfo(i).
m_raycastInfo.m_suspensionLength;
}
}
// Check documentation of Kart::updateGraphics for the following line

View File

@@ -74,7 +74,7 @@ ThreeStrikesBattle::~ThreeStrikesBattle()
{
m_tires.clearWithoutDeleting();
irr_driver->grabAllTextures(m_tire);
irr_driver->dropAllTextures(m_tire);
// Remove the mesh from the cache so that the mesh is properly
// freed once all refernces to it (which will happen once all
// karts are being freed, which would have a pointer to this mesh)

View File

@@ -485,6 +485,8 @@ World::~World()
if(m_physics)
delete m_physics;
delete m_script_engine;
m_world = NULL;
irr_driver->getSceneManager()->clear();

View File

@@ -77,6 +77,8 @@ namespace Scripting
ScriptEngine::~ScriptEngine()
{
// Release the engine
m_pending_timeouts.clearAndDeleteAll();
m_engine->DiscardModule(MODULE_ID_MAIN_SCRIPT_FILE);
m_engine->Release();
}

View File

@@ -82,7 +82,13 @@ LODNode* ModelDefinitionLoader::instanciateAsLOD(const XMLNode* node, scene::ISc
continue;
}
irr_driver->setAllMaterialFlags(a_mesh);
scene::ISkinnedMesh* sm =
dynamic_cast<scene::ISkinnedMesh*>(a_mesh);
if (sm)
{
MeshTools::createSkinnedMeshWithTangents(sm,
&MeshTools::isNormalMap);
}
a_mesh->grab();
//cache.push_back(a_mesh);

View File

@@ -1174,7 +1174,7 @@ bool Track::loadMainTrack(const XMLNode &root)
handleAnimatedTextures(scene_node, *track_node);
m_all_nodes.push_back(scene_node);
MeshTools::minMax3D(merged_mesh, &m_aabb_min, &m_aabb_max);
MeshTools::minMax3D(tangent_mesh, &m_aabb_min, &m_aabb_max);
// Increase the maximum height of the track: since items that fly
// too high explode, e.g. cakes can not be show when being at the
// top of the track (since they will explode when leaving the AABB
@@ -1868,8 +1868,10 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
sun->getLightData().SpecularColor = m_sun_specular_color;
}
else
{
irr_driver->createSunInterposer();
m_sun->grab();
}
createPhysicsModel(main_track_count);

View File

@@ -368,6 +368,16 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(
m_mesh = MeshTools::createMeshWithTangents(m_mesh,
&MeshTools::isNormalMap);
}
else
{
scene::ISkinnedMesh* sm =
dynamic_cast<scene::ISkinnedMesh*>(m_mesh);
if (sm)
{
MeshTools::createSkinnedMeshWithTangents(sm,
&MeshTools::isNormalMap);
}
}
init(&xml_node, parent, enabled);
} // TrackObjectPresentationMesh
@@ -959,6 +969,7 @@ TrackObjectPresentationLight::TrackObjectPresentationLight(
scene::ISceneNode* parent)
: TrackObjectPresentationSceneNode(xml_node)
{
m_color.set(0);
xml_node.get("color", &m_color);
const video::SColorf colorf(m_color);