Renderer/src/main/java/electrosphere/server/fluid/manager/ServerFluidChunk.java
austin 0e2c29d8a1
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good
explicit memory management of fluids
2024-12-01 13:07:33 -05:00

481 lines
13 KiB
Java

package electrosphere.server.fluid.manager;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import org.joml.Vector3f;
import org.joml.Vector3i;
/**
* Is a single chunk of terrain on the server
*/
public class ServerFluidChunk {
/**
* Number of adjacent arrays
*/
static final int ARRAY_CT = 27;
/**
* Index of the center buffer
*/
static final int CENTER_BUFF = 13;
/**
* Size of the true data. This is the data that is for this world position in particular
*/
public static final int TRUE_DATA_DIM = 16;
/**
* Size of the true data generator for meshing
*/
public static final int TRUE_DATA_GENERATOR_SIZE = TRUE_DATA_DIM + 1;
/**
* Number of positions to offset into the buffer before you will access the true data
*/
public static final int TRUE_DATA_OFFSET = 1;
/**
* Dimension of a fluid buffer. This includes positions that just store neighbor values
*/
public static final int BUFFER_DIM = TRUE_DATA_DIM + 2;
/**
* Size of a fluid buffer
*/
public static final int BUFFER_SIZE = ServerFluidChunk.BUFFER_DIM * ServerFluidChunk.BUFFER_DIM * ServerFluidChunk.BUFFER_DIM;
/**
* The world x coordinate of this chunk
*/
int worldX;
/**
* The world y coordinate of this chunk
*/
int worldY;
/**
* The world z coordinate of this chunk
*/
int worldZ;
/**
* The float view of the center weight buffer
*/
FloatBuffer weights;
/**
* The float view of the center velocity x buffer
*/
FloatBuffer velocityX;
/**
* The float view of the center velocity y buffer
*/
FloatBuffer velocityY;
/**
* The float view of the center velocity z buffer
*/
FloatBuffer velocityZ;
/**
* The array of all adjacent weight buffers for the fluid sim
*/
public ByteBuffer[] bWeights = new ByteBuffer[ARRAY_CT];
/**
* The array of all adjacent velocity x buffers for the fluid sim
*/
public ByteBuffer[] bVelocityX = new ByteBuffer[ARRAY_CT];
/**
* The array of all adjacent velocity y buffers for the fluid sim
*/
public ByteBuffer[] bVelocityY = new ByteBuffer[ARRAY_CT];
/**
* The array of all adjacent velocity z buffers for the fluid sim
*/
public ByteBuffer[] bVelocityZ = new ByteBuffer[ARRAY_CT];
/**
* The array of all adjacent weight buffers for the fluid sim
*/
public ByteBuffer[] b0Weights = new ByteBuffer[ARRAY_CT];
/**
* The array of all adjacent velocity x buffers for the fluid sim
*/
public ByteBuffer[] b0VelocityX = new ByteBuffer[ARRAY_CT];
/**
* The array of all adjacent velocity y buffers for the fluid sim
*/
public ByteBuffer[] b0VelocityY = new ByteBuffer[ARRAY_CT];
/**
* The array of all adjacent velocity z buffers for the fluid sim
*/
public ByteBuffer[] b0VelocityZ = new ByteBuffer[ARRAY_CT];
/**
* The chunk mask -- Stores which adjacent chunks are populated and which aren't
*/
public int chunkMask;
/**
* Tracks whether this chunk was updated or not
*/
public boolean updated = false;
/**
* The total density of the chunk
*/
public float totalDensity = 0;
/**
* Constructor
* @param worldX The world x coordinate
* @param worldY The world y coordinate
* @param worldZ The world z coordinate
*/
public ServerFluidChunk(int worldX, int worldY, int worldZ) {
this.worldX = worldX;
this.worldY = worldY;
this.worldZ = worldZ;
//allocate
this.allocate();
//order
this.bWeights[CENTER_BUFF].order(ByteOrder.LITTLE_ENDIAN);
this.bVelocityX[CENTER_BUFF].order(ByteOrder.LITTLE_ENDIAN);
this.bVelocityY[CENTER_BUFF].order(ByteOrder.LITTLE_ENDIAN);
this.bVelocityZ[CENTER_BUFF].order(ByteOrder.LITTLE_ENDIAN);
this.b0Weights[CENTER_BUFF].order(ByteOrder.LITTLE_ENDIAN);
this.b0VelocityX[CENTER_BUFF].order(ByteOrder.LITTLE_ENDIAN);
this.b0VelocityY[CENTER_BUFF].order(ByteOrder.LITTLE_ENDIAN);
this.b0VelocityZ[CENTER_BUFF].order(ByteOrder.LITTLE_ENDIAN);
//get float view
this.weights = this.bWeights[CENTER_BUFF].asFloatBuffer();
this.velocityX = this.bVelocityX[CENTER_BUFF].asFloatBuffer();
this.velocityY = this.bVelocityY[CENTER_BUFF].asFloatBuffer();
this.velocityZ = this.bVelocityZ[CENTER_BUFF].asFloatBuffer();
}
/**
* Gets the world x coordinate
* @return The world x coordinate
*/
public int getWorldX() {
return worldX;
}
/**
* Gets the world y coordinate
* @return The world y coordinate
*/
public int getWorldY() {
return worldY;
}
/**
* Gets the world z coordinate
* @return The world z coordinate
*/
public int getWorldZ() {
return worldZ;
}
/**
* Gets the world position of this terrain chunk as a joml Vector
* @return The vector
*/
public Vector3i getWorldPosition(){
return new Vector3i(worldX,worldY,worldZ);
}
/**
* Gets the weights buffer
* @return The weight buffer
*/
public FloatBuffer getWeights() {
return weights;
}
/**
* Gets the weight of a voxel at a poisiton
* @param localPosition The local position
* @return The weight of the specified voxel
*/
public float getWeight(Vector3i localPosition){
return getWeight(localPosition.x,localPosition.y,localPosition.z);
}
/**
* Gets the weight of a voxel at a poisiton
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @return The weight of the specified voxel
*/
public float getWeight(int x, int y, int z){
return weights.get(this.IX(x,y,z));
}
/**
* Sets a weight
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @param weight The weight
*/
public void setWeight(int x, int y, int z, float weight){
weights.put(this.IX(x,y,z),weight);
}
/**
* Gets the velocity x buffer
* @return The velocity x buffer
*/
public FloatBuffer getVelocityX() {
return velocityX;
}
/**
* Gets the x velocity at the point
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @return The x velocity at the point
*/
public float getVelocityX(int x, int y, int z){
return velocityX.get(this.IX(x, y, z));
}
/**
* Sets the velocity x buffer
* @param velocityX The velocity x buffer
*/
public void setVelocityX(FloatBuffer velocityX) {
this.velocityX = velocityX;
}
/**
* Sets the x velocity at the point
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @param velocity The x velocity
*/
public void setVelocityX(int x, int y, int z, float velocity){
this.velocityX.put(this.IX(x,y,z),velocity);
}
/**
* Gets the velocity y buffer
* @return The velocity y buffer
*/
public FloatBuffer getVelocityY() {
return velocityY;
}
/**
* Gets the y velocity at the point
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @return The y velocity at the point
*/
public float getVelocityY(int x, int y, int z){
return velocityY.get(this.IX(x, y, z));
}
/**
* Sets the velocity y buffer
* @param velocityY The velocity y buffer
*/
public void setVelocityY(FloatBuffer velocityY) {
this.velocityY = velocityY;
}
/**
* Sets the y velocity at the point
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @param velocity The y velocity
*/
public void setVelocityY(int x, int y, int z, float velocity){
this.velocityY.put(this.IX(x,y,z),velocity);
}
/**
* Gets the velocity z buffer
* @return The velocity z buffer
*/
public FloatBuffer getVelocityZ() {
return velocityZ;
}
/**
* Gets the z velocity at the point
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @return The z velocity at the point
*/
public float getVelocityZ(int x, int y, int z){
return velocityZ.get(this.IX(x, y, z));
}
/**
* Sets the velocity z buffer
* @param velocityZ The velocity z buffer
*/
public void setVelocityZ(FloatBuffer velocityZ) {
this.velocityZ = velocityZ;
}
/**
* Sets the z velocity at the point
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @param velocity The z velocity
*/
public void setVelocityZ(int x, int y, int z, float velocity){
this.velocityZ.put(this.IX(x,y,z),velocity);
}
/**
* Gets the velocity at a given point as a vector3f
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @return The velocity
*/
public Vector3f getVelocity(int x, int y, int z){
int index = this.IX(x,y,z);
return new Vector3f(
velocityX.get(index),
velocityY.get(index),
velocityZ.get(index)
);
}
//set a velocity at a given x, y, and z given three ints
/**
* Sets the full velocity at a given point
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @param velX The x component of the velocity
* @param velY The y component of the velocity
* @param velZ The z component of the velocity
*/
public void setVelocity(int x, int y, int z, float velX, float velY, float velZ){
int index = this.IX(x,y,z);
velocityX.put(index, velX);
velocityY.put(index, velY);
velocityZ.put(index, velZ);
}
/**
* Gets the inddex into the buffer
* @param x The x position
* @param y The y position
* @param z The z position
* @return The index
*/
public int IX(int x, int y, int z){
return x * ServerFluidChunk.BUFFER_DIM * ServerFluidChunk.BUFFER_DIM + y * ServerFluidChunk.BUFFER_DIM + z;
}
/**
* Gets the chunk mask for this chunk
* @return The chunk mask
*/
public int getChunkMask(){
return this.chunkMask;
}
/**
* Gets whether this chunk updated in its most recent frame or not
* @return true if it updated, false otherwise
*/
public boolean getUpdated(){
return updated;
}
/**
* Gets the neighbor index given an offset in each dimension
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @return The neighbor index
*/
public static final int getNeighborIndex(int x, int y, int z){
return x + y * 3 + z * 3 * 3;
}
/**
* Sets the neighbor of this chunk
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @param neighbor The neighbor ServerFluidChunk
*/
public void setNeighbor(int x, int y, int z, ServerFluidChunk neighbor){
if(neighbor == null){
bWeights[getNeighborIndex(x,y,z)] = null;
b0Weights[getNeighborIndex(x,y,z)] = null;
bVelocityX[getNeighborIndex(x,y,z)] = null;
bVelocityY[getNeighborIndex(x,y,z)] = null;
bVelocityZ[getNeighborIndex(x,y,z)] = null;
b0VelocityX[getNeighborIndex(x,y,z)] = null;
b0VelocityY[getNeighborIndex(x,y,z)] = null;
b0VelocityZ[getNeighborIndex(x,y,z)] = null;
} else {
bWeights[getNeighborIndex(x,y,z)] = neighbor.bWeights[CENTER_BUFF];
b0Weights[getNeighborIndex(x,y,z)] = neighbor.b0Weights[CENTER_BUFF];
bVelocityX[getNeighborIndex(x,y,z)] = neighbor.bVelocityX[CENTER_BUFF];
bVelocityY[getNeighborIndex(x,y,z)] = neighbor.bVelocityY[CENTER_BUFF];
bVelocityZ[getNeighborIndex(x,y,z)] = neighbor.bVelocityZ[CENTER_BUFF];
b0VelocityX[getNeighborIndex(x,y,z)] = neighbor.b0VelocityX[CENTER_BUFF];
b0VelocityY[getNeighborIndex(x,y,z)] = neighbor.b0VelocityY[CENTER_BUFF];
b0VelocityZ[getNeighborIndex(x,y,z)] = neighbor.b0VelocityZ[CENTER_BUFF];
}
}
/**
* Allocates the central arrays for this chunk
*/
private native void allocate();
/**
* Frees all native memory
*/
private native void free();
/**
* Frees the buffers contained within this chunk
*/
public void freeBuffers(){
this.free();
}
}