Nimbin[12]?Games / Entropie / entropie/src/render/shapes.h

Entropie git · main

Entropie festival game; first steps

sdl c game entropie cmake · first commit 2026-10-10 · last commit 2026-11-02 (18 hours ago) · synced 10 hours ago

C 88.5% Markdown 9.1% GLSL 2.3%
git clone https://git.christianimmanuel.de/games/Entropie.gitwget https://git.christianimmanuel.de/games/Entropie/archive/Entropie.tar.gz
entropie/src/render/shapes.h 16.3 KB · 340 lines raw
#ifndef RENDER_SHAPES_H
#define RENDER_SHAPES_H

/*
 * Procedural meshes. All meshes are centered on X/Z.
 * Buildings and trees are described by size structs so the game code can
 * build matching colliders from the same numbers.
 */

#include <stdbool.h>

#include "math/linalg.h"
#include "render/mesh.h"

typedef enum {
    PALETTE_STANDARD, /* white */
    PALETTE_GROUND,   /* brown sides, grass top */
    PALETTE_MODERN,   /* one bright color per face */
    PALETTE_WARM,     /* orange */
} Palette;

/* Box centered on the origin. */
Mesh Shapes_box(Vec3 size, Palette palette);
/* A white unit block (tinted when drawn): wood chips, sawdust. */
Mesh Shapes_chip(void);
/* A ball of smoke (1 across, white: tinted), drawn soft and see-through (Renderer_drawPuff). */
Mesh Shapes_puff(void);

/* Upright cylinder centered on the origin (single palette color). */
Mesh Shapes_cylinder(float diameter, float height, int segments, Palette palette);

typedef struct {
    float trunk_height;
    float trunk_radius;
    int   leaf_layers;   /* stacked cones, 0.6 apart, each 0.8 high */
    float leaf_radius;   /* radius of the lowest cone (fruit trees: the widest) */
    bool  fruit;         /* a round crown with apples instead of a pine */
    bool  cut;           /* felled: no foot, the cut face at its end (else the foot flares into roots) */
    bool  old;           /* old and half dead: gaps in the crown, brown dead layers, the top snapped off (a bare snag) */
    unsigned seed;       /* the foot's roots (Shapes_stump makes the same ones from the same seed) */
} TreeSize;

#define TREE_FRUIT_LAYERS 8  /* layers of a whole fruit tree crown */

/* Total height of a tree (trunk plus cones). */
float Shapes_treeHeight(TreeSize size);

/* Trunk with stacked cone layers; base at y = 0. Seed for a spot: Shapes_treeSeed. */
unsigned Shapes_treeSeed(float x, float z);
Mesh  Shapes_tree(TreeSize size);

/* Brick walls and a slate roof, or a farm hall: light walls, gray, red or solar roof. */
typedef enum {
    BUILDING_BRICK,
    BUILDING_PLASTER,       /* light walls, light grey roof */
    BUILDING_PLASTER_DARK,  /* light walls, dark roof */
    BUILDING_HALL, BUILDING_HALL_RED, BUILDING_HALL_SOLAR
} BuildingLook;

typedef struct {
    float length;       /* along X, the roof ridge direction */
    float width;        /* along Z */
    float wall_height;
    float roof_height;  /* ridge height above the walls */
    BuildingLook look;
    bool  door_set;     /* the front door at door_x (along X) instead of near the -X end */
    float door_x;
} BuildingSize;

typedef enum { BOTTLE_BEER, BOTTLE_SPIRITS, BOTTLE_WATER, BOTTLE_COLA, BOTTLE_ORANGE, BOTTLE_MATE } BottleStyle;

/* Bottle centered on the origin: glass, label, neck and cap.
   Brown beer bottle, clear with a red cap for spirits, light blue for water. */
Mesh  Shapes_bottle(float diameter, float height, BottleStyle style);

/* Food, centered on the origin. */
Mesh  Shapes_apple(float diameter);
/* Alice's toys: variant 0 a ball (size.x across), 1 a rope with knots (size.x long, size.y thick). */
Mesh  Shapes_toy(int variant, Vec3 size);
Mesh  Shapes_bread(Vec3 size);

