namrog84
I am trying to generate some structures via code in unreal engine.  Perhaps roughly to that of the LSystem the VS has, but trying to do it in UE4. 

For a simple scenario, Imagine a blocky world and I want to build the floor,  perhaps 10x10x1 cubes.  I know I could technically StampBlock of that exact size, but this is a simplified example.  Imagine a slightly more irregular shape. or perhaps want to make a checkerboard of materials?

So right now I can try to do a 2x for loop and stamp a 1x1x1 block in the 100 different places, but because for me to use SetLoS and StampBlock each time, I run into some weird issues.  First, I'd have to do some kind of 3d printer approach to make sure the new block is being added via the right camera loc and direction "printer") because LoS and StampBlock depends upon an existing block to be placed there and a proper LoS. This feels hackish instead of somehow setting voxel directly??  I think this might be doable via CellFactory or some Celldata value somewhere?  Perhaps I've messed up on searching forums or tutorials?

I feel like I should be using another mechanism for this somehow.  Either setting some voxel data directly, or generating some kind of temp voxel volume to be submitted to VF directly, instead of queueing up thousands of StampTasks for a small building. 

Having a function API call similar to that of IVoxelLayer is ideally what I'm looking for, but in the 'user edited' environment? 

Any suggestions or ideas on this would be great. I am hoping I just missed something super obvious. 
0 0
Kovak
I implemented a direct version of stamping a block inside the AVoxelFarmWorldActor, I was using it to do RPC for stamping blocks from client to server but it sounds like it might help for your use case as well.


void AVoxelFarmWorldActor::StampBlockDirect(const FVoxelFarmCellId& cellId, const FVector& voxelPos, const FVector& outsideDirection,
  const FVector& size, const FVector& physicsCheckSize, const int material)
{
  if (vfCellFactory && vfWorld)
  {
    
    VoxelFarm::CellId rCellId = VoxelFarm:😋ackCellId(cellId.Level, cellId.X, cellId.Y, cellId.Z);
    UE_LOG(LogTemp, Warning, TEXT("In stamp block direct %s, %s, %s, %d, %d"), *cellId.ToString(), *voxelPos.ToString(), *outsideDirection.ToString(), material, rCellId);
    UVoxelFarmCellFactory::StampQO* sqo = new UVoxelFarmCellFactory::StampQO();
    if (material == 0)
    {
      sqo->stampType = UVoxelFarmCellFactory::StampQO::BLOCK_REMOVE;
    }
    else
    {
      sqo->stampType = UVoxelFarmCellFactory::StampQO::BLOCK_ADD;
    }
    sqo->physicsScanRatio = physicsCheckSize;
    sqo->buildMaterial = material;
    sqo->buildSizes[0] = (int)size.X;
    sqo->buildSizes[1] = (int)size.Z;
    sqo->buildSizes[2] = (int)size.Y;
    sqo->hitID = rCellId;
    sqo->hitVoxel[0] = (int)voxelPos.X;
    sqo->hitVoxel[1] = (int)voxelPos.Y;
    sqo->hitVoxel[2] = (int)voxelPos.Z;
    sqo->hitHint[0] = outsideDirection.X;
    sqo->hitHint[1] = outsideDirection.Y;
    sqo->hitHint[2] = outsideDirection.Z;
    vfCellFactory->StampMesh(sqo);
  }
}
0 0
namrog84
FVoxelFarmCellId isn't an existing struct. I am assuming you just made VoxelFarm::CellId copy for UE4 compatability with UStruct(BlueprintType) for purposes of feeding a value in?
0 0
Kovak
Oh yeah sorry that is a structure I made to expose the CellId to blueprints (since they dont have int64s) you can see more on that here: http://cyboreal.online/voxel-farm-unreal-4-material-harvesting-rates.html
0 0
namrog84
Thanks!
So I was able to resolve and understand everything for the most part and got it working.



However, the timing makes this a non viable approach going forward for me. Because each block is queued as an individual task, there is just too much of a queue/overhead with having more than 1-2 blocks.  I think for this to work, I might need to refactor the Cellfactory a bit, in a way to queue up multiple stamps inside a single 'queued' modify, not sure the ramifications though. 

I think I'm going to need to craft a mesh procedural and then try stamping the mesh as a complete procedural generated object. Since it doesn't look like there is enough exposed functionality to modify voxel data directly in the way that I want right now.  Or at least that I have figured out how. 
Unless you have any nifty ideas of how to improve this queuing of each block?  


Bonus for future people:
For those curious, I just made a simple 2x for loop, with offsetting the VoxelPos generated by InfoAtLineOfSight based upon the index of for loops, and then calling StampBlockDirect with this individual VoxelPos.  In a more sophisticated case, this would need to take into account the voxel pos(0-40 voxel per axis) per chunk (cell), and need to adjust the cellID to account for this.

For Kovak's approach and reminder for those still learning
* CellID is essentially the chunk identifier including Level of Detail and x,y,z position (this cell or chunk encapsulates 40x40x40 voxels) (This was acquired through his provided InfoAtLineOfSight function) 

* Inside the cell, we have the VoxelPosition this is an integer indicating the index of each of these in the cell.  (Provided by previously mentioned function, and then offset by index to my choosing) 

* Outside Direction is the desired placement hint, if you don't want to place inside an object given your VoxelPosition.  If you leave this at 0,0,0 then each subsequent block would be placed in the same location if given the same VoxelPosition. Either you need to modify the VoxelPosition and/or CellID to not place 2 voxels in same place, or you need to choose a outside direction. This gives it a hint to allow VoxelFarm to a particular direction as if not to intersect with the actual given voxel.  So if you chose x=0,y=1,z=0,  if your desired location is already occupied, it will place it 1 unit above it.
0 0
namrog84
Looking more closely at the less exposed API, I found what I ultimately think i needed/wanted.

Inside the ClipmapView.h there are some functions called stampVoxels, it allows you to give it an block of voxels (in my case my stairs) and the material.

The simplest way I got it to work was by adding a new UVoxelFarmCellFactory::StampQO::BLOCK_ADD_STAIRS type.
So that I could set the SQO blocktype in the StampBlockDirect, and then in the VoxelFarmCellFactory I could add a new case for my particular set that I wanted. 


I have been having some unrelated issues with setting the data correctly, but I got enough of it to fundamentally work and believe it it should function as I want with some more effort.

I will post something later on when its bug free.
0 0