Loading...
Searching...
No Matches
Creating visualizations: Van der Waals visual model

This tutorial shows you how to create a new visual model that shows the van der Waals representation of a group of atoms.

Note: SAMSON already has a Van der Waals visual model which is installed by default.

The source code for an Extension created in this tutorial can be found at https://github.com/1A-OneAngstrom/SAMSON-Developer-Tutorials.

Generating an Extension

We will start by creating a new SAMSON Extension called VanDerWaals thanks to the SAMSON Extension generator (please, refer to the SAMSON Extension generator tutorial for a reminder on how to use it):

The SAMSON Extension generator generates a visual model class (derived from the SBMVisualModel class) and a property widget class for the visual model.

Now, try building the SAMSON Extension.

Setting up the visual model

A visual model is applied to a group of nodes passed to the constructor of the visual model. Since we want to apply a van der Waals visual model to a group of atoms, we add a member to the visual model to remember the list of atoms that we were passed.

Open the SEVanDerWaalsVisualModel.hpp file and include the SBAtom.hpp header:

#include "SBAtom.hpp"

And add the following member inside the declaration of the SEVanDerWaalsVisualModel class in the SEVanDerWaalsVisualModel.hpp file:

class SEVanDerWaalsVisualModel : public SBMVisualModel {
// ...
private:
SBPointerIndexer<SBAtom> atomIndexer;
};
This class is the base class to describe a visual model.
Definition: SBMVisualModel.hpp:29

A pointer indexer is similar to a node indexer, thus assigns indices to pointed objects, but automatically removes references from the indexer when a pointed object is deleted (in the C++ sense) so that it can never point to deleted memory.

Then, in the SEVanDerWaalsVisualModel.cpp file, modify the second constructor as follows:

SEVanDerWaalsVisualModel::SEVanDerWaalsVisualModel(const SBNodeIndexer& nodeIndexer) {
SBNodeIndexer temporaryIndexer;
SB_FOR(SBNode* node, nodeIndexer)
node->getNodes(temporaryIndexer, SBNode::IsType(SBNode::Atom));
SB_FOR(SBNode* node, temporaryIndexer)
atomIndexer.addReferenceTarget(node);
temporaryIndexer.clear();
SAMSON::setStatusMessage(QString("Van der Waals visual model: added for ") + QString::number(atomIndexer.size()), 0);
}
#define SB_FOR(VARIABLE, CONTAINER)
A macro to easily write for loops involving containers.
Definition: SBCContainerFor.hpp:83
static void setStatusMessage(const QString &message, int time=0)
Shows a message in the status bar.
Definition: SAMSON.cpp:1647
void clear()
Clears the indexer.
Definition: SBCContainerIndexer.hpp:349
This node predicate compares the node type with a given type.
Definition: SBDDataGraphNode.hpp:512
This class is the base class to describe a node in the data graph.
Definition: SBDDataGraphNode.hpp:33
@ Atom
Atom.
Definition: SBDDataGraphNode.hpp:67
This class describes a node indexer.
Definition: SBDDataGraphNodeIndexer.hpp:21

First, we collect atoms among the nodes passed to the constructor of the visual model (possibly among their descendants), then we add the atoms to the atom indexer atomIndexer.

Disabling the property window

The property window of a visual model is mainly used to display the possible parameters of the visual model to the user such that they can be modified.

Note: This is also can be done via the introspection mechanism by exposing visual model attributes. In this case they could be modified via the Inspector.

If enabled, the property window appears when the visual model was created or can be invoced from the context menu of the visual model node in the data graph. For simplicity, in this tutorial we will not be using the property window. To disable the property window, please open the SEVanDerWaalsDescriptor.cpp file that describes the SAMSON Extension and comment the following string:

//SB_ELEMENT_CLASS(SEVanDerWaalsVisualModelProperties);

You can also change the SAMSON Extension category to Visualization:

#define SB_ELEMENT_CATEGORY(CLASS_CATEGORY)
Declares a category of a SAMSON Extension.
Definition: SBCClassProxy.hpp:400
@ Visualization
The Visualization category.
Definition: SBCClass.hpp:200

Displaying spheres

To display something in the viewport, we overload the display function of the visual model. For convenience, SAMSON provides many functions to ease rendering objects (instead of having to use OpenGL functions).

The display function of the visual model receives SBNode::RenderingPass according to which the geometry is to be rendered. In this tutorial we will consider three of them:

