I’m new to Panda3D and trying to get my first app running, based on the tutorial examples, but I’m stuck to second example…
I’m using a custom class to hold the game engine functionality; within its setup() method I initialize panda framework, but I keep getting a reading violation error (either from ntdll.dll or libp3framework) when I call:
NodePath scene = window->load_model(framework.get_models(), "models/environment");
The strange thing is that, if I put the same code inside the main() function, everything runs smoothly.
Is there a “restriction”, namely to avoid using classes and keep the code within the main() function? I’m thinking to use game states classes, that will have different scenes, so it is neccessary to be able to load model from classes outside the main() function.
I’m using Visual Studio 2015 - Windows XP (v140_xp) toolset (which uses WinSDK 7.1A compiler) and compiling also against the Qt framework. Here is the code:
main.cpp
//---------------------------------------------------------------------------
// Include Qt modules
#include <QtCore/QCoreApplication>
#include <QtCore/QSettings>
#include <QtCore/QCommandLineParser>
#include <QtCore/QTranslator>
//---------------------------------------------------------------------------
// Include game engine headers
#include "pandaGameEngine.h"
//---------------------------------------------------------------------------
// Run !!
int main(int argc, char *argv[]) {
// Create application ...
QCoreApplication app(argc, argv);
// ... and set application details
app.setOrganizationName("...");
app.setOrganizationDomain("...");
app.setApplicationName("...");
app.setApplicationVersion("alpha");
// Load settings
QSettings *settings = new QSettings("settings.ini", QSettings::IniFormat);
// Parse command-line arguments
QCommandLineParser *cmdlParser = new QCommandLineParser;
cmdlParser->setApplicationDescription(QCoreApplication::tr("..."));
cmdlParser->addHelpOption();
cmdlParser->addVersionOption();
/* Create argument list */
cmdlParser->process(app);
const QStringList args = cmdlParser->positionalArguments();
/* Read the arguments */
// Update settings if neccesary
// ...
// Clear command-line arguments
delete cmdlParser;
cmdlParser = NULL;
// Load translations
QTranslator *translator = new QTranslator;
translator->load(settings->value("gui/language", "english").toString(), ":/resources/translations");
app.installTranslator(translator);
delete translator;
translator = NULL;
// Start game engine
pandaGameEngine *gameEngine = new pandaGameEngine(settings);
gameEngine->start(argc, argv);
// Delete game engine and exit
delete gameEngine; gameEngine = NULL;
delete settings; settings = NULL;
return 0;
}
pandaGameEngine.h
#ifndef PANDAGAMEENGINE_H
#define PANDAGAMEENGINE_H
//---------------------------------------------------------------------------
// Include Qt modules
#include <QtCore/QObject>
#include <QtCore/QSettings>
#include <QtCore/QVector>
//---------------------------------------------------------------------------
// Include Panda3D modules
#include "pandaFramework.h"
#include "pandaSystem.h"
//---------------------------------------------------------------------------
// Include game engine modules
#include "gameState.h"
//---------------------------------------------------------------------------
// Declare generic game state class
class gameState;
//---------------------------------------------------------------------------
// pandaGameEngine class
//---------------------------------------------------------------------------
class pandaGameEngine : public QObject
{
Q_OBJECT
public:
explicit pandaGameEngine(QSettings *settings = NULL);
~pandaGameEngine(void);
void start(int argc, char *argv[]);
public slots:
void changeState(gameState *state);
void pushState(gameState *state);
void popState(void);
protected:
QSettings *mSettings;
// Setup engine
bool setup(int argc, char *argv[]);
// Handle keyboard events
// ...
// Handle mouse events
// ...
// Handle joystick events
// ...
// Handle multitouch events
// ...
private:
// Panda3D framework
PandaFramework mFramework;
WindowFramework *mWindow;
// Game states
QVector<gameState*> mStates;
};
//---------------------------------------------------------------------------
#endif // #ifndef PANDAGAMEENGINE_H
pandaGameEngine.cpp
//---------------------------------------------------------------------------
// Include Qt modules
#include <QtCore/QSettings>
#include <QtCore/QDir>
#include <QtCore/QFile>
//---------------------------------------------------------------------------
// Include Panda3D modules
#include "pandaFramework.h"
#include "pandaSystem.h"
//---------------------------------------------------------------------------
// Include game engine modules
#include "pandaGameEngine.h"
//-----------------------------------------------------------------------------------------------------
// GAME ENGINE CLASS
//-----------------------------------------------------------------------------------------------------
// Create ogreGameEngine object
//---------------------------------------------------------------------------
pandaGameEngine::pandaGameEngine(QSettings *settings) {
// Load game engine settings
mSettings = settings;
}
//---------------------------------------------------------------------------
// Destroy ogreGameEngine object
//---------------------------------------------------------------------------
pandaGameEngine::~pandaGameEngine(void) {
// Clean up all game states
while (!mStates.empty()) {
mStates.back()->exit();
mStates.pop_back();
}
// Close Panda3D framework
delete mWindow; mWindow = NULL;
mFramework.close_framework();
}
//-----------------------------------------------------------------------------------------------------
// START GAME ENGINE
//-----------------------------------------------------------------------------------------------------
// Start game engine
//---------------------------------------------------------------------------
void pandaGameEngine::start(int argc, char *argv[]) {
if (!setup(argc, argv)) { return; } // Initialize engine
/* Start the engine */
mFramework.main_loop();
}
//-----------------------------------------------------------------------------------------------------
// SETUP GAME ENGINE
//-----------------------------------------------------------------------------------------------------
// Setup game engine
//---------------------------------------------------------------------------
bool pandaGameEngine::setup(int argc, char *argv[]) {
// Load the window and set its title.
mFramework.open_framework(argc, argv);
mFramework.set_window_title("My Panda3D Window");
WindowFramework *mWindow = mFramework.open_window();
// Load the environment model.
NodePath scene = mWindow->load_model(mFramework.get_models(), "data/models/environment");
// Reparent the model to render.
scene.reparent_to(mWindow->get_render());
// Apply scale and position transforms to the model.
scene.set_scale(0.25f, 0.25f, 0.25f);
scene.set_pos(-8, 42, 0);
return true;
};
//-----------------------------------------------------------------------------------------------------
// HANDLE INPUT EVENTS
//-----------------------------------------------------------------------------------------------------
// Keyboard events
//---------------------------------------------------------------------------
// ...
//---------------------------------------------------------------------------
// Handle mouse events
//---------------------------------------------------------------------------
// ...
//---------------------------------------------------------------------------
// Handle joystick events
//---------------------------------------------------------------------------
// ...
//---------------------------------------------------------------------------
// Handle multitouch events
//---------------------------------------------------------------------------
// ...
//-----------------------------------------------------------------------------------------------------
// GAME STATES
//-----------------------------------------------------------------------------------------------------
// Change game state
//---------------------------------------------------------------------------
void pandaGameEngine::changeState(gameState *state) {
// Cleanup the current state
if (!mStates.empty()) {
mStates.back()->exit();
QObject::disconnect(mStates.back(), SIGNAL(changeState(gameState)), this, SLOT(changeState(gameState)));
QObject::disconnect(mStates.back(), SIGNAL(pushState(gameState)), this, SLOT(pushState(gameState)));
QObject::disconnect(mStates.back(), SIGNAL(popState()), this, SLOT(popState()));
mStates.pop_back();
}
// Store and initialize the new state
mStates.push_back(state);
QObject::connect(mStates.back(), SIGNAL(changeState(gameState)), this, SLOT(changeState(gameState)));
QObject::connect(mStates.back(), SIGNAL(pushState(gameState)), this, SLOT(pushState(gameState)));
QObject::connect(mStates.back(), SIGNAL(popState()), this, SLOT(popState()));
mStates.back()->enter();
}
//---------------------------------------------------------------------------
// Push a new game state
//---------------------------------------------------------------------------
void pandaGameEngine::pushState(gameState *state) {
// Pause current state
if (!mStates.empty()) {
mStates.back()->pause();
}
// Store and initialize the new state
mStates.push_back(state);
QObject::connect(mStates.back(), SIGNAL(changeState(gameState)), this, SLOT(changeState(gameState)));
QObject::connect(mStates.back(), SIGNAL(pushState(gameState)), this, SLOT(pushState(gameState)));
QObject::connect(mStates.back(), SIGNAL(popState()), this, SLOT(popState()));
mStates.back()->enter();
}
//---------------------------------------------------------------------------
// Pop previous game state
//---------------------------------------------------------------------------
void pandaGameEngine::popState(void) {
// cleanup the current state
if (!mStates.empty()) {
mStates.back()->exit();
QObject::disconnect(mStates.back(), SIGNAL(changeState(gameState)), this, SLOT(changeState(gameState)));
QObject::disconnect(mStates.back(), SIGNAL(pushState(gameState)), this, SLOT(pushState(gameState)));
QObject::disconnect(mStates.back(), SIGNAL(popState()), this, SLOT(popState()));
mStates.pop_back();
}
// Resume previous state
if (!mStates.empty()) {
mStates.back()->resume();
}
}
//---------------------------------------------------------------------------