Engineering Dynamics Company
HVE Toolkit™
Simulation & Workflow Tools for Blender
A hands-on guide to using the HVE Toolkit add-on for Blender: HVE simulation setup, H3D export, and result import.
This guide walks you through installing the add-on, finding its panels, and completing the most common tasks step by step.
HVE Toolkit bridges Blender and HVE (Human Vehicle Environment) simulation workflows: set up and export scene objects (vehicles, environments, GATB surfaces) as HVE .h3d files, and import simulation results back into Blender (variable-output CSV/HVO, HVE FBX, RaceRender conversion).
The add-on gets its own sidebar tab in the 3D View (EDC Toolkits by default).
HVEToolkit-<version>.zip from the latest release (or clone this repository and run python tools/build_release.py to build dist/HVEToolkit-<version>.zip)..zip.Tip — rename the tab. The add-on's preferences (Edit → Preferences → Add-ons, expand the add-on) let you choose the sidebar tab name: the default EDC Toolkits, HVE, Human Vehicle Environment, or a custom name.
If you don't see the tab, confirm the add-on is enabled and that you are in the 3D View (not, say, the Shader Editor).
Everything sits inside one HVE Toolkit dropdown in the tab (so other EDC add-ons can share the tab, each under its own heading), with these panels:
| Panel | Use it for | Sub-panels |
|---|---|---|
| Pre-Simulation Setup | Getting Blender objects ready for HVE and exporting them | H3D Setup, Export to HVE |
| Post-Simulation Processing | Bringing HVE results back into Blender | HVE FBX Importer, Variable Output Importer, Imported Runs, Data Display Box, RaceRender Converter |
| HVE Configuration | Settings inside HVE itself, read when it starts | HVE Output Precision |
| Documentation | Opening this guide | Open User Guide opens the bundled offline copy in your browser; What's New shows the changelog for the version you are running, also offline |
Most panels are collapsed by default — click a panel header to expand it. The task guides below follow this same order: Pre-Simulation Setup, Post-Simulation Processing, then HVE Configuration.
HVE Configuration is separate from the other two because it does not touch this scene at all — it edits HVE's own Language.rsc, which HVE reads when it starts. It is also not a post-simulation step, despite being where you notice you need it: the precision it sets governs what HVE *writes*, so it has to be changed before the export, not after.
If you only use part of the toolkit, you can hide the rest. Open Edit → Preferences → Add-ons, expand HVE Toolkit, and use the Features checkboxes:
| Group | Feature | Hides |
|---|---|---|
| Pre-Simulation Setup | H3D Setup | Materials, object type, vehicle lighting, terrain properties |
| Export to HVE | Vehicle / environment .h3d and GATB surface .csv export | |
| Post-Simulation Processing | HVE FBX Importer | FBX import and the processing pipeline |
| Variable Output Importer | HVE .hvo / .csv variable-output import | |
| Data Display Box | The on-screen readout of imported variable-output channels | |
| Imported Runs | The list of imported files and each run's Time Zero and Time Scale | |
| RaceRender Converter | RaceRender .csv conversion | |
| HVE Configuration | HVE Output Precision | The Language.rsc editor: precision, labels and limits |
All eight are on by default. Unchecking one removes its panel from the sidebar immediately — no restart needed. Turn off every tool in a group and the group heading disappears too, so hiding both Pre-Simulation tools leaves just the Post-Simulation panels. Documentation always stays visible.
Nothing is uninstalled: the tools are only hidden, and re-checking a box brings the panel back with its settings intact.
Click Save Preferences (or enable Auto-Save Preferences) so your choices persist the next time you open Blender.
Each subsection below is a self-contained task, ordered to match the panels in the sidebar.
Open Pre-Simulation Setup → H3D Setup, then:
hve_presets/)..h3d.h3d.csvAny material texture is copied into a VehTextures/ folder (for vehicles) or EnvTextures/ folder (for environments) next to the saved .h3d and referenced with a relative path. This allows you to move the .h3d and its texture folder together while keeping the links working.
Open Post-Simulation Processing and pick the matching importer:
.fbx. On import, the HVE hierarchy is renamed into cleaner labels, the scene timeline is extended to cover the animation, and objects are organized into HVE collections by event, vehicle, wheels, and body. Then set Max Shape Key Samples (the cap on shape keys kept per mesh; 0 = no cap) and use the Process section to run the Reduce Keys → Merge Meshes → Smooth cleanup pipeline — see Choosing what gets processed for the three scopes..hvo/.csv of time plus variable-output columns. Choose feet or meters, optionally override the scale factor, and optionally save separate vehicle CSV files.Two-dimensional reconstructions import. A planar run carries no height, roll or pitch, and those three columns are filled with zero rather than the file being refused — zero is what they would have held had the program written them. What a file must carry is where the vehicle is on the ground and which way it points; without those there is no animation to build, and the importer says which columns are missing instead of failing partway through with a KeyError.
.csv files.Missing FBX textures are relinked from the HVE support files automatically, so a scene imported on a machine that does not share the original's paths still comes in textured. The folder searched is set in the add-on preferences and defaults to HVE's own install location.
All three buttons run the same pipeline — Reduce Keys → Merge Meshes → Smooth — and differ only in *which vehicles* they touch. They sit in the HVE FBX Importer → Process box, widest scope first:
| Button | Processes |
|---|---|
| Process All Imported FBX | Every HVE vehicle in the file, from every imported run |
| Process Selected Collection | Only vehicles whose body meshes sit inside the collection you pick above the button |
| Process Selected Imported Run | Only the vehicles from the run highlighted in Imported Runs |
The last two grey out until you have made the matching choice — a collection in the Collection field, or a row in the Imported Runs list.
This matters once a .blend holds more than one run. Process All Imported FBX really does mean all of them, so if you have imported two crashes and only want to work on one, use Process Selected Imported Run and the other is left exactly as it is.
Max Shape Key Samples applies to whichever button you press (the cap on shape keys kept per mesh; 0 = no cap).
Runs with the same vehicle names. Two imports of the same vehicles — a baseline and a variant, say — stay separate. Processing works one run at a time, so a
Freightlinerin one run is never merged into theFreightlinerin another, even with Process All Imported FBX.
By default an imported run starts at frame 0, with the vehicle's setup pose on frame -1. To leave room ahead of the crash — matching video, or staging two runs against each other — set Time Zero Frame in the importer panel before importing. Setting it to 300 puts t=0 on frame 300.
The setup pose stays on frame -1, and the add-on writes a hold key on the frame just before t=0 (frame 299 in this example) carrying that same pose. That span is therefore flat: the vehicle waits at its starting position instead of drifting slowly into place across the pre-roll, and the only motion is the same one-frame transition into t=0 that an unshifted import already has.
Changing it after import. Open Post-Simulation Processing → Imported Runs. Every imported FBX and variable-output file is listed by filename with its current time zero. Select one and edit Time Zero — the run moves immediately, hold key and all.
Each run is independent: re-timing one leaves every other import exactly where it is, so you can hold run A at 0 and push run B out to 300. All the vehicles from a single file share one time zero and move together, since a run is one synchronized event.
To process just this run, highlight it here and use Process Selected Imported Run in the HVE FBX Importer → Process box — see Choosing what gets processed.
Three actions sit under the list:
| Button | What it does |
|---|---|
| Select | Selects everything that came from the highlighted import |
| Delete | Deletes those objects and prunes the empty collections they leave behind, then drops the row |
| Forget | Drops the row only — the objects and their animation stay exactly as they are |
Delete asks for confirmation first, and touches only that run: other imports in the file are left alone. Use Forget when you want to keep the result but stop tracking it — after that it can no longer be re-timed as a group.
Re-timing moves everything the run animates, including vehicle damage (shape-key animation, which lives on the mesh rather than the object) so the crush stays synchronized with the motion.
Skids are handled too, but by a different mechanism. A skid is drawn progressively by a Geometry Nodes group that compares each vertex's index against the current frame, so no amount of keyframe shifting would delay it — re-timing therefore also writes Time Zero and Time Scale into that modifier, and the skid starts laying down when the run does and at the run's pace. Tire paths and vehicle paths are drawn in full rather than progressively, and their keyed values move with the rest of the run.
A
.blendsaved before this existed is upgraded in place the next time a variable output is imported or a run is re-timed — the node group gains the Time Zero and Time Scale inputs rather than being replaced.
The scene frame range is not changed when you re-time a run, so your own start/end stay put. Extend the range yourself if a run now ends past it.
Set the time zero before running Process Imported FBX where you can. Processing bakes and merges shape keys, so doing it in that order keeps the damage timing unambiguous.
An import lands one key per data sample, so the run plays at the rate it was exported at, not the rate the scene runs at. That is fine when the scene exists to show the run, and wrong in two common cases:
Both importers set the scene's frame rate from the data by default. Tick Keep Scene Frame Rate in the importer panel to leave the scene alone and have the run scaled to suit it instead.
An HVE FBX does not carry its frame rate. FBX has somewhere to put one — GlobalSettings holds a TimeMode, plus a CustomFrameRate for rates outside the standard list — and Blender reads it. HVE writes neither, so Blender substitutes its own default of 25 fps and nothing downstream can tell that apart from a file that genuinely says 25.
That number is not cosmetic. Time Scale, the speed bake and the acceleration bake are all derived from it, so a 100 fps run read as 25 fps has every derived speed wrong by a factor of four.
So the FBX importer asks, and the number it asks for is one you already have: HVE's Output Time Interval. An interval of 0.01 s is 100 fps.
There is no "read it from the file" option, because there is no case where that would be right — this importer reads HVE's FBX and nothing else, and HVE declares no rate. If a file *does* declare one, the import says so: it did not come from HVE, and the rate you entered is used anyway.
Frame Rate describes the data, not what you want. It is a fact about the file and never changes to suit the scene. Rescaling is a separate decision, below.
The panel echoes the interval back (= 0.01 s between samples in HVE) so you can check it against HVE without converting in your head, and says what the rate will do in *this* scene — either "Scene will change from 25 to 100 fps" or, with Keep Scene Frame Rate on, "Scene stays at 25 fps; run scaled to 0.25 frames per sample".
Both of those play at real speed; the toggle only decides which of the two gives way. What does *not* play at real speed is a wrong rate: 100 fps of data left in a 25 fps scene at a Time Scale of 1.0 runs at a quarter speed.
This is the difference from the Variable Output importer. A variable output file has a time column, so its rate is measured from the data and nothing needs entering. An FBX has neither a time column nor a declared frame rate, so the rate can only come from you. Imported Runs says which a given run used — *Entered at import* or *Read from the file's time column* — and lets you correct an FBX's rate afterwards without re-importing. Everything downstream is the same either way: Time Scale and Match Scene Frame Rate work on both.
Leave Frame Rate at 100 — that is what the data is, and it does not change. Then choose which side gives way:
| What to do | What happens | |
|---|---|---|
| Keep the scene at 30 | Set the scene to 30 fps, tick Keep Scene Frame Rate, import | The run is scaled to 0.3 frames per sample, so 100 samples fill 30 frames — one second of data in one second of playback |
| Let the run set the rate | Leave Keep Scene Frame Rate off | The scene becomes 100 fps and the run plays one sample per frame |
Both play at real speed. The first keeps 30 fps for footage or rendering and costs nothing but the scaling; the second is simpler when the scene exists only to show the run.
Already imported at the wrong setting? Set the scene to 30 fps, then press Match Scene Frame Rate in Imported Runs — same result, no re-import.
Every import reports which rate it used and where it came from. A file that declares nothing is reported as a warning rather than used quietly, and overriding a rate the file genuinely did carry is flagged too.
After import, the same thing is available per run. Open Imported Runs, select the row, and use Data Frame Rate and Time Scale:
| Field / button | What it means |
|---|---|
| Data Frame Rate | Samples per second in the source. Correct this if a run came in at the wrong rate — no re-import needed. A run still showing 25 fps is flagged, since that is Blender's stand-in |
| Time Scale | Timeline frames each data sample occupies. 1.0 is one sample per frame, as imported |
| Match Scene Frame Rate | Sets the scale so the run plays at real speed in this scene |
| Reset Scale | Back to one sample per frame |
The panel shows the source rate and the scene's rate side by side, so you can see what needs matching. A 100 fps run in a 30 fps scene wants a scale of 0.3: 100 samples become 30 frames, one second either way. A 10 fps run in the same scene wants 3.0.
Scaling pivots on the run's time zero — the frame you placed it on does not move, and the setup pose stays on frame -1. Time Zero and Time Scale are independent, so changing one never undoes the other.
This replaces re-running the simulation at the scene's rate just to export a matching FBX.
A scale below
1.0puts keys on fractional frames. Blender evaluates them correctly, but the *rendered* motion is still sampled once per frame, so a heavily compressed run shows fewer distinct poses than the data contains. That is the same limit re-exporting at the lower rate would hit.
Scale a run before Process Imported FBX where you can, for the same reason as time zero.
Use Data Display Box (under Post-Simulation Processing) to render imported variable-output data as live text inside an HVE-style box — label column, divider, value column — that updates on every frame.
The short version. The panel's sections aren't in the order you use them — the channel list is long, so it sits at the bottom, *below* the button that builds the box. Work in this order instead:
| Step | Do this | Where |
|---|---|---|
| 1 | Scan Imported Data | top of the panel |
| 2 | Tick the channels you want shown | Channels, at the bottom |
| 3 | Create / Update Display Box | Display Boxes & Cameras |
| 4 | Select a camera, then click the 🔗 link button beside the box | Display Boxes & Cameras |
The panel tracks where you are and shows the next step as a numbered line near the top (*"Step 2 of 4: Check channels to show"*). Click that line and it opens the section the step is talking about; hover it for the full instruction. Once a box is built and attached to a camera the line goes away. Everything after step 4 — labels, units, decimals, colours, size, placement — is tuning, and each of those edits updates the box in place while Auto Update is on.
The rest of this section is the detail behind those four steps.
V Tot (mph). The scan only shows data the Variable Output Importer itself created — a generic scene custom property, or data imported by the Recon Toolkit, won't appear here even if both add-ons are installed on the same scene.Each row also has detach and ✕ remove (to delete just that box). Both perspective and orthographic cameras are supported — orthographic framing is computed from the camera's Orthographic Scale rather than its field of view, so the box sizes and positions correctly either way. An attached box automatically re-anchors itself to its corner every time the box rebuilds — including when you check or uncheck channels afterward — so it never needs re-attaching just because its row count changed.
Removing a box also removes its profile, unless another box still shares it — at least one profile is always kept around to edit.
Once attached, a box's on-screen *size* is set by Screen Width Fraction, not by Box Width — Box Width only controls the box's internal layout (divider position, column widths), so changing it afterward resizes the box on screen without also inflating or shrinking the text. That calibration is captured the moment you click the attach button, so click it again on an already-attached box any time you want to recalibrate its on-screen size to the current Box Width.
An On Camera group closes the section, holding everything that only applies once a box is attached to a camera:
0.1 is a tenth of the frame, positive is right and up. Being fractions means a box nudged clear of a timestamp stays clear of it when the camera moves or the lens changes.The whole group stays greyed out until a box using the profile you're editing is attached to a camera: every control in it only ever repositions an attached box, so before that there is nothing for them to move.
Honda Fit EX-L 5-Dr HB, V Tot (mph) — clear it if you don't want the prefix. It also has a Zero Frame Offset — an extra frame shift added on top of the box's own Time Zero Frame, applied only to that subgroup's channels — for re-syncing one dataset that's drifted a fixed number of frames out of step with the others (for example two datasets checked into the same box) without affecting anything else in the box.If both the HVE and Recon toolkits are installed, each manages its own display boxes independently (scanning or rebuilding in one never touches the other's boxes); when the scene also contains boxes from the other toolkit, the panel notes how many so it's clear why they aren't listed here.
Values are sampled from the imported animation data each frame, so the box tracks the simulation during playback and in final renders. Re-scanning keeps your checked channels and edits.
Settings that live in HVE itself rather than in this scene. They are read when HVE starts, so a change here applies to the next HVE session and to anything exported from it -- not to data already on disk.
HVE Output Precision edits how many decimal places HVE writes for a variable, without touching the file an HVE update will overwrite.
Why you would. Every variable has a printf format in HVE's Language.rsc. VehKinematicX ships as 8.2f — position on a 0.01 ft grid. That is plenty for reading a coordinate off the screen, and not nearly enough to differentiate. At a 100 Hz export, one 0.01 ft step becomes 0.68 mph of speed and 3.1 g of acceleration, so a speed trace derived from position climbs in visible stairs and an acceleration trace is unusable. No averaging window recovers it, because the information was never written.
Setup. Point Edit → Preferences → Add-ons → HVE Toolkit → HVE Support Files at HVE's supportfiles folder. The add-on reads Language.rsc and language_overrides.rsc from the sys folder inside it.
Use.
VehKinematic finds the six position and rotation columns.VariableOutput + Column is what lands in an exported CSV, and is the default.The mark at the left of each row says what, if anything, language_overrides.rsc has to say about that record. The legend under the list repeats it:
| Mark | Meaning |
|---|---|
| *(none)* | Not overridden. What you see is HVE's own value. |
| ● precision | The override changes the format — the number in the right-hand column is yours, not HVE's. |
| ○ label/limits | Overridden, but the format is untouched; it changes a heading or a limit. |
| ✕ no effect | Overridden with a copy of what Language.rsc already says. It does nothing. See Remove Redundant Overrides. |
The filled mark is reserved for precision because that is the column the list shows: a filled dot means the format beside it did not come from HVE.
Language.rsc on the left, your override on the right — with a row for the format, one for each label line, and one each for the soft and hard limits:`` Language.rsc Override Format 7.4f 7.4f Label 1 "" "" Label 2 "time" "time" Soft limits 0 .. 40 → 0 .. 480 Hard limits 0 .. 40 → 0 .. 480 ``
The rows that actually differ are the ones not greyed out. Unchanged rows are still shown, because seeing that the format matches on both sides is how you find out the change you are looking for is somewhere else. An override can change any of the three things, so "overridden" on its own never told you which. If the answer is *nothing* — the override is a copy of Language.rsc — it says that too, and points at Remove Redundant Overrides. Selecting a record also loads its current width, decimals, label and limits into the edit fields, so you are always editing from the record's real values rather than from whatever was last typed. The ↩ button beside Precision, Label or Limits reloads that box, for when you want to undo an edit without reselecting.
Labels. Below the precision fields, what HVE calls the record — the text you see on its panel, and the heading above its column in an exported CSV.
"Turn" over " On " as a two-row heading, and the spaces inside the quotes are how the second row is centred under the first. Both lines get their own field, and the spaces are kept exactly as typed.NULL and blanking a coordinate label writes "".Label records hold HVE expressions rather than text — "Roll Steer:" + "Axle no. " + CurrentAxleNum. Those are not offered for editing: rewriting one as plain text would replace working code with the words it happened to contain.Presets. A saved copy of the whole language_overrides.rsc, under a name. Made for exactly the case where you keep one high-precision set for deriving speed and another at HVE's stock values, and switch between them.
Language.rsc value; the dialog says so before you commit. Merge lays the preset's records on top of what is already there and leaves the rest alone.supportfiles — an HVE update is what overwrites things there, which is the whole reason the overrides file exists. Use the folder button to open it; each preset is an ordinary language_overrides.rsc, so one can be handed to a colleague or dropped straight into an install without this add-on.Records HVE cannot see. If the overrides file contains a record that was pasted in with a leading tab, it reads as part of the record above it rather than as its own, and HVE silently falls back to the Language.rsc value. The symptom is an override that simply does nothing, with nothing anywhere to explain it. The panel says so at the top, names the record and its line, and Fix Indented Records moves it back to column 0 — only the indentation changes.
Limits. Below the label fields, the same record's soft and hard limits. Soft is the range HVE's panel offers by default; hard is the range it refuses to go beyond.
* means that limit is unset — 431 of the shipped rows are. Unset is not the same as zero, so it is shown as * rather than as a number.Language.rsc ships five like it, and refusing to write what the vendor ships would be a tool wrong about its own rules.Nothing is written until you press a Write button. The fields are just fields — typing in them changes nothing on disk, and neither does selecting a different record. There is no autosave and nothing to lose by looking around.
Changing many records at once. Set the filters until the count in the header is the set you want — VehKinematic + Column is the six position and rotation columns — then set Width and Decimal Places and press Write Precision to All Matches. It names the number before doing it, and writes straight away — there is no second step. Only the format changes; labels and limits are per-record and are left alone. A record that cannot hold the requested format is reported and skipped rather than abandoning the rest half-applied.
Undo. Blender's Ctrl+Z does not reach a file on disk, so every write keeps the previous language_overrides.rsc as language_overrides.rsc.bak and Undo Last Write swaps them back. It is one step deep, and it swaps rather than discards — pressing it twice returns you to where you started. A batch edit writes once, so one press undoes the whole batch. For a single record, Remove Override is the more precise tool: it drops just that record and lets Language.rsc apply again.
Tidying up. Remove Redundant Overrides drops every override that no longer says anything Language.rsc does not already say — the residue of setting a value and later putting it back. It lists what it will remove before doing it, and nothing HVE reads changes.
Worth doing occasionally: an override that matches the base is not harmless. It hides the fact that HVE's own default is what you are getting, and it will keep hiding it if a future HVE update changes that default, because the stale copy wins. An override that only changes a label or a limit is kept — it is still doing something, even though the precision matches.
Reading the files. The Files buttons load Language.rsc or language_overrides.rsc into Blender's Text Editor. That is a copy in the blend file, not a live view — edits made there do not reach HVE unless you save them yourself, and the panel will not see them.
What gets written. Only language_overrides.rsc. Language.rsc is never modified — and that is enforced rather than merely intended: every write in the add-on passes through one check that refuses HVE's own file by name, whatever it is handed and wherever the support files folder points. If something ever tries, it fails with a message instead of succeeding quietly. The whole record is copied across, not just the format, because HVE reads the overrides file on its own. The previous overrides file is kept as language_overrides.rsc.bak.
Restart HVE to apply — the overrides file is read at startup.
Recommended: 4 decimal places for position, 5 for angles (they are in radians, so 0.0001 rad is 0.006° — coarser than it looks). Width must leave room: use 10, not 8, or the column overruns and every row after it goes ragged. The panel refuses a width too small for its decimals rather than writing a broken column.
The error is absolute, not relative. The same 0.01 ft grid is 12% of a 5 mph manoeuvre and 1% of a 50 mph one. Slow manoeuvres need *more* precision, not less — the opposite of the intuition.
Lowering the export rate helps more than adding decimals. Ten times the gap between samples means ten times less amplification for speed and a hundred times less for acceleration. For a one-second low-speed manoeuvre, 20–50 Hz at the shipped precision beats 100 Hz at four decimals. The trade-off is time resolution: 10 Hz cannot resolve a crash pulse.
The EDC Toolkits tab is missing. Make sure the HVE Toolkit add-on is enabled in Preferences, you're in the 3D View, and the sidebar is open (N). Check the tab name in the add-on's preferences.
Which version am I running? The console prints it when the add-on loads — HVE Toolkit 3.3.11 successfully (re)loaded from <folder> — which also settles whether a second, older copy installed somewhere else is the one Blender picked up.
Panels are flat instead of nested. Switching the add-on off and on again in Preferences puts them back. If it keeps happening, the console output from a fresh Blender start is what helps — on Windows, Window → Toggle System Console.
The export button warns about mixed HVE object types. The selection contains objects classified as different types — use the one-click reclassify buttons in the warning (or H3D Setup → Object Type) to make the selection one type, then export.
HVE Toolkit™ is a trademark of Engineering Dynamics Company (Anthony Cornetto). The source code is GPL v2 or later. HVE Toolkit is a workflow aid for HVE simulation, not a substitute for professional engineering judgment — independently validate every result. See the bundled LICENSE file for licensing and the full disclaimer.
Official builds, updates, and support are provided by Engineering Dynamics Company; visit edccorp.com or contact EDC support.