RAMSES Documentation  27.0.130
Information for RAMSES users and developers
ramses-example-local-scene-referencing/src/main.cpp

Example for controlling scene state and data linking of scenes via scene referencing instead of renderer API.

// -------------------------------------------------------------------------
// Copyright (C) 2020 BMW AG
// -------------------------------------------------------------------------
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
// -------------------------------------------------------------------------
#include "ramses-client.h"
#include "ramses-utils.h"
#include <thread>
#include <unordered_map>
{
public:
void windowClosed(ramses::displayId_t /*displayId*/) override
{
m_windowClosed = true;
}
bool isWindowClosed() const
{
return m_windowClosed;
}
private:
bool m_windowClosed = false;
};
class SceneReferenceEventHandler final : public ramses::IClientEventHandler
{
public:
explicit SceneReferenceEventHandler(ramses::RamsesClient& client)
: m_client(client)
{}
virtual void sceneFileLoadFailed(const char*) override {}
virtual void sceneFileLoadSucceeded(const char*, ramses::Scene*) override {}
virtual void dataUnlinked(ramses::sceneId_t, ramses::dataConsumerId_t, bool) override {}
{
m_sceneRefState[sceneRef.getReferencedSceneId()] = state;
}
void waitForSceneRefState(ramses::sceneId_t sceneId, ramses::RendererSceneState state)
{
while (m_sceneRefState.count(sceneId) == 0 || m_sceneRefState.find(sceneId)->second != state)
{
std::this_thread::sleep_for(std::chrono::milliseconds(5));
m_client.dispatchEvents(*this);
}
}
private:
std::unordered_map<ramses::sceneId_t, ramses::RendererSceneState> m_sceneRefState;
};
static constexpr unsigned VPWidth = 600;
static constexpr unsigned VPHeight = 400;
static constexpr unsigned DispWidth = 1280;
static constexpr unsigned DispHeight = 480;
// Master scene's data provider IDs
static constexpr ramses::dataProviderId_t VP1OffsetProviderId{ 333 };
static constexpr ramses::dataProviderId_t VP1SizeProviderId{ 334 };
static constexpr ramses::dataProviderId_t VP2OffsetProviderId{ 335 };
static constexpr ramses::dataProviderId_t VP2SizeProviderId{ 336 };
static constexpr ramses::dataProviderId_t Color1ProviderId{ 337 };
static constexpr ramses::dataProviderId_t Color2ProviderId{ 338 };
static constexpr ramses::dataProviderId_t Color3ProviderId{ 339 };
static constexpr ramses::dataProviderId_t Color4ProviderId{ 340 };
// Content scene's data consumer IDs
static constexpr ramses::dataConsumerId_t VPOffsetConsumerId{ 350 };
static constexpr ramses::dataConsumerId_t VPSizeConsumerId{ 351 };
static constexpr ramses::dataConsumerId_t Color1ConsumerId{ 352 };
static constexpr ramses::dataConsumerId_t Color2ConsumerId{ 353 };
{
ramses::Scene* clientScene = client.createScene(sceneId);
ramses::PerspectiveCamera* camera = clientScene->createPerspectiveCamera("camera");
camera->setFrustum(19.f, 1280.f / 480.f, 0.1f, 1500.f);
camera->setTranslation(0.0f, 0.0f, 5.0f);
// Bind data objects to scene's camera viewport offset/size and mark as data consumers
const auto vpOffsetData = clientScene->createDataVector2i("vpOffset");
const auto vpSizeData = clientScene->createDataVector2i("vpSize");
vpOffsetData->setValue(0, 0);
vpSizeData->setValue(VPWidth, VPHeight);
camera->bindViewportOffset(*vpOffsetData);
camera->bindViewportSize(*vpSizeData);
clientScene->createDataConsumer(*vpOffsetData, VPOffsetConsumerId);
clientScene->createDataConsumer(*vpSizeData, VPSizeConsumerId);
ramses::RenderPass* renderPass = clientScene->createRenderPass("my render pass");
renderPass->setCamera(*camera);
ramses::RenderGroup* renderGroup = clientScene->createRenderGroup();
renderPass->addRenderGroup(*renderGroup);
float vertexPositionsArray[] = { -1.f, 0.f, -6.f, 1.f, 0.f, -6.f, 0.f, 1.f, -6.f };
ramses::ArrayResource* vertexPositions = clientScene->createArrayResource(ramses::EDataType::Vector3F, 3, vertexPositionsArray);
uint16_t indicesArray[] = { 0, 1, 2 };
ramses::ArrayResource* indices = clientScene->createArrayResource(ramses::EDataType::UInt16, 3, indicesArray);
effectDesc.setVertexShader(R"glsl(#version 100
uniform highp mat4 mvpMatrix;
attribute vec3 a_position;
void main() {
gl_Position = mvpMatrix * vec4(a_position, 1.0);
})glsl");
effectDesc.setFragmentShader(R"glsl(#version 100
uniform highp vec4 color;
void main(void) {
gl_FragColor = color + vec4(0.1);
})glsl");
ramses::Effect* effect = clientScene->createEffect(effectDesc, ramses::ResourceCacheFlag_DoNotCache, "glsl shader");
ramses::Appearance* appearance = clientScene->createAppearance(*effect, "triangle appearance");
ramses::GeometryBinding* geometry = clientScene->createGeometryBinding(*effect, "triangle geometry");
geometry->setIndices(*indices);
ramses::AttributeInput positionsInput;
effect->findAttributeInput("a_position", positionsInput);
geometry->setInputBuffer(positionsInput, *vertexPositions);
ramses::MeshNode* meshNode = clientScene->createMeshNode("triangle mesh node");
meshNode->setAppearance(*appearance);
meshNode->setGeometryBinding(*geometry);
renderGroup->addMeshNode(*meshNode);
ramses::MeshNode* meshNode2 = clientScene->createMeshNode("triangle mesh node 2");
ramses::Appearance* appearance2 = clientScene->createAppearance(*effect, "triangle appearance");
meshNode2->setAppearance(*appearance2);
meshNode2->setGeometryBinding(*geometry);
renderGroup->addMeshNode(*meshNode2);
meshNode2->setTranslation(0, -10, -5);
meshNode2->setScaling(100, 100, 1);
effect->findUniformInput("color", colorInput);
// Create data objects to hold color and bind them to appearance inputs
auto color1 = clientScene->createDataVector4f();
auto color2 = clientScene->createDataVector4f();
color1->setValue(1.f, 1.f, 1.f, 1.f);
color1->setValue(0.5f, 0.5f, 0.5f, 1.f);
appearance->bindInput(colorInput, *color1);
appearance2->bindInput(colorInput, *color2);
clientScene->createDataConsumer(*color1, Color1ConsumerId);
clientScene->createDataConsumer(*color2, Color2ConsumerId);
clientScene->flush();
clientScene->publish();
}
{
ramses::Scene* clientScene = client.createScene(sceneId);
// In master scene create data objects and mark them as providers to control other scenes' viewports
const auto vp1offset = clientScene->createDataVector2i("vp1offset");
const auto vp1size = clientScene->createDataVector2i("vp1size");
const auto vp2offset = clientScene->createDataVector2i("vp2offset");
const auto vp2size = clientScene->createDataVector2i("vp2size");
vp1offset->setValue(0, 0);
vp1size->setValue(DispWidth, DispHeight);
vp2offset->setValue(0, 0);
vp2size->setValue(DispWidth, DispHeight);
clientScene->createDataProvider(*vp1offset, VP1OffsetProviderId);
clientScene->createDataProvider(*vp1size, VP1SizeProviderId);
clientScene->createDataProvider(*vp2offset, VP2OffsetProviderId);
clientScene->createDataProvider(*vp2size, VP2SizeProviderId);
// Create data objects and mark them as providers to control content scenes colors
const auto color1 = clientScene->createDataVector4f("color1");
const auto color2 = clientScene->createDataVector4f("color2");
const auto color3 = clientScene->createDataVector4f("color3");
const auto color4 = clientScene->createDataVector4f("color4");
color1->setValue(1.f, 1.f, 0.3f, 1.f);
color2->setValue(0.f, 0.3f, 0.5f, 1.f);
color3->setValue(1.f, 0.f, 0.5f, 1.f);
color4->setValue(0.5f, 0.3f, 0.f, 1.f);
clientScene->createDataProvider(*color1, Color1ProviderId);
clientScene->createDataProvider(*color2, Color2ProviderId);
clientScene->createDataProvider(*color3, Color3ProviderId);
clientScene->createDataProvider(*color4, Color4ProviderId);
clientScene->flush();
clientScene->publish();
return clientScene;
}
int main(int argc, char* argv[])
{
// create a renderer and a client locally, open a display
ramses::RamsesFrameworkConfig config(argc, argv);
config.setRequestedRamsesShellType(ramses::ERamsesShellType_Console); //needed for automated test of examples
ramses::RamsesFramework framework(config);
ramses::RamsesClient& client(*framework.createClient("ExampleSceneReferencing"));
ramses::RendererConfig rendererConfig(argc, argv);
ramses::RamsesRenderer& renderer(*framework.createRenderer(rendererConfig));
renderer.startThread();
ramses::DisplayConfig displayConfig(argc, argv);
const ramses::displayId_t display = renderer.createDisplay(displayConfig);
renderer.flush();
framework.connect();
// prepare a master scene and two scenes, which are to be referenced
const ramses::sceneId_t refSceneId1(1u);
const ramses::sceneId_t refSceneId2(2u);
const ramses::sceneId_t sceneIdMaster(3u);
createContentProviderScene(client, refSceneId1);
createContentProviderScene(client, refSceneId2);
ramses::Scene* masterScene = createSceneMaster(client, sceneIdMaster);
ramses::RendererSceneControl& sceneControlAPI = *renderer.getSceneControlAPI();
sceneControlAPI.setSceneMapping(sceneIdMaster, display);
sceneControlAPI.flush();
// create a scene reference for both scenes
ramses::SceneReference* sceneRef1 = masterScene->createSceneReference(refSceneId1);
ramses::SceneReference* sceneRef2 = masterScene->createSceneReference(refSceneId2);
// request scene references state to rendered, they will be brought to state rendered alongside with master scene
masterScene->flush();
// request master scene to be ready, so scene references can become ready as well
sceneControlAPI.setSceneState(sceneIdMaster, ramses::RendererSceneState::Ready);
sceneControlAPI.flush();
// wait for referenced scene to be available, before trying to data link
SceneReferenceEventHandler eventHandler(client);
eventHandler.waitForSceneRefState(refSceneId1, ramses::RendererSceneState::Ready);
eventHandler.waitForSceneRefState(refSceneId2, ramses::RendererSceneState::Ready);
// Link master scene's data objects to other scenes cameras' viewports
masterScene->linkData(nullptr, VP1OffsetProviderId, sceneRef1, VPOffsetConsumerId);
masterScene->linkData(nullptr, VP1SizeProviderId, sceneRef1, VPSizeConsumerId);
masterScene->linkData(nullptr, VP2OffsetProviderId, sceneRef2, VPOffsetConsumerId);
masterScene->linkData(nullptr, VP2SizeProviderId, sceneRef2, VPSizeConsumerId);
masterScene->flush();
// Link master scene's data objects to scene1 and scene2 colors
masterScene->linkData(nullptr, Color1ProviderId, sceneRef1, Color1ConsumerId);
masterScene->linkData(nullptr, Color2ProviderId, sceneRef1, Color2ConsumerId);
masterScene->linkData(nullptr, Color3ProviderId, sceneRef2, Color1ConsumerId);
masterScene->linkData(nullptr, Color4ProviderId, sceneRef2, Color2ConsumerId);
masterScene->flush();
// wait and check for data link result events for all links, skipped here for example simplicity
// Now that everything is set up properly, bring master scene to a rendered state
sceneControlAPI.setSceneState(sceneIdMaster, ramses::RendererSceneState::Rendered);
sceneControlAPI.flush();
// These are master scene's data objects linked to scene1 and scene2 cameras' viewports
auto scene1vpOffset = ramses::RamsesUtils::TryConvert<ramses::DataVector2i>(*masterScene->findObjectByName("vp1offset"));
auto scene1vpSize = ramses::RamsesUtils::TryConvert<ramses::DataVector2i>(*masterScene->findObjectByName("vp1size"));
auto scene2vpOffset = ramses::RamsesUtils::TryConvert<ramses::DataVector2i>(*masterScene->findObjectByName("vp2offset"));
auto scene2vpSize = ramses::RamsesUtils::TryConvert<ramses::DataVector2i>(*masterScene->findObjectByName("vp2size"));
// start animating data provider values after scenes are being rendered
eventHandler.waitForSceneRefState(refSceneId1, ramses::RendererSceneState::Rendered);
eventHandler.waitForSceneRefState(refSceneId2, ramses::RendererSceneState::Rendered);
int animParam = 0;
bool animInc = true;
RendererEventHandler rendererEventHandler;
while (!rendererEventHandler.isWindowClosed())
{
renderer.dispatchEvents(rendererEventHandler);
// animate master scene
scene1vpOffset->setValue(VPWidth / 8 + VPWidth / 2 * animParam / 100, VPHeight / 8 + VPHeight / 4 * animParam / 100);
scene1vpSize->setValue(VPWidth / 4 + VPWidth / 2 * animParam / 100, VPHeight / 4 + VPHeight / 4 * animParam / 100);
const auto invAnimParam = 100 - animParam;
scene2vpOffset->setValue(DispWidth / 2 - VPWidth / 2 * invAnimParam / 100, DispHeight - DispHeight / 4 - VPHeight / 4 * invAnimParam / 100);
scene2vpSize->setValue(VPWidth / 2 + VPWidth / 2 * invAnimParam / 100, VPHeight / 4 + VPHeight / 4 * invAnimParam / 100);
masterScene->flush();
animParam = (animInc ? animParam + 1 : animParam - 1);
if (animParam == 0 || animParam == 100)
animInc = !animInc;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
Definition: main.cpp:24
void windowClosed(ramses::displayId_t) override
This method will be called when a display's window has been closed.
Definition: main.cpp:26
bool isWindowClosed() const
Definition: main.cpp:31
The Appearance describes how an object should look like. This includes GLSL uniform values,...
Definition: Appearance.h:34
status_t bindInput(const UniformInput &input, const DataObject &dataObject)
Bind a DataObject to the Appearance's uniform input. The value from the DataObject will be used and a...
The ArrayResource stores a data array of a given type. The data is immutable. The resource can be use...
Definition: ArrayResource.h:26
The AttributeInput is a description of an attribute effect input.
Definition: AttributeInput.h:22
status_t bindViewportOffset(const DataVector2i &offsetData)
Binds a ramses::DataObject to be used as source for viewport offset values.
status_t bindViewportSize(const DataVector2i &sizeData)
Binds a ramses::DataObject to be used as source for viewport size values.
status_t setValue(int32_t x, int32_t y)
Sets/updates the stored values of the vector.
status_t setValue(float x, float y, float z, float w)
Sets/updates the stored values of the vector.
The DisplayConfig holds a set of parameters to be used to initialize a display.
Definition: DisplayConfig.h:22
An effect description holds all necessary information for an effect to be created.
Definition: EffectDescription.h:21
status_t setVertexShader(const char *shaderSource)
Sets vertex shader source from string.
status_t setFragmentShader(const char *shaderSource)
Sets fragment shader source from string.
status_t setUniformSemantic(const char *inputName, EEffectUniformSemantic semanticType)
Sets an uniform semantic. Used for uniforms which are not locally available on the client,...
An effect describes how an object will be rendered to the screen.
Definition: Effect.h:26
status_t findUniformInput(const char *inputName, UniformInput &uniformInput) const
Finds uniform input by input name.
status_t findAttributeInput(const char *inputName, AttributeInput &attributeInput) const
Finds attribute input by input name.
A geometry binding together with an appearance describe how an object will be rendered to the screen.
Definition: GeometryBinding.h:25
status_t setIndices(const ArrayResource &indicesResource)
Assign a data array with data type UInt16 or UInt32 to be used when accessing vertex data.
status_t setInputBuffer(const AttributeInput &attributeInput, const ArrayResource &arrayResource, uint32_t instancingDivisor=0)
Assign a data array resource to a given effect attribute input.
Provides an interface for handling the result of client events. Implementation of this interface must...
Definition: IClientEventHandler.h:27
virtual void sceneReferenceStateChanged(SceneReference &sceneRef, RendererSceneState state)=0
This method will be called when state on renderer side of a scene referenced using ramses::SceneRefer...
virtual void dataUnlinked(sceneId_t consumerScene, dataConsumerId_t consumerId, bool success)=0
This method will be called when the data link between a data provider and data consumer is destroyed ...
virtual void sceneFileLoadFailed(const char *filename)=0
This method will be called when asynchronous loading of a scene or one of its associated resource fil...
virtual void sceneFileLoadSucceeded(const char *filename, Scene *loadedScene)=0
This method will be called when asynchronous loading of a scene file and its associated resource file...
virtual void dataLinked(sceneId_t providerScene, dataProviderId_t providerId, sceneId_t consumerScene, dataConsumerId_t consumerId, bool success)=0
This method will be called when the data link between a data provider and data consumer is establishe...
virtual void sceneReferenceFlushed(SceneReference &sceneRef, sceneVersionTag_t versionTag)=0
This method will be called after a flush with version tag (ramses::Scene::flush) has been applied and...
The MeshNode holds all information which is needed to render an object to the screen.
Definition: MeshNode.h:25
status_t setAppearance(Appearance &appearance)
Sets the Appearance of the MeshNode.
status_t setGeometryBinding(GeometryBinding &geometry)
Sets the GeometryBinding of the MeshNode.
status_t setScaling(float x, float y, float z)
Sets the absolute scale in all three dimensions.
status_t setTranslation(float x, float y, float z)
Sets the absolute translation the absolute values.
The PerspectiveCamera is a local camera which defines a perspective view into the scene.
Definition: PerspectiveCamera.h:23
status_t setFrustum(float fov, float aspectRatio, float nearPlane, float farPlane)
An alternative method (see ramses::Camera::setFrustum) to set the perspective view frustum of the cam...
Entry point of RAMSES client API.
Definition: RamsesClient.h:34
Scene * createScene(sceneId_t sceneId, const SceneConfig &sceneConfig=SceneConfig(), const char *name=nullptr)
Create a new empty Scene.
The RamsesFrameworkConfig holds a set of parameters to be used to initialize ramses.
Definition: RamsesFrameworkConfig.h:23
Class representing ramses framework components that are needed to initialize an instance of ramses cl...
Definition: RamsesFramework.h:35
RamsesRenderer is the main renderer component which provides API to configure and control the way con...
Definition: RamsesRenderer.h:37
The RenderGroup is a container used to collect renderables which are supposed to be rendered together...
Definition: RenderGroup.h:31
status_t addMeshNode(const MeshNode &mesh, int32_t orderWithinGroup=0)
Add a mesh to this RenderGroup. If a mesh is already contained in this RenderGroup only its render or...
The RenderPass is a container used to collect meshes which are supposed to be rendered together.
Definition: RenderPass.h:31
status_t setCamera(const Camera &camera)
Set the camera to use for rendering the objects of this renderpass.
status_t setClearFlags(uint32_t clearFlags)
Set the clear flags which enable/disable the clearing of the render target assigned to this RenderPas...
status_t addRenderGroup(const RenderGroup &renderGroup, int32_t orderWithinPass=0)
Add a RenderGroup to this RenderPass for rendering.
The RendererConfig holds a set of parameters to be used to initialize a renderer.
Definition: RendererConfig.h:26
Convenience empty implementation of IRendererEventHandler that can be used to derive from when only s...
Definition: IRendererEventHandler.h:194
Control states of scenes.
Definition: RendererSceneControl.h:33
status_t setSceneState(sceneId_t sceneId, RendererSceneState state)
Request state change of a scene.
status_t setSceneMapping(sceneId_t sceneId, displayId_t displayId)
Set scene display mapping.
status_t flush()
Submits scene control commands (API calls on RendererSceneControl) since previous flush to be execute...
The SceneReference object refers to another ramses scene using its sceneId.
Definition: SceneReference.h:37
status_t requestState(RendererSceneState requestedState)
Set a requested state for this scene reference.
sceneId_t getReferencedSceneId() const
Get the sceneId of the referenced scene.
The Scene holds a scene graph. It is the essential class for distributing content to the ramses syste...
Definition: Scene.h:83
MeshNode * createMeshNode(const char *name=nullptr)
Creates a scene graph MeshNode. MeshNode is a Node with additional properties and bindings that repre...
Effect * createEffect(const EffectDescription &effectDesc, resourceCacheFlag_t cacheFlag=ResourceCacheFlag_DoNotCache, const char *name=nullptr)
Create a new Effect by parsing a GLSL shader described by an EffectDescription instance....
SceneReference * createSceneReference(sceneId_t referencedScene, const char *name=nullptr)
Creates a new SceneReference object.
DataVector4f * createDataVector4f(const char *name=nullptr)
Creates a data object within the scene, which holds a data value of type Vector4f.
GeometryBinding * createGeometryBinding(const Effect &effect, const char *name=nullptr)
Creates a new GeometryBinding.
ArrayResource * createArrayResource(EDataType type, uint32_t numElements, const void *arrayData, resourceCacheFlag_t cacheFlag=ResourceCacheFlag_DoNotCache, const char *name=nullptr)
Create a new ArrayResource. It makes a copy of the given data of a certain type as a resource,...
status_t publish(EScenePublicationMode publicationMode=EScenePublicationMode_LocalAndRemote)
Publishes the scene to the ramses system.
status_t linkData(SceneReference *providerReference, dataProviderId_t providerId, SceneReference *consumerReference, dataConsumerId_t consumerId)
Tell the RamsesRenderer to link a data provider to a data consumer across two scenes.
RenderPass * createRenderPass(const char *name=nullptr)
Create a render pass in the scene.
Appearance * createAppearance(const Effect &effect, const char *name=nullptr)
Creates a new Appearance.
DataVector2i * createDataVector2i(const char *name=nullptr)
Creates a data object within the scene, which holds a data value of type Vector2i.
RenderGroup * createRenderGroup(const char *name=nullptr)
Create a RenderGroup instance in the scene.
PerspectiveCamera * createPerspectiveCamera(const char *name=nullptr)
Creates a Perspective Camera in this Scene.
status_t createDataConsumer(const DataObject &dataObject, dataConsumerId_t dataId)
Annotates a DataObject as a data consumer. Data provider and data consumer can be linked on Ramses Re...
status_t createDataProvider(const DataObject &dataObject, dataProviderId_t dataId)
Annotates a DataObject as a data provider. Data provider and data consumer can be linked on Ramses Re...
const RamsesObject * findObjectByName(const char *name) const
Get an object from the scene by name.
status_t flush(sceneVersionTag_t sceneVersionTag=InvalidSceneVersionTag)
Commits all changes done to the scene since the last flush or since scene creation....
The UniformInput is a description of an uniform effect input.
Definition: UniformInput.h:22
@ EClearFlags_None
Definition: RamsesFrameworkTypes.h:257
@ ModelViewProjectionMatrix
Model-view-projection matrix 4x4.
@ UInt16
one component of type uint16_t per data element
@ Vector3F
three components of type float per data element
@ ERamsesShellType_Console
Definition: RamsesFrameworkTypes.h:169
RendererSceneState
Definition: RendererSceneState.h:19
@ Rendered
Scene is being rendered.
@ Ready
Scene is ready to start rendering (its resources are uploaded).
constexpr const resourceCacheFlag_t ResourceCacheFlag_DoNotCache
Requests the render to not cache a resource. This is the default value.
Definition: RamsesFrameworkTypes.h:212
uint64_t sceneVersionTag_t
Scene version tag used to refer to content versions of a scene. A scene version may be updated along ...
Definition: RamsesFrameworkTypes.h:49
int main(int argc, char *argv[])
Definition: main.cpp:21
void createContentProviderScene(ramses::RamsesClient &client, ramses::sceneId_t sceneId)
Definition: main.cpp:96
ramses::Scene * createSceneMaster(ramses::RamsesClient &client, ramses::sceneId_t sceneId)
Definition: main.cpp:178