In this tutorial, we are going to use the displaySpheres function, to draw one sphere per atom, with a radius equal to the van der Waals radius of the atom.

Let's now code inside the display function of the visual model. Please note that the code demonstrated below is not optimized and is shown for the tutorial purposes. For the optimized code please see the source code for this Extension in https://github.com/1A-OneAngstrom/SAMSON-Developer-Tutorials.

First, we allocate arrays needed to transfer data to SAMSON for rendering spheres and initialize them to zeros:

void SEVanDerWaalsVisualModel::display(RenderingPass renderingPass) {
const unsigned int numberOfAtoms = atomIndexer.size();
// allocate arrays and initialize them to zeros
float* positionData = new float[3 * numberOfAtoms]();
float* radiusData = new float[numberOfAtoms]();
float* colorData = new float[4 * numberOfAtoms]();
unsigned int* flagData = new unsigned int[numberOfAtoms]();
unsigned int* nodeIndexData = new unsigned int[numberOfAtoms]();

Observe the different array sizes above: we need 3 float per atom for the position, 1 float for the radius, 4 float for the color (red, green, blue, and opacity), and 2 unsigned int for flags used to alter the rendering colors (e.g. the selection flag and the highlighting flag) and for node indices used for selections (see Enabling selection section).

We also need to know whether a color scheme is applied to the visual model, so we retrieve the pointer to the material applied to the visual model:

// retreive the pointer to the material applied to the visual model
SBNodeMaterial* material = getMaterial();
This class describes a material.
Definition: SBDDataGraphNodeMaterial.hpp:24

We can now fill the arrays by traversing the list of atoms:

// fill in the arrays
for (unsigned int i = 0; i < numberOfAtoms; i++) {
SBPointer<SBAtom> currentAtom = atomIndexer[i];
// check if the atom is not null
if (!currentAtom.isValid()) continue;
// check if the atom is not erased
if (currentAtom->isErased()) continue;
// fill the position array
SBPosition3 position = currentAtom->getPosition();
positionData[3 * i + 0] = (float)position.v[0].getValue();
positionData[3 * i + 1] = (float)position.v[1].getValue();
positionData[3 * i + 2] = (float)position.v[2].getValue();
// fill the radius array
radiusData[i] = (float)currentAtom->getVanDerWaalsRadius().getValue();
// fill the color array based on the material applied to the visual model, if any
if (material) {
// if a material is applied to the visual model use its color scheme
material->getColorScheme()->getColor(colorData + 4 * i, currentAtom());
}
else if (currentAtom->getMaterial()) {
// else if a material is applied to the current atom use its color scheme
currentAtom->getMaterial()->getColorScheme()->getColor(colorData + 4 * i, currentAtom());
}
else {
// else set the default color
colorData[4 * i + 0] = 1.0f;
colorData[4 * i + 1] = 1.0f;
colorData[4 * i + 2] = 1.0f;
colorData[4 * i + 3] = 1.0f;
}
// fill the flag array based on the combination of the flags for the visual model and the current atom
flagData[i] = currentAtom->getInheritedFlags() | getInheritedFlags();
// fill the node index array
nodeIndexData[i] = currentAtom->getNodeIndex();
}
virtual void getColor(float *color, SBDDataGraphNode *node=nullptr, const SBPosition3 &position=SBPosition3::zero) const
Returns a color given a node and / or a position.
Definition: SBDDataGraphNodeColorScheme.cpp:32
SBDDataGraphNodeColorScheme * getColorScheme() const
Returns the color scheme.
Definition: SBDDataGraphNodeMaterial.cpp:168
constexpr Value const & getValue() const noexcept
Returns the value.
Definition: SBDQuantityType.hpp:94
Quantity v[3]
The components of the physical vector.
Definition: SBDTypePhysicalVector3.hpp:768

Here, first we check whether the atom has been deleted or not. Thus, we will display spheres only for atoms, present in the data graph.

Then, we fill the position array and the radius array based on atom's position and the van der Waals radius, respectively. Both physical quantities have length units (SBQuantity::length), so we extract their numerical value with the getValue function, and cast the resulting double as a float, which is expected by the renderer.

Then, we fill the color array based on the material applied to the visual model, if any. Precisely, if a material is applied to the visual model, we charge it of filling the color array, based on the current atom we’re examining. Else, we check whether the atom itself has a color scheme in order to use it. If it has no color scheme, we set the color to white (red, green, blue, and opacity are set to their maximum value: 1.0f).

Finally, we fill the flag array based on an “or” combination of the flags of the visual model and the flags of the current atom, to help the user have visual feedback when nodes are highlighted or selected.

We can now ask SAMSON to display these spheres when rendering opaque geometry:

// display spheres for atoms
SAMSON::displaySpheres(numberOfAtoms, positionData, radiusData, colorData, flagData);
}
static void displaySpheres(unsigned int nSpheres, const float *positionData, const float *radiusData, const float *colorData, const unsigned int *flagData, bool shadowPassFlag=false, bool transparency=false, float opacity=1.0f)
Displays spheres.
Definition: SAMSON.cpp:3716
@ OpaqueGeometry
The pass where opaque geometry is rendered.

