Particle Reader Plugins
The PtServer supports dynamic loading of reader plugins, allowing you to extend the server with custom particle file format readers. A reader plugin acts as a provider of particle data to the server, enabling in-house file formats to be served with the same ease of use and performance as the built-in PTFX and VTP readers.
Particle Plugin Discovery
To use reader plugins with the PtServer, set the CEW_PT_READER_PLUGIN_FOLDER environment variable to point to the folder containing your plugin shared libraries. The PtServer will scan this folder and load all libraries matching the naming convention on startup.
Plugins must be named with the cpt_ prefix (case-insensitive):
cpt_{PLUGIN_NAME}.[dll|so|dylib]
Examples:
cpt_MyCustomFormat.dll (Windows)
cpt_MyCustomFormat.so (Linux)
cpt_MyCustomFormat.dylib (macOS)
The PtServer checks for duplicates and only loads files that match the required prefix and platform extension. Subdirectories are not recursively scanned.
Particle Reader Plugin API (C ABI)
Reader plugins expose a single C entry point and register themselves with the framework via a callback.
Required export:
extern "C" CPT_PLUGIN_EXPORT CPT_PluginExitFunc initializeReaderPlugin(
const CPT_FrameworkServices* frameworkServices);
The initializeReaderPlugin function is called once when the plugin is loaded. The plugin must:
- Check API version compatibility (major version must match).
- Optionally call
setPluginInfoFuncto report plugin metadata (name, version, author). - Call
registerReaderFuncto register one or more reader factories. - Return a cleanup function (or
nullptrif no cleanup is needed).
Framework services provided to the plugin:
struct CPT_FrameworkServices {
int pluginApiMajorVer; // Currently 1
int pluginApiMinorVer; // Currently 0
CPT_RegisterReaderFunc registerReaderFunc; // Register reader factories
CPT_LogFunc logFunc; // Server-side logging
CPT_SetPluginInfoFunc setPluginInfoFunc; // Report plugin metadata
};
Reader registration parameters:
struct CPT_RegisterReaderParams {
int pluginApiMajorVer;
int pluginApiMinorVer;
CPT_CreateReaderFunc createReaderFunc; // Factory: create a reader instance
CPT_DestroyReaderFunc destroyReaderFunc; // Destroy a reader instance
CPT_CanReadFunc canReadFunc; // Test if a file path is supported
};
Function signatures:
typedef cee::pt::ParticleDatasetReader* (*CPT_CreateReaderFunc)();
typedef void (*CPT_DestroyReaderFunc)(cee::pt::ParticleDatasetReader*);
typedef bool (*CPT_CanReadFunc)(const char* filePath);
The canReadFunc is called to determine whether the plugin can handle a given file path (typically
by checking the file extension). The createReaderFunc returns a new instance of your reader that
implements the ParticleDatasetReader interface.
Implementing ParticleDatasetReader
Your plugin’s reader must derive from cee::pt::ParticleDatasetReader and implement the following
virtual methods:
class ParticleDatasetReader {
public:
virtual bool open(const cee::Str& filePath, Error* error = nullptr) = 0;
virtual bool setActiveScalarField(const cee::Str& fieldName) = 0;
protected:
virtual std::unique_ptr<FrameData> readFrame(
size_t frameIndex, const cee::Str& activeScalar) = 0;
virtual void resetDerivedState() {}
};
open(): Open the dataset at the given path. Populate the dataset header (frame count, bounding box, particle count, scalar field names) and returntrueon success.setActiveScalarField(): Switch the active scalar field for subsequent frame reads.readFrame(): Read a single frame’s particle data (positions, IDs, and optional scalar values) and return it as aFrameDataobject.resetDerivedState(): Optional cleanup hook called when the reader is closed.
The base class provides thread-safe caching, so readFrame() is only called on cache misses. The
base class also handles close(), clearActiveScalarField(), and LRU cache eviction.
Particle Reader Plugin SDK
To create your own reader plugin, download HOOPS Envision for Desktop from https://developer.techsoft3d.com. The particle reader plugin framework is found in the CeeParticleModel folder in the distribution, which includes:
ParticleReaderPluginApi.h: the C ABI header your plugin must include.ParticleDatasetReader.h: the base class your reader must implement.FrameData.h/DatasetHeader.h: data structures for frame and header information.
The framework is provided as source code so you can compile with your preferred compiler and settings.
For the full desktop API reference, see the HOOPS Envision for Desktop documentation: https://docs.techsoft3d.com/hoops/latest/envision-desktop/api-ref/components.html
In-Process Custom Particle Readers (Desktop)
In addition to the plugin mechanism (shared libraries loaded at runtime), the desktop
ParticleModel API also supports injecting a custom reader directly via:
bool ParticleModel::open(std::unique_ptr<ParticleDatasetReader> reader, Error* error = nullptr);
This transfers ownership of your reader instance to the model. Use this approach when:
- You want to embed particle reading in your own application (no separate server).
- Your reader requires application-specific context (e.g. database connections) that cannot be passed through the plugin C ABI.
- You are prototyping a new format before packaging it as a plugin.
Version Compatibility
The plugin API uses semantic versioning:
- Major version (
CPT_API_MAJOR_VER): Must match between plugin and host. A mismatch causes the plugin to be rejected at load time. - Minor version (
CPT_API_MINOR_VER): Additive changes only. A plugin compiled against an older minor version will still load on a newer host.
Current version: 1.0.
Cross-References
- Server for Particle Models (PtServer): PtServer setup and configuration.
- Data Provider Plugins (RemoteModel): equivalent plugin system for UgServer (Data Providers).
- Distribution Content: distribution layout including
server/PtServer.