-
Notifications
You must be signed in to change notification settings - Fork 6
Models
The major feature of the application is rendering the images on 3D models. We use threejs as the main graphics engine. Some models used for rendering have been created specifically for use with this application.
- The user begins the flow when they select "Add Layer" in the UI.
- The details in the requested layer are passed to the scene, which asks the model factory to create the model for this layer.
- The model factory determines which model class to use based on the given metadata, and returns a model instance to the scene.
- The scene stores the model information and renders it, and also passes the new model metadata back to the UI.
The Model interface is defined in types.ts
.
This interface provides the functions needed on the model instance to pass information from the scene into the model and ultimately into the threejs renderer.
As an example, the source code for creating models for SDO and other full-disk images can be found in model_factory.js:CreateSolarModel
(aside: if you would like a task, try migrating the code that creates the model into its own file within the src/Models
folder).
When a model is created, the following metadata is provided:
metadata | description |
---|---|
Source ID | The unique ID for an observatory or other data source, these align with Helioviewer's Data Source API |
Start Date | The start of the time range being rendered in the scene |
End Date | The end of the time range being rendered in the scene |
Cadence | The amount of time between each time step from start to end (in seconds) |
scale | Scale of the image (vague because this author isn't sure what unit this is at the time of writing...) |
Using this metadata, the SDO Model code will query the Helioviewer API for images between the given start and end dates at each time step in between. These images are downloaded and turned into textures within the device's GPU (via threejs). The metadata for each texture and date is stored in the model instance, and a single model is rendered to the scene.
When the user presses the play button to begin an animation, the scene executes SetTime()
via the Model interface. This notifies the SDO model that it should update its texture to align with the new Date. By doing so, the animation appears as the textures continuously update.
The PFSS model in Helios is backed by PFSS field lines traced with pfsspy.
The field lines are generated with LinePlotterGong.py
. This is a long running script which uses FIDO to download GONG data, which is fed into pfsspy to trace the field lines.
Once traced, these lines are stored in a binary format which can be read with server/scripts/pfss/pfss.py
. The binary files contain lists of points that make up each line.
In the web client, the lines are parsed with pfss.ts
and rendered with Models/MagneticField/FieldLoaderGong.ts
and Models/MagneticField/MagneticField.js
.
-
FieldLoaderGong.ts
is the loader called by the Model Factory. It downloads the pfss binaries generated withLinePlotterGong.py
, then passes them toMagneticField.js
.FieldLoaderGong.ts
also implements a class calledLineManager
which implements the Model Interface and handles swapping out the set of lines based on the given time. -
MagneticField.js
performs the line drawing via threejs based on the given line data.
If you'd like to create a new model, you must do the following:
-
Write the source code which gathers data for your model and renders it in threejs in the
Models
folder. This part is model specific, though some models can use the same renderer i.e. full-disk images are already supported with the existing SDO model. Make sure your model conforms to the Model interface. -
Add a new source ID to
sources.ts
. This will immediately add your new model to the data source dropdown in the UI. -
Update the
CreateModel
function in the model factory to load your new model upon request. Add the line:
if (source === GetModelFromName("My new model")) {
return await MyModelLoader();
}
Replace "My new model" with whatever you named it in step 2. And "MyModelLoader" with your model loader created in step 1.
The first step is of course the most difficult part. The threejs library provides decent documentation information on how to render 3D objects within the framework.