And we complete the display function by cleaning up memory:

delete[] positionData;
delete[] radiusData;
delete[] colorData;
delete[] flagData;
delete[] nodeIndexData;

Now, if you build and launch SAMSON, and apply this visual model ( Ctrl / Cmd⌘ + Shift + V ) to a molecule without any material applied, it will show white spheres. Let's make it more appealing with default color set based on the CPK color scheme. For that, add the <SBElementTable.hpp header file in the SEVanDerWaalsVisualModel.cpp file:

#include "SBElementTable.hpp"

and change the setting of the default color to the following line:

// else set the default color based on CPK color
memcpy(&colorData[4 * i],
SBElementTable::getElement(currentAtom->getElementType()).getColorCPK(),
4 * sizeof(float));
const float(& getColorCPK() const)[4]
Returns the CPK color of the element.
Definition: SBMElement.cpp:67
static const SBElement & getElement(SBMElement::Type element)
Returns a reference to periodic table element element.
Definition: SBMElementTable.cpp:41

Here we get the CPK color for a current atom element type.

Now, if you build and launch SAMSON, and apply this visual model to a molecule without any material applied:

Adding the Van der Waals visual model

it will show spheres with CPK color:

Van der Waals visual model with CPK colors and no shadows casted from the visual model

You can see that the visual model does not cast any shadows, and the only the shadows you see are casted by the molecule itself. Learn how to make you visual model to cast shadows in the next section.

Casting shadows

SAMSON uses a shadow map algorithm in order to render shadows. This algorithm performs a hidden rendering pass from the point of view of the light and uses this render to determine whether a point is shadowed during the main rendering pass. In order to cast shadows, we thus need to render spheres again, but in the SBNode::RenderingPass::ShadowingGeometry pass. Shadow pass only cares to render geometry and to determine the depth of objects and it doesn't need colors.

In the display function of the visual model, add the following pass after the SBNode::RenderingPass::OpaqueGeometry:

// display for shadows
SAMSON::displaySpheres(numberOfAtoms, positionData, radiusData, nullptr, nullptr, true, true);
}
@ ShadowingGeometry
The pass where shadowing geometry is rendered.

The visual model then casts shadows:

Van der Waals visual model with shadows

Enabling selection

In SAMSON, picking objects in the viewport is also implemented with rendering functions. However, instead assigning colors to each pixel of the viewport, we assign the index of the node being rendered at this location (see nodeIndexData). Visual models can thus become selectable if they implement the SBNode::RenderingPass::SelectableGeometry pass in their display function.

In the display function of the visual model, add the following pass after the SBNode::RenderingPass::ShadowingGeometry:

// display spheres for atoms
SAMSON::displaySpheresSelection(numberOfAtoms, positionData, radiusData, nodeIndexData);
}
static void displaySpheresSelection(unsigned int nSpheres, const float *positionData, const float *radiusData, const unsigned int *nodeIndexData)
Displays spheres for selection.
Definition: SAMSON.cpp:3728
@ SelectableGeometry
The pass where selectable geometry is rendered.

Note that in the SelectableGeometry pass we don't need to deal with colors but we need to fill the index array with the unique node index that SAMSON has assigned to the atom. As a result, when the user attempts to pick a sphere in the visual model, the atom is selected:

Van der Waals visual model with selection

Modifying the properties

Let's now make it possible for the user to change the size of the spheres.

For that we introduce a dimensionless variable radiusFactor in the SEVanDerWaalsVisualModel class (file SEVanDerWaalsVisualModel.hpp) together with according getter and setter functions:

