In this project, I programmed cloth physics simulation in a software renderer. The program takes in .obj format for the cloth and the sphere model. Space hashing was used to speed up the simulation steps.

Technical Details


Barycentric Interpolation

During rasterization, barycentric interpolation is used both for determining if a point is inside the triangle and for interpolating the pixel’s depth and color values. Compared to linear interpolation, barycentric interpolation is faster and simpler, offering the additional benefit that the returned u, v, w values can also indicate whether the pixel lies within the triangle.

inline void BarycentricInterp(float v1[], float v2[], float v3[], float& u, float& v, float& w)
{
double d00 = dotproduct(v1, v1);
double d01 = dotproduct(v1, v2);
double d11 = dotproduct(v2, v2);
double d20 = dotproduct(v3, v1);
double d21 = dotproduct(v3, v2);
double denom = (double)(1.0 / (d00 * d11 - d01 * d01));
v = (d11 * d20 - d01 * d21) * denom;
w = (d00 * d21 - d01 * d20) * denom;
u = 1.0f - v - w;
}
# v: Vertices Coordinates
v 1.670000 -1.680000 -2.020000
...
# vt: Texture Coordinates
vt 0.181819 0.000000
...
# vn: Vertices Normal
vn 0.1024 -0.9435 0.3151
...
# f: Polygonal Face Elements, which are v/vt/vn
f 1/1/1 14/2/1 13/3/1
...
.OBJ Format Import

Spheres and cloth models are generated using Blender and exported in .obj format. Upon importing, vertices coordinates, texture coordinates, and vertex normals are all stored separately in a vector list. When reading face element information, the triangle is constructed by retrieving the previously stored vertex information, and then it is added to a vector list for triangles.

During simulation, the triangle’s face normal is also required, which is calculated by averaging the normals of all vertices surrounding the face.

Spatial Hashing

During each simulation step, a hash value is generated for all point masses on the simulated cloth. Point masses located within the same 3D box volume share the same hash value. From these calculations, a spatial unordered map is constructed.

As the simulation must determine whether any point masses are self-colliding, spatial hashing significantly accelerates this process. It does so by limiting checks to point masses that occupy the same volume.

float Cloth::hash_position(STCoord pos) 
{
double w = (double) 3 * 4 / 65;
double h = (double) 3 * 4 / 65;
double t = max(w, h);
double a = 0.0, b = 0.0, c = 0.0;
a = fmod(pos[0], w);
b = fmod(pos[1], h);
c = fmod(pos[2], t);

return (float)(3.0 * a + 7.0 * b + 11.0 * c);
}