January 2018 Development Update

The new year has brought with it new developments to the Panda3D engine, some of which we would like to present to you today. This is however by no means a comprehensive listing of the improvements we’re working on. Stay tuned for more posts, as we’ve got some exciting plans for 2018 ahead!

RenderPipeline light system

The light manager of Tobias Springer’s excellent RenderPipeline project has made its way into the Panda3D codebase. This is a light system designed to be used in conjunction with the GPU light culling and deferred rendering methods provided by the RenderPipeline, and is implemented in C++ for optimal performance. Now that it is included with Panda3D, it is even easier to use the RenderPipeline in your projects as it is no longer necessary to compile any C++ modules to do so—you now simply put the Python module into your project and follow the usual steps from there on out.

This feature is mainly useful from a RenderPipeline setup, but we are continuing to work on bringing the built-in lighting system more closely in line with the RenderPipeline lights. Examples of this are additional light types such as sphere and rectangle area lights and the possibility to set a light’s color temperature.

Input device support

The input-overhaul branch has received plenty of changes again and is day by day getting closer to a state where it can be merged into the master branch. The latest improvements include more devices being supported as well as overall improved handling and mapping of devices’ buttons and axes, such as for joysticks. For Windows users, there is also a new input manager available based on the Windows raw input system, which is used for devices that are not supported under the existing XInput implementation. Panda3D automatically chooses the right implementation to use for a device, so this all happens seamlessly to the developer.

Support for 3D mice has also been added. This is a class of devices that allow movement in six degrees of freedom (thrice as many as a regular mouse), and is particularly used by 3D artists for intuitively navigating a camera around a model or through a scene. This may be of particular use for the various CAD programs that are built around Panda3D.

Android developments

Android support is actively being worked on and great strides have already been made in this area. Stay tuned for the next post, in which we will have some exciting announcements to make on this front!


December 2017 Development Update

Hello everyone to our heavily delayed December post. Even though we’re quite late with this one due to lack of time, we wish you all a happy new year! Much has happened during the winter holidays, so read on to see what’s new.

What happened in the last month

The work on the input overhaul branch is almost complete and needs some more polish to finalize the API before we will merge it into the development trunk. In addition, we started to add a mapping table for known devices to have them work as expected. For other devices, the mapping is provided by the device driver with the help of some heuristics to detect the device type. Currently the input overhaul is still in heavy development and API changes will occur, though for those who are interested in testing it, sample applications are available and some manual entries with more or less accurate instructions have been created and will be finalized as soon as the API is stable.

Some long-standing bugs with the multithreaded pipeline were finally resolved. These issues caused deadlocks that occurred whenever geometry data was being manipulated on another thread, or when shadows were enabled using the automatic shader generator; as such, they were a significant barrier that prevented the multithreaded pipeline from being useful for some applications. However, more testing is needed before we can be completely confident that all the threading issues are resolved.

On macOS, it is now possible to get an offscreen rendering buffer without opening a window. This lets you render to a buffer on a headless mac server, which can be useful for plenty of things. Aside from scientific simulations where no immediate output is necessary or even desirable, another example is to send a frame rendered by Panda3D over a socket or network to display it elsewhere. This technique is used in the BlenderPanda project to render a Panda3D frame into a Blender viewport and thereby get a live display of how a model will look when used with the engine.

Looking into the crystal ball

In the coming months some of the newly developed features (input-overhaul, deploy-ng) will be polished off and merged into the master branch of panda3d. More work is also planned on the introduction of a new physically-based material model as well as support for the glTF 2.0 format. Stay tuned for more updates!


November 2017 Development Update

Hello and welcome to our first official informative post in this series of Panda3D development blog posts. We’ll showcase newly added features as well as behind-the-scenes information and other changes in November, 2017.

Note that this is just an overview highlighting a few of the bigger features that were added this month. It is by no means a comprehensive list of all the features and bugfixes that were added. For a full list of changes, check out the git commit log.

What happened in the last month

Unit testing

Panda3D got initial test coverage utilizing the mature and full-featured PyTest toolset. This means that core features of the engine will always be tested for their intended functionality and bugs in those places will be caught earlier, helping to keep the engine in an overall good and stable state. Currently there is basic test coverage for NodePath, serializability of Bullet shapes, various interrogate features and some display configurations, but we plan to add more in the future.

Coroutines and async/await

The most exciting change this month is perhaps the support for coroutines and async/await. This is a new syntax introduced in Python 3.5 to simplify asynchronous programming. It can be hard to understand at first, but the possibilities are quite interesting.

Simply put, a “coroutine” is a function that can be temporarily suspended, pending an asynchronous operation, and continued at a later time. For example, if you use a coroutine to set up your scene, you can temporarily suspend it while a model is being loaded asynchronously, so that other operations can continue without blocking the rendering loop.

Asynchronous operations were already possible in Panda using callbacks, but these get messy quite quickly when dealing with multiple operations. The async/await syntax introduced in Python 3.5 makes it significantly easier to write code that involves a series of asynchronous operations.

Here is a side-by-side example of loading a scene using the new approach. (Use of classes is omitted for brevity.) Note that coroutines need to be added to the task manager to make use of them.

# With coroutines

async def loadScene():
    text = OnscreenText("Loading…")

    # Suspend the coroutine while waiting for it to load
    scene = await loader.loadModel("scene"blocking=False)
    scene.reparentTo(render)

    text.hide()

taskMgr.add(loadScene())
# With callbacks

def loadScene():
    global text
    text = OnscreenText("Loading…")
    loader.loadModel("scene"callback=loadSceneCallback)

def loadSceneCallback(scene):
    scene.reparentTo(render)
    text.hide()

loadScene()

The way this works is that loadModel, when passing blocking=False, will schedule the load operation to happen in another thread, and immediately return a ‘future’ object. This is a special object (called a ‘promise’ in some languages) that represents an operation that is not yet complete, but will later return a result. The ‘await’ keyword is what suspends the operation of the coroutine until the future is complete. At a later time, the task manager notices that the future is done, and will resume execution of the loadScene function.

The ‘await’ keyword isn’t only supported when loading models. Any task has been made ‘awaitable’, meaning you can suspend a task waiting for another task to complete. You can also ‘await’ various other operations that can occur in the background. At present, that includes:

  • any task or asynchronous loader request
  • messenger.future('event') (waits for the given event to be thrown)
  • interval.start() (waits for the interval to complete)
  • win.triggerCopy() (waits for the copy operation to be complete)
  • texture.prepare() and shader.prepare() (waits for the resource to be prepared)

Coroutines need to be added to the task manager, but they can also be used as event handlers. Here is an example of an asynchronous event handler that uses ‘await’ to time how long the spacebar was held, without needing to store external state:

async def on_press_space():
    # Record the time at which the space key was pressed.
    begin = time.time()

    # Suspend the method until the space-up event is detected.
    await messenger.future("space-up")

    # Now measure how much time it took.
    duration = time.time() - begin
    print("spacebar was held for {} seconds".format(duration))

base.accept("space", on_press_space)

This is still an experimental feature, and we’d love to get your feedback on how we can further improve support for asynchronous programming in Panda3D.

Bullet physics

With the help of the community, all Bullet Physics engine shapes supported by Panda3D have now been made serializable. This means all Bullet structures can now be written to a .bam file, paving the way for future model conversion tools to implement support for Bullet physics.

Interrogate property interfaces

It has been a long-requested feature to enable property interfaces in the Python bindings, as a way to access members instead of the traditional getters and setters. This has been developed further by refining the support for sequence and mapping properties. For example, instead of the get_tag() and set_tag() methods, NodePath now also exposes its tags through a tags property that behaves like a Python dictionary, implementing many standard dictionary methods such as update() and keys(). The same applies to properties that expose collections, providing a predictable, standard and aesthetic interface to manipulate the API.

Released games section

In this section we’ll give you an overview of released and updated game titles that have been written with Panda3D

New game releases

The Traveling Fox

Updated games

Kitsunetsuki
YORG