Skip to content

Commit cd90846

Browse files
authored
Merge development work
- document more engine parts (ESL, GRIM, EGF rendering, animation system, physics engine) - rewritten egfMan2 with eqPhysics, removed Jolt and old DkPhysics interface - fixed various bugs
2 parents 8dbcdde + c2b565d commit cd90846

503 files changed

Lines changed: 3218 additions & 106698 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎AGENTS.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ Before editing:
4444

4545
## Documentation
4646

47-
- TODO
47+
- Before working with an engine system, find its overview in the "Related documents" table of
48+
`docs/architecture.md` and read it to learn which systems, classes and entry points to use
49+
(for example `docs/physics_overview.md` for `shared/physics`). Check the code when the
50+
document and the code disagree.
4851

4952

5053

‎TODO.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ needs review by the code owner before changing.
6060
- [ ] `core/e2core/Localize.cpp` — style does not match `docs/codestyle.md` (C-style casts,
6161
`_FindToken` reserved identifier, missing `override`, `pszDefaultToken = 0`, mixed `if(` /
6262
`if (`). Only relevant if the file is refactored.
63+
- [ ] `shared/scripting/esl_bind.h:338`, `:341` — `EQSCRIPT_BIND_VAR_EX_SET_NAMED` is defined twice
64+
(identical definitions).
65+
- [ ] `shared/sys/scripting/sys_esl_core.h:31-81` — the `ENABLE_MULTIPLAYER` block still binds
66+
`Networking::Buffer` / `CNetworkThread` with the old OOLUA macros (`OOLUA_PROXY`), which do not
67+
exist in ESL; it would not compile with `ENABLE_MULTIPLAYER`.
68+
- [ ] `shared/sys/scripting/sys_esl_engine.h:31` — the Lua class of `DDOrientedBox` is named
69+
`"DDOrientedBox"`, while the other debug shapes use `Dbg*` names (`DbgBox`, `DbgSphere`, ...)
70+
and its constructor function is `DbgOriBox`. Renaming changes the script API.
6371

6472
## Features
6573

