InDI: Industrial Digital Twin Platform
Transforming Industrial Operations Through Immersive 3D Digital Twins and Real-Time Data Integration
Executive Summary
InDI (Industrial Digital Integration) is an enterprise-grade digital twin platform that revolutionizes how industrial facilities are visualized, monitored, and managed. By combining high-fidelity 3D visualization with real-time operational data, InDI enables organizations to make faster, more informed decisions about their critical infrastructure.
Built on a modern .NET 8/9 architecture with Unity 3D integration, InDI bridges the gap between static CAD/design models and live operational intelligence. The platform serves mining, oil & gas, manufacturing, and utilities sectors with a comprehensive solution that spans from CAD processing pipelines through to immersive VR experiences.

Key Value Propositions
For Business Stakeholders:
- Operational Clarity: Transform complex CAD models into interactive 3D environments with live data overlays
- Rapid Insights: Navigate massive industrial facilities with instant access to equipment status and metadata
- Risk Mitigation: Train personnel in virtual environments before engaging with real equipment
- Cost Reduction: Identify issues and plan maintenance without physical site visits
- Multi-Tenant Architecture: Support multiple industrial sites from a single deployment with flexible storage backends
- Vendor Independence: Deploy on Azure, AWS, on-premises, or hybrid cloud with zero code changes

For Software Developers:
- Clean Architecture: Domain-driven design with clear separation of concerns across 36+ reusable libraries
- Scalable Processing: THOR pipeline transforms millions of CAD assets into optimized 3D tilesets
- High-Performance Graphics: Unity-based rendering with DOTS/ECS for millions of entities at 60+ FPS
- gRPC Performance: 4x throughput improvement over REST with bidirectional streaming
- Storage Abstraction: Unified API supporting FileSystem, Azure Blob, AWS S3, and MinIO
- Lucene Search: Sub-second full-text search across millions of assets with faceted filtering
- Comprehensive Testing: 15 test projects with 700+ tests covering unit, integration, and E2E scenarios
- Modern Build Pipeline: Type-safe C# build automation with Nuke and Azure Pipelines
Target Users & Deployments
- Mining Operations: BHP, Rio Tinto, Fortescue Metals Group (FMG), Roy Hill
- Oil & Gas: Shell, Chevron, Woodside
- Manufacturing: Processing plants, refineries
- Utilities: Power generation, water treatment

Repository Scope
This monorepo contains the complete InDI platform:
- 36+ Libraries: Modular components for storage, search, data integration, and visualization
- 5 Applications: Web apps, Unity viewers, console tools, and background services
- 1,560+ C# Files: Professional codebase with extensive documentation
- 15 Test Projects: NUnit, BUnit, and Selenium tests ensuring quality
- .NET 8/9: Modern framework with cross-platform support
Project Overview
What is InDI?
InDI is a comprehensive digital twin platform designed for large-scale industrial operations. The platform encompasses:
Complete Data Pipeline:
- THOR Pipeline: CAD processing engine that transforms raw Navisworks exports into optimized 3D assets
- Storage Layer: Multi-backend abstraction supporting Azure, AWS S3, MinIO, and local filesystems
- Search Engine: Lucene.NET-powered indexing for millions of assets with hierarchical queries
- Integration Layer: Real-time data streaming from SCADA, IoT, PIMS, and health management systems
Visualization & Interaction:
- Unity Viewer: High-performance 3D rendering with VR support and DOTS/ECS for millions of entities
- Blazor Web App: Server-side UI with real-time SignalR updates and embedded Unity integration
- Multi-Layer Interop: Seamless communication between Blazor ↔ JavaScript ↔ Unity ↔ Embedded Browser
- Asset Status System: Real-time equipment health visualization with colored highlights and contextual cards
Key Capabilities:
- High-Performance 3D Visualization: Render millions of CAD assets in real-time with smooth navigation
- Real-Time Data Integration: Overlay live equipment status, sensor readings, and operational data onto 3D models
- Immersive Experiences: Support for VR headsets (Oculus, HTC Vive) and 360° immersive environments (Igloo systems)
- Intelligent Search: Full-text search across complex CAD hierarchies with sub-second response times
- Multi-Platform Delivery: Desktop viewers, web applications, and VR experiences from a single codebase
- Configuration-Driven: Zero code changes required between dev, staging, and production environments
Problems We Solve
For Operations Teams:
- Navigating complex facilities with thousands of equipment items is overwhelming
- Understanding equipment health requires context switching between multiple systems
- Training on complex operations is expensive and risky
- Planning maintenance activities without complete facility understanding leads to inefficiencies
For Engineering Teams:
- CAD models are static and don’t reflect current operational state
- Integrating design documentation with as-built reality is manual and error-prone
- Identifying spatial relationships in 2D drawings is difficult and time-consuming
For Management:
- Lack of visibility into facility-wide equipment health
- Difficulty communicating complex technical issues to stakeholders
- High cost of physical site visits for remote facilities
- Slow response times when incidents occur
Technical Architecture
System Architecture Overview
InDI employs a multi-tier architecture that separates concerns between CAD processing, 3D rendering, web UI, data integration, and storage. The platform follows layered architecture principles with clear separation between presentation, business logic, data access, and infrastructure concerns.
Navisworks] SCADA[SCADA Systems
Real-time Data] IOT[IoT Sensors
MQTT Feeds] AHM[Asset Health
Management APIs] PBI[PowerBI
Analytics] end subgraph "Processing Pipeline - THOR" NW[Navisworks Export
~500k triangles/batch] META[Metadata Extraction
SQLite Database] GRAPH[Node Graph Builder
CAD Hierarchy] TILE[Tileset Demarcator
Spatial Subdivision] OPT[Geometry Optimizer
LOD Generation] INDEX[CAD Index Assignment
Unique IDs] EXPORT[Format Export
glTF/b3dm/Unity] end subgraph "Storage Layer" BLOB[Azure Blob Storage
Versioned Assets] LUCENE[Lucene Index
Full-Text Search] CACHE[Memory-Mapped Files
Fast Random Access] end subgraph "Application Layer" VIEWER[Unity Viewer
3D Rendering + VR] WEBAPP[Blazor Web App
UI Components] BROWSER[Embedded Browser
JS Components] SEARCH[Search Service
Lucene Queries] SCREEN[Screen Analysis
DOTS System] end subgraph "Presentation" DESKTOP[Desktop Client
High Fidelity] WEB[Web Browser
Overlay UI] VR[VR Headset
Immersive] IGLOO[Igloo System
360° Environment] end CAD --> NW NW --> META NW --> GRAPH GRAPH --> TILE TILE --> OPT OPT --> INDEX INDEX --> EXPORT META --> GRAPH EXPORT --> BLOB GRAPH --> LUCENE EXPORT --> CACHE BLOB --> VIEWER LUCENE --> SEARCH CACHE --> VIEWER SCADA --> WEBAPP IOT --> WEBAPP AHM --> WEBAPP PBI --> WEBAPP VIEWER --> DESKTOP VIEWER --> VR VIEWER --> IGLOO WEBAPP --> WEB BROWSER --> WEB SEARCH --> WEBAPP SCREEN --> WEBAPP VIEWER <--> WEBAPP WEBAPP <--> BROWSER classDef dataSource fill:#1e3a5f,stroke:#4a90e2,color:#e1e4e8 classDef processing fill:#1f3a4f,stroke:#39d353,color:#e1e4e8 classDef storage fill:#3d2f1f,stroke:#ff9800,color:#e1e4e8 classDef application fill:#1f3d2f,stroke:#4caf50,color:#e1e4e8 classDef presentation fill:#3d1f3d,stroke:#9c27b0,color:#e1e4e8 class CAD,SCADA,IOT,AHM,PBI dataSource class NW,META,GRAPH,TILE,OPT,INDEX,EXPORT processing class BLOB,LUCENE,CACHE storage class VIEWER,WEBAPP,BROWSER,SEARCH,SCREEN application class DESKTOP,WEB,VR,IGLOO presentation
For Business Stakeholders: Architecture Benefits
Scalability: The tileset-based architecture allows InDI to handle facilities with millions of individual components without performance degradation. Whether you’re visualizing a small processing unit or an entire mine site, the system maintains smooth, responsive performance.
Maintainability: Clear separation of concerns means updates to the UI don’t affect 3D rendering, and changes to data sources don’t require reprocessing CAD models. This reduces maintenance costs and allows rapid deployment of new features.
Reliability: Transactional indexing and immutable data artifacts ensure data integrity. If a processing step fails, the system can retry without corrupting existing data.
Cost Efficiency: The processing pipeline runs once during CAD model ingestion, producing optimized assets that require minimal cloud compute resources during normal operation. This keeps operational costs predictable and low.
Flexibility: The platform integrates with any data source accessible via REST, SOAP, gRPC, or MQTT protocols. This means InDI can connect to legacy systems, modern cloud APIs, and everything in between.
For Software Developers: Technical Deep Dive
Processing Pipeline (THOR)
The THOR pipeline transforms raw CAD exports into optimized, spatially-organized 3D assets:
- Navisworks Export: CAD models are exported in batches of ~500,000 triangles using the Navisworks API
- Metadata Extraction: Equipment properties, hierarchies, and relationships are stored in SQLite
- Node Graph Construction: A complete graph of CAD nodes is built, tracking original Navisworks relationships and handling virtual duplication
- Tileset Demarcation: The site is subdivided spatially using polygon count and bounding box heuristics
- Geometry Optimization: Meshes are optimized (vertex welding, normal recalculation, triangle reduction)
- CAD Index Assignment: Each node receives a unique integer ID, assigned spatially for cache coherence
- Format Export: Assets are exported to glTF, 3D Tiles (b3dm), or Unity AssetBundles
Key Innovation: Tileset Port Architecture
Traditional scene-based pipelines process geometry linearly, blocking metadata processing until geometry is ready. The Tileset Port architecture decouples these concerns:
- Three Data Channels: SceneHandles (geometry), TilesetData (spatial organization), NodeGraph (metadata)
- Parallel Processing: Tileset demarcation begins as soon as node bounds are available, even while geometry is still being optimized
- Type-Safe Message Passing: DataFlow blocks ensure correct sequencing without manual synchronization
- Flexible Step Configuration: Each processing step declares which port types it requires and produces
This architecture reduced pipeline processing time by 40% for typical facility models.
Rendering Architecture (Unity Viewer)
The Unity-based viewer leverages:
- Universal Render Pipeline (URP): Modern render pipeline with mobile and desktop optimization
- Data-Oriented Technology Stack (DOTS): High-performance systems for visibility culling and screen analysis
- Entity Component System (ECS): Efficient memory layout for millions of entities
- Custom Shaders: Status-based emission for equipment health visualization
- LOD System: Automatic level-of-detail switching based on distance and importance
- Occlusion Culling: GPU-based occlusion queries to skip rendering hidden geometry
Search System (Lucene.NET)
Full-text search across CAD hierarchies using Lucene indexes:
- Field Types: Tokenized text fields for names/descriptions, non-tokenized string fields for IDs/GUIDs
- Hierarchical Queries: Navigate parent-child relationships in O(1) time using stored path fields
- Incremental Updates: Add/remove/update documents without full reindexing
- Memory-Mapped Indexes: Direct file access for minimal memory footprint
- Custom Analyzers: Domain-specific tokenization for equipment naming conventions
// Example: Searching for pumps in a specific area
var query = new BooleanQuery
{
{ new TermQuery(new Term("Type", "Pump")), Occur.MUST },
{ new WildcardQuery(new Term("Path", "*/Area51/*")), Occur.MUST }
};
var results = indexSearcher.Search(query, 100);
Web Application (Blazor Server)
Blazor provides:
- Component-Based Architecture: Reusable UI components with C# code-behind
- SignalR Communication: WebSocket-based real-time updates from server to client
- JS Interop: Seamless integration with JavaScript libraries for specialized functionality
- Dependency Injection: Scoped services for user-specific data and state management
Multi-Layer JavaScript Interoperability
One of the most complex aspects of InDI is the three-layer JavaScript interop:
- Blazor ↔ JavaScript: Standard Blazor JS interop for web components
- JavaScript ↔ Unity: Custom web component system with mutation observers
- Unity ↔ Embedded Browser: ZFBrowser API for direct DOM manipulation
This architecture enables:
- Real-time synchronization between 3D scene and web UI
- Performant updates using web workers for heavy calculations
- Bidirectional communication without polling
Technology Stack
Backend Technologies
| Technology | Purpose | Why We Chose It |
|---|---|---|
| .NET 8.0+ | Application framework | Cross-platform, high performance, excellent async support, mature ecosystem |
| ASP.NET Core | Web application hosting | Lightweight, modular, cloud-native design |
| Blazor Server | Interactive web UI | C# code sharing between server and client, reduces JavaScript complexity |
| gRPC | High-performance RPC | Binary protocol, streaming support, strong typing via Protocol Buffers |
| Lucene.NET | Full-text search | Proven technology for complex hierarchical queries, self-hosted (no cloud dependency) |
| Entity Framework Core | ORM for metadata | LINQ queries, migration support, multiple database provider support |
Frontend Technologies
| Technology | Purpose | Why We Chose It |
|---|---|---|
| Unity 2022.3 LTS | 3D rendering engine | Best-in-class VR support, cross-platform (Windows/Android/WebGL), large asset ecosystem |
| Universal Render Pipeline | Graphics pipeline | Modern, scriptable, mobile-optimized render pipeline |
| ECS/DOTS | High-performance systems | Massive performance gains for systems processing millions of entities |
| Zenject | Dependency injection | Flexible IoC container for Unity, supports complex dependency graphs |
| UniTask | Async operations | Allocation-free async for Unity, better performance than coroutines |
| Reactive Extensions (Rx) | Event-driven architecture | Composable event streams, natural fit for real-time data integration |
| ZFBrowser | Embedded web browser | Chromium-based browser for Unity, enables web content within 3D viewer |
Data Layer
| Technology | Purpose | Why We Chose It |
|---|---|---|
| Azure Blob Storage | 3D asset storage | Scalable, versioned, cost-effective for large binary files |
| AWS S3 / MinIO | S3-compatible storage | Vendor flexibility, on-premises support |
| SQLite | Embedded metadata | Zero-configuration, serverless, transactional, perfect for local metadata |
| DuckDB | Analytical queries | Embedded OLAP database, columnar storage, excellent for ad-hoc analysis |
| Memory-Mapped Files | Fast random access | OS-managed caching, O(1) lookups for CAD index → metadata mappings |
Integration Layer
| Technology | Purpose | Why We Chose It |
|---|---|---|
| Azure IoT Hub | IoT device connectivity | Managed service, bidirectional communication, device twins |
| MQTT Brokers | Message queuing | Lightweight pub/sub, ideal for sensor data streaming |
| REST APIs | Generic integration | Ubiquitous, well-understood, easy to consume from any platform |
| SOAP APIs | Legacy system integration | Still widely used in industrial systems, mature tooling |
| PowerBI Embedded | Analytics integration | Native embedding APIs, single sign-on, familiar interface for users |
Development & DevOps
| Tool | Purpose |
|---|---|
| JetBrains Rider | Primary C# IDE, excellent Unity integration |
| Visual Studio | Enterprise debugging, profiling, Azure integration |
| VS Code | Lightweight editing, TypeScript development |
| Azure DevOps | CI/CD pipelines, work item tracking, source control |
| Nuke.Build | Type-safe build automation in C# |
| Docker | Containerization (Azurite emulator for local dev) |
| Unity Profiler | Runtime performance analysis |
| RenderDoc | Graphics debugging |
| Lucene Luke | Index inspection and debugging |
| Navisworks | CAD model viewing and export |
Core Subsystems and Components
1. THOR Pipeline (CAD Processing)
Purpose: Transform raw CAD models into optimized, spatially-organized 3D assets suitable for real-time rendering.
Key Technologies: .NET 8, Aspose.3D, TPL Dataflow, System.Threading.Channels
Design Patterns:
- Pipeline Pattern: Processing steps connected via typed channels
- Actor Model: Each step processes messages independently and asynchronously
- Immutable Data Structures: Scene handles represent immutable geometry, new versions are created for modifications
Integration Points:
- Input: Navisworks CAD exports (FBX, OBJ), metadata SQLite database
- Output: Unity AssetBundles, glTF files, 3D Tiles (b3dm), Lucene indexes, CAD index binary files
Aspose.3D] BUILD[Build Hierarchy
Node Graph] INJECT[Inject Metadata
SQLite → NodeData] UNMERGE[Unmerge Geometry
Island Detection] DEMARCATE[Create Tileset
Spatial Subdivision] ASSIGN[Assign CAD Index
Unique IDs] OPTIMIZE[Optimize Tiles
LOD Generation] REMOVE[Remove Empty Nodes
Graph Cleanup] EXPORT_CAD[Export CAD JSON
Metadata Files] EXPORT_CESIUM[Export 3D Tiles
glTF/b3dm] EXPORT_UNITY[Export Unity
AssetBundles] end LOAD --> BUILD BUILD --> INJECT INJECT --> UNMERGE UNMERGE --> DEMARCATE DEMARCATE --> ASSIGN ASSIGN --> OPTIMIZE OPTIMIZE --> REMOVE REMOVE --> EXPORT_CAD REMOVE --> EXPORT_CESIUM REMOVE --> EXPORT_UNITY classDef loadPhase fill:#1e3a5f,stroke:#4a90e2,color:#e1e4e8 classDef demarcatePhase fill:#3d2f1f,stroke:#ff9800,color:#e1e4e8 classDef optimizePhase fill:#3d1f3d,stroke:#9c27b0,color:#e1e4e8 classDef exportPhase fill:#1f3d2f,stroke:#4caf50,color:#e1e4e8 class LOAD loadPhase class DEMARCATE demarcatePhase class OPTIMIZE optimizePhase class EXPORT_CAD,EXPORT_CESIUM,EXPORT_UNITY exportPhase
Notable Implementation Details:
Tileset Port Base Class: All processing steps inherit from TilesetPortStepBase, which provides:
- Automatic port management (SceneHandle, TilesetData, NodeGraph)
- Dependency tracking (RequireNodeGraphForSceneProcessing, RequireTilesetForSceneProcessing)
- Auto-propagation of completion signals
- Fault handling and cancellation support
Worker Pool Pattern: The Optimize Tiles step spawns ~64 worker tasks that continuously pull tiles from a queue and optimize them in parallel. This maximizes CPU utilization on multi-core servers.
Unmerge Geometry: Identifies “islands” of connected vertices within a single mesh and splits them into separate meshes. This is critical for creating sensible tile boundaries. Uses a union-find algorithm for connected component detection.
2. Unity Viewer (3D Rendering)
Purpose: Render large-scale 3D environments with real-time data overlays, support VR interaction, and communicate with web UI layer.
Key Technologies: Unity 2022.3 LTS, Universal Render Pipeline, ECS/DOTS, Zenject
Design Patterns:
- Entity Component System: Data-oriented design for performance-critical systems
- Dependency Injection: Zenject container for service location and lifecycle management
- Observer Pattern: Reactive Extensions (Rx) for event streams
- Command Pattern: VR controller actions as commands
- Singleton Pattern: Managers for global services (PlayerManager, CadNodeManager, EmissionManager)
Integration Points:
- Input: Unity AssetBundles from THOR, glTF/b3dm files, CAD index binary files
- Output: Rendered frames, VR tracking data, screen analysis results
- Communication: Blazor Web App (via custom web components), Embedded Browser (via ZFBrowser)
Zenject Installer] PLAYER[Player Manager
VR Controllers] CAD[CAD Node Manager
Entity Lifecycle] MODEL[Model3D Service
Asset Loading] SCREEN[Screen Analysis
DOTS System] EMISSION[Emission Manager
Highlighting] NAV[Navigation System
Navmesh + Teleport] DOM[DOM System
Web Components] BROWSER[ZFBrowser
Embedded Chromium] BOOT --> PLAYER BOOT --> CAD BOOT --> MODEL BOOT --> SCREEN BOOT --> EMISSION BOOT --> NAV BOOT --> DOM BOOT --> BROWSER PLAYER --> NAV MODEL --> CAD SCREEN --> CAD EMISSION --> CAD DOM <--> BROWSER end subgraph "DOTS Systems" DOTS_RENDER[Render System
Batching] DOTS_CULL[Culling System
Frustum + Occlusion] DOTS_SCREEN[Screen Analysis
Visible Assets] DOTS_EMISSION[Emission System
Batch Updates] end CAD --> DOTS_RENDER CAD --> DOTS_CULL CAD --> DOTS_SCREEN EMISSION --> DOTS_EMISSION classDef bootstrap fill:#1e3a5f,stroke:#4a90e2,color:#e1e4e8 classDef dots fill:#3d2f1f,stroke:#ff9800,color:#e1e4e8 class BOOT bootstrap class DOTS_RENDER,DOTS_CULL,DOTS_SCREEN,DOTS_EMISSION dots
Screen Analysis System (DOTS)
The screen analysis system identifies all CAD assets visible on screen in a given frame. This drives the asset status highlighting feature.
How it works:
- Frustum Culling: Filter entities to those within camera frustum (DOTS job)
- Occlusion Culling: Query GPU for visibility (async)
- Entity → CAD Index Mapping: Convert visible entities to CAD indexes (DOTS job)
- Aggregation: Collect results into a
NativeList<OnScreenAsset>
Performance: Processes ~100,000 entities in <2ms on modern hardware
// Simplified screen analysis job
[BurstCompile]
struct ScreenAnalysisJob : IJobChunk
{
[ReadOnly] public ComponentTypeHandle<LocalToWorld> TransformType;
[ReadOnly] public ComponentTypeHandle<RenderBounds> BoundsType;
[ReadOnly] public ComponentTypeHandle<CadIndexComponent> CadIndexType;
[ReadOnly] public FrustumPlanes Frustum;
public NativeList<OnScreenAsset>.ParallelWriter Results;
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
{
var transforms = chunk.GetNativeArray(TransformType);
var bounds = chunk.GetNativeArray(BoundsType);
var cadIndices = chunk.GetNativeArray(CadIndexType);
for (int i = 0; i < chunk.Count; i++)
{
var worldBounds = AABB.Transform(transforms[i].Value, bounds[i].Value);
if (Frustum.Intersect(worldBounds))
{
Results.AddNoResize(new OnScreenAsset
{
CadIndex = cadIndices[i].Value,
ScreenPosition = WorldToScreen(worldBounds.Center)
});
}
}
}
}
3. Blazor Web Application
Purpose: Provide interactive web UI, integrate external data sources, display asset status information, and communicate with Unity Viewer.
Key Technologies: Blazor Server, SignalR, JavaScript Interop, Reactive Extensions
Design Patterns:
- MVVM Pattern: Blazor components as views, C# classes as view models
- Repository Pattern: Service classes encapsulate data access
- Factory Pattern: Service providers create scoped instances
- Observer Pattern: Rx observables for real-time data streams
- Circuit Breaker Pattern: Resilient HTTP clients with Polly
Integration Points:
- Input: REST APIs (AHM, Equipment, SCADA), MQTT brokers, PowerBI, Lucene search
- Output: HTML/CSS/JavaScript to browser, SignalR messages to Unity
- Communication: Unity Viewer (via JavaScript web components)
UI Components] SERVICES[Domain Services
Business Logic] CLIENTS[HTTP Clients
External APIs] CACHE[In-Memory Cache
Response Caching] BACKGROUND[Background Services
Data Sync] INTEROP[JS Interop
Web Components] PAGES --> SERVICES SERVICES --> CLIENTS SERVICES --> CACHE CLIENTS --> CACHE BACKGROUND --> CACHE PAGES --> INTEROP end subgraph "External Systems" AHM_API[AHM API
Asset Health] EQUIP_API[Equipment API
Metadata] SCADA[SCADA API
Live Data] MQTT[MQTT Broker
Telemetry] end CLIENTS --> AHM_API CLIENTS --> EQUIP_API CLIENTS --> SCADA CLIENTS --> MQTT classDef blazorComponent fill:#1e4d7b,stroke:#4a90e2,color:#e1e4e8 classDef externalApi fill:#3d2f1f,stroke:#ff9800,color:#e1e4e8 classDef backgroundService fill:#3d2f1f,stroke:#ff9800,color:#e1e4e8 classDef cacheService fill:#1f3d2f,stroke:#4caf50,color:#e1e4e8 class PAGES,SERVICES,CLIENTS,INTEROP blazorComponent class AHM_API,EQUIP_API,SCADA,MQTT externalApi class BACKGROUND backgroundService class CACHE cacheService
Asset Status Highlighting Implementation
This feature demonstrates the complexity and elegance of the InDI architecture:
- User navigates to Asset Status page in Blazor
- Blazor appends
<screen-analysis>custom element to DOM - Unity detects element via mutation observer, creates
Indi3DScreenAnalysisproxy - User moves camera in Unity
- Unity runs DOTS screen analysis job, collects visible CAD indexes
- Unity executes JavaScript via ZFBrowser:
screenAnalysis.onScreenAnalysisResults(json) - JavaScript forwards data to SharedWorker for position calculations
- JavaScript invokes Blazor:
blazorRef.invokeMethodAsync('onObjectsOnScreenChanged', json) - Blazor queries Equipment API to map asset IDs → functional locations
- Blazor queries AHM API (via cache) to get health status for each functional location
- Blazor generates
IndiCardDataand serializes to JSON - Blazor sends JSON to JavaScript:
jsRuntime.InvokeVoidAsync('indicards.onCardData', json) - JavaScript updates card DOM elements with new data and positions
- JavaScript updates
<indi-highlighting>elements with colors - Unity applies emission colors via DOTS batch update
4. Storage Abstraction Layer
Purpose: Provide a unified interface for interacting with diverse storage backends (local file system, Azure, AWS S3, MinIO) without vendor lock-in.
Key Technologies: .NET 8, Azure.Storage.Blobs, AWSSDK.S3
Design Patterns:
- Strategy Pattern: Swap storage implementations at runtime via configuration
- Factory Pattern:
IndiStorageProviderconstructs appropriate storage instances - Repository Pattern: A unified
IStorageAPI hides underlying storage details
Integration Points:
- Input: Configuration from
appsettings.jsondefining storage keys and endpoints - Output:
IStorageinstances for blob manipulation (list, get, upload, delete)
Factory] INTERFACE[IStorage Interface
- ListBlobs
- GetBlobAsync
- UploadBlobAsync
- DeleteBlobAsync] end subgraph "Implementations" FS[IndiFileSystemStorage
Local Files] AZURE[IndiAzureStorage
Azure Blobs] S3[IndiS3Storage
AWS S3 / MinIO] end PROVIDER -->|creates| INTERFACE INTERFACE -.->|implements| FS INTERFACE -.->|implements| AZURE INTERFACE -.->|implements| S3 classDef interface fill:#1e3a5f,stroke:#4a90e2,color:#e1e4e8 classDef impl fill:#1f3d2f,stroke:#4caf50,color:#e1e4e8 class INTERFACE interface class FS,AZURE,S3 impl
Configuration Example:
{
"Endpoints": {
"Tileset": { "StorageKey": "Azure.Production", "RelativePath": "Tilesets" },
"AssetData": { "StorageKey": "MinIO.Dev", "RelativePath": "AssetData" },
"Model3d": { "StorageKey": "Local.Content", "RelativePath": "Indexes/Model3d" }
}
}
5. Search System (Lucene)
Purpose: Provide fast full-text search across millions of CAD assets with hierarchical queries.
Key Technologies: Lucene.NET, Memory-Mapped Files
Design Patterns:
- Index Pattern: Pre-computed data structures for O(log n) lookups
- Document Store Pattern: Denormalized data for read optimization
- Repository Pattern:
IAssetObjectQueryabstracts Lucene details
Index Structure:
Each CAD asset is a Lucene document with fields for Name, Description, Category, Type, and Path. The Path field enables efficient hierarchical queries (e.g., find all pumps under Area 51).
Performance Optimizations:
- Memory-Mapped Indexes: OS-managed caching for frequently accessed index pages
- Term Vectors: Store term positions for fast highlighting
- Compound Files: Bundle index files to reduce file handles
- Warm-Up Queries: Execute common queries on startup to populate OS page cache
6. MQTT Real-Time Integration
Purpose: Ingest raw telemetry from industrial IoT sensors and PLCs, transform it, and route it to visualization clients.
Key Technologies: MQTTnet, .NET Worker Service, gRPC
Design Patterns:
- Message Broker Pattern: Decouple data producers (sensors) from consumers (clients)
- ETL (Extract, Transform, Load): A message transformation pipeline subscribes to MQTT topics, applies business logic, and publishes enriched messages
Design Patterns and Best Practices
Architectural Patterns
- Pipeline Pattern (THOR): Processing steps connected via typed channels for clear data flow and parallelism.
- Entity Component System (Unity Viewer): Data-oriented design with DOTS/ECS for cache-friendly memory layout and scalability to millions of entities.
- Repository Pattern (Blazor Web App): Service classes encapsulate data access for testability and flexibility.
- Observer Pattern (Reactive Extensions): Composable event streams for declarative event handling and subscription management.
- Dependency Injection (Zenject & ASP.NET Core): Inversion of Control for loose coupling, testability, and lifecycle management.
Code Organization
- Vertical Slice Architecture: Feature folders group related concerns (UI, code-behind, services, models).
- Namespace Alignment: Namespaces match folder structure for intuitive navigation.
- Separation of Concerns: Domain models have no dependencies; implementations depend on abstractions.
Testing Strategies
A multi-layered testing strategy with 15 test projects:
- Unit Tests (NUnit): >80% code coverage for business logic with NSubstitute for mocking.
- Integration Tests (WebApplicationFactory): Multi-component testing with TestContainers for database dependencies.
- Component Tests (BUnit): Blazor UI component testing with rendered output verification.
- End-to-End Tests (Playwright/Selenium): Critical user workflow testing with browser automation.
Error Handling
- Global Exception Middleware: Catches unhandled exceptions and logs to Application Insights.
- Circuit Breaker Pattern (Polly): Resilient HTTP clients for external APIs with automatic retry and exponential backoff.
- Result Pattern: For critical operations, returning explicit success/failure states instead of throwing exceptions.
Notable Technical Achievements
1. Scalability to Millions of Assets
- Challenge: Oil & gas facilities can have 5-10 million individual CAD assets.
- Solution: A multi-pronged approach combining spatial subdivision (tilesets), LOD generation, occlusion culling, instancing, and DOTS/ECS processing.
- Result: 60 FPS with 10 million assets on mid-range hardware (RTX 3060).
2. Sub-Second Search Across Massive Hierarchies
- Challenge: Users expect Google-like search speed on CAD hierarchies with millions of nodes.
- Solution: Lucene-based indexing with hierarchical path fields, prefix trees, and memory-mapped files.
- Result: <100ms search time for queries across 5 million assets.
3. Real-Time Asset Status with Low API Overhead
- Challenge: External APIs are slow, lack bulk support, and have rate limits. Querying 100 assets could take 50+ seconds.
- Solution: Multi-layer caching, background data synchronization, Reactive Extensions for batching, and speculative prefetching.
- Result: <2 second latency from camera movement to status visualization (95th percentile).
4. Seamless Multi-Layer JavaScript Interop
- Challenge: Three separate systems (Blazor Server, JavaScript, Unity Viewer) need to communicate in real-time.
- Solution: A custom web component system using mutation observers and direct DOM manipulation via an embedded browser.
- Result: <16ms end-to-end latency for most interactions.
5. Network Graph Alignment for 3D Piping
- Challenge: P&ID diagrams and 3D scans describe the same piping network in different formats and coordinate systems.
- Solution: Dual graph construction (one from P&ID, one from 3D point cloud) and automatic alignment using graph isomorphism algorithms.
- Result: 90%+ automatic tagging accuracy with human-in-the-loop validation.
6. Memory-Efficient CAD Index Lookups
- Challenge: Mapping CAD indexes to metadata requires random access to millions of records, which is impractical to load into RAM.
- Solution: Memory-mapped binary files with fixed-width records.
- Result: O(1) lookup time (~100 nanoseconds) with minimal RAM footprint.
Deployment and Operations
Deployment Architecture
The platform supports both cloud-native (Azure, AWS) and on-premises deployments. A hybrid cloud model is common, leveraging different providers for different storage types (e.g., Azure for indexes, S3 for tilesets, MinIO for models).
Blazor Web App] PROD_BLOB[Blob Storage
3D Assets] PROD_SEARCH[Azure Search
Lucene Index] PROD_IOT[IoT Hub
Telemetry] PROD_APPINS[Application Insights
Monitoring] end end subgraph "On-Premise" PREM_VIEWER[Unity Viewer
Windows Desktop] PREM_IIS[IIS
Blazor Web App] PREM_MINIO[MinIO
S3-Compatible Storage] end
CI/CD Pipeline
- Source Control: Git with trunk-based development (dev, test, prod branches).
- Build Automation: Nuke.Build for type-safe build scripts in C#.
- Pipelines: Azure DevOps for CI/CD orchestration.
- Release Strategy: Staging slots for zero-downtime deployments with smoke tests and automatic rollbacks.
Monitoring and Observability
- Application Insights: Request telemetry, exception tracking, custom metrics, and user flows.
- Unity Telemetry: Custom events and performance counters sent to Application Insights.
- Alerts: Configured for high error rates, slow response times, API failures, and resource exhaustion.
Conclusion
InDI represents a sophisticated integration of 3D graphics, web technologies, real-time data, and enterprise systems. It demonstrates mastery of performance-critical systems, distributed architecture, modern web development, 3D graphics, and data engineering.
The project showcases the ability to:
- Design scalable architectures that handle millions of entities
- Integrate disparate technologies (Unity, Blazor, external APIs)
- Solve complex technical challenges (graph alignment, real-time highlighting)
- Deliver business value (reduced training costs, faster incident response)
- Maintain code quality (testing, CI/CD, monitoring)
InDI is not just a technical achievement—it’s a practical solution to real industrial problems, deployed in production at some of the world’s largest mining and energy companies.
Appendix: C4 Diagrams
A. System Context Diagram
Monitors equipment health] ENG[Engineering Team
Plans maintenance] MGMT[Management
Strategic decisions] end subgraph "InDI Platform" INDI[Digital Twin
Visualization System] end subgraph "External Systems" CAD[CAD Systems
Navisworks, Revit] SCADA[SCADA
Real-time process data] AHM[Asset Health
Equipment health APIs] PBI[PowerBI
Analytics dashboards] IOT[IoT Sensors
MQTT telemetry] end OPS -->|Views facility status| INDI ENG -->|Plans maintenance| INDI MGMT -->|Reviews KPIs| INDI INDI -->|Imports 3D models| CAD INDI -->|Queries process data| SCADA INDI -->|Gets health status| AHM INDI -->|Embeds dashboards| PBI INDI -->|Subscribes to telemetry| IOT classDef platform fill:#1e4d7b,stroke:#4a90e2,color:#e1e4e8 classDef users fill:#1e3a5f,stroke:#64b5f6,color:#e1e4e8 classDef external fill:#3d2f1f,stroke:#ff9800,color:#e1e4e8 class INDI platform class OPS,ENG,MGMT users class CAD,SCADA,AHM,PBI,IOT external
B. Container Diagram
Unity 2022.3
3D rendering, VR support] WEBAPP[Blazor Web App
ASP.NET Core
Web UI, data integration] PIPELINE[THOR Pipeline
.NET 8
CAD processing] SEARCH[Search Service
Lucene.NET
Full-text search] end subgraph "Data Stores" BLOB[(Blob Storage
Azure/S3/MinIO
3D assets)] LUCENE[(Lucene Index
File system
Search index)] end subgraph "External Systems" CAD[CAD Systems] AHM[Asset Health] end USER -->|Uses| VIEWER USER -->|Uses| WEBAPP VIEWER -->|Loads assets| BLOB VIEWER <-->|Web components & gRPC| WEBAPP WEBAPP -->|Queries| SEARCH WEBAPP -->|Queries health status| AHM PIPELINE -->|Imports models| CAD PIPELINE -->|Writes assets| BLOB PIPELINE -->|Writes index| LUCENE SEARCH -->|Reads index| LUCENE classDef container fill:#1e4d7b,stroke:#4a90e2,color:#e1e4e8 classDef datastore fill:#2d4a2d,stroke:#66bb6a,color:#e1e4e8 classDef external fill:#3d2f1f,stroke:#ff9800,color:#e1e4e8 class VIEWER,WEBAPP,PIPELINE,SEARCH container class BLOB,LUCENE datastore class CAD,AHM external