A software 3D rendering engine written in C, driven by MDL (My/Modeling/Description Language), a small domain-specific scripting language parsed with flex/bison. It rasterizes polygon meshes and parametric solids into PPM/PNG images, supports flat, Gouraud, and Phong shading, perspective projection, animation, and can load external .obj/.stl meshes.
Created alongside JonAlf Dyrland-Weaver's computer graphics course. Files were archived, but commit history lost to school organization's data purge.
- MDL scripting language: a text-based scene description format (parsed via
mdl.l/mdl.y) for defining shapes, transformations, coordinate systems, lighting, and animation. - Primitives: spheres, tori, boxes, lines, circles, Bezier and Hermite curves.
- Mesh import: load external triangle meshes from
.objand.stlfiles (mesh_parser.c). - Transformation stack:
push/popcoordinate system stack with translate, scale, and rotate operations, plus named/saved coordinate systems. - Shading modes: flat, Gouraud, and Phong shading with ambient, diffuse, and specular lighting (
gmath.c,draw.c). - Perspective projection: simple pinhole-camera perspective division as well as an OpenGL-style perspective matrix (
perspective.c). - Z-buffering: hidden-surface removal via a per-pixel z-buffer.
- Animation:
frames/vary/tweenknobs interpolate values across frames, rendering an image sequence that's stitched into a GIF via ImageMagick'sconvert. - Output: save frames as PPM or PNG (
stb_image_write), or pop up a live SDL2 window withdisplay.
gccflexbisonSDL2andSDL2_image(for live display viasdl2-config)- ImageMagick's
convertcommand (for animation/GIF assembly)
On Debian/Ubuntu: sudo apt install flex bison libsdl2-dev libsdl2-image-dev imagemagick
makeThis runs flex on mdl.l and bison on mdl.y to generate the lexer/parser (lex.yy.c, y.tab.c, y.tab.h), compiles all engine sources, and links everything into an mdl executable.
make cleanRemoves generated parser files, object files, and rendered output (*.o, *.png, *.gif, contents of anim/ and images/).
./mdl script.mdlor, to build and immediately run the sample script bundled in the makefile:
make runwhich builds the parser and runs ./mdl thingmabob.mdl.
If no script is provided, the parser reads from stdin.
| File | Purpose |
|---|---|
mdl.l |
Flex lexer for the MDL language |
mdl.y |
Bison grammar; builds the opcode list (op[]) consumed by the interpreter and drives main() |
my_main.c |
Interprets the parsed MDL opcode list frame-by-frame: manages the coordinate stack, lighting, shading mode, perspective, and drawing |
parser.h (referenced) |
Shared opcode/command struct definitions |
symtab.c |
Symbol table for named constants, lights, coordinate systems, and knob values |
stack.c |
Coordinate-system transformation stack |
matrix.c |
4xN matrix type: identity, translate/scale/rotate matrices, multiplication, Bezier/Hermite coefficient generation |
draw.c |
Shape generation (spheres, tori, boxes, circles, curves) and scanline rasterization (flat, Gouraud, Phong) plus Bresenham line drawing |
gmath.c |
Lighting math: ambient/diffuse/specular calculation, vertex normal averaging for smooth shading |
perspective.c |
Perspective projection (pinhole model and OpenGL-style projection matrix) |
mesh_parser.c |
.obj and .stl mesh file loading |
display.c |
Screen/z-buffer manipulation, PPM/PNG output, ImageMagick animation assembly, SDL2 live display |
print_pcode.c |
Debug utility to print the parsed opcode list |
main.c |
Legacy/alternate entry point exercising the engine directly in C (not used by the mdl build target) |
makefile |
Build rules |
mdl.y/mdl.lparse the script into an array of opcodes (op[]).my_main.cruns a first pass to determine frame count and basename, then a second pass to compute per-frame knob values for animated scenes.- For each frame, opcodes are replayed in order: shapes are generated into a temporary point matrix, transformed by the current coordinate system, optionally perspective-projected, and rasterized into the screen buffer with z-buffering.
- Completed frames are saved as PNG (single image) or as a numbered sequence in
anim/(animation), which is then assembled into a GIF with ImageMagick.