b3view/Engine.cpp

359 lines
11 KiB
C++
Raw Normal View History

2010-04-21 07:48:36 -07:00
#include "Engine.h"
#include "UserInterface.h"
#include "View.h"
#include "Utils.h"
using std::cout;
using std::wcerr;
using std::endl;
using std::wstring;
using std::wstringstream;
using namespace irr;
using namespace irr::core;
using namespace irr::scene;
using namespace irr::video;
using namespace irr::gui;
2010-04-21 07:48:36 -07:00
/* //////////////////////////////////////////////////////////////////////////
PRIVATE METHODS
/////////////////////////////////////////////////////////////////////// */
void Engine::setupScene()
{
// Setup Light
2010-08-16 05:23:20 -07:00
m_SceneLight = m_Scene->addLightSceneNode();
m_SceneLight->setID( SIID_LIGHT );
m_SceneLight->setLightType( ELT_DIRECTIONAL );
m_SceneLight->getLightData().AmbientColor = SColorf( 0.2f, 0.2f, 0.2f );
m_SceneLight->getLightData().DiffuseColor = SColorf( 0.8f, 0.8f, 0.8f );
2010-04-21 07:48:36 -07:00
m_Scene->setAmbientLight( SColorf( 0.2f, 0.2f, 0.2f ));
// Setup Camera
// (so z-forward characters face camera partially (formerly vector3df( 0, 0, -10 ), vector3df())
2019-03-09 13:41:56 -08:00
m_CamPos = vector3df( 4.5, 3, 9 );
m_CamTarget = vector3df(0, 3, 0);
ICameraSceneNode *camera = m_Scene->addCameraSceneNode(nullptr, m_CamPos, m_CamTarget); // this will be overridden by View m_Yaw and m_Pitch--see "calculate m_Yaw" further down
camera->setAspectRatio((f32)m_Driver->getScreenSize().Width / m_Driver->getScreenSize().Height);
2010-04-21 07:48:36 -07:00
}
IGUIEnvironment * Engine::getGUIEnvironment() const
{
return m_Device->getGUIEnvironment();
}
void Engine::drawAxisLines()
{
SMaterial *lineX = new SMaterial();
lineX->Lighting = false;
lineX->EmissiveColor = SColor( 255, 255, 0, 0 );
lineX->Thickness = 1.0f;
SMaterial *lineY = new SMaterial( *lineX );
lineY->EmissiveColor = SColor( 255, 0, 255, 0 );
SMaterial *lineZ = new SMaterial( *lineX );
lineZ->EmissiveColor = SColor( 255, 0, 0, 255 );
m_Driver->setTransform( ETS_WORLD, matrix4() );
m_Driver->setMaterial( *lineX );
m_Driver->draw3DLine( vector3df(), vector3df( 5, 0, 0 ), SColor( 255, 255, 0, 0 ));
position2d<s32> textPos = m_Scene->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition( vector3df( 5.2, 0, 0 ));
dimension2d<u32> textSize;
if (m_AxisFont != nullptr) {
textSize = m_AxisFont->getDimension( L"X+" );
m_AxisFont->draw( L"X+", rect<s32>( textPos, textSize ), SColor( 255, 255, 0, 0 ), true, true );
}
2010-04-21 07:48:36 -07:00
m_Driver->setMaterial( *lineY );
m_Driver->draw3DLine( vector3df(), vector3df( 0, 5, 0 ), SColor( 255, 0, 255, 0 ));
textPos = m_Scene->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition( vector3df( 0, 5.2, 0 ));
if (m_AxisFont != nullptr) {
textSize = m_AxisFont->getDimension( L"Y+" );
m_AxisFont->draw( L"Y+", rect<s32>( textPos, textSize ), SColor( 255, 0, 255, 0 ), true, true );
}
2010-04-21 07:48:36 -07:00
m_Driver->setMaterial( *lineZ );
m_Driver->draw3DLine( vector3df(), vector3df( 0, 0, 5 ), SColor( 255, 0, 0, 255 ));
textPos = m_Scene->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition( vector3df( 0, 0, 5.2 ));
if (m_AxisFont != nullptr) {
textSize = m_AxisFont->getDimension( L"Z+" );
m_AxisFont->draw( L"Z+", rect<s32>( textPos, textSize ), SColor( 255, 0, 0, 255 ), true, true );
}
2010-04-21 07:48:36 -07:00
delete lineX;
delete lineY;
delete lineZ;
}
void Engine::drawBackground()
{
dimension2d<u32> screenSize = m_Driver->getScreenSize();
m_Driver->draw2DRectangle( rect<s32>( 0, 0, screenSize.Width, screenSize.Height ),
SColor( 255, 128, 128, 255 ),
SColor( 255, 128, 128, 255 ),
SColor( 255, 224, 224, 255 ),
SColor( 255, 224, 224, 255 ));
}
void Engine::checkResize()
{
if(( m_WindowSize->Width != m_Driver->getScreenSize().Width ) || ( m_WindowSize->Height != m_Driver->getScreenSize().Height ))
{
m_WindowSize->Width = m_Driver->getScreenSize().Width;
m_WindowSize->Height = m_Driver->getScreenSize().Height;
// Send custom event
IEventReceiver *eventReceiver = m_Device->getEventReceiver();
SEvent event;
event.EventType = EET_USER_EVENT;
event.UserEvent.UserData1 = UEI_WINDOWSIZECHANGED;
eventReceiver->OnEvent( event );
2010-04-21 07:48:36 -07:00
}
}
s32 Engine::getNumberOfVertices()
{
IMesh *mesh = m_LoadedMesh->getMesh()->getMesh( 0, 255, -1, -1 );
int vertices = 0;
for( int bufferIndex = 0; bufferIndex < mesh->getMeshBufferCount(); bufferIndex ++ )
vertices += mesh->getMeshBuffer( bufferIndex )->getVertexCount();
cout << vertices << endl;
return vertices;
}
2010-04-21 07:48:36 -07:00
/* //////////////////////////////////////////////////////////////////////////
PUBLIC METHODS
/////////////////////////////////////////////////////////////////////// */
Engine::Engine()
{
2019-03-07 21:52:29 -08:00
this->worldFPS = 60;
this->prevFPS = 30;
this->textureExtensions.push_back(L"png");
this->textureExtensions.push_back(L"jpg");
2010-04-22 01:44:10 -07:00
#if WIN32
2019-03-07 10:23:54 -08:00
m_Device = createDevice( EDT_DIRECT3D9, dimension2d<u32>( 1024, 768 ), 32, false, false, false, nullptr );
2010-04-22 01:44:10 -07:00
#else
2019-03-07 10:23:54 -08:00
m_Device = createDevice( EDT_OPENGL, dimension2d<u32>( 1024, 768 ), 32, false, false, false, nullptr );
2010-04-22 01:44:10 -07:00
#endif
2010-04-21 07:48:36 -07:00
m_Device->setResizable( true );
m_EventHandler = new EventHandler( m_Device );
m_Device->setEventReceiver( m_EventHandler );
m_Driver = m_Device->getVideoDriver();
m_Scene = m_Device->getSceneManager();
2019-03-07 10:23:54 -08:00
wstringstream windowTitle;
windowTitle << L"b3view (Blitz3D/Irrlicht Viewer) [" << m_Driver->getName() << L"]";
2010-04-22 01:44:10 -07:00
m_Device->setWindowCaption( windowTitle.str().c_str() );
2010-04-21 07:48:36 -07:00
setupScene();
// Setup User Interface
m_UserInterface = new UserInterface( this );
m_EventHandler->addEventReceiver( ERT_USERINTERFACE, m_UserInterface );
// Setup 3D View
m_View = new View( this );
m_EventHandler->addEventReceiver( ERT_3DVIEW, m_View );
// Load font for displaying Axis names
m_AxisFontFace = new CGUITTFace();
2019-03-09 13:41:56 -08:00
// NOTE: m_FontPath is modified y UserInterface constructor above if font was missing
if (m_AxisFontFace->load(m_FontPath.c_str())) {
m_AxisFont = new CGUITTFont( m_UserInterface->getGUIEnvironment() );
m_AxisFont->attach( m_AxisFontFace, 14 );
m_AxisFont->AntiAlias = false;
}
else {
delete m_AxisFontFace;
m_AxisFontFace = nullptr;
}
2010-04-21 07:48:36 -07:00
// Set Engine enabled
m_RunEngine = true;
2019-03-07 10:23:54 -08:00
m_LoadedMesh = nullptr;
2010-04-21 07:48:36 -07:00
// Store actual window size
m_WindowSize = new dimension2d<u32>();
m_WindowSize->Width = m_Driver->getScreenSize().Width;
m_WindowSize->Height = m_Driver->getScreenSize().Height;
// (do not calculate m_Yaw and m_Pitch, here, but in View constructor)
2019-03-07 21:52:29 -08:00
this->playAnimation();
2010-04-21 07:48:36 -07:00
}
Engine::~Engine()
{
m_Device->drop();
delete m_WindowSize;
delete m_AxisFont;
delete m_AxisFontFace;
2010-04-21 07:48:36 -07:00
}
2010-04-22 05:16:15 -07:00
void Engine::loadMesh( const wstring &fileName )
{
this->m_PreviousPath = fileName; // even if bad, set this
// to allow F5 to reload
2019-03-07 10:23:54 -08:00
if( m_LoadedMesh != nullptr )
2010-04-22 05:16:15 -07:00
m_LoadedMesh->remove();
irr::scene::IAnimatedMesh* mesh = m_Scene->getMesh( fileName.c_str());
if (mesh != nullptr) {
m_LoadedMesh = m_Scene->addAnimatedMeshSceneNode( mesh );
Utility::dumpMeshInfoToConsole( m_LoadedMesh );
}
2010-04-22 05:16:15 -07:00
}
void Engine::reloadMesh()
{
2019-03-07 21:52:29 -08:00
if (this->m_PreviousPath.length() > 0) {
loadMesh(this->m_PreviousPath);
}
}
void Engine::reloadTexture()
{
if (this->m_PrevTexturePath.length() > 0) {
loadTexture(this->m_PrevTexturePath);
}
}
bool Engine::loadTexture(const wstring &fileName)
2019-03-07 14:17:42 -08:00
{
ITexture* texture = this->m_Driver->getTexture(fileName.c_str());
bool ret = false;
if (texture != nullptr) {
m_LoadedMesh->setMaterialTexture(0, texture);
ret = true;
}
this->m_PrevTexturePath = fileName;
return ret;
2019-03-07 14:17:42 -08:00
}
2010-08-16 05:23:20 -07:00
void Engine::setMeshDisplayMode( bool wireframe, bool lighting )
{
for( int materialIndex = 0; materialIndex < m_LoadedMesh->getMaterialCount(); materialIndex ++ )
{
// Set Wireframe display
m_LoadedMesh->getMaterial( materialIndex ).Wireframe = wireframe;
// Set Lighting
if( ! lighting )
{
m_LoadedMesh->getMaterial( materialIndex ).Lighting = false;
m_LoadedMesh->getMaterial( materialIndex ).EmissiveColor = SColor( 255, 255, 255, 255 );
}
else
{
m_LoadedMesh->getMaterial( materialIndex ).Lighting = true;
m_LoadedMesh->getMaterial( materialIndex ).EmissiveColor = SColor( 255, 0, 0, 0 );
}
}
}
2019-03-07 21:52:29 -08:00
bool Engine::isAnimating()
{
return this->isPlaying;
}
void Engine::playAnimation()
{
if (this->animationFPS() < 1) {
this->setAnimationFPS(5);
}
if (!this->isAnimating()) {
if (this->m_LoadedMesh != nullptr) {
if (this->prevFPS < 1) this->prevFPS = 5;
this->m_LoadedMesh->setAnimationSpeed(this->prevFPS);
}
}
this->isPlaying = true;
}
void Engine::pauseAnimation()
{
if (this->isAnimating()) {
this->prevFPS = animationFPS();
if (this->m_LoadedMesh != nullptr) {
this->prevFPS = this->m_LoadedMesh->getAnimationSpeed();
this->m_LoadedMesh->setAnimationSpeed(0);
}
}
this->isPlaying = false;
}
void Engine::toggleAnimation()
{
if (this->isAnimating()) {
this->pauseAnimation();
debug() << "paused " << this->animationFPS() << "fps" << endl;
}
else {
this->playAnimation();
debug() << "unpaused " << this->animationFPS() << "fps" << endl;
}
}
void Engine::setAnimationFPS(u32 animationFPS)
{
if (this->m_LoadedMesh != nullptr) {
this->m_LoadedMesh->setAnimationSpeed(animationFPS);
}
}
u32 Engine::animationFPS()
{
u32 ret = 0;
if (this->m_LoadedMesh != nullptr) {
ret = this->m_LoadedMesh->getAnimationSpeed();
}
return ret;
}
2010-04-21 07:48:36 -07:00
void Engine::run()
{
2019-03-07 21:52:29 -08:00
u32 timePerFrame = 1000.0f;
if (this->worldFPS > 0) {
timePerFrame = ( u32 ) ( 1000.0f / this->worldFPS );
}
2010-04-21 07:48:36 -07:00
ITimer *timer = m_Device->getTimer();
2019-03-07 21:52:29 -08:00
// Run the Device with fps frames/sec
2010-04-21 07:48:36 -07:00
while( m_Device->run() && m_RunEngine )
{
u32 startTime = timer->getRealTime();
checkResize();
2019-03-07 21:52:29 -08:00
if (this->m_LoadedMesh != nullptr) {
if (isPlaying) {
this->m_LoadedMesh->setLoopMode(true);
}
else {
this->m_LoadedMesh->setLoopMode(false);
}
}
2010-04-21 07:48:36 -07:00
m_Driver->beginScene();
drawBackground(); // Draw Background
drawAxisLines(); // Draw XYZ Axis
m_Scene->drawAll(); // Draw Scenegraph
2010-04-21 07:48:36 -07:00
m_UserInterface->getGUIEnvironment()->drawAll();
m_UserInterface->drawStatusLine();
2010-04-21 07:48:36 -07:00
m_Driver->endScene();
u32 sleepTime = timePerFrame - ( timer->getRealTime() - startTime );
if( sleepTime > 0 && sleepTime < timePerFrame )
m_Device->sleep( sleepTime, false );
}
}