Hello, I've been doing some small excercises to familiarize myself with ogre-next. In this excercise, I'm trying to create my own window, and then have ogre render to it so that I have more control over the wndproc. I've been studying from the code in Sample_Tutorial00_Basic and the code from this post: viewtopic.php?t=67402. Here's the entire code:
Code: Select all
#include "OgreAbiUtils.h"
#include "OgreArchiveManager.h"
#include "OgreCamera.h"
#include "OgreConfigFile.h"
#include "OgreRoot.h"
#include "OgreWindow.h"
#include "OgreHlmsManager.h"
#include "OgreHlmsPbs.h"
#include "OgreHlmsUnlit.h"
#include "Compositor/OgreCompositorManager2.h"
#include "OgreWindowEventUtilities.h"
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
# include "OSX/macUtils.h"
#endif
static void registerHlms()
{
using namespace Ogre;
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
// Note: macBundlePath works for iOS too. It's misnamed.
const String resourcePath = Ogre::macResourcesPath();
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
const String resourcePath = Ogre::macBundlePath() + "/";
#else
String resourcePath = "";
#endif
ConfigFile cf;
cf.load(resourcePath + "resources2.cfg");
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE || OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
String rootHlmsFolder = macBundlePath() + '/' + cf.getSetting("DoNotUseAsResource", "Hlms", "");
#else
String rootHlmsFolder = resourcePath + cf.getSetting("DoNotUseAsResource", "Hlms", "");
#endif
if (rootHlmsFolder.empty())
rootHlmsFolder = "./";
else if (*(rootHlmsFolder.end() - 1) != '/')
rootHlmsFolder += "/";
// At this point rootHlmsFolder should be a valid path to the Hlms data folder
HlmsUnlit* hlmsUnlit = 0;
HlmsPbs* hlmsPbs = 0;
// For retrieval of the paths to the different folders needed
String mainFolderPath;
StringVector libraryFoldersPaths;
StringVector::const_iterator libraryFolderPathIt;
StringVector::const_iterator libraryFolderPathEn;
ArchiveManager& archiveManager = ArchiveManager::getSingleton();
{
// Create & Register HlmsUnlit
// Get the path to all the subdirectories used by HlmsUnlit
HlmsUnlit::getDefaultPaths(mainFolderPath, libraryFoldersPaths);
Archive* archiveUnlit =
archiveManager.load(rootHlmsFolder + mainFolderPath, "FileSystem", true);
ArchiveVec archiveUnlitLibraryFolders;
libraryFolderPathIt = libraryFoldersPaths.begin();
libraryFolderPathEn = libraryFoldersPaths.end();
while (libraryFolderPathIt != libraryFolderPathEn)
{
Archive* archiveLibrary =
archiveManager.load(rootHlmsFolder + *libraryFolderPathIt, "FileSystem", true);
archiveUnlitLibraryFolders.push_back(archiveLibrary);
++libraryFolderPathIt;
}
// Create and register the unlit Hlms
hlmsUnlit = OGRE_NEW HlmsUnlit(archiveUnlit, &archiveUnlitLibraryFolders);
Root::getSingleton().getHlmsManager()->registerHlms(hlmsUnlit);
}
{
// Create & Register HlmsPbs
// Do the same for HlmsPbs:
HlmsPbs::getDefaultPaths(mainFolderPath, libraryFoldersPaths);
Archive* archivePbs = archiveManager.load(rootHlmsFolder + mainFolderPath, "FileSystem", true);
// Get the library archive(s)
ArchiveVec archivePbsLibraryFolders;
libraryFolderPathIt = libraryFoldersPaths.begin();
libraryFolderPathEn = libraryFoldersPaths.end();
while (libraryFolderPathIt != libraryFolderPathEn)
{
Archive* archiveLibrary =
archiveManager.load(rootHlmsFolder + *libraryFolderPathIt, "FileSystem", true);
archivePbsLibraryFolders.push_back(archiveLibrary);
++libraryFolderPathIt;
}
// Create and register
hlmsPbs = OGRE_NEW HlmsPbs(archivePbs, &archivePbsLibraryFolders);
Root::getSingleton().getHlmsManager()->registerHlms(hlmsPbs);
}
RenderSystem* renderSystem = Root::getSingletonPtr()->getRenderSystem();
if (renderSystem->getName() == "Direct3D11 Rendering Subsystem")
{
// Set lower limits 512kb instead of the default 4MB per Hlms in D3D 11.0
// and below to avoid saturating AMD's discard limit (8MB) or
// saturate the PCIE bus in some low end machines.
bool supportsNoOverwriteOnTextureBuffers;
renderSystem->getCustomAttribute("MapNoOverwriteOnDynamicBufferSRV",
&supportsNoOverwriteOnTextureBuffers);
if (!supportsNoOverwriteOnTextureBuffers)
{
hlmsPbs->setTextureBufferDefaultSize(512 * 1024);
hlmsUnlit->setTextureBufferDefaultSize(512 * 1024);
}
}
}
class MyWindowEventListener final : public Ogre::WindowEventListener
{
bool mQuit;
public:
MyWindowEventListener() : mQuit(false) {}
void windowClosed(Ogre::Window* rw) override { mQuit = true; }
bool getQuit() const { return mQuit; }
};
//------------------------------------------------------------------------------------
class LowLevelOgreNext
{
public:
LowLevelOgreNext(void);
LowLevelOgreNext(HWND h);
virtual ~LowLevelOgreNext(void);
Ogre::Root* go(HWND hwnd,
const Ogre::String pluginsFolder,
const Ogre::String writeAccessFolder,
const char* pluginsFile);
protected:
Ogre::Root* mRoot;
Ogre::Camera* mCamera;
Ogre::SceneManager* mSceneMgr;
Ogre::Window* mWindow;
};
//-------------------------------------------------------------------------------------
LowLevelOgreNext::LowLevelOgreNext(HWND h) : mRoot(0), mCamera(0), mSceneMgr(0), mWindow(0) {}
LowLevelOgreNext::~LowLevelOgreNext(void) { delete mRoot; }
//-------------------------------------------------------------------------------------
Ogre::Root* LowLevelOgreNext::go(HWND hwnd,
const Ogre::String pluginsFolder,
const Ogre::String writeAccessFolder,
const char* pluginsFile)
{
const Ogre::AbiCookie abiCookie = Ogre::generateAbiCookie();
mRoot = OGRE_NEW Ogre::Root(&abiCookie, pluginsFolder + pluginsFile, //
writeAccessFolder + "ogre.cfg", //
writeAccessFolder + "Ogre.log");
//--------------------------------------------------------------------------------------
if (!mRoot->showConfigDialog())
return NULL;
// Initialize Root
mRoot->getRenderSystem()->setConfigOption("sRGB Gamma Conversion", "Yes");
//***************************************************************
mRoot->initialise(false);
HWND hWnd = hwnd; // Get the hWnd of the application!
Ogre::NameValuePairList misc;
misc["externalWindowHandle"] = Ogre::StringConverter::toString((int)hWnd);
mWindow = mRoot->createRenderWindow("Main RenderWindow", 800, 600, false, &misc);
//***************************************************************
registerHlms();
// Create SceneManager
const size_t numThreads = 1u;
mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC, numThreads, "ExampleSMInstance");
// Create & setup camera
mCamera = mSceneMgr->createCamera("Main Camera");
// Position it at 500 in Z direction
mCamera->setPosition(Ogre::Vector3(0, 5, 15));
// Look back along -Z
mCamera->lookAt(Ogre::Vector3(0, 0, 0));
mCamera->setNearClipDistance(0.2f);
mCamera->setFarClipDistance(1000.0f);
mCamera->setAutoAspectRatio(true);
// Setup a basic compositor with a blue clear colour
Ogre::CompositorManager2* compositorManager = mRoot->getCompositorManager2();
const Ogre::String workspaceName("Demo Workspace");
const Ogre::ColourValue backgroundColour(0.2f, 0.4f, 0.6f);
compositorManager->createBasicWorkspaceDef(workspaceName, backgroundColour, Ogre::IdString());
compositorManager->addWorkspace(mSceneMgr, mWindow->getTexture(), mCamera, workspaceName, true);
return mRoot;
}
const wchar_t g_szClassName[] = L"myWindowClass";
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/*
switch (uMsg)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
*/
if( uMsg == WM_CREATE )
{ // Store pointer to Win32Window in user data area
SetWindowLongPtr( hWnd, GWLP_USERDATA,
(LONG_PTR)( ( (LPCREATESTRUCT)lParam )->lpCreateParams ) );
return 0;
}
// look up window instance
// note: it is possible to get a WM_SIZE before WM_CREATE
Ogre::Window *win = (Ogre::Window *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
if( !win )
return DefWindowProc( hWnd, uMsg, wParam, lParam );
// LogManager* log = LogManager::getSingletonPtr();
// Iterator of all listeners registered to this Window
Ogre::WindowEventUtilities::WindowEventListeners _msListeners;
Ogre::WindowEventUtilities::WindowEventListeners::iterator index, start = _msListeners.lower_bound( win ),
end = _msListeners.upper_bound( win );
switch( uMsg )
{
case WM_ACTIVATE:
{
bool active = ( LOWORD( wParam ) != WA_INACTIVE );
win->setFocused( active );
for( ; start != end; ++start )
( start->second )->windowFocusChange( win );
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint( hWnd, &ps );
win->_setVisible( !IsRectEmpty( &ps.rcPaint ) );
EndPaint( hWnd, &ps );
break;
}
case WM_SYSKEYDOWN:
switch( wParam )
{
case VK_CONTROL:
case VK_SHIFT:
case VK_MENU: // ALT
// return zero to bypass defProc and signal we processed the message
return 0;
}
break;
case WM_SYSKEYUP:
switch( wParam )
{
case VK_CONTROL:
case VK_SHIFT:
case VK_MENU: // ALT
case VK_F10:
// return zero to bypass defProc and signal we processed the message
return 0;
}
break;
case WM_SYSCHAR:
// return zero to bypass defProc and signal we processed the message, unless it's an
// ALT-space
if( wParam != VK_SPACE )
return 0;
break;
case WM_ENTERSIZEMOVE:
// log->logMessage("WM_ENTERSIZEMOVE");
break;
case WM_EXITSIZEMOVE:
// log->logMessage("WM_EXITSIZEMOVE");
break;
case WM_MOVE:
// log->logMessage("WM_MOVE");
win->windowMovedOrResized();
for( index = start; index != end; ++index )
( index->second )->windowMoved( win );
break;
case WM_DISPLAYCHANGE:
win->windowMovedOrResized();
for( index = start; index != end; ++index )
( index->second )->windowResized( win );
break;
case WM_SIZE:
// log->logMessage("WM_SIZE");
win->windowMovedOrResized();
for( index = start; index != end; ++index )
( index->second )->windowResized( win );
break;
case WM_GETMINMAXINFO:
// Prevent the window from going smaller than some minimu size
( (MINMAXINFO *)lParam )->ptMinTrackSize.x = 100;
( (MINMAXINFO *)lParam )->ptMinTrackSize.y = 100;
break;
case WM_CLOSE:
{
// log->logMessage("WM_CLOSE");
bool close = true;
for( index = start; index != end; ++index )
{
if( !( index->second )->windowClosing( win ) )
close = false;
}
if( !close )
return 0;
for( index = _msListeners.lower_bound( win ); index != end; ++index )
( index->second )->windowClosed( win );
win->destroy();
return 0;
}
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR strCmdLine, INT nCmdShow)
#else
int main(int argc, const char* argv[])
#endif
{
//using namespace Ogre;
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
const String pluginsFolder = macResourcesPath();
const String writeAccessFolder = macLogPath();
#else
const Ogre::String pluginsFolder = "./";
const Ogre::String writeAccessFolder = pluginsFolder;
#endif
#ifndef OGRE_STATIC_LIB
# if OGRE_DEBUG_MODE && \
!( ( OGRE_PLATFORM == OGRE_PLATFORM_APPLE ) || ( OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS ) )
const char* pluginsFile = "plugins_d.cfg";
# else
const char* pluginsFile = "plugins.cfg";
# endif
#else
const char* pluginsFile = 0; // TODO
#endif
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Window Registration Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassName, L"The title of my window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInst, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, L"Window Creation Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
UpdateWindow(hwnd);
LowLevelOgreNext app(hwnd);// Create application object
Ogre::Root* m_Root = app.go(hwnd, pluginsFolder, writeAccessFolder, pluginsFile);
if (m_Root == NULL)
return 1;
ShowWindow(hwnd, nCmdShow);
// Step 3: The Message Loop
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
m_Root->renderOneFrame();
}
return Msg.wParam;
}
Ogre-next did render to the window but the color is a different shade of blue from Sample_Tutorial00_Basic. I even tried copy WindowEventUtilities::_WndProc to my wndproc to see if that's the issue. I've been going through Root::Initialise to see what setup I'm missing but i'm quite lost right now, anyone know what the issue is?