class SEVanDerWaalsVisualModel : public SBMVisualModel {
public:
// ...
/// \name Getter/setter functions
//@{
const float& getRadiusFactor() const;
void setRadiusFactor(const float& r);
//@}
private:
SBPointerIndexer<SBAtom> atomIndexer;
float radiusFactor; ///< The radius factor
};

And implementation of these functions in the SEVanDerWaalsVisualModel.cpp file:

const float& SEVanDerWaalsVisualModel::getRadiusFactor() const {
return radiusFactor;
}
void SEVanDerWaalsVisualModel::setRadiusFactor(const float& r) {
if (r < 0.0f) return;
radiusFactor = r;
// request re-rendering of the viewport
}
static void requestViewportUpdate()
Requests a viewport update.
Definition: SAMSON.cpp:1402

In the second constructor of the SEVanDerWaalsVisualModel class (file SEVanDerWaalsVisualModel.cpp) we set the default value for the radius factor to 1.0:

SEVanDerWaalsVisualModel::SEVanDerWaalsVisualModel(const SBNodeIndexer& nodeIndexer) {
radiusFactor = 1.0f; // set a default radius factor
// ...
}

And in both display and displayForSelection functions of the visual model modify the computation of the sphere radius by multiplying by the radius factor:

// fill the radius array
radiusData[i] = radiusFactor * (float)currentAtom->getVanDerWaalsRadius().getValue();

There are two main ways to provide a possibility for the user to modify properties of the visual model:

You can use either one of them or both.

You can also specify the range of the radiusFactor in the Inspector and expose the visual model transparency in the Inspector. To see how to do that, please check the source code for this Extension in https://github.com/1A-OneAngstrom/SAMSON-Developer-Tutorials.

Inspector

Now, we expose the radius factor as a read and write attribute thanks to the getter and setter functions and the introspection mechanism. Note that the getter and setter function names should differ only in the get and set parts. Open the SEVanDerWaalsVisualModelDescriptor.hpp file and add the following attribute exposure:

SB_CLASS_BEGIN(SEVanDerWaalsVisualModel);
// ...
SB_ATTRIBUTE_READ_WRITE(const float&, SEVanDerWaalsVisualModel, RadiusFactor, "Radius factor", "Geometry");
SB_CLASS_END(SEVanDerWaalsVisualModel);
#define SB_INTERFACE_END
Declares the end of the class interface.
Definition: SBCClassInterface.hpp:122
#define SB_INTERFACE_BEGIN
Declares the beginning of the class interface.
Definition: SBCClassInterface.hpp:107
#define SB_ATTRIBUTE_READ_WRITE(TYPE, CLASS, NAME, DESCRIPTION, GROUP)
Definition: SBCClassInterface.hpp:948
#define SB_CLASS_END(CLASS)
Declares the end of a class.
Definition: SBCClassProxy.hpp:260
#define SB_CLASS_BEGIN(CLASS)
Declares the beginning of a class.
Definition: SBCClassProxy.hpp:173

Here, we specify the type of the attribute (const float&), the class, the root name of the getter and setter functions, the description of the attribute, and an attribute's group (a group box in the Inspector window where this attribute will be placed).

Now, the user can modify the radius factor in the Inspector when the visual model is selected:

Changing the visual model properties in the Inspector

You can also limit the range of the radiusFactor in the Inspector using SB_ATTRIBUTE_READ_WRITE_RANGE and expose the visual model transparency as a slider using SB_ATTRIBUTE_READ_WRITE_RESET_RANGE_SLIDER. To see how to do that, please check the source code for this Extension in https://github.com/1A-OneAngstrom/SAMSON-Developer-Tutorials.

Property window

First, if you disabled the property window of the visual model, enable it back by uncommenting the following string in the Extension's descriptor file (SEVanDerWaalsDescriptor.cpp):

SB_ELEMENT_CLASS(SEVanDerWaalsVisualModelProperties);
#define SB_ELEMENT_CLASS(CLASS)
Declares a class in a SAMSON Extension.
Definition: SBCClassProxy.hpp:362

Open the SEVanDerWaalsVisualModelProperties file, modify the default label, and add a QDoubleSpinBox. Rename this spin box to doubleSpinBoxRadiusFactor and set its parameters as on an image below (the defaul value to 1.0 and the minimum to 0.0):

Property window: adding a spin box

Add a slot onRadiusFactorChanged(double):

Property window: adding a slot

