1.10.8. Get tile

This request returns direct access to the LDM tile containing the specified voxel. In addition to the resolution parameter, this request takes an SbVec3i32 SbVec3i32 specifying the IJK position of a voxel in the volume. Unlike other requests, get tile does not have a subvolume parameter. More importantly, this request does not copy any data. It provides read-only access to the data managed by LDM. This is very efficient for algorithms that can work on a single tile of data. It can also be efficient for getting the value of a single voxel.

If the requested tile is on a face of the volume, it may not be a complete tile.

The request returns a DataInfo struct containing:

  • errorFlag – Set to CORRECT if the request succeeded.

  • bufferSize – Set to the required buffer size in bytes.

  • bufferDimension – Set to the dimensions (SbVec3i32) of the buffer in voxels.

The data type is not included in this struct, but can be queried from the volume data node as shown in a previous section.

The following example shows how to access the full resolution data tile containing the voxel at position 63,0,0. In this example the volume contains unsigned integer data. The bufferSize returned will be 1,048,576 (64**3 times 4 bytes per value) and the bufferDimension will be [64,64,64]. As usual the example code does not show error checking. In production code the application should check the errorFlag parameter in the returned DataInfoBox DataInfoBox DataInfoBox struct.

// Voxel coordinate
SbVec3i32 voxelPos(63,0,0);
int resolution = 0;

// Call to get the data
SoLDMDataAccess& access = pVolData->getLdmDataAccess();
SoLDMDataAccess::DataInfo info = access.getData( resolution, voxelPos );

// Access the data then release the tile
unsigned int* pData = (unsigned int*)info.tileData;
unsigned int value = pData[0];
 . . .
access.releaseData( info.tileID );
// Voxel coordinate
SbVec3i32 voxelPos = new SbVec3i32(63, 0, 0);
int resolution = 0;

// Call to get the data
SoLDMDataAccess access = VolData.GetLdmDataAccess();
SoLDMDataAccess.DataInfo info = access.GetData(resolution, voxelPos);

// Access the data then release the tile
SbNativeArray<uint> data = (SbNativeArray<uint>)info.TileData;
uint value = data[0];
. . .
access.ReleaseData(info.TileID);
// Voxel coordinate
SbVec3i32 voxelPos = new SbVec3i32(63, 0, 0);
int resolution = 0;

// Call to get the data
SoLDMDataAccess access = volData.getLdmDataAccess();
SoLDMDataAccess.DataInfo info = access.getData(resolution, voxelPos);

// Access the data then release the tile
ByteBuffer buffer = info.tileData;
IntBuffer ibuffer = buffer.asIntBuffer();
int value = ibuffer.get(0);
. . .
access.releaseData(info.tileID);

Now suppose we want the value of the specific voxel whose position we passed. We have the position of the desired voxel in absolute IJK coords. From the DataInfo DataInfo DataInfo struct we can get the tile size and start corner of the tile (tilePosMin) in IJK coords, so we can compute the voxel position relative to the tile. There is one complication - the tiles on the edges of the volume are normally partial tiles, so we also have to consider the tilePosMax. Once we have the relative voxel position inside the tile we can compute the offset into the memory that contains the tile data, compute the address of the voxel value and extract that value.

// Compute voxel coordinate relative to the tile origin
SbVec3i32 tilePosMin, tilePosMax;
info.tilePosition.getBounds( tilePosMin, tilePosMax );

SbVec3i32 tileSize = info.tileDimension;
SbVec3i32 relPos;
relPos[0] = (voxelPos[0] - tilePosMin[0]) * tileSize[0] / (tilePosMax[0] - tilePosMin[0] + 1);
relPos[1] = (voxelPos[1] - tilePosMin[1]) * tileSize[1] / (tilePosMax[1] - tilePosMin[1] + 1);
relPos[2] = (voxelPos[2] - tilePosMin[2]) * tileSize[2] / (tilePosMax[2] - tilePosMin[2] + 1);

// Compute index into memory and fetch value of voxel
int64_t index = (relPos[2]*tileSize[1] + relPos[1])*tileSize[0] + relPos[0];
unsigned int* pData = ((unsigned int *)info.tileData);
unsigned int voxel = pData[index];
// Compute voxel coordinate relative to the tile origin
SbVec3i32 tilePosMin = info.TilePosition.Min;
SbVec3i32 tilePosMax = info.TilePosition.Max;
SbVec3i32 tileSize = info.TileDimension;
SbVec3i32 relPos = new SbVec3i32();
relPos.X = (voxelPos.X - tilePosMin.X) * tileSize.X / (tilePosMax.X - tilePosMin.X + 1);
relPos.Y = (voxelPos.Y - tilePosMin.Y) * tileSize.Y / (tilePosMax.Y - tilePosMin.Y + 1);
relPos.Z = (voxelPos.Z - tilePosMin.Z) * tileSize.Z / (tilePosMax.Z - tilePosMin.Z + 1);

// Compute index into memory and fetch value of voxel
int index = (relPos.Z * tileSize.Y + relPos.Y) * tileSize.X + relPos.X;
uint voxel = data[index];
// Compute voxel coordinate relative to the tile origin
SbVec3i32 tilePosMin = info.tilePosition.getMin();
SbVec3i32 tilePosMax = info.tilePosition.getMax();
SbVec3i32 tileSize   = info.tileDimension;
SbVec3i32 relPos = new SbVec3i32();
relPos.setX( (voxelPos.getX() - tilePosMin.getX()) * tileSize.getX()
             / (tilePosMax.getX() - tilePosMin.getX() + 1) );
relPos.setY( (voxelPos.getY() - tilePosMin.getY()) * tileSize.getY()
             / (tilePosMax.getY() - tilePosMin.getY() + 1) );
relPos.setZ( (voxelPos.getZ() - tilePosMin.getZ()) * tileSize.getZ()
             / (tilePosMax.getZ() - tilePosMin.getZ() + 1) );

// Compute index into memory and fetch value of voxel
int index = (relPos.getZ() * tileSize.getY() + relPos.getY()) * tileSize.getX() + relPos.getX();
int voxel = ibuffer.get(index);