/* Supplies, centered on the origin: a crate heaped with apples, a water barrel,
   a cool box (sausages), a carton with a roll of garbage bags. */
Mesh  Shapes_appleCrate(Vec3 size);
Mesh  Shapes_barrel(float diameter, float height);
Mesh  Shapes_coolBox(Vec3 size);
Mesh  Shapes_bagCarton(Vec3 size);

/* A sausage along Y, centered; brown and striped once grilled. */
Mesh  Shapes_sausage(float length, bool grilled);

/* Fireplace: a ring of stones round a bed of ashes, base at y = 0, and the
   wooden tripod over it (the grill hangs from it). */
Mesh  Shapes_fireplace(float diameter);
/* Where the tripod's pole k (0..2) stands, from the fireplace's middle. */
Vec3  Shapes_tripodFoot(float diameter, int k);
#define TRIPOD_OUT  1.3f   /* its poles stand this far outside the stones (they don't catch fire) ... */
#define TRIPOD_PAST 0.6f   /* ... and reach this far past the top */
/* Flames over the middle, base at y = 0. Their colors glow in the dark. */
Mesh  Shapes_flames(void);

/* Litter, centered on the origin; kind as in OBJ_TRASH (a palette). */
Mesh  Shapes_trash(Palette kind, unsigned seed);
/* A cigarette butt: the filter and a burnt end. */
Mesh  Shapes_butt(void);
/* Size of a piece of litter. */
Vec3  Shapes_trashSize(Palette kind);
/* A black garbage bag, centered; fullness 0 (empty) .. 1 (full). */
Mesh  Shapes_bag(float fullness);
Vec3  Shapes_bagSize(float fullness);
/* A glowing dashed frame lying at y = 0 (length along X, depth along Z): "here". */
Mesh  Shapes_marker(float length, float depth);

/* The grill: chain and grate hanging below the top of the tripod (origin). */
Mesh  Shapes_grill(void);
#define GRILL_TOP   3.9f   /* the tripod's rods meet this high over the fire */
#define GRILL_DROP  3.3f   /* the grate hangs this far below */

typedef enum {
    FURN_WORKBENCH, FURN_TOOLWALL, FURN_SHELF, FURN_STOVE, FURN_COUNTER, FURN_TABLE,
    FURN_CHAIR, FURN_BENCH, FURN_CAR, FURN_TIRES, FURN_TOILET, FURN_TAP, FURN_ASHTRAY, FURN_GATE, FURN_SMOKES, FURN_BAR, FURN_COUNT
} FurnitureKind;
#define SEAT_HEIGHT 0.45f  /* chairs and log benches */

/* Furniture standing on y = 0, size = its box (length along X, height, depth along Z).
   Fronts face +Z. */
Mesh  Shapes_furniture(FurnitureKind kind, Vec3 size);
/* The ashtray with this many butts in it (a few show, a heap when full). */
Mesh  Shapes_ashtray(Vec3 size, int butts);
/* Ivy up a wall (at z = 0, facing +Z), this wide and high. */
Mesh  Shapes_ivy(float width, float height, unsigned seed);
/* Your estate car standing on y = 0, nose to +Z (CAR_WIDTH x about 1.45 m x CAR_LENGTH); the boot open:
   the hatch up. */
#define CAR_WIDTH  1.78f
#define CAR_LENGTH 4.6f
#define CAR_COLOR  ((Vec3){ 0.50f, 0.55f, 0.46f }) /* (an old faded green) */
Mesh  Shapes_car(Vec3 color, bool boot_open);
/* ... seen from the driver's seat: the bonnet, the dashboard, the wheel, the pillars, the roof. */
Mesh  Shapes_carInside(Vec3 color);
/* Rain: a thin light streak at each drop (world space), len long. */
Mesh  Shapes_rain(const Vec3 *drops, int n, float len, Vec3 lean);
/* A crate of bottles (centred): variant 0 beer, 1 water, 2 soda (cola and orange), 3 mate; this many bottles in it. */
#define CRATE_SIZE_X 0.40f
#define CRATE_SIZE_Y 0.30f
#define CRATE_SIZE_Z 0.30f
/* What's in each slot of a crate: 0 nothing, else a bottle - its kind
   (CRATE_KIND) and how many sips are left in it (CRATE_SIPS, 0: an empty). */
