Server for Particle Models (PtServer)
Getting Started with ParticleModel (Particle Simulation Playback)
The prerequisites for the particle server can be found in Supported Platforms.
The PtServer is a stateless REST server: unlike UgServer (WebSocket-based), no sticky sessions are required and the server can be horizontally scaled behind a load balancer. Multiple clients can connect to the same server concurrently, sharing cached dataset readers.
Download and extract HOOPS Envision for Web distribution archive from the Tech Soft 3D Developer Zone: https://developer.techsoft3d.com/
Specify your license, either by modifying server/PtServer/Main.js to specify your license code:
ptServer.setLicenseCode(myCode);
or by copying the hoops_license.h file downloaded from the developer zone into the server/PtServer folder, or by specifying the
CEW_TECH_SOFT_LICENSE_FILEenvironment variable to point to the hoops_license.h, or by setting theCEW_TECH_SOFT_LICENSE_CODEenvironment variable directly.With a terminal prompt, go to the
server/PtServerfolder inside the distribution.Execute the following command to install dependencies:
> npm install
Start the server using npm:
Start the server with the appropriate command for your platform:
> npm run server:pt:linux > npm run server:pt:win > npm run server:pt:mac
Node will then run Main.js, and the server will start on port 8999 by default. The port can be changed by setting the
CEW_PT_PORTenvironment variable.You can verify that the server is running by opening http://localhost:8999 in a browser. You should then see a message like this:
HOOPS Envision PtServer is alive Server ver: 1.0.0-abcdef12 Node.js ver: v20.11.0 (linux|x64)
We have included a simple http server for hosting the example web apps. To start the http server, go to the Examples/HttpServer folder and run:
> npm install
Then start the server by running:
> npm start
This will start the server on port 8000. This can be changed by the PORT environment variable or editing the HttpServer.js file.
Open http://localhost:8000 in your browser and navigate to the particle example (e.g. Examples/MinimalPtTypeScript).
Please refer to the documentation to learn more about HOOPS Envision for Web. The central classes are:
CloudSession: Applications will typically create a single instance of CloudSession for managing viewers.Viewer: Handles user interaction (pan/rotate/zoom), picking and other view related functions.ParticleModel: The main class for interacting with particle datasets. Handles model opening, frame fetching, scalar field selection, and animation. ParticleModel requires the presence of a running PtServer.Animation: Time-step animation controller with configurable frame rate, looping, and preloading support.
Configuring the PtServer
The PtServer is configured via environment variables. All variables use the CEW_PT_ prefix.
Server configuration:
| Environment Variable | Default | Description |
|---|---|---|
CEW_PT_PORT |
8999 |
TCP port the server listens on. |
CEW_PT_USE_HTTPS |
false |
Enable HTTPS. Requires MyDomain_private.key and MyDomain.crt in the server folder. |
CEW_PT_MODEL_PATH |
./test-data/particles |
Directory containing particle datasets (PTFX/VTP files or subdirectories). |
CEW_PT_ENABLE_REST_API_QUERY |
true |
Enable the query endpoints (list models, get info, get frames, switch scalar). |
CEW_PT_ENABLE_REST_API_UPLOAD |
false |
Enable the upload/delete endpoints. Disabled by default for security. |
CEW_PT_ENABLE_CORS |
false |
Enable Cross-Origin Resource Sharing headers. |
CEW_PT_READER_PLUGIN_FOLDER |
(empty) | Path to folder containing reader plugin shared libraries (cpt_*.dll/.so/.dylib). |
CEW_PT_COMPRESSION_LEVEL |
6 |
Gzip compression level for binary responses (0 = disabled, 1-9). |
CEW_PT_COMPRESSION_THRESHOLD |
1024 |
Minimum response size in bytes before compression is applied. |
CEW_PT_MAX_UPLOAD_SIZE |
5368709120 (5 GB) |
Maximum upload file size in bytes. |
CEW_PT_MAX_CONCURRENT_UPLOADS |
3 |
Maximum number of concurrent upload requests. |
CEW_PT_CACHE_MEMORY_LIMIT_MB |
0 |
Server-side C++ frame cache memory limit in MB. 0 = use C++ default (5 GB). |
Logging in PtServer
The PtServer supports logging to console and file in two different formats: Standard (more human readable) and JSON (for easy processing or consumption by e.g. Logstash).
The logging output of the PtServer can be controlled via the following environment variables:
CEW_PT_LOG_CONSOLE_OUTPUT_TYPE: Format for console log. Possible values: “standard”, “json”, “none”. Default: “standard”.CEW_PT_LOG_FILE_OUTPUT_TYPE: Format for file log. Possible values: “standard”, “json”, “none”. Default: “json”.CEW_PT_LOG_FILENAME: If file output type is not NONE, use this to specify the name of the log file. Default: “c3_pt_server.log”.CEW_PT_LOG_LEVEL: Specify what to log. Possible values: 1: Error, 2: Warning, 3: Info, 4: Debug. A 3 will log Error, Info and Warning, but not any debug messages. This is default.CEW_PT_LOG_HTTP: Log every HTTP request. Default: “false”.
Note
Unlike UgServer, PtServer does not support client-side log-context key/value injection
(i.e. there is no equivalent of RemoteModel.setServerLogContextKeyValueArr()).
Each REST request is independent and carries no session state.
On Linux, logging of segmentation faults is also added to help debugging situations where the server crashes.
Session Model / Scalability
The PtServer architecture differs fundamentally from UgServer in its session model:
- UgServer (WebSocket): maintains one session per socket, with a 1:1
VizDataExtractorper client. State is tied to the socket connection. - PtServer (REST): completely stateless HTTP. No session concept. N clients share M cached dataset
readers via a
DatasetReaderFactorywith ref-counting and LRU eviction.
Key implications:
- Horizontal scaling: PtServer instances can be placed behind a standard HTTP load balancer with no sticky-session requirement.
- Multi-client: Multiple clients requesting the same model share one reader instance (concurrent access serialized by a C++ mutex). Different models get separate readers from the factory cache.
- No reconnection handling needed: Because PtServer is stateless, there is no equivalent of
UgServer’s
CEW_UG_MAX_DISCONNECT_DURATION_MS. Each request is self-contained.
REST API Reference
All endpoints are prefixed with /api/v1. The query endpoints require CEW_PT_ENABLE_REST_API_QUERY=true
(default). The upload/delete endpoints require CEW_PT_ENABLE_REST_API_UPLOAD=true.
Query endpoints:
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/models |
List all available models in the configured model path. Returns a JSON array of model keys. |
| GET | /api/v1/models/:modelKey/info |
Get dataset metadata: modelKey, maxParticleCount, frameCount, boundingBox, scalarFieldNames, activeScalarField, hasScalarData, scalarRange. |
| GET | /api/v1/models/:modelKey/frame/:frameIndex |
Fetch a binary frame buffer. Optional query parameter decimation (0.0-1.0) for LOD reduction.
Response header X-Particle-Count indicates actual particle count in the buffer. |
| PUT | /api/v1/models/:modelKey/scalar/:fieldName |
Switch the active scalar field for subsequent frame requests. |
| DELETE | /api/v1/models/:modelKey/scalar |
Clear the active scalar field (position-only mode). |
Upload/delete endpoints (requires CEW_PT_ENABLE_REST_API_UPLOAD=true):
| Method | Path | Description |
|---|---|---|
| POST | /api/v1/models |
Upload a new model (multipart form data). Subject to CEW_PT_MAX_UPLOAD_SIZE and
CEW_PT_MAX_CONCURRENT_UPLOADS limits. |
| DELETE | /api/v1/models/:modelKey |
Delete a model from the server. Symlinks are rejected for safety. |
Health endpoint:
| Method | Path | Description |
|---|---|---|
| GET | / |
Returns server-alive message with version info (non-production mode). |
Binary Wire Format
Frame data is transmitted in a compact binary SOA (Structure of Arrays) format optimized for bandwidth:
- Particle count (uint32): number of particles in this frame.
- IDs (int32[]): delta-encoded particle identifiers.
- X positions (uint16[]): quantized X coordinates.
- Y positions (uint16[]): quantized Y coordinates.
- Z positions (uint16[]): quantized Z coordinates.
- Scalars (uint16[], optional): quantized scalar values (only present when a scalar field is active).
Quantization formula: quantized = round((value - min) / (max - min) x 65535)
Without scalars the format uses 10 bytes per particle; with scalars 12 bytes per particle. Combined with gzip compression, this typically achieves 4x bandwidth savings compared to full-precision float transmission.
Note
This is an internal wire protocol. SDK users do not need to decode it: the
ParticleModel client class handles decoding and dequantization automatically.
Request Cancellation
Because PtServer uses REST (not WebSockets), there is no socket reconnection handling. However, the
client-side ParticleModel implements request cancellation:
Calling setFrame automatically cancels any previous inflight frame
request using an AbortController pattern. This ensures that rapid frame seeking (e.g. during
scrubbing or animation) does not queue up stale responses, and only the most recent frame request
completes.
Particle Reader Plugins
The PtServer supports dynamic loading of reader plugins for custom particle file formats. Plugins are
discovered from the folder specified by CEW_PT_READER_PLUGIN_FOLDER and must follow the naming
convention cpt_{NAME}.dll (Windows), cpt_{NAME}.so (Linux), or cpt_{NAME}.dylib (macOS).
See Particle Reader Plugins for full details on the plugin API and development workflow.
Examples
A minimal TypeScript example demonstrating PtServer usage is included in the distribution at
Examples/MinimalPtTypeScript/. See Examples for a full list of included examples.
Cross-References
- Modules: module overview including
cee.pt. - Distribution Content: distribution layout including
server/PtServer. - Particle Reader Plugins: reader plugin development for PtServer.
- Class Index: API reference for
cee.pt.ParticleModel,cee.pt.Animation, and other classes.