268 lines
7.5 KiB
Java
268 lines
7.5 KiB
Java
package electrosphere;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.ByteOrder;
|
|
import java.nio.FloatBuffer;
|
|
import java.nio.file.Files;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Random;
|
|
import java.util.Set;
|
|
|
|
import org.joml.Vector2i;
|
|
import org.lwjgl.BufferUtils;
|
|
import org.lwjgl.PointerBuffer;
|
|
import org.lwjgl.system.MemoryUtil;
|
|
|
|
/**
|
|
* Simulates a fluid via opencl
|
|
*/
|
|
public class FluidSim {
|
|
|
|
static {
|
|
System.out.println(System.getProperty("user.dir"));
|
|
System.load(System.getProperty("user.dir") + "/shared-folder/libfluidsim.dll");
|
|
}
|
|
|
|
public static final int DIM = 18;
|
|
|
|
ByteBuffer x = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4);
|
|
ByteBuffer x0 = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4);
|
|
ByteBuffer u = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4);
|
|
ByteBuffer v = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4);
|
|
ByteBuffer w = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4);
|
|
ByteBuffer u0 = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4);
|
|
ByteBuffer v0 = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4);
|
|
ByteBuffer w0 = ByteBuffer.allocateDirect(DIM * DIM * DIM * 4);
|
|
|
|
//The densities for every voxel for the current frame
|
|
float[] densityArrayView = new float[DIM * DIM * DIM];
|
|
//Should be set to add water to the current frame
|
|
float[] density0ArrayView = new float[DIM * DIM * DIM];
|
|
//The force vector for each voxel for the current frame
|
|
float[] uArrayView = new float[DIM * DIM * DIM];
|
|
float[] vArrayView = new float[DIM * DIM * DIM];
|
|
float[] wArrayView = new float[DIM * DIM * DIM];
|
|
//these should be set to the
|
|
float[] u0ArrayView = new float[DIM * DIM * DIM];
|
|
float[] v0ArrayView = new float[DIM * DIM * DIM];
|
|
float[] w0ArrayView = new float[DIM * DIM * DIM];
|
|
|
|
|
|
static final float DIFFUSION_CONSTANT = 0.0f;
|
|
static final float VISCOSITY_CONSTANT = 0.0f;
|
|
|
|
static final int LINEARSOLVERTIMES = 20;
|
|
|
|
static final float GRAVITY = -1000f;
|
|
|
|
public void setup(){
|
|
x.order(ByteOrder.LITTLE_ENDIAN);
|
|
x0.order(ByteOrder.LITTLE_ENDIAN);
|
|
u.order(ByteOrder.LITTLE_ENDIAN);
|
|
v.order(ByteOrder.LITTLE_ENDIAN);
|
|
w.order(ByteOrder.LITTLE_ENDIAN);
|
|
u0.order(ByteOrder.LITTLE_ENDIAN);
|
|
v0.order(ByteOrder.LITTLE_ENDIAN);
|
|
w0.order(ByteOrder.LITTLE_ENDIAN);
|
|
FloatBuffer xf = x.asFloatBuffer();
|
|
FloatBuffer uf = u.asFloatBuffer();
|
|
FloatBuffer vf = v.asFloatBuffer();
|
|
FloatBuffer wf = w.asFloatBuffer();
|
|
|
|
Random rand = new Random(1);
|
|
//make a cube of water in the center
|
|
for(int i = 0; i < DIM; i++){
|
|
for(int j = 0; j < DIM; j++){
|
|
for(int k = 0; k < DIM; k++){
|
|
if(
|
|
Math.abs(16 - i) < 4 &&
|
|
Math.abs(8 - j) < 4 &&
|
|
Math.abs(10 - k) < 4
|
|
){
|
|
xf.put(1);
|
|
uf.put(rand.nextFloat() * 0.1f);
|
|
vf.put(-1f);
|
|
wf.put(rand.nextFloat() * 0.1f);
|
|
} else {
|
|
xf.put(0);
|
|
uf.put(0);
|
|
vf.put(0);
|
|
wf.put(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Runs a frame of the fluid simulation
|
|
*/
|
|
public void simulate(int step, float timestep){
|
|
|
|
//
|
|
// Add forces and density here
|
|
//
|
|
addGravity();
|
|
|
|
//
|
|
//Performs main fluid simulation logic
|
|
//
|
|
writeNewStateIntoBuffers();
|
|
|
|
if(x.position() > 0){
|
|
x.position(0);
|
|
}
|
|
if(x0.position() > 0){
|
|
x0.position(0);
|
|
}
|
|
if(u.position() > 0){
|
|
u.position(0);
|
|
}
|
|
if(v.position() > 0){
|
|
v.position(0);
|
|
}
|
|
if(w.position() > 0){
|
|
w.position(0);
|
|
}
|
|
if(u0.position() > 0){
|
|
u0.position(0);
|
|
}
|
|
if(v0.position() > 0){
|
|
v0.position(0);
|
|
}
|
|
if(w0.position() > 0){
|
|
w0.position(0);
|
|
}
|
|
simulate(DIM, DIM, DIM, x, x0, u, v, w, u0, v0, w0, DIFFUSION_CONSTANT, VISCOSITY_CONSTANT, timestep);
|
|
|
|
//
|
|
//Reads out the results of the fluid sim
|
|
//
|
|
readDataIntoArrays();
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Used post-simulation call to read data from the simulation from buffers back into arrays
|
|
*/
|
|
private void readDataIntoArrays(){
|
|
//
|
|
//Read data back into arrays
|
|
//
|
|
if(x.position() > 0){
|
|
x.position(0);
|
|
}
|
|
if(u.position() > 0){
|
|
u.position(0);
|
|
}
|
|
if(v.position() > 0){
|
|
v.position(0);
|
|
}
|
|
if(w.position() > 0){
|
|
w.position(0);
|
|
}
|
|
for(int i = 0; i < DIM; i++){
|
|
for(int j = 0; j < DIM; j++){
|
|
for(int k = 0; k < DIM; k++){
|
|
densityArrayView[IX(i,j,k)] = x.getFloat();
|
|
uArrayView[IX(i,j,k)] = u.getFloat();
|
|
vArrayView[IX(i,j,k)] = v.getFloat();
|
|
wArrayView[IX(i,j,k)] = w.getFloat();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Writes data from the java-side arrays into buffers that get passed into c-side
|
|
*/
|
|
private void writeNewStateIntoBuffers(){
|
|
if(x0.position() > 0){
|
|
x0.position(0);
|
|
}
|
|
if(u0.position() > 0){
|
|
u0.position(0);
|
|
}
|
|
if(v0.position() > 0){
|
|
v0.position(0);
|
|
}
|
|
if(w0.position() > 0){
|
|
w0.position(0);
|
|
}
|
|
FloatBuffer x0FloatView = x0.asFloatBuffer();
|
|
FloatBuffer u0FloatView = u0.asFloatBuffer();
|
|
FloatBuffer v0FloatView = v0.asFloatBuffer();
|
|
FloatBuffer w0FloatView = w0.asFloatBuffer();
|
|
for(int i = 0; i < DIM; i++){
|
|
for(int j = 0; j < DIM; j++){
|
|
for(int k = 0; k < DIM; k++){
|
|
x0FloatView.put(density0ArrayView[IX(i,j,k)]);
|
|
u0FloatView.put(u0ArrayView[IX(i,j,k)]);
|
|
v0FloatView.put(v0ArrayView[IX(i,j,k)]);
|
|
w0FloatView.put(w0ArrayView[IX(i,j,k)]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds gravity to the simulation
|
|
*/
|
|
private void addGravity(){
|
|
for(int i = 0; i < DIM; i++){
|
|
for(int j = 0; j < DIM; j++){
|
|
for(int k = 0; k < DIM; k++){
|
|
v0ArrayView[IX(i,j,k)] = densityArrayView[IX(i,j,k)] * GRAVITY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The native function call to simulate a frame of fluid
|
|
* @param DIM_X
|
|
* @param DIM_Y
|
|
* @param DIM_Z
|
|
* @param x
|
|
* @param x0
|
|
* @param u
|
|
* @param v
|
|
* @param w
|
|
* @param u0
|
|
* @param v0
|
|
* @param w0
|
|
* @param DIFFUSION_CONSTANT
|
|
* @param VISCOSITY_CONSTANT
|
|
* @param timestep
|
|
*/
|
|
private native void simulate(
|
|
int DIM_X,
|
|
int DIM_Y,
|
|
int DIM_Z,
|
|
ByteBuffer x,
|
|
ByteBuffer x0,
|
|
ByteBuffer u,
|
|
ByteBuffer v,
|
|
ByteBuffer w,
|
|
ByteBuffer u0,
|
|
ByteBuffer v0,
|
|
ByteBuffer w0,
|
|
float DIFFUSION_CONSTANT,
|
|
float VISCOSITY_CONSTANT,
|
|
float timestep
|
|
);
|
|
|
|
public float[] getData(){
|
|
return densityArrayView;
|
|
}
|
|
|
|
public static final int IX(int x, int y, int z){
|
|
return ((x)+(DIM)*(y) + (DIM)*(DIM)*(z));
|
|
}
|
|
|
|
}
|