Controlling the Camera Tutorial Problem [Resolved]

Here is the link to the tutorial: panda3d.org/manual/index.php … the_Camera

Obviously I am working with the C++ version of the code.

So after plugging in the code as shown on that page, even copy/pasting the code from the page into MSVS2008, the exe crashes on start. I have tried rebuilding the project, since it seems that if you do not Panda3D will crash every time you try to run it, and I have tried altering some bits of the code but without the ability to run in debug mode I am at a loss for what is actually causing the problem.

Here is the unedited code from my project:

#include "pandaFramework.h"
#include "pandaSystem.h"
 
#include "genericAsyncTask.h"
#include "asyncTaskManager.h"
 
// The global task manager
PT(AsyncTaskManager) taskMgr = AsyncTaskManager::get_global_ptr(); 
// The global clock
PT(ClockObject) globalClock = ClockObject::get_global_clock();
// Here's what we'll store the camera in.
NodePath camera;
 
// This is our task - a global or static function that has to return DoneStatus.
// The task object is passed as argument, plus a void* pointer, containing custom data.
// For more advanced usage, we can subclass AsyncTask and override the do_task method.
AsyncTask::DoneStatus spinCameraTask(GenericAsyncTask* task, void* data)
{
	// Calculate the new position and orientation (inefficient - change me!)
	double time = globalClock->get_real_time();
	double angledegrees = time * 6.0;
	double angleradians = angledegrees * (3.14 / 180.0);
	camera.set_pos(20*sin(angleradians),-20.0*cos(angleradians),3);
	camera.set_hpr(angledegrees, 0, 0); 

	// Tell the task manager to continue this task the next frame.
	return AsyncTask::DS_cont;
}
 
int main(int argc, char *argv[])
{
	// Load the window and set its title.
	PandaFramework framework;
    framework.open_framework(argc, argv);
    framework.set_window_title("My Panda3D Window");
    WindowFramework *window = framework.open_window();
    // Get the camera and store it in a variable.
    camera = window->get_camera_group();
 
    // Load the environment model.
    NodePath environ = window->load_model(framework.get_models(), "models/environment");
    // Reparent the model to render.
    environ.reparent_to(window->get_render());
    // Apply scale and position transforms to the model.
    environ.set_scale(0.25, 0.25, 0.25);
    environ.set_pos(-8, 42, 0);
 
    // Add our task.
    // If we specify custom data instead of NULL, it will be passed as the second argument
    // to the task function.
    taskMgr->add(new GenericAsyncTask("Spins the camera", &spinCameraTask, (void*) NULL));
 
    // Run the engine.
    framework.main_loop();
    // Shut down the engine when done.
    framework.close_framework();
    return (0);
}

Edit 1:

I decided to load the program into a debugging instance of MSVS 2008 as a JIT debugging solution and according to that the problem is occurring when it tries to load the environment model. I tried commenting out all of the added code between the previous tutorial and this one and it still works however something in the code for this specific tutorial is causing problems.

Still have not tracked it down yet but I have a hunch.

Edit 2:

I have narrowed the issues down to the problem line of code:

PT(AsyncTaskManager) taskMgr = AsyncTaskManager::get_global_ptr(); 

After commenting out and uncommenting lines of code, after this one was uncommented (with everything else added by the tutorial mentioned commented out), the crashing started to happen again. For whatever reason MSVS 2008 installed on Windows 7 does not like this line of code.

With it commented out and any dependent code also commented out there are no problems and the program runs properly. Once this particular line is uncommented the program crashes on start up.

By assigning the value of AsyncTaskManager::get_global_ptr() in a static initialiser, you are causing get_global_ptr to be invoked at static init time, which happens sometime before the main() method is invoked. Since C++ does not guarantee any particular order in which static initialisations happen, this can often lead to mysterious crashes when the code ran by one static initialiser depends on another static variable being initialised.

Long story short, put that problematic line of code within your main(). If you must keep it a global, you could initialise it to NULL and then in your main() reassign it to AsyncTaskManager::get_global_ptr().

I would suggest doing the same for ClockObject.

Thanks rdb, I shall give that a try. If it works then the tutorial for this functionality should also be fixed in a similar fashion as the code I posted is verbatim from the tutorial page.

Edit 1:

All right I have tried this two different ways thus far and both have produced crashes but on new lines of the code from the original post:

#include "pandaFramework.h"
#include "pandaSystem.h"
 
#include "genericAsyncTask.h"
#include "asyncTaskManager.h"

// The global task manager
PT(AsyncTaskManager) taskMgr;

// The global clock
PT(ClockObject) globalClock;

// Here's what we'll store the camera in.
NodePath camera;

// This is our task - a global or static function that has to return DoneStatus.
// The task object is passed as argument, plus a void* pointer, containing custom data.
// For more advanced usage, we can subclass AsyncTask and override the do_task method.
AsyncTask::DoneStatus spinCameraTask(GenericAsyncTask* task, void* data)
{
	// Calculate the new position and orientation (inefficient - change me!)
	double time = globalClock->get_real_time();
	double angledegrees = time * 6.0;
	double angleradians = angledegrees * (3.14 / 180.0);
	camera.set_pos(20*sin(angleradians),-20.0*cos(angleradians),3);
	camera.set_hpr(angledegrees, 0, 0); 

	// Tell the task manager to continue this task the next frame.
	return AsyncTask::DS_cont;
}
 
int main(int argc, char *argv[])
{
	// Setup the global task manager
	taskMgr = AsyncTaskManager::get_global_ptr(); 
	// Set the global clock
	globalClock = ClockObject::get_global_clock();	

	// Load the window and set its title.
	PandaFramework framework;
    framework.open_framework(argc, argv);
    framework.set_window_title("My Panda3D Window");
    WindowFramework *window = framework.open_window();
   
	// Get the camera and store it in a variable.
    camera = window->get_camera_group();
	
 
    // Load the environment model.
    NodePath environ = window->load_model(framework.get_models(), "models/environment");
    // Reparent the model to render.
    environ.reparent_to(window->get_render());
    // Apply scale and position transforms to the model.
    environ.set_scale(0.25, 0.25, 0.25);
    environ.set_pos(-8, 42, 0);
 
    // Add our task.
    // If we specify custom data instead of NULL, it will be passed as the second argument
    // to the task function.
    taskMgr->add(new GenericAsyncTask("Spins the camera", &spinCameraTask, (void*) NULL));
 
    // Run the engine.
    framework.main_loop();
    // Shut down the engine when done.
    framework.close_framework();
    return (0);
}

The other way was this:

//includes...

// The global task manager
PT(AsyncTaskManager) taskMgr = NULL;

// The global clock
PT(ClockObject) globalClock = NULL;

//rest of code ...

Both produce crashes on this line:

framework.set_window_title("My Panda3D Window");

I have examined the python version of the page as well as the C++ and python version of the Tasks documentation page but have turned up no new clues yet.

Edit 2:

I had a thought that occurred to me that maybe the window has to load first before the task manager and clock can be initialized so I added them after the window frame creation code and this time the debugged points to the get_global_clock function.

I am not sure if these are actual results or if this is just the debugger jumping around due to code changes. I have been attempting to get a debug enabled version of Panda3D built but have yet to successfully build it in MSVS 2012.

Very odd. I just reinstalled Panda3D 1.8.1 and the tutorial works now. I wonder if the problem was that I was using MSVS 2008 for the latest build instead of MSVS 2010. Either way, the problem has been solved; even using the code posted in the OP.

Yes - this sort of crash (Particularly the one on set_window_title) is to be expected when mixing and matching different MSVC versions.