And connect the valueChanged(double) signal of the spin box to this slot:

Property window: connecting a signal to a slot

Now, add this slot in the SEVanDerWaalsVisualModelProperties class declaration (SEVanDerWaalsVisualModelProperties.hpp file):

class SEVanDerWaalsVisualModelProperties : public SBGDataGraphNodeProperties {
Q_OBJECT
public:
// ...
public slots:
/// \name Properties
//@{
void onRadiusFactorChanged(double radiusFactor);
//@}
private:
// ...
};
#define SB_CLASS
Macro that is added inside the class declaration for Introspection, etc.
Definition: SBCClass.hpp:241
This class describes a widget that allows users to view and potentially edit properties of data graph...
Definition: SBGDataGraphNodeProperties.hpp:12

And its implementation in the SEVanDerWaalsVisualModelProperties.cpp file:

void SEVanDerWaalsVisualModelProperties::onRadiusFactorChanged(double radiusFactor) {
if (!visualModel.isValid()) return;
// set the radius factor for the visual model
visualModel->setRadiusFactor(radiusFactor);
// request re-rendering of the viewport
}

Here, we set the radius factor of the visual model from the property window and request to force the update of SAMSON's viewport which will render the viewport thus rendering the visual model with new parameters.

Now, the user can modify the radius factor in the property window and it will automaticaly update the visual model representation:

Changing the visual model properties with the property window

Serializing the visual model

If you want for your visual model to be copyable and savable it is necessary to implement its serialization. Serialization is used in SAMSON to:

  • copy nodes in the data graph,
  • save documents in SAMSON format files (.sam, .samx) and further load it from them.

Please, see the Serialization section for more information.

By default, the newly created visual model is not serialized.

Open the SEVanDerWaalsVisualModel.cpp file and modify the isSerializable function to return true.

bool SEVanDerWaalsVisualModel::isSerializable() const {
return true;
}

This indicates to SAMSON that this class is serializable.

Now, we need to re-implement both serialize and unserialize functions.

When SAMSON serializes a group of nodes, it proceeds in two passes:

  • First, all nodes that are to be serialized are added to a nodeIndexer. This way, each node that's about to be serialized has an index. It's those indices that need to be used to indicate which nodes are referenced by other nodes if the referenced nodes are serialized as well, else we need to use addresses of the referenced nodes.
  • Then, the serialize function of each node is called. This function receives the nodeIndexer.

During unserialization, SAMSON also proceeds in two steps:

  • First, it creates all required nodes and indexes them in a nodeIndexer, in the same order as during serialization.
  • Then, the unserialize function of each node is called. This function receives the nodeIndexer.

The serialize function allows for serialization of your visual model.

void SEVanDerWaalsVisualModel::serialize(SBCSerializer* serializer, const SBNodeIndexer& nodeIndexer, const SBVersionNumber& sdkVersionNumber, const SBVersionNumber& classVersionNumber) const {
// Serialization of the parent class
SBMVisualModel::serialize(serializer, nodeIndexer, sdkVersionNumber, classVersionNumber);
// Write the radius factor
serializer->writeFloatElement("radiusFactor", radiusFactor);
// Write the number of atoms to which this visual model is applied
serializer->writeUnsignedIntElement("numberOfAtoms", atomIndexer.size());
unsigned int atomIndex = 0; // the index of the atom in the indexer
// Write indices of the atoms to which this visual model is applied
SB_FOR(SBPointer<SBAtom> atom, atomIndexer) {
if (nodeIndexer.getIndex(atom(), atomIndex)) {
// the atom is indexed
serializer->writeBoolElement("atomIsIndexed", true);
serializer->writeUnsignedIntElement("atomIndex", atomIndex);
}
else {
// the atom is not indexed, the user must be copying just the visual model
// so we serialize the atom address itself
serializer->writeBoolElement("atomIsIndexed", false);
serializer->writeUnsignedLongLongElement("atomIndex", (unsigned long long)atom());
}
}
}
This class describes a version number.
Definition: SBCContainerVersionNumber.hpp:14
This class is the base class for serializers.
Definition: SBCSerializer.hpp:10
virtual void writeFloatElement(const std::string &elementName, float element)
Writes an element of float type with elementName name and value element.
Definition: SBCSerializer.cpp:70
virtual void writeUnsignedLongLongElement(const std::string &elementName, unsigned long long element)
Writes an element of unsigned long long integer type with elementName name and value element.
Definition: SBCSerializer.cpp:66
virtual void writeUnsignedIntElement(const std::string &elementName, unsigned int element)
Writes an element of unsigned integer type with elementName name and value element.
Definition: SBCSerializer.cpp:46
virtual void writeBoolElement(const std::string &elementName, bool element)
Writes an element of boolean type with elementName name and value element.
Definition: SBCSerializer.cpp:22
unsigned int getIndex(SBDDataGraphNode *node) const
Returns the index associated to the node.
Definition: SBDDataGraphNodeIndexer.cpp:127
virtual void serialize(SBCSerializer *serializer, const SBNodeIndexer &nodeIndexer, const SBVersionNumber &sdkVersionNumber=SB_SDK_VERSION_NUMBER, const SBVersionNumber &classVersionNumber=SBVersionNumber(1, 0, 0)) const override
Serializes the node.
Definition: SBMVisualModel.cpp:38

First we invoke the serialization function of the parent class. The parent functions do many things (all the way up to SBNode itself, i.e. SBVisualModel::serialize calls SBModel::serialize which calls SBNode::serialize) and are needed for correct saving and loading of node properties. This allows to save the node's name, visibility flag, a material, etc. Then we save information on our visual model itself: the radius factor, number of nodes to which the visual model is applied (nodes referenced by the visual model), and the indices of these nodes in the nodeIndexer or their addresses. For the last part, we check whether the atom itself was serialized or not. Basically, saving of the document leads to the serialization of every node that can be serialized, while copying leads to the serialization only of the copied nodes. If the atom was serialized we save its index in the nodeIndexer, else we save the atom's address.

The unserialize function allows for unserialization of your visual model.

void SEVanDerWaalsVisualModel::unserialize(SBCSerializer* serializer, const SBNodeIndexer& nodeIndexer, const SBVersionNumber& sdkVersionNumber, const SBVersionNumber& classVersionNumber) {
// Unserialization of the parent class
SBMVisualModel::unserialize(serializer, nodeIndexer, sdkVersionNumber, classVersionNumber);
// Read the radius factor
radiusFactor = serializer->readFloatElement();
// Read the number of atoms to which this visual model is applied
unsigned int numberOfAtoms = serializer->readUnsignedIntElement();
bool atomIsIndexed;
unsigned int atomIndex = 0; // the index of the atom in the indexer
// Read indices of the atoms to which this visual model is applied and
// add these node into the atom indexer of the visual model
for (unsigned int i = 0; i < numberOfAtoms; ++i) {
atomIsIndexed = serializer->readBoolElement();
if (atomIsIndexed) {
// the atom was serialized too
atomIndex = serializer->readUnsignedIntElement();
atomIndexer.addReferenceTarget(nodeIndexer[atomIndex]);
}
else {
// the atom was not serialized, it must still exist in memory
atomIndexer.addReferenceTarget((SBAtom*)serializer->readUnsignedLongLongElement());
}
}
}
virtual float readFloatElement()
Reads an element of float type.
Definition: SBCSerializer.cpp:172
virtual unsigned int readUnsignedIntElement()
Reads an element of unsigned integer type.
Definition: SBCSerializer.cpp:138
virtual unsigned long long readUnsignedLongLongElement()
Reads an element of unsigned long long integer type.
Definition: SBCSerializer.cpp:166
virtual bool readBoolElement()
Reads an element of boolean type.
Definition: SBCSerializer.cpp:102
This class describes an atom in a structural model.
Definition: SBMStructuralModelNodeAtom.hpp:34
virtual void unserialize(SBCSerializer *serializer, const SBNodeIndexer &nodeIndexer, const SBVersionNumber &sdkVersionNumber=SB_SDK_VERSION_NUMBER, const SBVersionNumber &classVersionNumber=SBVersionNumber(1, 0, 0)) override
Unserializes the node.
Definition: SBMVisualModel.cpp:44

First, we invoke the unserialization function of the parent class. This will create the node in the data graph. Then we read information on our visual model itself: the radius factor, number of nodes to which the visual model is applied (nodes referenced by the visual model), and the indices of these nodes in the nodeIndexer or their addresses. We check whether the atom itself was serialized or not. If the atom was serialized we read its index in the nodeIndexer, else we read the atom's address.

This code allows us to both copy the visual model in the data graph and save it in SAMSON format files or load it from them.