‎docs/animating_egf_overview.md‎

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# EGF animation overview — `shared/animating`
2+
3+
`animatingLib` animates the skeleton of an EGF model: sequences from motion packages (`.mop`),
4+
activities, blending and transitions, pose controllers, animation events and an experimental IK
5+
solver. The result is an array of bone matrices used to draw the model with skinning (see
6+
[rendering_egf_overview.md](rendering_egf_overview.md)). File formats:
7+
[public_egf_overview.md](public_egf_overview.md).
8+
9+
| File | Contents |
10+
|---|---|
11+
| `Animating.h/.cpp` | `CAnimatingEGF` — the animation component |
12+
| `BoneSetup.h/.cpp` | Runtime structures: `AnimSequence`, `AnimSequenceTimer`, `AnimPoseController`, `AnimIkChain`, `AnimFrame` |
13+
| `anim_activity.h/.cpp` | `Activity` enum, `GetActivityByName`, `GetActivityName` |
14+
| `anim_events.h/.cpp` | `AnimationEvent` enum, `GetEventByName`, `GetEventName` |
15+
16+
## Usage
17+
18+
`CAnimatingEGF` is meant to be a base class (or member) of a game object that has a model:
19+
20+
```cpp
21+
class CPedestrian : public CAnimatingEGF
22+
{
23+
protected:
24+
Activity TranslateActivity(Activity act, int slot) const override;
25+
void HandleAnimatingEvent(AnimationEvent event, const char* options) override;
26+
};
27+
28+
// the model must be fully loaded (see rendering_egf_overview.md: loading)
29+
EGF_LOADING_CRITICAL_SECTION(geom); // or init from geom->GetLoadingFuture() callback
30+
ped->InitAnimating(geom); // skeleton, IK chains, motion packages of the model
31+
ped->InitMotionData("models/peds/shared_anims"); // optional extra package
32+
ped->SetActivity(ACT_IDLE);
33+
34+
// every frame
35+
ped->AdvanceFrame(dt); // timers, pose controllers, events
36+
ped->RecalcBoneTransforms(); // recomputes bones if anything changed
37+
ped->UpdateIK(dt, worldMatrix); // optional
38+
39+
// drawing
40+
RenderBoneTransform bones[128];
41+
const int numBones = geom->ConvertBoneMatricesToQuaternions(ped->GetBoneMatrices(), bones);
42+
...
43+
```
44+
45+
- `InitAnimating(geom)` — binds the model: copies the bind pose to the bone matrices, creates IK
46+
chains and adds all motion packages referenced by the model. The model must be in
47+
`MODEL_LOAD_OK` state (asserted): skeleton and motion packages are filled by the loading jobs. `DestroyAnimating()` releases it;
48+
`IsAnimatingInitialized()`.
49+
- `InitMotionData(name)` — adds one more motion package (by file name, through `g_studioCache`).
50+
Packages are identified by file name without path and extension.
51+
- `GetBoneMatrices()` — model-space bone matrices (`Matrix4x4[numBones]`), valid after
52+
`RecalcBoneTransforms`.
53+
- `FindBone(name)`, `GetLocalBoneOrigin(bone)`, `GetLocalBoneDirection(bone)`.
54+
- `GetLocalStudioTransformMatrix(idx)` — model-space matrix of an EGF transform (attachment),
55+
following its bone if it is attached to one.
56+
57+
## Sequences and activities
58+
59+
A **sequence** (from the `.mop`, compiled by `animca`) is what gets played: one or more
60+
animations, framerate, flags (`SEQFLAG_LOOP`, `SEQFLAG_SLOTBLEND`), transition time, an optional
61+
pose controller, layered sequences and events. An **activity** is a game-level name for "what the
62+
object is doing" (`ACT_IDLE`, `ACT_WALK`, `ACT_VEHICLE_STEER`, ...); sequences declare the activity
63+
and slot they implement.
64+
65+
```cpp
66+
SetActivity(ACT_RUN); // sequence by activity (+ slot)
67+
SetSequenceByName("pedestrian.wave", 1); // "package.sequence"
68+
69+
const int seqId = FindSequence("pedestrian.wave"); // -1 if not found
70+
SetSequence(seqId, 1);
71+
ResetSequenceTime(1);
72+
PlaySequence(1);
73+
```
74+
75+
- `SetActivity(act, slot)` calls `TranslateActivity` (override to pick a variant, e.g. a different
76+
run for a wounded character), finds the sequence with `FindSequenceByActivity`, resets the time
77+
and plays it.
78+
- `SetSequenceByName(name, slot)` / `FindSequence(name)` take `"<package>.<sequence>"`.
79+
- `SetSequence(seqId, slot)` only assigns the sequence (no reset, no play).
80+
- Playback: `PlaySequence`, `StopSequence` (pause), `IsSequencePlaying`, `ResetSequenceTime`,
81+
`SetSequenceTime(frame)`, `SetPlaybackSpeedScale`.
82+
- Queries: `GetCurrentActivity`, `GetSequenceById`, `GetSequenceTimer`,
83+
`GetCurrentAnimationFrameCount`, `GetCurrentAnimationDuration` / `Time` /
84+
`RemainingDuration` (seconds).
85+
- Non-looping sequences stop on the last frame; looping ones wrap and restart their events.
86+
- `ACT_SCRIPTED_SEQUENCE` sequences are not registered by activity — play them by name.
87+
- To add an activity, extend `Activity` in `anim_activity.h` and the name table in
88+
`anim_activity.cpp` (sequences refer to activities by name).
89+
90+
### Slots, blending and transitions
91+
92+
There are `MAX_SEQUENCE_TIMERS` (5) slots; each plays its own sequence:
93+
94+
- Slot 0 is the base pose (weight always 1). Other slots are mixed in with
95+
`SetSequenceBlending(weight, slot)`: sequences with `SEQFLAG_SLOTBLEND` are added on top
96+
(scaled by the weight; e.g. upper-body gestures), others are interpolated towards by the weight.
97+
- When a slot switches to another sequence, the previous one keeps playing in a transition timer
98+
and fades out over the new sequence's `transitiontime` (default `SEQ_DEFAULT_TRANSITION_TIME` =
99+
0.15 s). `IsTransitionCompleted(slot)`.
100+
- `SwapSequenceTimers(a, b)` swaps two slots.
101+
102+
### Pose controllers
103+
104+
A pose controller is a named value that blends between the animations of a sequence (e.g. aim
105+
direction, steering angle): the value is mapped over the controller's blend range onto the
106+
sequence's animations, and the two nearest animations are interpolated.
107+
108+
```cpp
109+
const int steerCtrl = FindPoseController("steer");
110+
SetPoseControllerValue(steerCtrl, steerAngle);
111+
```
112+
113+
- `GetPoseControllerValue`, `GetPoseControllerInterpValue` (the value used for blending; it
114+
follows the set value smoothly in `AdvanceFrame`), `GetPoseControllerRange`.
115+
- Controllers are shared by name between all motion packages of the object; their initial value is
116+
the middle of the range.
117+
118+
## Animation events
119+
120+
Sequences carry events at frames (`command` + `parameter` strings in the `.asc` script). When the
121+
timer passes the event frame, `HandleAnimatingEvent(event, parameter)` is called with the
122+
`AnimationEvent` resolved by name (`EV_SOUND`, `EV_MUZZLEFLASH`, `EV_IK_*`) or, if the name is
123+
unknown, by number (`atoi(command)`). Override it in the game object, e.g. to play a sound:
124+
125+
```cpp
126+
void CPedestrian::HandleAnimatingEvent(AnimationEvent event, const char* options)
127+
{
128+
if (event == EV_SOUND)
129+
{
130+
EmitParams ep(options, GetOrigin());
131+
EmitSound(CSoundingObject::ID_RANDOM, &ep); // object is also a CSoundingObject
132+
}
133+
}
134+
```
135+
136+
To add an event type, extend `AnimationEvent` and `anim_event_register` in `anim_events.cpp`.
137+
138+
## Inverse kinematics
139+
140+
IK chains come from the EGF (`studioIkChain_t`, defined in the `egfca` script):
141+
142+
```cpp
143+
const int chain = FindIKChain("left_leg");
144+
SetIKChainEnabled(chain, true);
145+
SetIKWorldTarget(chain, footTargetWorld, worldMatrix); // or SetIKLocalTarget(chain, localPos)
146+
...
147+
UpdateIK(dt, worldMatrix); // after RecalcBoneTransforms
148+
```
149+
150+
Disabled chains follow the animated pose. The solver iterates `r_ikIterations` times per update.
151+
The IK code is marked as broken in the source (`UpdateIkChain` FIXME) — treat it as experimental.
152+
153+
## Debugging
154+
155+
- `DebugRender(worldMatrix)` with cheat ConVars `r_debugSkeleton` (bones), `r_debugShowBone <idx>`
156+
and `r_debugIK` (IK targets).
157+
- Lua: `AnimatingEGF` is bound in `shared/sys/scripting/sys_esl_animating.cpp` (see
158+
[scripting_esl_overview.md](scripting_esl_overview.md)).
159+
- `tools/egfMan2` (`CAnimatedModel`, derived from `CAnimatingEGF`) plays sequences, edits pose
160+
controllers and shows bones; use it to check motion packages.

‎docs/architecture.md‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ Related documents:
2020
| [public_localization.md](public_localization.md) | Localization: language files, tokens, helpers |
2121
| [public_rendering_overview.md](public_rendering_overview.md) | Material system overview: materials, variables, proxies, textures, debug drawing, fonts |
2222
| [public_egf_overview.md](public_egf_overview.md) | EGF (Entity Geometry Format): models, motion packages, physics models |
23+
| [rendering_egf_overview.md](rendering_egf_overview.md) | EGF runtime (`shared/studio`): studio cache, model loading, GPU geometry, skins, LODs, drawing |
24+
| [animating_egf_overview.md](animating_egf_overview.md) | EGF animation (`shared/animating`): sequences, activities, blending, pose controllers, events, IK |
25+
| [rendering_matsystem_shaders_overview.md](rendering_matsystem_shaders_overview.md) | Material shaders: `CBaseShader`, pipelines, bind groups, `.def` files, overrides, `BaseUnlit` with GRIM |
26+
| [rendering_grim_overview.md](rendering_grim_overview.md) | GRIM: GPU-driven instance rendering, its shaders, `samples/GPUDriven` |
27+
| [sys_application_overview.md](sys_application_overview.md) | Application framework (`shared/sys`): start-up, game loop, app states, console, configs |
28+
| [input_overview.md](input_overview.md) | Input: key codes, command bindings, vector actions, touch zones, controllers |
29+
| [physics_overview.md](physics_overview.md) | Physics (`shared/physics`, eqPhysics): world, collision objects, rigid bodies, ray tests, constraints |
30+
| [sound_emitter_system_overview.md](sound_emitter_system_overview.md) | Sound emitter system: script banks, sounding objects, parameter graphs, audio system |
31+
| [scripting_esl_overview.md](scripting_esl_overview.md) | ESL (Eq Script Library): Lua bindings, engine Lua state |
2332
| [tools_overview.md](tools_overview.md) | Content tools: egfCA, animCA, EGFMan2, FCompress, ShaderCooker, TexCooker, localization tool |
2433

2534
## Overview
@@ -67,7 +76,7 @@ Public interfaces are declared in `public/` and implemented in `core/` or `share
6776
| `core/materialsystem1/Shaders/` | Material shader definitions: `Base/` (built into `eqBaseShaders`), `Engine/` |
6877
| `public/core/` | Core interfaces: `IDkCore`, `IFileSystem`, `IConsoleCommands`, `ICommandLine`, `ILocalize`, `IEqParallelJobs`, `IEqCPUServices`, `InterfaceManager` — see [public_core.md](public_core.md) |
6978
| `public/materialsystem1/` | Material system interfaces, `BaseShader`, `MeshBuilder`, render definitions; `renderers/` holds RHI interfaces (`IShaderAPI`, `ITexture`, `IGPUBuffer`, ...) |
70-
| `public/{audio,font,input,physics,render,egf,dkphysics}/` | Public headers of the corresponding `shared/` libraries |
79+
| `public/{audio,font,input,physics,render,egf}/` | Public headers of the corresponding `shared/` libraries |
7180
| `shared/dpk/` | DPK package and ZIP readers/writer |
7281
| `shared/font/` | Font loading, caching and text layout |
7382
| `shared/render/` | Render utilities: debug overlay, particles, decals, sprites, render lists, blur/sort compute |
@@ -76,8 +85,7 @@ Public interfaces are declared in `public/` and implemented in `core/` or `share
7685
| `shared/egf/` | EGF/motion package generator and source model loaders (ESM, FBX, OBJ) — tools only |
7786
| `shared/animating/` | Skeletal animation, bone setup, activities and events |
7887
| `shared/audio/` | Audio system on OpenAL, sound emitters/scripts/mixer; `source/` holds WAV/OGG sources |
79-
| `shared/physics/` | EqPhysics engine on top of Bullet collision |
80-
| `shared/dkphysics/` | Legacy Darktech physics on Jolt (deprecated, kept for EGFMan2) |
88+
| `shared/physics/` | EqPhysics engine on top of Bullet collision — see [physics_overview.md](physics_overview.md) |
8189
| `shared/equi/` | EqUI interface library: manager, controls, scheme |
8290
| `shared/imgui_backend/` | ImGui host and material-system renderer backend |
8391
| `shared/scripting/` | ESL — Lua binding library |
@@ -208,7 +216,6 @@ All are static libraries using `public` and `shared` include paths.
208216
| `scriptLib` | `scripting/**` | (lua) |
209217
| `sysLib` | `sys/**`, `input/**` | scriptLib, renderUtilLib, equiLib, movieLib, imguiBackendLib (SDL2, imgui_lua, tracy) |
210218
| `egfLib` | `egf/**` | studioFileLib (bullet2, zlib, openfbx, meshoptimizer) — `ENABLE_TOOLS` only |
211-
| `dkPhysicsLib` | `dkphysics/**` | studioLib, animatingLib (jolt) — `ENABLE_TOOLS` only |
212219

213220
### Tools (`tools/premake5.lua`, `ENABLE_TOOLS`)
214221

‎docs/commit_messages.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ lines:
3030
- Start every line with `- ` (dash and space).
3131
- `<scope>` — the module or area changed, lowercase, matching the directory or project name:
3232
`ds`, `math`, `core`, `framework`, `keyvalues`, `esl`, `sys`, `matsystem`, `rhi`, `nvrhi`,
33-
`wgpu`, `render`, `grim`, `equi`, `physics`, `dkphysics`, `studio`, `egf`, `audio`, `input`,
33+
`wgpu`, `render`, `grim`, `equi`, `physics`, `studio`, `egf`, `audio`, `input`,
3434
`font`, `dpk`, `network`, `premake`, `deps`, `natvis`, `tests`, `docs`, and tool names
3535
(`egfca`, `animca`, `egfman2`, `fcompress`, `shadercooker`, `texcooker`). A sub-area may follow
3636
the scope: `sys: esl math ...`, `core: filesystem - ...`.

0 commit comments

Comments
 (0)