#define CRATE_SLOTS 20
enum { BOTTLE_KIND_NONE, BOTTLE_KIND_BEER, BOTTLE_KIND_WATER, BOTTLE_KIND_COLA, BOTTLE_KIND_ORANGE, BOTTLE_KIND_MATE };
#define CRATE_SLOT(kind, sips) ((unsigned char)(((kind) & 7) | ((sips) << 3)))
#define CRATE_KIND(code)       ((code) & 7)
#define CRATE_SIPS(code)       ((code) >> 3)
Mesh  Shapes_crate(int variant, const unsigned char *slots, int n);
/* An umbrella along Y, centred, length long: folded (a crook at the bottom), or
   open (the canopy over the top end, radius across). */
/* shape: UMBRELLA_FOLDED, UMBRELLA_OPEN, UMBRELLA_INSIDE_OUT (blown: the canopy up like a cup, ribs bent) */
enum { UMBRELLA_FOLDED, UMBRELLA_OPEN, UMBRELLA_INSIDE_OUT };
Mesh  Shapes_umbrella(float length, float radius, int shape, Vec3 color);
/* A floor's stage as far as it's built: stage (0 marked out .. 5 done) and how far into
   it (0..1); width along X, depth along Z (the front at +Z), its colour for the paint and
   the banners. The platform is STAGE_DECK high once the floor is in. */
#define STAGE_DECK 0.5f
Mesh  Shapes_stage(int stage, float part, float width, float depth, Vec3 accent);
/* A hat lying about (HAT_CAP, HAT_BEANIE), its crown up, the cap's brim along +Z. */
Mesh  Shapes_hat(int kind, Vec3 color);
/* Camping things (centred, lying along X): kind 0 a sleeping bag in its sack, 1 a foam mat rolled up,
   2 a small tent in its bag, 3 a big one. */
Mesh  Shapes_gear(int kind, Vec3 color);
/* The scythe (centred, its snath along Y, the blade at the bottom); a vineyard snail (on y = 0);
   a log carved into a figure (on y = 0): kind 0 an owl, 1 a bear, 2 a mushroom man. */
Mesh  Shapes_scythe(float length);
Mesh  Shapes_snail(void);
/* The ambulance (the estate's shape: white, a red band, blue lights). */
Mesh  Shapes_ambulance(void);
/* The big tree's rope from a to c (local), sagging; coil: the rest lying in loops at c. The throw line's bag. */
Mesh  Shapes_rope(Vec3 a, Vec3 c, float sag, bool coil);
Mesh  Shapes_throwBag(void);
/* A wooden phone pole this high (mast: the tall one), and the wires along n cross arms' middles (local);
   down: torn, hanging to the ground (ground_y under each point, local; may be NULL). */
Mesh  Shapes_phonePole(float height, bool mast);
Mesh  Shapes_wires(const Vec3 *points, int n, bool down, const float *ground_y);
Mesh  Shapes_sculpture(int kind, float diameter, float height);
/* The marker over who or what to go to next: a diamond, centred, this tall. */
Mesh  Shapes_questMarker(float height, Vec3 color);
/* A party pavilion on y = 0 (centred): side x side, the eaves and the roof's peak this high, its canvas colour. */
Mesh  Shapes_pavilion(float side, float eaves, float peak, Vec3 canvas);
/* Building material (centred, size = its box): kind 0 a strapped bundle of 8 boards (long along X),
   1 a box of nails, 2 a box of screws, 3 a bucket of paint (size.x across). */
Mesh  Shapes_material(int kind, Vec3 size);
/* A dome tent standing on y = 0, the door to +Z: big 0 small (two people
   squeezed), 1 the big one. How far it's up: stage 0 laid out flat, 1 the
   poles going in and up (progress 0..1), 2 the cover going over it (from the
   back), 3 being pegged (pegs in), 4 standing. */
