HiScene JSON Format Reference
HiScene is FCS's internal scene representation format, serialized as JSON and consumed by Three.js for WebGL rendering. For AI agents, HiScene provides complete 3D geometry data in a structured, parseable format - making it ideal for automated validation.
Quick Export
# Export HiScene from fli.exe
fli.exe model.fcs "Main" --t 3JS --o output.hiscene.json
Format Overview
{
"metadata": { "formatVersion": 3.1 },
"faceMaterials": [...], // Face material definitions
"lineMaterials": [...], // Line material definitions
"labelMaterials": [...], // Text label materials
"classes": [...], // Geometry classes (the actual 3D data)
"mainClassHash": "..." // Entry point class hash
}
Top-Level Properties
metadata
{"formatVersion": 3.1}
The format version. Current version is 3.1.
faceMaterials
Array of face material definitions for surfaces:
[
{
"colorDiffuse": [0.647, 0.165, 0.165], // RGB (0-1)
"doubleSided": true
},
{
"colorDiffuse": [0.753, 1, 1],
"doubleSided": true,
"opacity": 0.588,
"transparent": true,
"depthTest": true,
"depthWrite": false
}
]
lineMaterials
Array of line material definitions for edges:
[
{
"colorDiffuse": [0, 0, 0],
"dashPattern": [] // Empty = solid line
}
]
classes
The main geometry data. Each class can contain:
- Direct geometry (
threeJsModel) - References to other classes (
objects) - Or both
Class Structure
Geometry Class (with threeJsModel)
{
"className": "LinearTractionPart:8",
"classHash": "IJRbWKqNZyo",
"threeJsModel": {
"vertices": [0.07, 0.07, -0.025, 0.07, 0.07, 0.025, ...],
"faces": [3, 0, 1, 2, 3, 0, 3, 4, 5, 6, 7, 0, ...]
},
"fcsLines": {
"linesMaterialRle": [24, 0],
"lines": [1, 0, 2, 1, 3, 2, ...]
}
}
Reference Class (with objects)
{
"className": "WindowFill:1",
"classHash": "U5S3WyNYAG0",
"objects": [
{"n": "gbFrame", "h": "druNm0dGnpA"},
{"n": "gbRungs", "h": "N+rN+odnIyc"},
{"n": "gbGlassings", "h": "kurz2lx73AM"}
]
}
Geometry Data
vertices Array
Flat array of floats: [x1, y1, z1, x2, y2, z2, ...]
- Every 3 consecutive values = one vertex
- Vertex count =
vertices.length / 3
AI Parsing:
vertices = data["threeJsModel"]["vertices"]
vertex_count = len(vertices) // 3
points = [(vertices[i*3], vertices[i*3+1], vertices[i*3+2])
for i in range(vertex_count)]
faces Array
Three.js JSON Model format faces. Each face is encoded as:
[type, v1, v2, v3, material_index, ...]
Where type = 3 indicates a triangle face.
AI Parsing (triangles only):
faces = data["threeJsModel"]["faces"]
i = 0
triangles = []
while i < len(faces):
face_type = faces[i]
if face_type == 3: # Triangle
v1, v2, v3 = faces[i+1], faces[i+2], faces[i+3]
mat_idx = faces[i+4]
triangles.append((v1, v2, v3, mat_idx))
i += 5
fcsLines Object
Edge lines for wireframe rendering:
{
"linesMaterialRle": [24, 0], // RLE: 24 segments with material 0
"lines": [1, 0, 2, 1, ...] // Pairs: [start_vertex, end_vertex, ...]
}
Object References
Objects reference other classes with optional local coordinate system:
{
"n": "gbDetailedModel", // Name
"h": "gs1C3bHiNKU", // Hash (references another class)
"lcs": { // Optional: local coordinate system
"origin": [3, 0, 0],
"axes": [[0, 1, 0], [-1, 0, 0], [0, 0, 1]]
}
}
AI Validation Patterns
Count Vertices
def count_vertices(hiscene):
total = 0
for cls in hiscene["classes"]:
if "threeJsModel" in cls:
total += len(cls["threeJsModel"]["vertices"]) // 3
return total
Count Triangles
def count_triangles(hiscene):
total = 0
for cls in hiscene["classes"]:
if "threeJsModel" in cls:
faces = cls["threeJsModel"]["faces"]
i = 0
while i < len(faces):
if faces[i] == 3: # Triangle
total += 1
i += 5
return total
Compute Bounding Box
def compute_bbox(hiscene):
all_coords = []
for cls in hiscene["classes"]:
if "threeJsModel" in cls:
v = cls["threeJsModel"]["vertices"]
for i in range(0, len(v), 3):
all_coords.append((v[i], v[i+1], v[i+2]))
if not all_coords:
return None
xs, ys, zs = zip(*all_coords)
return {
"min": [min(xs), min(ys), min(zs)],
"max": [max(xs), max(ys), max(zs)]
}
Extract Class Names
def get_class_names(hiscene):
return [cls["className"] for cls in hiscene["classes"]]
Geometry Hash (Exact Match)
import hashlib
import json
def geometry_hash(hiscene):
# Normalize and hash the full scene
canonical = json.dumps(hiscene, sort_keys=True, separators=(',', ':'))
return hashlib.sha256(canonical.encode()).hexdigest()
Test Validation Example
Test Definition
{
"id": "test-geometry-box",
"task": "Create a simple box",
"validation": {
"type": "hiscene",
"scene_expression": "Main",
"vertex_count": 8,
"class_count": 1
}
}
PowerShell Validation
# In Run-GolemTests.ps1 with -ExportHiScene switch
$hiscene = Get-Content "test.hiscene.json" -Raw | ConvertFrom-Json
# Count vertices across all geometry classes
$totalVertices = ($hiscene.classes |
Where-Object { $_.threeJsModel } |
ForEach-Object { $_.threeJsModel.vertices.Count / 3 } |
Measure-Object -Sum).Sum
# Count geometry-containing classes
$classCount = ($hiscene.classes | Where-Object { $_.threeJsModel }).Count
HiScene vs Other Formats
| Aspect | HiScene | PNG Image | Numeric Invariants |
|---|---|---|---|
| Data completeness | Full 3D | 2D projection only | Summary only |
| Exact geometry | ✓ | ✗ | Partial |
| Topology | ✓ | ✗ | ✓ |
| Materials | ✓ | Baked | ✗ |
| Named hierarchy | ✓ | ✗ | ✗ |
| File size | 10-100KB | 50-500KB | ~100 bytes |
| AI parseable | ✓ | Requires vision | ✓ |
Summary
HiScene provides the complete internal representation of FCS geometry:
- Exact vertex positions - no rasterization loss
- Full topology - faces, edges, connectivity
- Material assignments - colors, transparency
- Hierarchical structure - named classes and references
- Deterministic - same model produces identical JSON
For AI validation, HiScene is the definitive source of truth.