It is currently Sat Aug 22, 2020 5:01 am


All times are UTC




Post new topic Reply to topic  [ 31 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject: Re: Changes to basic voxel types
PostPosted: Sat Feb 18, 2012 1:25 pm 
User avatar

Joined: Wed Jan 26, 2011 3:20 pm
Posts: 203
Location: Germany
I have a question... how will the CubicSurfaceExtractor decide which direction the quad should be visible from?
I mean, i will want to create a surface from glas to air, that is only visible from the air direction.
but I will also want to create a surface air/water that is visible from air to water AND from water to air...
will isQuadNeeded always be called twice for each quad, swapping the material arguments?


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Changes to basic voxel types
PostPosted: Sun Feb 19, 2012 8:59 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
I hadn't really considered this, but I agree we should allow for this scenario. I think calling the 'isQuadNeeded()' function twice will be a good solution, but I'll think about it more carefully when I get there.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Changes to basic voxel types
PostPosted: Wed Mar 14, 2012 2:47 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
Ok, I'm still on this. Lot's of distractions from Voxeliens (nearly finished!) but it is creeping forward.

David Williams wrote:
...PolyVox would include 'asDensity()' functions for all the primitive types, and actually this concept can still work with the Density/Material classes because asDensity() could just call through to 'getDensity()' for that type...
.
.
.
...where 'isQuadNeeded()' is a free function in the same way as 'asDensity()'. Again, PolyVox would provide a version of this function for built in types, and users could provide their own version for their own types...
.
.
.
...I may be able to provide default implementations of these funtions via template functions, and then users could override then via specialization... but I'm not really sure about this yet. I'll have to see how it goes.


I'm now thinking that this approach does not provide enough flexibility. If we consider the Raycast class (which needs to determine whether a given voxel is solid) then there are a couple of different criteria we could use. If it was a visibility raycast then it would probably want to consider transparent voxels as 'passable', whereas if it was a collision detection raycast it would want to consider them as 'blocking'.

Asking the user to provide free functions with a given name is not a good solution here, because they can only specify one behaviour for the function.

I think it makes sense to use a more flexible call back meshanism, so that when the user builds the Raycast they can specify the callback to use. I've spent some time profiling the various options and have basically found that C++ function objects (as used by std::sort(), etc) are flexible, get inlined effectively, and have no performance penalty.

However, PolyVox algorithms are implemented as classes rather than functions (this is a decision which needs to be questioned in the future) and this actually makes functions objects rather messy to use. Therefore, for the time being I suggest using std::function as the callback mechanism.

The only catch is that std::function does have a measurable performance penalty. For example, I performed 1000000 raycasts in 4 seconds using the function objects but it took 6 seconds using the std::function callback. However, keep in mind that the Raycast spends nearly all its time calling the callback as there is very little other logic in it. I expect the performance difference to be less for other algorithms but have yet to mesure it.

In summary: I expect to use std::function for the callback mechanism in the next version of PolyVox, but I will may well switch to function objects in the future.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Changes to basic voxel types
PostPosted: Wed Mar 14, 2012 7:34 pm 

Joined: Wed Apr 27, 2011 7:10 am
Posts: 43
David Williams wrote:

The only catch is that std::function does have a measurable performance penalty. For example, I performed 1000000 raycasts in 4 seconds using the function objects but it took 6 seconds using the std::function callback. However, keep in mind that the Raycast spends nearly all its time calling the callback as there is very little other logic in it. I expect the performance difference to be less for other algorithms but have yet to mesure it.


I haven't been following the entire conversation but I can give some insight into function-objects. boost::function (std::function) has a virtual function call underneath, so it is far more difficult to inline. std/boost::bind does not have this problem, but it is hard to store a result of boost::bind. To store boost::bind, you must either use auto, or boost::function. And if you need to store it in a generic way that can take any function with that signature, or need to store it in a class where the type must be known explicitly, boost::function can store a boost::bind result.

However, accepting stl-like function objects (function-object as a template) can take any type of object that has operator(), and this includes actual functions, stl function-objects, and std::function. The downside is that the actual template object that represents the function can be quite complicated in some cases do to the fact that these functions are sometimes composed (for example using std/boost::bind). Thus, it is best if these templates can be implicit (like an implicit template in a function parameter). If it must be a class-template (the algorithm is used class-wide), then the class should preferable have a shortcut creation function (like std::make_pair or std/boost::bind is), which also means it is hard to store (which is one of the points of using "auto").

If you look at the code I wrote for TVA, I use stl-like function-objects extensively, at the expense of some verbosity.

_________________
irc://irc.freenode.net/#polyvox


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Changes to basic voxel types
PostPosted: Thu Mar 15, 2012 10:55 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
realazthat wrote:
...but it is hard to store a result of boost::bind. To store boost::bind, you must either use auto, or boost::function. And if you need to store it in a generic way that can take any function with that signature, or need to store it in a class where the type must be known explicitly, boost::function can store a boost::bind result.


At the moment the function does need to be stored, because it is specified during class creation but not used until the 'execute()' function is called. This is one example of where the seperation between 'construction' and 'execute()' is problematic in PolyVox. If the algorithms were simple free function such as 'performRaycast()' and 'extractSurface()' then I don't think there would be a need to store it.

realazthat wrote:
...If it must be a class-template (the algorithm is used class-wide), then the class should preferable have a shortcut creation function (like std::make_pair or std/boost::bind is), which also means it is hard to store (which is one of the points of using "auto").


I only recently discovered that when instantiating a templatized class you always need to specify the types of the template parameters, whereas when using a templatized function the type of the template parameters can often be deduced (leading to simpler code for the user). As far as I can tell, this is why functions such as 'make_pair' exist. 'make_pair' can deduce the types of it's arguments, whereas the 'pair' class cannot.

This is a second example of why it can be problematic to represent algorithms as classes.

In your work with a TVA extractor, have you found that this representation is useful? Did you implement your algorithm as a class (like the existing SurfaceExtractor) or just as a free function which takes a volume as a parameter? I don't really remember why it was done that way and there may not have been a good reason. However, replacing the algorithm classes with free functions is not something I want to do at the moment, just because it is a large and breaking change. It will be strongly considered in the future though.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Changes to basic voxel types
PostPosted: Thu Mar 15, 2012 1:47 pm 

Joined: Wed Apr 27, 2011 7:10 am
Posts: 43
David Williams wrote:
In your work with a TVA extractor, have you found that this representation is useful? Did you implement your algorithm as a class (like the existing SurfaceExtractor) or just as a free function which takes a volume as a parameter? I don't really remember why it was done that way and there may not have been a good reason. However, replacing the algorithm classes with free functions is not something I want to do at the moment, just because it is a large and breaking change. It will be strongly considered in the future though.


The tva surface_extractor is implemented as a class, *and* the execute is templatized. The class takes a "traits" template which defines generally generic types and class-static functions which define some types (density_type for example), and policies (for example, I managed to abstract material selection, interpolation, and normalization to the traits). Then execute() is static, and takes some more template paramaters such as "VertexOutputIterator" vertices, "IndexOutputIterator" indices, "deck_range_t" deck_range. So, instead of dumping vertices into a SurfaceMesh, I decided to be more generic and use the OutputIterator concept from stl. The reason I did this was because boost provides make_function_output_iterator() which can take a function object and turn it into an output-iterator concept. This allows the user to specify *exactly* what they want to do with the vertices; they can just count it, they can insert it into a surface mesh, or use the stl-provided std::back_inserter to push_back() into any object, or they can make their own function-object that does any combination of these or anything else, or even write their own structure that matches the OutputIterator concept directly.

The "deck_range_t" is the variable that my extractor uses to obtain voxel/cell data, and is a special concept I define and provide an implementation for polyvox volumes for (it is not a function object and another subject).

Internally, I have useful functions such as extract_cell_triangles() which takes a "cell" and a function-object called "for_each_triangle". For every triangle it finds in the cell, it will call the callback for_each_triangle. This is not exposed to the user for now though.

In general the reason there is a "traits" and template functions is that I put types and functionality into traits that shouldn't be changing from one extraction to the next, while execute() takes very specific one-time-use types like output iterators.

The genericity allows me to make a PolyVox specialization that exactly matches the PolyVox API where applicable (for the SurfaceExtractor for example). This means that I can probably make a competing version of the Marching Cubes SurfaceExtractor (leaving aside the transition_extractor entirely), and in fact, in an old refactor I had this. Currently, in the demo, the transition extraction and scene management (octree etc.) is complex enough that I think it best just to force/leave/expose the output-iterator interface.

_________________
irc://irc.freenode.net/#polyvox


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Changes to basic voxel types
PostPosted: Fri May 18, 2012 1:33 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
I thought I should drop in and update this thread as things have been so quiet recently. I did a blog post about the remaining tasks on Voxeliens, and this is basically what is holding up progress on PolyVox. Not enough hours in the day...

However, I did want to say that I added the 'isQuadNeeded()' callback to the CubicSurfaceExtractorWithNormals (as discussed earlier in this thread) and in principle this is what will make transparent voxels possible. Using this callback the user can have a lot more control over whether a quad in generated between any two voxels. It's not really tested though, as we need to also add transparency support in our rendering code.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Changes to basic voxel types
PostPosted: Wed Jul 11, 2012 3:48 pm 

Joined: Sun Oct 03, 2010 10:13 pm
Posts: 73
Hi there! Yes I'm still alive and kicking ;)
Can you elaborate a bit more on the isQuadNeeded function? Does it already work? Can you give a small code example how it works and how to use it? I guess it can only be found in the current Git version of PolyVox. Do you intend to release another stable release anytime soon?

BTW, don't think I said it before, so congratulations on releasing Voxeliens! Do you plan to talk about the game sales some day in the future? ;)


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Changes to basic voxel types
PostPosted: Wed Jul 11, 2012 9:28 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
As I recall it is already implemented for CubicSurfaceExtractorWithNormals but not the regular CubicSurfaceExtractor (you could just ignore the normals if you don't want them). Yes, it's only in Git and you will find a function called 'defaultIsQuadNeeded'. You can make a copy of this function with a different name, change the logic, and pass it as the last parameter to the CubicSurfaceExtractorWithNormals constructor.

It's not well tested and the interface will probably change (to use a function object like std::sort rather than an std::function) but the idea will remain the same. I'll be interested in whether it works for you. And yes, we'll push out a new stable release as soon as we can. See this blog post if you missed it.

AndiNo wrote:
BTW, don't think I said it before, so congratulations on releasing Voxeliens! Do you plan to talk about the game sales some day in the future?


Thanks! We've been showing it off at the Develop Conference today and people seem to like it. But it's too early to talk much about sales because we still have a lot of distribution options which we need to set up. E.g. we need to apply to Desura, Steam, IndieCity, etc and then allow some time to see how each one performs. It's amazing how much work is required after the game is supposedly finished! This is something we weren't quite expecting.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Changes to basic voxel types
PostPosted: Wed Jul 11, 2012 10:41 pm 

Joined: Sun Oct 03, 2010 10:13 pm
Posts: 73
Thanks for your answer! :)
At the moment I'm using the CubicSurfaceExtractorWithNormals anyway to get correct lighting with the voxels, so that's not a problem. I'll see if I can get it working within the next days. You know, PolyVox' documentation might not be the best, but with you around this never seems to be a big deal ;)

About Voxeliens: I understand that it's too early to talk about such statistics. However it seems you would be able to write some kind of post-mortem with all the experiences you made while developing and releasing it. It would surely be interesting for me IF I ever finish my game. :)


Top
Offline Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 31 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Theme created StylerBB.net