#define TENT_STAGES 5
#define TENT_W(big) ((big) ? 2.2f : 1.4f)
#define TENT_L(big) ((big) ? 2.4f : 2.1f)
#define TENT_H(big) ((big) ? 1.3f : 1.0f)
#define TENT_PEGS(big) ((big) ? 10 : 6)
Mesh  Shapes_tent(int big, int stage, float progress, int pegs, Vec3 inner, Vec3 fly);
/* Where peg k goes (local, the tent's middle at 0, 0). */
void  Shapes_tentPeg(int big, int k, float *x, float *z);
/* A pullover put down (see clothes.h), its colour: lay 0 spread out flat on the ground (y = 0 under it,
   the neck to +Z, sleeves out), 1 hung over an edge along X (y = 0 its top; gap: how thick that edge is),
   2 folded up (y = 0 under it). */
Mesh  Shapes_pullover(int lay, Vec3 color, float gap);

/* A dachshund, its nose towards -Z, standing on y = 0: a plain body for picking it
   out (she's drawn as a painted figure, see people/dog.c); her proportions. */
Mesh  Shapes_dogBody(void);
#define DOG_HIP_Y     0.13f
#define DOG_HIP_X     0.055f
#define DOG_HIP_Z     0.20f
#define DOG_TAIL_Y    0.24f
#define DOG_TAIL_Z    0.27f

/* Garden hose: its nozzle (centered), and one piece of hose 1 m long along +Y from the origin. */
Mesh  Shapes_hoseNozzle(void);
Mesh  Shapes_hosePiece(void);
/* Duct tape round a piece of hose (like Shapes_hosePiece, a bit thicker, grey). */
Mesh  Shapes_hoseTape(void);
/* A roll of duct tape, centered, lying flat. */
Mesh  Shapes_tapeRoll(void);
/* A watering can, centered, spout towards +Z. */
Mesh  Shapes_wateringCan(void);
#define TAP_HEIGHT 0.8f   /* where the hose comes out of the tap */
#define SMOKES_PACKS 20   /* a pack from the cigarette machine (FURN_SMOKES: on a wall, back at z = -hz) */
/* A telescopic ladder: rungs on tubes that slide into each other. Local +Y up
   along it from the feet (y = 0), rungs along X. extend 0 = slid together .. 1 = out. */
#define LADDER_RUNGS 20
#define LADDER_WIDTH 0.48f
float Shapes_ladderLength(float extend);
/* Height of rung k (0 = the lowest) along the ladder. */
float Shapes_ladderRung(float extend, int k);
Mesh  Shapes_ladder(float extend);
/* The folding ladder (two hinged sections): unfold 0 = folded .. 1 = straight. */
#define FOLD_RUNGS 9 /* per section */
float Shapes_foldLadderLength(float unfold);
float Shapes_foldLadderRung(int k);
Mesh  Shapes_foldLadder(float unfold);
/* The step ladder: a front leg with flat treads (+Y up it, +Z its front) and a
   back leg hinged at the top. open 0 = folded flat .. 1 = standing (legs spread). */
#define STEP_TREADS   5     /* the top platform comes on top of these */
#define STEP_HINGE_Z -0.06f /* the back leg's hinge, behind the front leg */
float Shapes_stepLadderLength(void);
/* Tread k along the front leg; k = STEP_TREADS: the top platform. */
float Shapes_stepLadderRung(int k);
/* Angle between the legs (rad). */
float Shapes_stepLadderSpread(float open);
Mesh  Shapes_stepLadder(float open);

/* A round bush, base at y = 0. */
Mesh  Shapes_bush(float diameter, float height, unsigned seed);

/* A big waste container, centered on the origin. */
Mesh  Shapes_bin(Vec3 size);

/* Ground under a decal: surface height at world (x, z), and where the mesh origin is. */
typedef struct {
    float     (*height)(const void *ctx, float x, float z);
    const void *ctx;
    Vec3        origin;
} ShapeGround;


