Volumes Of Fun http://www.volumesoffun.com/phpBB3/ |
|
Ogre World Coordinate to PolyVox Voxel Coordinate http://www.volumesoffun.com/phpBB3/viewtopic.php?f=14&t=495 |
Page 1 of 1 |
Author: | holocronweaver [ Sat Apr 06, 2013 2:07 am ] |
Post subject: | Ogre World Coordinate to PolyVox Voxel Coordinate |
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. |
Author: | David Williams [ Sat Apr 06, 2013 9:13 am ] |
Post subject: | Re: Ogre World Coordinate to PolyVox Voxel Coordinate |
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. |
Author: | holocronweaver [ Sat Apr 06, 2013 10:47 pm ] |
Post subject: | Re: Ogre World Coordinate to PolyVox Voxel Coordinate |
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. |
Author: | David Williams [ Sun Apr 07, 2013 1:47 pm ] |
Post subject: | Re: Ogre World Coordinate to PolyVox Voxel Coordinate |
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. |
Author: | Clonkex [ Tue Apr 16, 2013 5:42 am ] |
Post subject: | Re: Ogre World Coordinate to PolyVox Voxel Coordinate |
@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 |
Page 1 of 1 | All times are UTC |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |