#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 #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 */