/* A tree stump (centered), and the roots left when it's chopped out (lying on the ground). */
Mesh  Shapes_stump(float diameter, float height, unsigned seed);
Mesh  Shapes_roots(float diameter, unsigned seed, ShapeGround ground);
/* Log (a tree trunk without branches) centered on the origin, along Y. */
Mesh  Shapes_log(float diameter, float length);
/* Cut-off branch along Y with a few twigs and leaves. */
Mesh  Shapes_branch(float length);

/* Two sleepers on the ground for a woodpile (length along X, depth along Z). */
Mesh  Shapes_woodpile(float length, float depth);

/* A half (parts 2) or quarter (parts 4) of a log along Y, centered on its
   bounding box; the bark side faces +Z. */
Mesh  Shapes_firewood(float diameter, float length, int parts);
/* Pruning shears along Y, blades up. */
Mesh  Shapes_shears(float length);
/* Chainsaw: motor at the back, bar along -Z (forward). About 0.18 x 0.25 x 0.75 m. */
Mesh  Shapes_chainsaw(void);

/* Axe centered on the origin: handle along Y, blade at the top towards +Z. */
Mesh  Shapes_axe(float length);

/* Sick on the ground (following its bumps), and stink lines rising from the ground. */
Mesh  Shapes_vomit(float radius, unsigned seed, ShapeGround ground);
Mesh  Shapes_stink(float radius, unsigned seed, ShapeGround ground);

/* A painted line on a road: across offset from the middle, width, and
   dash / gap lengths (gap 0: a solid line). */
typedef struct {
    float offset, width, dash, gap;
} RoadLine;

/* Painted lines along a road (world x/z, y ignored), lying on the ground
   (the road itself is part of the ground: see Site_surface). */
Mesh  Shapes_roadLines(const Vec3 *points, int count, const RoadLine *lines, int line_count, ShapeGround ground);

/* Loose stones lying on a gravel road (or a gravelled patch) along points:
   fewer in the ruts and the grassy middle of a road, bigger ones at the
   edges (density: stones per square meter). */
Mesh  Shapes_gravelStones(const Vec3 *points, int count, float width, float density, bool road, ShapeGround ground);

/* A loose stone, lumpy and flattened, centered (size = bounding box). */
Mesh  Shapes_stone(Vec3 size, unsigned seed);

/* A flat square of water (centered, side length), its surface at y = 0. */
Mesh  Shapes_water(float side);

/* A broken bottle: glass pieces in a beer puddle, lying at y = 0. */
Mesh  Shapes_shards(float diameter, unsigned seed);

/* Walls with a gable roof; base at y = 0. Details adds windows and doors. */
Mesh  Shapes_building(BuildingSize size, bool with_details);

/* A building made of parts (see world/manor.c): boxes, windows and doors on
   the walls, gable roofs. */
typedef struct { Vec3 min, max; Vec3 color; bool brick; } ShapeSlab; /* brick: mortar courses on its sides */
typedef enum { OPENING_WINDOW, OPENING_PANE, OPENING_DOOR, OPENING_FRAME } OpeningKind;
typedef struct {
    OpeningKind kind;
    Vec3  at;     /* on the wall face: a window's middle, a door's foot */
    float yaw;    /* turns its front (+Z) to yaw_front(yaw) (see linalg.h) */
    float w, h;
    Vec3  frame;
} ShapeOpening;
typedef struct {
    Vec3  center;     /* x, z of the middle */
    float length, width, wall_top, roof_height; /* length along the ridge: X, or Z if across */
    BuildingLook look;
    bool  across;
    float valley;     /* > 0: the ridge runs on this far past its +X end into a roof across it (valleys, no eaves) */
} ShapeRoof;
Mesh  Shapes_structure(const ShapeSlab *slabs, int n_slabs, const ShapeOpening *openings, int n_openings,
                       const ShapeRoof *roofs, int n_roofs);
Vec3  Shapes_roofColor(BuildingLook look);

#endif /* RENDER_SHAPES_H */