It is currently Sat Aug 22, 2020 4:29 am


All times are UTC




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Ogre World Coordinate to PolyVox Voxel Coordinate
PostPosted: Sat Apr 06, 2013 2:07 am 
User avatar

Joined: Wed Feb 06, 2013 4:06 pm
Posts: 20
I am using Ogre in combination with the LargeVolume in PolyVox and am having trouble figuring out the proper coordinate transforms to go from world to voxel coordinates and back.

In the Ogre scene manager, my LargeVolume is given a world position. Ogre is then used to scale the extracted mesh by a factor of 150 on all three axis. I am currently trying to perform a PolyVox raycast, obtain the first intersected voxel position using the LargeVolume sampler, and then place a sphere at the equivalent world position of the intersection so I can see where on the LargeVolume mesh the intersection occurred.

What is the relation between the voxel coordinates used internally in PolyVox and the Ogre world coordinates?

If there is no simple relation, then how can I know where to place my mesh at the raycast intersection?

I have tried performing the above task on a non-scaled voxel mesh to figure out the mathematical relation, but if there is one it does not appear to be a simple linear transformation of a*x + b as my intuition would suggest.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Ogre World Coordinate to PolyVox Voxel Coordinate
PostPosted: Sat Apr 06, 2013 9:13 am 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
The only relationship is the one you define yourself. PolyVox does not define any particular units for the positions and neither does Ogre (or graphics APIs in general). So the relationship between the 'volume space' and Ogre's system is just defined by the scaling and translation which you have performed.

The best approach to debugging this is probably to print out voxel positions from within the raycast callback function. That is, print out the actual positions at which it is sampling the PolyVox volume and make sure that these are the expected positions within the volume. This will also help you notice if something strange is happening such as the ray stopping after only one step due to a bad condition or something.

But I should warn you that I've never actually tried applying transformations to the volumes so there could be something I'm overlooking. I will need to do it in the future though.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Ogre World Coordinate to PolyVox Voxel Coordinate
PostPosted: Sat Apr 06, 2013 10:47 pm 
User avatar

Joined: Wed Feb 06, 2013 4:06 pm
Posts: 20
I probably should have mentioned that I am using Marching Cubes for smooth surface extraction and hence my voxel density values range continuously between [0, 255]. Looking over the Raycast source code, it appears raycasting currently only behaves as expected for binary voxel densities.

If that is the case, I seem better off doing raycasting on the mesh rather than the volume. Unless there is an efficient way to raycast on smooth voxel density distributions? I can see how this would be tricky. Assuming my understanding is correct, it would require looking at neighbors of every sampled voxel to determine if Marching Cubes would have generated a mesh there. I would think that wouldn't be too bad if the LargeVolume Sampler does not cause any paging, but I would need to look deeper into the source.

David Williams wrote:
...the relationship between the 'volume space' and Ogre's system is just defined by the scaling and translation which you have performed.

That is what I thought. I assumed that without translation or scaling, there should be a default 1:1 correspondence between Ogre and PolyVox coordinates. The linear transform between coordinates should then be:

scale * (coordinate vector) + translation vector

but I was confused because even without translation and scaling there appeared to be no 1:1 correspondence since the raycast would 'halt' quite a ways before the smooth Marching Cubes generated mesh. Now I know it is simply due to a limitation of the PolyVox raycast method.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Ogre World Coordinate to PolyVox Voxel Coordinate
PostPosted: Sun Apr 07, 2013 1:47 pm 
Developer
User avatar

Joined: Sun May 04, 2008 6:35 pm
Posts: 1827
Yes, it makes a big difference that it is a smooth voxel field for the reasons you describe. However, raycasting such a field is quite straightforward with a naive approach. You basically take tiny steps along the ray and, for each position, you compute the interpolated position from the eight surrounding voxels. Here is some code from Cubiquity that does it:

Code:
// Note: This function is not implemented in a very efficient manner and it rather slow.
// A better implementation should make use of the 'peek' functions to sample the voxel data,
// but this will require careful handling of the cases when the ray is outside the volume.
// It could also compute entry and exit points to avoid having to test every step for whether
// it is still inside the volume.
// Also, should we handle computing the exact intersection point? Repeatedly bisect the last
// two points, of perform interpolation between them? Maybe user code could perform such interpolation?
template<typename VolumeType, typename Callback>
::PolyVox::RaycastResult smoothRaycastWithDirection(VolumeType* polyVoxVolume, const Vector3F& v3dStart, const Vector3F& v3dDirectionAndLength, Callback& callback, float fStepSize = 1.0f)
{      
    POLYVOX_ASSERT(fStepSize > 0.0f, "Raycast step size must be greater than zero");
    uint32_t mMaxNoOfSteps = static_cast<uint32_t>(v3dDirectionAndLength.length() / fStepSize);

    Vector3F v3dPos = v3dStart;
    const Vector3F v3dStep =  v3dDirectionAndLength / static_cast<float>(mMaxNoOfSteps);

    for(uint32_t ct = 0; ct < mMaxNoOfSteps; ct++)
    {
        float fPosX = v3dPos.getX();
        float fPosY = v3dPos.getY();
        float fPosZ = v3dPos.getZ();

        float fFloorX = floor(fPosX);
        float fFloorY = floor(fPosY);
        float fFloorZ = floor(fPosZ);

        float fInterpX = fPosX - fFloorX;
        float fInterpY = fPosY - fFloorY;
        float fInterpZ = fPosZ - fFloorZ;

        // Conditional logic required to round negative floats correctly
        int32_t iX = static_cast<int32_t>(fFloorX > 0.0f ? fFloorX + 0.5f : fFloorX - 0.5f);
        int32_t iY = static_cast<int32_t>(fFloorY > 0.0f ? fFloorY + 0.5f : fFloorY - 0.5f);
        int32_t iZ = static_cast<int32_t>(fFloorZ > 0.0f ? fFloorZ + 0.5f : fFloorZ - 0.5f);

        const typename VolumeType::VoxelType& voxel000 = polyVoxVolume->getVoxelAt(iX, iY, iZ);
        const typename VolumeType::VoxelType& voxel001 = polyVoxVolume->getVoxelAt(iX, iY, iZ + 1);
        const typename VolumeType::VoxelType& voxel010 = polyVoxVolume->getVoxelAt(iX, iY + 1, iZ);
        const typename VolumeType::VoxelType& voxel011 = polyVoxVolume->getVoxelAt(iX, iY + 1, iZ + 1);
        const typename VolumeType::VoxelType& voxel100 = polyVoxVolume->getVoxelAt(iX + 1, iY, iZ);
        const typename VolumeType::VoxelType& voxel101 = polyVoxVolume->getVoxelAt(iX + 1, iY, iZ + 1);
        const typename VolumeType::VoxelType& voxel110 = polyVoxVolume->getVoxelAt(iX + 1, iY + 1, iZ);
        const typename VolumeType::VoxelType& voxel111 = polyVoxVolume->getVoxelAt(iX + 1, iY + 1, iZ + 1);

        typename VolumeType::VoxelType tInterpolatedValue = ::PolyVox::trilerp(voxel000,voxel100,voxel010,voxel110,voxel001,voxel101,voxel011,voxel111,fInterpX,fInterpY,fInterpZ);
   
        if(!callback(v3dPos, tInterpolatedValue))
        {
            return ::PolyVox::RaycastResults::Interupted;
        }

        v3dPos += v3dStep;
    }

    return ::PolyVox::RaycastResults::Completed;
}


It might only work with the 'develop' branch of PolyVox but it should at least give you some idea of the approach. And something like this should eventually be merged into PolyVox of course.


Top
Offline Profile  
Reply with quote  
 Post subject: Re: Ogre World Coordinate to PolyVox Voxel Coordinate
PostPosted: Tue Apr 16, 2013 5:42 am 
User avatar

Joined: Sun Apr 14, 2013 12:47 am
Posts: 30
Location: Northern Tablelands, NSW, Australia
@holocronweaver:

I'm pretty sure it makes no difference with positions, but just remember that with rotations, you cannot simply use a 1:1 relationship. However since you are, as far as I can see, only working with positions it should all work fine.

So my post is basically useless. -__-

Clonkex


Top
Offline Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

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