Я просто повторно опубликую то, что я публиковал на форумах OGRE:
Я не уверен, будет ли лучше размещать сообщения здесь или на форуме «Использование OGRE на практике», но я попробую, так как это наиболее посещаемый раздел досок.
Итак, я делаю привязки для своего собственного фреймворка, который использует OGRE внутри, я привязал основные объекты, и по большей части они работают нормально (ввод и работа с окнами работают правильно), но у меня была одна проблема, которую я могу решить. не докопаюсь - вьюпорт приложения Python всегда черный (у меня нет объектов кроме камеры, просто задаю цвет фона вьюпорта).
Странно то, что точный эквивалент в C++ работает нормально, а код, связанный с python, - нет. В журнале ничего важного не отображается.
Вот как я связываю свои объекты:
#include "boost/python.hpp"
#include "boost/exception/diagnostic_information.hpp"
#include "Demo.hpp"
#include "Demo.cpp"
#include "XMLLevelLoader.h"
void addResourceLocation(const Crimson::String& group, const Crimson::String& loc)
{
Ogre::ResourceGroupManager* resmgr = Ogre::ResourceGroupManager::getSingletonPtr();
resmgr->addResourceLocation(loc, "FileSystem", group);
}
void initResourceGroup(const Crimson::String& group)
{
Ogre::ResourceGroupManager* resmgr = Ogre::ResourceGroupManager::getSingletonPtr();
resmgr->initialiseResourceGroup(group);
}
class AppWrapper : public Crimson::Application, public boost::python::wrapper<Crimson::Application>
{
public:
void onKeyDown(const SDL_KeyboardEvent& e)
{
boost::python::override over = this->get_override("onKeyDown");
if (over)
over(e);
}
using Crimson::Application::mQuit;
};
BOOST_PYTHON_MODULE(PyEngine)
{
using namespace boost::python;
def("initResourceGroup", initResourceGroup);
def("addResourceLocation", addResourceLocation);
enum_<SDL_Scancode>("SDL_Scancode");
class_<Ogre::ColourValue>("Color", init<const float, const float, const float, const float>())
.def_readwrite("r", &Ogre::ColourValue::r)
.def_readwrite("g", &Ogre::ColourValue::g)
.def_readwrite("b", &Ogre::ColourValue::b)
.def_readwrite("a", &Ogre::ColourValue::a);
class_<Ogre::Viewport>("Viewport", init<Ogre::Camera* , Ogre::RenderTarget*, float, float, float, float, int>())
.def("setBackgroundColour", &Ogre::Viewport::setBackgroundColour);
class_<Crimson::WindowInfo>("WindowInfo")
.def_readonly("renderWnd", &Crimson::WindowInfo::renderWnd)
.def_readonly("sdlWnd", &Crimson::WindowInfo::sdlWnd)
.def("addViewport", &Crimson::WindowInfo::addViewport, return_value_policy<reference_existing_object>())
.def("getAspectRatio", &Crimson::WindowInfo::getAspectRatio)
.def("getWidth", &Crimson::WindowInfo::getWidth)
.def("getHeight", &Crimson::WindowInfo::getHeight);
class_<Crimson::Kernel>("Kernel")
.def("initialize", &Crimson::Kernel::initialize)
.def("createRenderWindow", &Crimson::Kernel::createRenderWindow, return_value_policy<reference_existing_object>())
.def("getWindowInfo", &Crimson::Kernel::getWindowInfo, return_value_policy<reference_existing_object>())
.def("destroy", &Crimson::Kernel::destroy)
.def("render", &Crimson::Kernel::render);
class_<Crimson::Actor>("Actor", init<Crimson::Level*, const Crimson::String&, Crimson::Actor*>())
.def("setPosition", static_cast<void(Crimson::Actor::*)(const Crimson::Vector3&)>(&Crimson::Actor::setPosition))
.def("getPosition", &Crimson::Actor::getPosition);
class_ <Crimson::Mesh, bases<Crimson::Actor>>("Mesh", init<Crimson::Level*, const Crimson::String&, const Crimson::String&, Crimson::Actor*>());
class_ <Crimson::Camera, bases<Crimson::Actor>>("Camera", init<Crimson::Level*, const Crimson::String&, Crimson::Actor*>())
.def("setAspectRatio", &Crimson::Camera::setAspectRatio);
class_<rapidxml::xml_node<>, boost::noncopyable>("xml_node", init<rapidxml::node_type>())
.def("first_node", &rapidxml::xml_node<>::first_node, return_value_policy<reference_existing_object>());
class_<rapidxml::xml_document<>, boost::noncopyable>("xml_document")
.def("first_node", &rapidxml::xml_document<>::first_node, return_value_policy<reference_existing_object>())
.def("parse", &rapidxml::xml_document<>::parse<0>);
class_<Crimson::Level>("Level", init<Crimson::Kernel*>())
.def("initialize", &Crimson::Level::initialize)
.def("destroy", &Crimson::Level::destroy)
.def("createActor", &Crimson::Level::createActor, return_value_policy<reference_existing_object>())
.def("createMesh", &Crimson::Level::createMesh, return_value_policy<reference_existing_object>())
.def("createCamera", &Crimson::Level::createCamera, return_value_policy<reference_existing_object>());
class_<Crimson::XMLLevelLoader>("XMLLevelLoader", init<Crimson::String>())
.def("load", &Crimson::XMLLevelLoader::load)
.def("loadFileAsString", &Crimson::XMLLevelLoader::loadFileAsString)
.def("loadResources", &Crimson::XMLLevelLoader::loadResources)
.staticmethod("loadFileAsString")
.staticmethod("loadResources");
class_<AppWrapper, boost::noncopyable>("Application")
.def("initialize", &Crimson::Application::initialize)
.def("destroy", &Crimson::Application::destroy)
.def("onKeyDown", &Crimson::Application::onKeyDown)
.def("start", &Crimson::Application::start)
.def("updateGraphics", &Crimson::Application::updateGraphics)
.def("updateInput", &Crimson::Application::updateInput)
.def("isRunning", &Crimson::Application::isRunning)
.def("quit", &Crimson::Application::quit)
.def("getKernel", &Crimson::Application::getKernel, return_value_policy<reference_existing_object>());
class_<SDL_Keysym>("SDL_Keysym")
.def_readonly("mod", &SDL_Keysym::mod)
.def_readonly("scancode", &SDL_Keysym::scancode);
class_<SDL_KeyboardEvent>("SDL_KeyboardEvent")
.def_readonly("keysym", &SDL_KeyboardEvent::keysym);
class_<Ogre::Vector3>("Vector3", init<const float, const float, const float>())
.def_readwrite("x", &Ogre::Vector3::x)
.def_readwrite("y", &Ogre::Vector3::y)
.def_readwrite("z", &Ogre::Vector3::z);
}
Код Python (пустое окно просмотра):
import sys
from PyEngine import *
# Class definition
class TestPythonApp(Application):
def initialize(self):
Application.initialize(self)
mLevel = Level(self.getKernel())
mLevel.initialize()
mCamera = mLevel.createCamera("test", None)
vp = self.getKernel().getWindowInfo().addViewport(mCamera)
vp.setBackgroundColour(Color(0.8, 0, 0, 1))
def start(self):
while self.isRunning():
self.updateInput()
self.updateGraphics(1)
mLevel = None
mCamera = None
# /Class definition
# Script execution
app = TestPythonApp()
app.initialize()
app.start()
app.destroy()
Эквивалент С++ (цветное окно просмотра):
-- Заголовок
#ifndef PYAPP_HPP
#define PYAPP_HPP
#include "Application.h"
#include "XMLLevelLoader.h"
class PythonApp : public Crimson::Application
{
public:
bool initialize();
void start();
protected:
Crimson::Camera* mCamera;
Crimson::Level* mLevel;
};
#endif
-- Source:
bool PythonApp::initialize()
{
Application::initialize();
mLevel = new Crimson::Level(mKernel);
mLevel->initialize();
mCamera = mLevel->createCamera("cam");
Ogre::Viewport* vp = mKernel->getWindowInfo()->addViewport(mCamera);
vp->setBackgroundColour(Ogre::ColourValue(0.7f, 0.8f, 0.7f));
return true;
}
void PythonApp::start()
{
while (isRunning())
{
updateInput();
updateGraphics(1);
}
}
int main(int argc, char* argv[])
{
PythonApp game;
game.initialize();
game.start();
game.destroy();
return 0;
}
Я проверил - mBackColor
(в Ogre::Viewport) правильно настроен через Python, так что это не проблема.
Кроме того, код Python по какой-то причине отлично работает, если я поместил цикл рендеринга внутри функции initialize()
, но не вне ее. Из-за этого у меня такое ощущение, что это проблема контекста (возможно, данные повреждаются, когда интерпретатор выходит из функции инициализации или что-то в этом роде.
Вот странно работающий код Python:
import sys
from PyEngine import *
# Class definition
class TestPythonApp(Application):
def initialize(self):
Application.initialize(self)
mLevel = Level(self.getKernel())
mLevel.initialize()
mCamera = mLevel.createCamera("test", None)
vp = self.getKernel().getWindowInfo().addViewport(mCamera)
vp.setBackgroundColour(Color(0.8, 0, 0, 1))
self.start() # Moved line app.start() to here.
def start(self):
while self.isRunning():
self.updateInput()
self.updateGraphics(1)
mLevel = None
mCamera = None
# /Class definition
# Script execution
app = TestPythonApp()
app.initialize()
#app.start() # This moved up to initialize makes it work
app.destroy()
-- Некоторая информация о моем фреймворке: ядро содержит и вызывает Ogre::Root
, mLevel
содержит диспетчер сцен, а mCamera
- это обычная камера OGRE, просто обернутая через мой собственный API для простоты использования. WindowInfo - еще один класс-оболочка, который обрабатывает настройки окна (между OGRE и SDL), и я просто вызываю renderOneFrame()
в своей функции updateGraphics(delta)
.
Так что же я делаю неправильно, что код Python с теми же вызовами, что и вызовы C++, приводит к другому результату?