A Viewer is a specific FlowVR Module with an output port (often named scene) sending scene primitives. FlowVR-render extends the FlowVR-app standard library to provide a ModuleViewer class that eases the description of new viewer. This class extends the FlowVR-app Module class to add a scene port.
If your viewer doesn't need other new ports, you can use directly the ModuleViewer class to describe your viewer and to create a MetaModule that launches the process associated to your viewer.
The MetaModule describing the first viewer of this tutorial (the viewer cube, refer to section
for more details) is an example. The name of the executable is set using the constructor as for standard metamodule.
//Mandatory virtual destructor virtual MetaModuleViewerCube();
// Mandatory create method virtual Component* create() const return new MetaModuleViewerCube(getId());; ;
In this tutorial, we use this composite component (ViewersGroup) as a container for all viewers. This component has only an output port scenes gathering primitives from all viewers. These primitives will be sent to the Renderer. The Renderer component will then merge and render all the primitives.
To add a new viewer in this container, we only need to add the MetaModule of the viewer and link its scene port with the scenes port of the ViewersGroup which will be later linked to the scene port of the Renderer. For instance, in the ViewersGroup::execute() method, these two instructions add and link the MetaModuleViewerCube:
The parameter example enables to select which example must be executed. That is the possible values:
)
)
)
)
)
)
)
)
flowvr -L Tutorial -P tutorial:example=1 -x -s -l
First, the interface of the module must be declared to the daemon as a standard FlowVR module. The port that will send the scene is a specific type of port (Type SceneOutputPort instead of OutputPort)
// Declare a FlowVR Render output port to send our scene description. SceneOutputPort pOut("scene");
// Initialize FlowVR std::vector<flowvr::Port*> ports; ports.push_back(&pOut); flowvr::ModuleAPI* module = flowvr::initModule(ports);
if (module == NULL) return 1;
A specific class defines message with the scene primitives:
At the first iteration, we have to declare the IDs of objects involved in the scene. There are two kind of objects:
A primitives contains references (ID) to several resources. A primitive should have at least these two ressources:
A resource could be shared between different primitives.
In this example, we have one primitive with a vertex buffer and an index buffer. The following code will create their ID:
Then, we fill the ressources. First, we need to reserve necessary space in the FlowVR message.
After this reservation, the vertex buffer in the FlowVR message will have the following structure (Fig
)
The data can be set directly on this data section:
// Normals = Positions for this example for(unsigned int i = 0; i != 8; ++i) vdata[3*i +1] = vdata[3*i]; vdata[3*i +1].normalize();
// A different color for each vertices for(unsigned int i = 0; i != 8; ++i) vdata[3*i+2] = Vec3f((float)(i&1), (float)((i»1)&1), (float)((i»2)&1));
Then we set the index buffer:
// Index buffer. We set values of the 12 triangles Vec<3,char>* idata = (Vec<3,char>*) ib->data(); idata[0] = Vec<3,char>(0, 2, 1); idata[1] = Vec<3,char>(0, 3, 2); idata[2] = Vec<3,char>(0, 1, 4); idata[3] = Vec<3,char>(1, 5, 4); idata[4] = Vec<3,char>(3, 7, 0); idata[5] = Vec<3,char>(0, 7, 4); idata[6] = Vec<3,char>(4, 6, 5); idata[7] = Vec<3,char>(4, 7, 6); idata[8] = Vec<3,char>(1, 5, 2); idata[9] = Vec<3,char>(2, 5, 6); idata[10] = Vec<3,char>(2, 3, 6); idata[11] = Vec<3,char>(6, 3, 7);
Now, the primitive can be created:
And we link ressources using the addParamID method. First, we link the vertex buffer resource. Two steps compose this link:
)
The index buffer is linked to the primitive:
Global parameter as the light vector for the shading or projection matrices can be associated to a primitive using the addParam or addParamEnum methods.
A specific example is dedicated to these methods addParamID, addParam and addParamEnum and shaders customization. Refer to the section
for more details.
At least, we can write the main FlowVR loop. Here, the scene is static, so we just send the message at each iteration.
// Main FlowVR loop. Contains the animations of the scene while (module->wait()) // Update scene // Nothing in this simple example...
// Send message scene.put(&pOut); sleep(1); //To avoid overflow
module->close();
return 0;
flowvr -L Tutorial -P``tutorial:example=3 tutorial:OBJFILE=bunny.obj'' -x -s -l
flowvr -L Tutorial -P tutorial:example=2 tutorial:textureFileName=exampleTexture.jpg -x -s -l
You can try another image filename instead of exampleTexture.jpg
2009-04-06