Personal project · OpenGL + Qt 5

Edifice

A shape-grammar engine for procedurally generating 3D buildings, with a custom DSL, a Flex/Bison parser, and a live in-editor reparse.

C++ · Qt 5 · OpenGL 4.1 · 2024 — 2025 · Windows
Animated demo of Edifice generating two rows of city towers along a street, rendered in real time from a split-grammar script.

Buildings, written as grammars.

You write rules saying how a face breaks down — floors, then rooms, then window strips — and the engine derives the geometry from that. Edifice implements a split grammar, a subset of shape grammars in the Wonka 2003 / CGA-shape tradition: the central operator is split(axis, pcts) { ChildRule* }, which carves a face along an axis at explicit per-cut percentages and dispatches a named rule for each piece. Pieces inherit the parent shape, so rules compose recursively.

Three primitive types: box for cubes, gable for pitched roofs (5 faces, ridge along Z), and hip for 4-sided pyramid roofs along the longer footprint axis. Roof faces are colorable and texturable but not splittable — their triangular ends would degenerate.

From text source to rendered geometry.

The pipeline runs end-to-end inside the app. A Flex lexer and Bison parser (regenerated on every build) compile DSL source to an AST in Ast.h. A tree-walking interpreter executes the AST, maintaining a rule registry and an implicit "current shape" stack, and lowering grammar features down to the Building::* primitive layer. The geometry that comes out drives a Qt 5 viewport on an OpenGL 4.1 core profile context with 4× MSAA, an orbit camera, and frame-locked WASD pan.

The CodeEditor dock re-parses and re-renders as you type. Auto-render is debounced at 900 ms, with an immediate render on cursor-line-change or Enter. Sit on a broken line for 2.5 s and a non-modal red banner explains the syntax error without interrupting the edit. AST diff plus checkpointed snapshots make incremental edits cheap.

Three demo scenes.

Skyline scene: two rows of five city towers along a street with sidewalks, lamp posts, and lane markings.
skyline.txt Two rows of five city towers along a street with sidewalks, lamp posts, and lane markings. The auto-loaded scene at app start.
City center scene: tiered central skyscraper with cantilevered balconies, ringed by four corner towers on a raised plaza.
cityCenter.txt Tiered central skyscraper with cantilevered balconies, ringed by four corner towers on a raised plaza.
Sears Tower scene: 9-block bundled-tube geometry rendered through the texture pipeline rather than the windowed-strip grammar.
searsTower_textured.txt 9-block bundled-tube geometry rendered through the texture pipeline rather than the windowed-strip grammar.

The pieces underneath.

  • Custom DSL with Flex/Bison parser
  • Tree-walking interpreter with rule registry & shape stack
  • Live in-editor reparse, debounced at 900 ms
  • 3D viewer: Qt 5, OpenGL 4.1 core, 4× MSAA, orbit camera
  • Procedural texture catalog on a GL_TEXTURE_2D_ARRAY
  • Wavefront OBJ export with per-vertex color extension
  • Loading panel with chunked GPU upload progress
  • Three primitive types: box, gable, hip
  • Bundled scripts library: skyline, city center, Sears, houses

C++, Qt 5, OpenGL 4.1, Flex/Bison, GLM, stb_image. Visual Studio on Windows, with win_flex and win_bison vendored at tools/winflexbison/ so the parser regenerates on every build with no separate install.

Edifice grew out of an earlier 3D building project I worked on with Zachariah Menzie. About 14% of the code — mostly the block-geometry core in Building.{cpp,hpp} and BuildingBlock.{cpp,h} — is Zach's original authorship, and everything Edifice does still rests on top of it. The DSL, the interpreter, the shape-grammar layer, the live editor, the texture pipeline, the orbit camera, and the procedural texture and script tooling were all written for this rewrite.

Thank you, Zach. You were a great partner on the original, and Edifice doesn't exist without the work we did together.