SAM-Viewer/src/scene.cpp

321 lines
7.9 KiB
C++

#include <stdlib.h>
#include <iostream>
#include <irrlicht.h>
#include "config.h"
#include "scene.h"
Scene::Scene(ISceneNode *parent, ISceneManager *smgr, s32 id) :
ISceneNode(parent, smgr, id),
conf(0),
show_grid(true),
show_axes(true)
{
material.Lighting = false;
material.MaterialType = EMT_TRANSPARENT_ALPHA_CHANNEL;
material.BackfaceCulling = false;
grid_color = SColor(64,128,128,128);
}
bool Scene::load(Config *config)
{
conf = config;
if (!loadModelMesh(conf->getCStr("model_mesh")))
return false;
setAttachment();
loadWieldMesh(conf->getCStr("wield_mesh"));
setBackFaceCulling(conf->getBool("backface_cull"));
setGridColor(conf->getHex("grid_color"));
return true;
}
bool Scene::loadModelMesh(const io::path &filename)
{
if (!conf)
return false;
IAnimatedMesh *mesh = SceneManager->getMesh(filename);
if (!mesh)
return false;
ISceneNode *wield = getNode(E_SCENE_ID_WIELD);
if (wield)
wield->setParent(this);
ISceneNode *model = getNode(E_SCENE_ID_MODEL);
if (model)
{
model->remove();
model = 0;
}
model = SceneManager->addAnimatedMeshSceneNode(mesh, this,
E_SCENE_ID_MODEL);
if (!model)
return false;
Vector pos = conf->getVector("model_position");
Vector rot = conf->getVector("model_rotation");
f32 s = (f32)conf->getInt("model_scale") / 100;
u32 mat = conf->getInt("model_material");
model->setMaterialFlag(EMF_LIGHTING, false);
model->setPosition(vector3df(pos.x, pos.y, pos.z));
model->setRotation(vector3df(rot.x, rot.y, rot.z));
model->setScale(vector3df(s,s,s));
model->setMaterialType((E_MATERIAL_TYPE)mat);
model->setMaterialFlag(EMF_BILINEAR_FILTER,
conf->getBool("bilinear"));
model->setMaterialFlag(EMF_TRILINEAR_FILTER,
conf->getBool("trilinear"));
model->setMaterialFlag(EMF_ANISOTROPIC_FILTER,
conf->getBool("anisotropic"));
setDebugInfo(conf->getBool("debug_info"));
if (wield)
setAttachment();
loadTextures(model, "model");
return true;
}
bool Scene::loadWieldMesh(const io::path &filename)
{
if (!conf)
return false;
IMesh *mesh = SceneManager->getMesh(filename);
if (!mesh)
return false;
ISceneNode *wield = getNode(E_SCENE_ID_WIELD);
if (wield)
{
wield->remove();
wield = 0;
}
wield = SceneManager->addMeshSceneNode(mesh, this,
E_SCENE_ID_WIELD);
if (!wield)
return false;
Vector pos = conf->getVector("wield_position");
Vector rot = conf->getVector("wield_rotation");
f32 s = (f32)conf->getInt("wield_scale") / 100;
u32 mat = conf->getInt("wield_material");
wield->setMaterialFlag(EMF_LIGHTING, false);
wield->setPosition(vector3df(pos.x, pos.y, pos.z));
wield->setRotation(vector3df(rot.x, rot.y, rot.z));
wield->setScale(vector3df(s,s,s));
wield->setVisible(conf->getBool("wield_show"));
wield->setMaterialType((E_MATERIAL_TYPE)mat);
wield->setMaterialFlag(EMF_BILINEAR_FILTER,
conf->getBool("bilinear"));
wield->setMaterialFlag(EMF_TRILINEAR_FILTER,
conf->getBool("trilinear"));
wield->setMaterialFlag(EMF_ANISOTROPIC_FILTER,
conf->getBool("anisotropic"));
wield->setVisible(conf->getBool("wield_show"));
setAttachment();
loadTextures(wield, "wield");
return true;
}
void Scene::loadTextures(ISceneNode *node, const std::string &prefix)
{
IVideoDriver *driver = SceneManager->getVideoDriver();
for (u32 i = 0; i < node->getMaterialCount(); ++i)
{
std::string key = prefix + "_texture_" + std::to_string(i + 1);
io::path fn = conf->getCStr(key);
ITexture *texture = driver->getTexture(fn);
if (texture)
driver->removeTexture(texture);
texture = driver->getTexture(fn);
if (texture)
{
SMaterial &material = node->getMaterial(i);
material.TextureLayer[0].Texture = texture;
}
}
}
ISceneNode *Scene::getNode(s32 id)
{
return SceneManager->getSceneNodeFromId(id);
}
void Scene::setAttachment()
{
if (!conf)
return;
IAnimatedMeshSceneNode *model =
(IAnimatedMeshSceneNode*)getNode(E_SCENE_ID_MODEL);
ISceneNode *wield = getNode(E_SCENE_ID_WIELD);
if (!model || !wield)
return;
IBoneSceneNode *bone = 0;
if (model->getJointCount() > 0)
{
stringc wield_bone = conf->getCStr("wield_bone");
bone = model->getJointNode(wield_bone.c_str());
}
if (bone)
wield->setParent(bone);
else
wield->setParent(model);
}
void Scene::setAnimation(const u32 &start, const u32 &end, const s32 &speed)
{
if (!conf)
return;
IAnimatedMeshSceneNode *model =
(IAnimatedMeshSceneNode*)getNode(E_SCENE_ID_MODEL);
if (model)
{
model->setFrameLoop(start, end);
model->setAnimationSpeed(speed);
}
}
void Scene::setFilter(E_MATERIAL_FLAG flag, const bool &is_enabled)
{
ISceneNode *model = getNode(E_SCENE_ID_MODEL);
if (model)
model->setMaterialFlag(flag, is_enabled);
ISceneNode *wield = getNode(E_SCENE_ID_WIELD);
if (wield)
wield->setMaterialFlag(flag, is_enabled);
}
void Scene::setBackFaceCulling(const bool &is_enabled)
{
ISceneNode *model = getNode(E_SCENE_ID_MODEL);
if (model)
model->setMaterialFlag(EMF_BACK_FACE_CULLING, is_enabled);
ISceneNode *wield = getNode(E_SCENE_ID_WIELD);
if (wield)
wield->setMaterialFlag(EMF_BACK_FACE_CULLING, is_enabled);
}
void Scene::setDebugInfo(const bool &is_visible)
{
ISceneNode *model = getNode(E_SCENE_ID_MODEL);
if (model)
{
u32 state = (is_visible) ? conf->getInt("debug_flags") : EDS_OFF;
model->setDebugDataVisible(state);
}
}
void Scene::rotate(s32 axis, const s32 &step)
{
vector3df rot = getRotation();
switch (axis)
{
case E_SCENE_AXIS_X:
rot.X = int(rot.X / step) * step + step;
break;
case E_SCENE_AXIS_Y:
rot.Y = int(rot.Y / step) * step + step;
break;
case E_SCENE_AXIS_Z:
rot.Z = int(rot.Z / step) * step + step;
break;
}
setRotation(rot);
}
void Scene::refresh()
{
ISceneNode *model = getNode(E_SCENE_ID_MODEL);
if (model)
loadTextures(model, "model");
ISceneNode *wield = getNode(E_SCENE_ID_WIELD);
if (wield)
loadTextures(wield, "wield");
}
void Scene::jump()
{
// quick and dirty jump animation to test attachment inertia
// this should eventually be improved or removed
ISceneNode *model = getNode(E_SCENE_ID_MODEL);
if (!model)
return;
Vector p = conf->getVector("model_position");
vector3df start = vector3df(p.x,p.y,p.z);
vector3df end = start + vector3df(0,10,0);
ISceneNodeAnimator *anim =
SceneManager->createFlyStraightAnimator(start, end, 380, false, true);
model->removeAnimators();
model->addAnimator(anim);
anim->drop();
}
void Scene::OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
void Scene::render()
{
if (!show_grid)
return;
IVideoDriver *driver = SceneManager->getVideoDriver();
driver->setMaterial(material);
driver->setTransform(ETS_WORLD, AbsoluteTransformation);
SColor grid = grid_color;
grid.setAlpha(64);
for (f32 n = -10; n <= 10; n += 2)
{
driver->draw3DLine(vector3df(n,0,-10), vector3df(n,-0,10), grid);
driver->draw3DLine(vector3df(-10,0,n), vector3df(10,-0,n), grid);
}
if (!show_axes)
return;
SColor red(128,255,0,0);
SColor green(128,0,255,0);
SColor blue(128,0,0,255);
driver->draw3DLine(vector3df(-10,0,-10), vector3df(-8,0,-10), red);
driver->draw3DLine(vector3df(-8,0,-10), vector3df(-8.5,0,-9.8), red);
driver->draw3DLine(vector3df(-8,0,-10), vector3df(-8.5,0,-10.2), red);
driver->draw3DLine(vector3df(-10,0,-10), vector3df(-10,2,-10), green);
driver->draw3DLine(vector3df(-10,2,-10), vector3df(-9.8,1.5,-10), green);
driver->draw3DLine(vector3df(-10,2,-10), vector3df(-10.2,1.5,-10), green);
driver->draw3DLine(vector3df(-10,0,-10), vector3df(-10,0,-8), blue);
driver->draw3DLine(vector3df(-10,0,-8), vector3df(-9.8,0,-8.5), blue);
driver->draw3DLine(vector3df(-10,0,-8), vector3df(-10.2,0,-8.5), blue);
IGUIEnvironment *env = SceneManager->getGUIEnvironment();
IGUIFont *font = env->getFont("fontlucida.png");
if (font)
{
s32 btm = driver->getScreenSize().Height;
s32 top = btm - 20;
font->draw(L"X", rect<s32>(5,top,15,btm), red);
font->draw(L"Y", rect<s32>(15,top,25,btm), green);
font->draw(L"Z", rect<s32>(25,top,35,btm), blue);
}
}