This project implements a cloth simulation system in C. It models various types of cloth-like structures using a mesh of points connected by springs. The simulation can handle different scenarios such as curtains, tablecloths, and stretchable materials.
- Multiple mesh types: curtain, tablecloth, and soft (stretchable) material
- Spring-based physics simulation
- Customizable parameters for mesh properties, spring characteristics, and simulation settings
- Logging system for debugging and information output
- VTK file output for visualization
- Standard C libraries (stdlib.h, stdio.h, stdbool.h, time.h, string.h, math.h)
- GCC compiler
- Make
- OpenMP for parrallelism
- Valgrind (optional, used for memory checking)
The project consists of several source and header files:
src/main.c: Entry point of the programsrc/mesh.candinclude/mesh.h: Mesh structure and related functionssrc/params.candinclude/params.h: Simulation parameterssrc/space.candinclude/space.h: Vector and point operationssrc/spring.candinclude/spring.h: Spring structure and related functionsinclude/log.candinclude/log.h: Logging utilitiesinclude/utils.candinclude/utils.h: Utility functions
To build the project, use the provided Makefile:
makeThis will compile the source files and create an executable named app in the bin directory.
The Makefile provides several targets for running different mesh types:
-
For curtain simulation:
make run-rideau -
For tablecloth simulation:
make run-nappe -
For soft (stretchable) material simulation:
make run-tissus -
For flag simulation:
make run-drapeau -
For all the simulation:
make run-all
To run the simulation with Valgrind for memory checking:
-
For curtain:
make saferun-rideau -
For tablecloth:
make saferun-nappe -
For soft material:
make saferun-tissus -
For flag simulation:
make saferun-drapeau
To remove all built files and VTK output:
make clean
The simulation can be configured by modifying the parameters in src/params.c. Key parameters include:
- Mesh dimensions (M, N)
- Spring properties (stiffness, energy threshold, damage threshold)
- Simulation settings (time step, number of updates, output frequency)
To modify parameters only for a certain type of cloth, use the custom_param() function in mesh.c.
To create a new mesh type:
- Add a new enum value to the
meshTypeenum ininclude/mesh.h. - Modify the
isFixedPointfunction insrc/mesh.cto define fixed points for your new mesh type. - Update the
initMeshfunction insrc/mesh.cto initialize the positions of points for your new mesh type. - If needed, add custom parameters for your mesh type in the
customs_paramsfunction insrc/mesh.c. - Implement any additional forces specific to your mesh type in the
computeAddForcesfunction insrc/mesh.c. - Update the argument parsing in the
parseArgumentsandgetTypeNamefunctions inutils.cto recognize the new mesh type from command-line arguments. - Add a new run target in the Makefile for the new mesh type.
Example: Adding a "dome" mesh type
// In mesh.h
typedef enum {
CURTAIN,
TABLE_CLOTH,
SOFT,
DOME // New mesh type
} meshType;
// In mesh.c
bool isFixedPoint(unsigned int i, unsigned int j, Mesh* mesh, meshType type) {
// ...
case DOME:
return (i == 0 || i == mesh->n - 1 || j == 0 || j == mesh->m - 1);
// ...
}
void initMesh(Mesh* mesh, meshType type) {
// ...
case DOME:
mesh->P[i][j] = newVector(origin.x + i * SPACING,
origin.y + sqrt(RADIUS*RADIUS - pow(i*SPACING - (mesh->n-1)*SPACING/2, 2) - pow(j*SPACING - (mesh->m-1)*SPACING/2, 2)),
origin.z + j * SPACING);
// ...
}
// In utils.c
meshType parseArguments(int argc, char *argv[]) {
// ...
else if (strcmp(argv[1], "dome")== 0)
{
return DOME;
}
// ...
}
//...The mesh struct presents as follow :
typedef struct Mesh {
unsigned int n; // number of lines
unsigned int m; // number of columns
float t; // the time at which position P are calculated
Vector **P; // Coordinate in the space at t time, should be used for rendering
Vector **V; // Velocity matrix n*m
Vector **P0; // Initial position matrix
Spring
*springs; // list of springs of the mesh, refered as R in the litterature
unsigned int n_springs; // number of non-break springs in the mesh
unsigned int **
*face_spring_indices; // 3D array of spring indices for each face
} Mesh;At the initial time (t = 0), the positions P and P0 are identical.
Face are defined by the bottom-left point and others points are computed in a very short time.
The face_spring_indices is a 3D array that maps each face (i, j) in the position matrix P to the indices of the springs connected to that point. The integer k represents the index of a spring for a face associated with a given point (0 to 4 for structural springs), and the corresponding value in the array is the index of the spring in the springs array.
This allow for each face, to quickly identify breaked-springs.
The springs are initialized and counted in a specific order. The process starts from the bottom-left point (0, 0) and proceeds by attempting to connect to other points by incrementing the indices i and j by 1 or 2 (e.g., (i, j+1), (i+1, j), (i+1, j+1), (i+2, j), (i, j+2)).
This method allows the springs to be computed simultaneously while initializing the matrix values for other points.
The simulation generates VTK files in the vtk_poly_<mesh_type> and vtk_grid_<mesh_type> directories for visualization. These can be viewed using appropriate VTK visualization software.
Free to use
- WATCHO KEUGONG Gabby Pavel (gwathok@etu.utc.fr)
- ChatGPT and code for boilerplate.
- Stack Overflow contribution for logging utilities : https://stackoverflow.com/a/23446001