I've been trying to reverse the equations for converting from world to voxel position found on another post here:


double scale = (1 lod)*CELL_SIZE; // here lod is which level of detail you would like to sample, use LOD_0 constant for highest detail
int xc = (int)(x / scale);
int yc = (int)(y / scale);
int zc = (int)(z / scale);
CellId cell = packCellId(lod, xc, yc, zc);

The voxel coordinates can be computed as:

int vx = (int)(BLOCK_DIMENSION)*(x/scale - xc)) + BLOCK_MARGIN;
int vy = (int)(BLOCK_DIMENSION)*(y/scale - yc)) + BLOCK_MARGIN;
int vz = (int)(BLOCK_DIMENSION)*(z/scale - zc)) + BLOCK_MARGIN;

I thought I did my math correctly, but I don't seem to be getting a sensible response back:

int blockD = VoxelFarm::BLOCK_DIMENSION;
  int blockM = VoxelFarm::BLOCK_MARGIN;
  int level, xc, xy, xz;
  VoxelFarm::unpackCellId(breakEvent.CellId, level, xc, xy, xz);
  double scale = level * VoxelFarm::CELL_SIZE;
  float newX = scale * (((breakEvent.X - blockM) / blockD) + xc);
  float newY = scale * (((breakEvent.Y - blockM) / blockD) + xy);
  float newZ = scale * (((breakEvent.Z - blockM) / blockD) + xz);
  return FVector(newX, newY, newZ);

Did I do my math wrong/am I missing some adjustment?
0 0
From my notes, the formula for the scale appears to be wrong, it should  be:

double scale = (1 << level) * VoxelFarm::CELL_SIZE;

Cells double in size every level, so it is (2^level)
0 0
Even with this correction, the results is vastly out of scale with the world itself, and not near the result for AVoxelFarmWorldActor::GetCellTransform. I have better success attempting to calculate the offset for the block from the CellTransform, this gets within the ballpark but still isn't quite right either:

  int blockD = VoxelFarm::BLOCK_DIMENSION;
  int level, xc, yc, zc;
  int xIndex = breakEvent.X;
  int yIndex = breakEvent.Y;
  int zIndex = breakEvent.Z;
  VoxelFarm::unpackCellId(breakEvent.CellId, level, xc, yc, zc);
  const double cellScale = (1 << level)*VoxelFarm::CELL_SIZE;  
  FVector cellT = GetCellTransform(breakEvent.CellId);
  float xOffset = ((xIndex * cellScale / blockD)) * VOX_TO_UE;
  float yOffset = ((yIndex * cellScale / blockD)) * VOX_TO_UE;
  float zOffset = ((zIndex * cellScale / blockD)) * VOX_TO_UE;
  FVector blockOffset = FVector(xOffset, yOffset, zOffset);
  return cellT + blockOffset;
0 0
Hey Everyone,

Here is the final answer to how to go from cell id and voxel pos to world pos.

//this is the number of blocks in a cell
float blockD = float(VoxelFarm::BLOCK_DIMENSION);
int level, xc, yc, zc;
VoxelFarm::unpackCellId(breakEvent.CellId, level, xc, yc, zc);
//we need to calculate the size of a cell for the level of detail
const double cellScale = (1 << level)*VoxelFarm::CELL_SIZE;
//finally we need to calculate the 'partial amount' we are through another cell this should be between 0 and 1.0, here
//my breakEvent is a structure specific to my project but X, Y, Z is the position of the voxel and SizeX,SizeY, SizeZ is the size of the
//cube being stamped into the environment. The goal here is to get the center of the stamped block in my case.
//You could replace it with just xIndex, yIndex, zIndex of voxel pos if you didn't want the center of a cube.
float xPartial = float(breakEvent.X + float(breakEvent.SizeX) / 2.0f) / blockD;
float yPartial = float(breakEvent.Y + float(breakEvent.SizeY) / 2.0f) / blockD;
float zPartial = float(breakEvent.Z + float(breakEvent.SizeZ) / 2.0f) / blockD;
//Finally, we calculate the cell position plus the partial cell position, multiply by the size of a cell, subtract the location of the
//origin and then multiply by the voxel farm to engine scaling factor.
//the key thing to note is that Z and Y coordinates are flipped for cells, but that the world origin is already correctly flipped.
float newX = float((cellScale * (xPartial + xc) - ORIGINX) * VOX_TO_UE);
float newY = float((cellScale * (zPartial + zc) - ORIGINY) * VOX_TO_UE);
float newZ = float((cellScale * (yPartial + yc) - ORIGINZ) * VOX_TO_UE);
return FVector(newX, newY, newZ);
1 0