PolyVox (voxel mesh extraction) integration

I need to get 500k~750k voxels into Panda, and there’s no existing voxel library, so I was going to wrap the free PolyVox library.

My plan is to create a VoxelNode which subclasses GeomNode (or is there a better node?) and automatically populates the GeomNode’s Geom with the mesh from its voxel array. The only catch is that I have zero idea how to work with Panda’s C++ side and the panda/src/skel code is pretty mystifying to me. Is there some other documentation out there?

~ C.

Hi, I am the author of that library and was notified of this thread by Google Alerts. While I can’t really help with the Panda specific aspects of the integration, I just wanted to say it would be great to see other Open Source engines using/wrapping/integrating my work.

For those who do know Panda, I can tell you that Polyvox simply provides index/vertex buffers containing the triangle data. You should be able to inject this into one of your own classes quite easily.

To the OP, do ask if you have any problems/issues with PolyVox. For example I can add in VS2005/2008 support if you need it. And i’ll be interested in your experiences as i’m always keen to improve the library.

To answer the OP, subclassing GeomNode sounds like a fine approach, though it might be better to subclass PandaNode and override cull_callback(), similar to the way that TextNode and CollisionNode create visible geometry out of thin air. You’ll also have to create a reasonable bounding volume for your node, so it won’t get culled automatically.

Copying the vertex and index buffers from a third-party library into Panda’s GeomVertexArrayData and GeomPrimitive structures should be straightforward. Does the data change every frame, or is it static? It might make sense to implement a caching mechanism of some kind to minimize redundant copying, but this depends on the nature of the incoming data.

Most of the documentation for the C++ structures is found in the manual (at a high level), and in the code itself (at a lower level). There are some sample programs scattered throughout the forums. There are a few coding conventions you have to learn to use Panda effectively, most importantly the rule about reference-counting and PT(objecttype), but otherwise it should be fairly straightforward.


I figure I shouldn’t be totally silent.

I got the basic subclassed node built. Had to kind of divine the meaning of a few things.

*.I files are meant for inlined methods in header files, I guess?

_type_handle was kind of interesting. I ended up copying what other files did, only initing the types for parent classes. Inheriting only from PandaNode makes that easier. I still get this when importing, though:

interrogatedb(warning): Class PolyvoxNode has a zero TypeHandle value; check that init_type() is called.

The build system’s interesting. Touching Sources.pp appears to not matter when doing makepanda? Is there a clean way to regenerate the composite C++ files? I ended up just manually touching them; I’m pretty certain that’s not right.

Also I couldn’t figure out how to create a new third-party feature or use it; I guess I can worry about that later.

Now to go learn about cull_callback() and start making geometry!

Right, the .I files are included from the .h files and contain the inlined methods.

As for the warning: you need to make sure that init_type() is called when the library is loaded. Usually, this is done in the init function in config_xyz.cxx.

Sources.pp is only used by ppremake. You do need to manually edit the composite files, we don’t have a system to automatically generate them.

I’ve hit a bit of a wall.

    *** Error in polyvoxNode.h near line 42, column 1:
    Symbol PolyVox is not a known scope in ::PolyvoxNode
    *** Error in polyvoxNode.h near line 42, column 1:
    syntax error, unexpected IDENTIFIER, expecting '{' or ';' or ':' or '='

The offending line is almost certainly this:
PolyVox::UInt16Volume volume;

It looks like the second-stage parser doesn’t really like external namespaces. What’s the accepted solution?

My C++ is rustier than I thought. Oh well.

It rather seems that it doesn’t know what that is, because hasn’t seen a declaration of it yet. Perhaps it failed to include a header file before? Try running interrogate with the -v flag to get debug output.

Okay, so I’ve found the “problem.” PolyVox would like cstdint, but Panda doesn’t do that whole C++0x thing. Should I go change PolyVox to use stdint.h instead, or is there another option?

Also sorry for taking forever to reply again, Real Life and Paid Work kind of ganged up on me, as they are wont to do. :T

Sure, you don’t need to ask interrogate to parse the PolyVox headers. In general, we don’t usually try to make interrogate read through third-party headers; instead, we shadow the third-party header files with a dummy header file in dtool/src/parser-inc (which gets copied into includes/parser-inc by ppremake).

The idea is to just stub declare each of the required typenames in the dummy header file, so that interrogate knows which types are defined in PolyVox that you might be making use of in your own code. You can see the existing dummy header files for examples.

The header files in parser-inc are read by interrogate, but not by the actual compiler.


Just a few points - forgive my lack of knowledge of Panda. As you’ve noticed, PolyVox uses C++0x but actually the 0x part is fairly minimal - it uses the for the fixed size integers and shared_ptr for some of the memory management. Beyond that it’s regular C++.

I believe Panda is written in C++ but with most of its functionality exposed through Python? Is ‘interrogate’ the tool for exposing this functionality? If so, I would imagine that the PolyVox functions do not need to to be directly exposed. More likely you only call them from internal C++ code to generate the mesh, and then provide your own slightly higher level interface to add or remove voxels to your node. Really, PolyVox will just be an implementation detail.

I prepped some parser-inc headers, and they work just fine. However, I discovered two things:

  1. Panda cannot be built with C++0x. I ran into two separate bugs trying to make it happen, so I’m not going to pursue that route.

  2. PolyvoxNode cannot be built without C++0x, because the PolyVox headers #include and use std::shared_ptr.

Is there a way to specify compiler flags for just one section of code? If I could compile just pgraph this way, I’d be set. The next best thing, unfortunately, is probably to mod the PolyVox headers, and honestly, if I have to do that, I’d rather just go build Cython bindings instead and incur a small penalty when transferring meshes out of PolyVox and into Panda.

Hmm, it sounds problematic. Even if you compile only pgraph, it means you are actually compiling everything that pgraph includes with this compiler flag. And anything that includes pgraph may need to have this same compiler setting.

In general, it is possible to set a custom compiler flag for pgraph only, but it may or may not be what you’re actually looking for. One cheesy way to do this is to put the following line in pgraph/Sources.pp:

#define CFLAGS $[CFLAGS] my-additional-opts

There are better ways if this actually turns out to work.


So I’ve made some Cython bindings. Not complete, but nearly complete enough to extract meshes.

I found a fun PolyVox quirk. Apparently, even though Volumes specialized on integers and floats are legal, they can’t be used with SurfaceExtractor because SurfaceExtractor can’t be specialized on anything but MaterialDensity types.

Anyway, I’ll post again when I have the whole shebang working.

I agree this is a little weird and needs tidying up. It’s just the way it’s evolved over time - the MaterialDensity class was added recently so that the surface extractor could consider both the material and the density when extracting the surface. It’s templatised, and if you only have for example a density then you can just return a constant for the material.

The MaterialDensity class should probably just be called ‘Voxel’, and a Volume should probably always contain those. I used to abuse the Volume class for storing other things like pointers but I’ve since added the multidimensional Array class which is more appropriate for that.

Basically, it’s constantly evolving :slight_smile:

p.s. I committed a change/hack so that PolyVox will build without C++0x, but you’ll need Boost present for the boost::shared_ptr class.


I would like to know if there is any progress in getting PolyVox to work with Panda3D :slight_smile: I want to use PolyVox for my Bachelor Project (a stone carving game), and switched recently from Ogre3D to Panda3D. I tried to wrap some functionality of PolyVox with Boost.Python, but beause of my rusty C++ knowledge there are some obstacles i was not able to overcome.