Howdy! I'm Joshua Zimmerman and welcome to my website! This page will help break down what I did for my final project in CSCE 450.
I set out to:
Libraries I used in my program and why:
openvdb::FloatGrid
to export each cell's density as a value in a widely used volumetric data formatA breakdown of core program functionality:
Some tips for someone who wants to implement a similar system:
Eigen::SparseMatrix<double> Amatrix(gridSize, gridSize);
std::vector<Eigen::Triplet<double>> coefficients;
for x y z in grid {
uint32_t i = flattenIndex(x, y, z);
coefficients.emplace_back(i, i, 6);
coefficients.emplace_back(i, flattenIndex(x + 1, y, z), -1);
coefficients.emplace_back(i, flattenIndex(x - 1, y, z), -1);
coefficients.emplace_back(i, flattenIndex(x, y + 1, z), -1);
coefficients.emplace_back(i, flattenIndex(x, y - 1, z), -1);
coefficients.emplace_back(i, flattenIndex(x, y, z + 1), -1);
coefficients.emplace_back(i, flattenIndex(x, y, z - 1), -1);
}
Amatrix.setFromTriplets(coefficients.begin(), coefficients.end());
Eigen::Vector3d vxp = grid.getVelocity(x + 1, y, z);
Eigen::Vector3d vxm = grid.getVelocity(x - 1, y, z);
Eigen::Vector3d vyp = grid.getVelocity(x, y + 1, z);
Eigen::Vector3d vym = grid.getVelocity(x, y - 1, z);
Eigen::Vector3d vzp = grid.getVelocity(x, y, z + 1);
Eigen::Vector3d vzm = grid.getVelocity(x, y, z - 1);
double divergence = 0.5 * (
vxp.x() - vxm.x() + // ∂u/∂x
vyp.y() - vym.y() + // ∂v/∂y
vzp.z() - vzm.z() // ∂w/∂z
);
b[flattenIndex(x, y, z)] = -divergence; // b in Ax = b system
Eigen::ConjugateGradient<Eigen::SparseMatrix<double>>
as a solver for your linear system to get a Eigen::VectorXd
that you can access with solutionVector[flattenIndex(x, y, z)]
Eigen::Vector3d Simulator::computeVorticity(int x, int y, int z) {
Eigen::Vector3d vxp = grid.getVelocity(x + 1, y, z);
Eigen::Vector3d vxm = grid.getVelocity(x - 1, y, z);
Eigen::Vector3d vyp = grid.getVelocity(x, y + 1, z);
Eigen::Vector3d vym = grid.getVelocity(x, y - 1, z);
Eigen::Vector3d vzp = grid.getVelocity(x, y, z + 1);
Eigen::Vector3d vzm = grid.getVelocity(x, y, z - 1);
double dw_dy = (vzp.y() - vzm.y()) * 0.5;
double dv_dz = (vyp.z() - vym.z()) * 0.5;
double du_dz = (vxp.z() - vxm.z()) * 0.5;
double dw_dx = (vzp.x() - vzm.x()) * 0.5;
double dv_dx = (vyp.x() - vym.x()) * 0.5;
double du_dy = (vxp.y() - vxm.y()) * 0.5;
return Eigen::Vector3d(dv_dz - dw_dy, dw_dx - du_dz, du_dy - dv_dx);
}
And vorticity force equation: f = ε ( ∇|ω| × ω ) where:
Eigen::Vector3d vort = computeVorticity(x, y, z);
double nx = computeVorticity(x + 1, y, z).norm() - computeVorticity(x - 1, y, z).norm();
double ny = computeVorticity(x, y + 1, z).norm() - computeVorticity(x, y - 1, z).norm();
double nz = computeVorticity(x, y, z + 1).norm() - computeVorticity(x, y, z - 1).norm();
Eigen::Vector3d gradMag(nx, ny, nz);
gradMag = 0.5;
Eigen::Vector3d confinement = gradMag.cross(vort) VORTICITY_CONFINEMENT_SCALE * dt;
If I had another semester with this project I would aim to: