Code: Select all
// 002_MAIN_CPP
// I dont know who wrote the original code, but I made some changes
// and made GLSL also work.
// All three the original files were also combined into this single file..
#include <irrlicht.h>
#include <iostream>
#pragma comment(lib,"irrlicht.lib")
using namespace irr;
using namespace scene;
using namespace video;
using namespace io;
using namespace core;
class HWSkinCB : public video::IShaderConstantSetCallBack
{private:
IrrlichtDevice *device;
ISkinnedMesh* mesh;
void copyMat(f32* pointer, matrix4 &mat);
u32 oldtimer;
u32 delay;
bool lightsenabled;
public:
HWSkinCB();
~HWSkinCB();
static HWSkinCB* getInstance();
void setupNode(IrrlichtDevice* device, IAnimatedMeshSceneNode* node, u32 refresh);
virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData);
};
HWSkinCB::HWSkinCB() {delay = 0;} // (17 ms = appr 1/60th of a second = 60 FPS)
// I didn't quite get this..
HWSkinCB::~HWSkinCB() {this->drop();}
//-------------------- ---- --- -- -
HWSkinCB* HWSkinCB::getInstance()
{static HWSkinCB* instance = 0;
if (!instance) instance = new HWSkinCB();
return instance;
}
void HWSkinCB::setupNode(IrrlichtDevice *device, IAnimatedMeshSceneNode* node, u32 refresh)
{if (refresh) delay = refresh;
bool result = node->getMaterial(0).getFlag(video::EMF_LIGHTING);
if (result == false) lightsenabled = false;
else lightsenabled = true;
this->device = device;
this->mesh = (ISkinnedMesh*)node->getMesh();
// this->mesh->setHardwareMappingHint(EHM_STREAM);
// Just for interest's sake..
// EHM_NEVER Don't store on the hardware.
// EHM_STATIC Rarely changed, usually stored completely on the hardware.
// EHM_DYNAMIC Sometimes changed, driver optimized placement.
// EHM_STREAM Always changed, cache optimizing on the GPU.
this->mesh->setHardwareMappingHint(EHM_DYNAMIC, EBT_VERTEX_AND_INDEX); // Didn't really help..
// Enumerator:
// EBT_NONE Does not change anything.
// EBT_VERTEX Change the vertex mapping.
// EBT_INDEX Change the index mapping.
// EBT_VERTEX_AND_INDEX Change both vertex and index mapping to the same value.
//-------------------- ---- --- -- -
ISceneManager* smgr = device->getSceneManager();
IVideoDriver* driver = device->getVideoDriver();
// for(u32 BufferIndex = 0; BufferIndex < this->mesh->getMeshBuffers().size(); ++BufferIndex)
for(u32 BufferIndex = 0; BufferIndex < this->mesh->getMeshBuffers().size(); BufferIndex++)
{for(u32 g = 0; g < this->mesh->getMeshBuffers()[BufferIndex]->getVertexCount(); g++)
{this->mesh->getMeshBuffers()[BufferIndex]->getVertex(g)->Color = SColor(0,0,0,0);
}
}
for(u32 JointIndex = 0; JointIndex < this->mesh->getJointCount(); JointIndex++)
{for(u32 WeightIndex = 0; WeightIndex < this->mesh->getAllJoints()[JointIndex]->Weights.size(); WeightIndex++)
{int buffId = this->mesh->getAllJoints()[JointIndex]->Weights[WeightIndex].buffer_id; // how is this assigned?
int vertexId = this->mesh->getAllJoints()[JointIndex]->Weights[WeightIndex].vertex_id;
SColor* vColor = &this->mesh->getMeshBuffers()[buffId]->getVertex(vertexId)->Color;
if(vColor->getRed() == 0) vColor->setRed(JointIndex + 1);
else if(vColor->getGreen() == 0) vColor->setGreen(JointIndex + 1);
else if(vColor->getBlue() == 0) vColor->setBlue(JointIndex + 1);
else if(vColor->getAlpha() == 0) vColor->setAlpha(JointIndex + 1);
}
}
printf("Joint Num: %d, current limit is 55 joints.\n", mesh->getJointCount()); // What sort of difference did this make?
// Applying the shader..
IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
int HWSkinMat = EMT_SOLID;
if(driver->getDriverType() == EDT_OPENGL && !lightsenabled)
{HWSkinMat = gpu->addHighLevelShaderMaterialFromFiles ("HWSkinV.glsl","main",EVST_VS_2_0,"","",EPST_PS_2_0,this);
}
if(driver->getDriverType() == EDT_OPENGL && lightsenabled)
{HWSkinMat = gpu->addHighLevelShaderMaterialFromFiles ("HWSkinV_lights.glsl","main",EVST_VS_2_0,"","",EPST_PS_2_0,this);
}
if(driver->getDriverType() != EDT_OPENGL)
{HWSkinMat = gpu->addHighLevelShaderMaterialFromFiles ("HWSkin.hlsl","vertexMain",EVST_VS_2_0,"","",EPST_PS_2_0,this);
}
node->setMaterialType((E_MATERIAL_TYPE)HWSkinMat);
mesh->setHardwareSkinning(true); // Now...
}
// ------------------------------------------------- ---- --- -- -
// CopyMatrix..
void HWSkinCB::copyMat(f32* pointer, matrix4 &mat)
{for(int MatrixIndex = 0; MatrixIndex < 16; MatrixIndex++) *pointer++ = mat[MatrixIndex];
}
// ------------------------------------------------- ---- --- -- -
//
void HWSkinCB::OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{if(services->getVideoDriver()->getDriverType() == EDT_DIRECT3D9)
{core::matrix4 worldViewProj;
worldViewProj = services->getVideoDriver()->getTransform(video::ETS_PROJECTION);
worldViewProj *= services->getVideoDriver()->getTransform(video::ETS_VIEW);
worldViewProj *= services->getVideoDriver()->getTransform(video::ETS_WORLD);
core::matrix4 world;
world = services->getVideoDriver()->getTransform(video::ETS_WORLD)[0];
services->setVertexShaderConstant("mWorldViewProj", &worldViewProj[0], 16);
// COMPLETELY DISABLED LIGHTS IN GLS AS I DO THEM IN FRAGMENT SHADER..
}
u32 timer = device->getTimer()->getRealTime();
if (timer - oldtimer >= delay)
{oldtimer = timer;
if (mesh)
{f32* JointArray = new f32[(mesh->getJointCount() + 1) * 16]; // DONT NEW AND DELETE IN A LOOP!!!
int copyIncrement = 0;
for(u32 JointIndex = 0; JointIndex < this->mesh->getJointCount(); JointIndex++)
{core::matrix4 JointVertexPull(core::matrix4::EM4CONST_NOTHING);
// Set this matrix to be the product of two matrices.. i.e. Multiply by another matrix.. Calculate b*a??
// Definition at line 688 of file matrix4.h.
JointVertexPull.setbyproduct(mesh->getAllJoints()[JointIndex]->GlobalAnimatedMatrix,
mesh->getAllJoints()[JointIndex]->GlobalInversedMatrix);
copyMat(JointArray + copyIncrement, JointVertexPull);
copyIncrement += 16;
} // Is The Glitch's question related to this?
// IMPORTANT "ARRAY ACCESS" DIFFERENCE BETWEEN GLSL AND HLSL!!
if(services->getVideoDriver()->getDriverType() == EDT_DIRECT3D9)
{bool success = services->setVertexShaderConstant("JointTransform", JointArray, mesh->getJointCount() * 16);
}
// Using this secret "[0]" works for GLSL and we HAVE NO FRAMERATE DROP!! (when no lights active)
if(services->getVideoDriver()->getDriverType() == EDT_OPENGL)
{bool success = services->setVertexShaderConstant("JointTransform[0]", JointArray, mesh->getJointCount() * 16);
}
delete(JointArray);
}
}
}
// Yey for globals... (thats for sure!)=/
IrrlichtDevice* device = 0;
IrrlichtDevice* TheIRRNullDevice = 0;
IAnimatedMeshSceneNode* dwarf; // here now because it is refered to in the event receiver..
ISkinnedMesh* mesh;
core::dimension2d<u32> TheDeskResolution;
int DebugRendMode;
float CameraFov;
f32 CurrentAnimSpeed; // Couldnt get this one right..
scene::ICameraSceneNode* TheCamera;
// core::matrix4 M01World; // For use (un-altered) in the Vertex Program for fixing Raw Vertex Normals..
class MyEventReceiver : public IEventReceiver
{public:
MyEventReceiver()
{for (u32 i = 0; i < KEY_KEY_CODES_COUNT; ++i) KeyIsDown[i] = false;
}
virtual bool OnEvent(const SEvent& CurrEvent)
// AUTOMATICALLY BECAUSE WE DID.. TheDevice = createDevice(video::EDT_DIRECT3D9,TheDeskResolution, 32,x,x, x, &TheReceiver);"..
{if(CurrEvent.EventType == irr::EET_KEY_INPUT_EVENT)
{KeyIsDown[CurrEvent.KeyInput.Key] = CurrEvent.KeyInput.PressedDown;
if(!CurrEvent.KeyInput.PressedDown)
{switch(CurrEvent.KeyInput.Key)
{case irr::KEY_KEY_E: DebugRendMode ++; break;
case irr::KEY_KEY_Q: DebugRendMode --; break;
case irr::KEY_KEY_O: CameraFov *= 1.1;
TheCamera->setFOV(CameraFov * 0.017453 );
break;
case irr::KEY_KEY_P: CameraFov *= (1.0 / 1.1);
TheCamera->setFOV(CameraFov * 0.017453 );
break;
case irr::KEY_KEY_T:
CurrentAnimSpeed *= 2.0;
mesh->setAnimationSpeed (CurrentAnimSpeed) ;
break;
case irr::KEY_KEY_Y:
CurrentAnimSpeed *= (1.0 / 2.0);
mesh->setAnimationSpeed (CurrentAnimSpeed) ;
break;
}
}
}
return false;
}
virtual bool IsKeyDown(EKEY_CODE keyCode) const {return KeyIsDown[keyCode];}
private:
bool KeyIsDown[KEY_KEY_CODES_COUNT];
};
// ==================================================== ===== ==== === == =
int main()
{char i = 0; char j = 0; char k = 0;
printf("Dx or Ogl?\n1.Dx\n2.Ogl\n");
std::cin >> i;
// Why was this removed, yet kept to be seen?
//printf("Use ATI Technique?\n1.Yes\n2.No\n");
//std::cin >> use_ati;
printf("Activate the hardware skinning?\n1.Yes\n2.No\n3.Disable skinning\n");
std::cin >> j;
printf("Enable Lighting?\n1.Yes\n2.No\n");
std::cin >> k;
TheIRRNullDevice = createDevice(video::EDT_NULL); // Null Device for us to get our windows resolution..
TheDeskResolution = TheIRRNullDevice->getVideoModeList()->getDesktopResolution(); // As set by you in windows setup..
TheIRRNullDevice->drop(); // We got the desktop resolution, so drop the Null Device..
MyEventReceiver TheReceiver; // This receiver is the one assigned in the CREATE DEVICE function..
if(i == '1') device = createDevice(EDT_DIRECT3D9, TheDeskResolution, 32, false, false, false, &TheReceiver);
else device = createDevice(EDT_OPENGL, TheDeskResolution, 32, false, false, false, &TheReceiver);
ISceneManager* smgr = device->getSceneManager();
IVideoDriver* driver = device->getVideoDriver();
DebugRendMode = 0;
CurrentAnimSpeed = 20.0;
// CAMERA CAMERA CAMERA CAMERA CAMERA CAMERA CAMERA CAMERA CAMERA CAMERA
SKeyMap keyMap[8];
keyMap[0].Action = EKA_MOVE_FORWARD; keyMap[0].KeyCode = KEY_UP; // Arrow keys and "WASD"..
keyMap[1].Action = EKA_MOVE_FORWARD; keyMap[1].KeyCode = KEY_KEY_W;
keyMap[2].Action = EKA_MOVE_BACKWARD; keyMap[2].KeyCode = KEY_DOWN;
keyMap[3].Action = EKA_MOVE_BACKWARD; keyMap[3].KeyCode = KEY_KEY_S;
keyMap[4].Action = EKA_STRAFE_LEFT; keyMap[4].KeyCode = KEY_LEFT;
keyMap[5].Action = EKA_STRAFE_LEFT; keyMap[5].KeyCode = KEY_KEY_A;
keyMap[6].Action = EKA_STRAFE_RIGHT; keyMap[6].KeyCode = KEY_RIGHT;
keyMap[7].Action = EKA_STRAFE_RIGHT; keyMap[7].KeyCode = KEY_KEY_D;
TheCamera = smgr->addCameraSceneNodeFPS(0, 200, 0.0800, -1, keyMap, 8);
TheCamera->setPosition(core::vector3df(0.0,0.0,100.0));
TheCamera->setTarget(core::vector3df(0.0, 0.0, 0.0)); // This changes unseen when a FPS camera is mouse-aimed and moved around..
CameraFov = 80.0;
TheCamera->setFOV(CameraFov * 0.017453 );
// CAMERA CAMERA CAMERA CAMERA CAMERA CAMERA CAMERA CAMERA CAMERA CAMERA
dwarf = smgr->addAnimatedMeshSceneNode(smgr->getMesh("X_009_ULTRA_LOWRES_FRAGFIX.x"));
// I could write a lot about preparing models for Irrlicht..
mesh = (ISkinnedMesh*)dwarf->getMesh();
dwarf->setScale(vector3df( 9.0 , 9.0 , 9.0 )); // If you thought of scaleing it..
if (j=='3') mesh->setHardwareSkinning(true); // Now the GLSL side of it works fine with this NOT SET..
if (k=='1') dwarf->setMaterialFlag(EMF_LIGHTING, true); // We could ofcourse have the shader do the lighting!
else dwarf->setMaterialFlag(EMF_LIGHTING, false);
// if (j == '1') HWSkinCB::getInstance()->setupNode(device,dwarf,17);
if (j == '1') HWSkinCB::getInstance()->setupNode(device,dwarf,1); // Plaued with delay..
// Here we clone the item into a SQUADRON OF INSTANCES!
// How do Culling handle these??
for(int z = 0; z < 3; z++)
{for(int x = 0; x <= 3; x++)
{if (x != 0 || z != 0)
{ISceneNode* dwarfClone = dwarf->clone();
dwarf->setPosition(vector3df(x*50, 0, z*50));
}
}
}
// I didnt concentrate on lighting.. (not my code)
ILightSceneNode* light = smgr->addLightSceneNode(0,vector3df(0,0,0));
light->addAnimator(smgr->createFlyCircleAnimator(vector3df(125,180,125),100,0.001f));
light->getLightData().DiffuseColor = SColorf(0.5f,0.5f,0.0f,0.0f);
light = smgr->addLightSceneNode(0,vector3df(0.0f,0.0f,0.0f));
light->addAnimator(smgr->createFlyCircleAnimator(vector3df(125,180,125),100.0f,-0.001f));
light->getLightData().DiffuseColor = SColorf(0.0f,1.0f,0.0f,0.0f);
light = smgr->addLightSceneNode(0,vector3df(0.0f,0.0f,0.0f));
light->addAnimator(smgr->createFlyCircleAnimator(vector3df(125,180,125),80.0f,0.001f));
light->getLightData().DiffuseColor = SColorf(0.0f,0.5f,1.0f,0.0f);
light = smgr->addLightSceneNode(0,vector3df(0.0f,0.0f,0.0f));
light->addAnimator(smgr->createFlyCircleAnimator(vector3df(125,180,125),60.0f,-0.002f));
light->getLightData().DiffuseColor = SColorf(0.8f,0.2f,0.0f,0.0f);
int lastFPS=0;
while(device->run())
{mesh->setAnimationSpeed(CurrentAnimSpeed); // ???
if (DebugRendMode > 8) {DebugRendMode = 0;}
if (DebugRendMode < 0) {DebugRendMode = 8;}
if (DebugRendMode == 0) {dwarf->setDebugDataVisible(EDS_OFF);}
if (DebugRendMode == 1) {dwarf->setDebugDataVisible(EDS_BBOX);}
if (DebugRendMode == 2) {dwarf->setDebugDataVisible(EDS_NORMALS);}
if (DebugRendMode == 3) {dwarf->setDebugDataVisible(EDS_SKELETON);}
if (DebugRendMode == 4) {dwarf->setDebugDataVisible(EDS_MESH_WIRE_OVERLAY);}
if (DebugRendMode == 5) {dwarf->setDebugDataVisible(EDS_HALF_TRANSPARENCY);}
if (DebugRendMode == 6) {dwarf->setDebugDataVisible(EDS_BBOX_BUFFERS);} // THIS ONE !!!
if (DebugRendMode == 7) {dwarf->setDebugDataVisible(EDS_BBOX_ALL);}
if (DebugRendMode == 8) {dwarf->setDebugDataVisible(EDS_FULL);}
// Yes.. I know.. "Should have been a SWITCH"
driver->beginScene(true,true,SColor( 255 , 207 , 211 , 192 ));
smgr->drawAll();
driver->endScene();
int fps = driver->getFPS();
if (lastFPS != fps)
{core::stringw str = L"Hardware Skinning example";
if (j=='2') str += "(Hardware Skinning is disabled)";
str += " FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
device->closeDevice();
device->drop();
return 0;
};
// O.K.