/**
* This example demonstrates how to use AnchorPoint to track
* Ramses scene content in 2D.
*/
struct SceneAndNodes
{
ramses::Scene* scene;
ramses::Node* node;
ramses::PerspectiveCamera* mainCamera;
ramses::OrthographicCamera* orthoCamera;
};
/**
* Helper method which creates a simple ramses scene. For more ramses
* examples, check the ramses docs at https://bmwcarit.github.io/ramses
*/
SceneAndNodes CreateSceneWithTriangles(ramses::RamsesClient& client, std::array<uint32_t, 2> displaySize);
/**
* Helper to create a simple animation for given node, see animation example for more details on how to create an animation.
*/
void CreateAnimationForNode(rlogic::LogicEngine& logicEngine, const rlogic::RamsesNodeBinding* nodeBinding);
int main()
{
/**
* Use simple class to create ramses framework objects which are not essential for this example.
* For more info on those, please refer to the ramses docs: https://bmwcarit.github.io/ramses
*/
SimpleRenderer renderer;
/**
* Create a simple Ramses scene with 3D mesh (a triangle) and a camera it is rendered with.
* We will track the 3D mesh using AnchorPoint with the help of a 2D camera that will visualize
* the tracking.
*/
auto [scene, node3dToTrack, camera3d, cameraSimulating2d] = CreateSceneWithTriangles(*renderer.getClient(), SimpleRenderer::GetDisplaySize());
/**
* Anchor points require feature level 02 or higher
*/
rlogic::LogicEngine logicEngine{ rlogic::EFeatureLevel_02 };
/**
* First we need to create a Ramses Logic representation of the node we will track using Ramses binding.
*/
rlogic::RamsesNodeBinding* nodeToTrackBinding = logicEngine.createRamsesNodeBinding(*node3dToTrack);
/**
* Create a simple animation for the 3D mesh we are about to track, see animation example for more details on how to create an animation.
*/
CreateAnimationForNode(logicEngine, nodeToTrackBinding);
/**
* Show the scene on the renderer
*/
renderer.showScene(scene->getSceneId());
/**
* Create camera binding for the camera that is used for rendering the 3D mesh we want to track
*/
rlogic::RamsesCameraBinding* camera3dBinding = logicEngine.createRamsesCameraBinding(*camera3d);
/**
* Finally create anchor point, we must provide not only the node we want to track but also the camera that is used to render the 3D mesh
* associated with that node.
*/
const rlogic::AnchorPoint* anchorPoint = logicEngine.createAnchorPoint(*nodeToTrackBinding, *camera3dBinding);
/**
* Simulate an application loop.
*/
while (!renderer.isWindowClosed())
{
/**
* Update the LogicEngine. This will apply changes to Ramses scene from any running animation.
*/
logicEngine.update();
/**
* In this example we manually extract the 2D coordinates and apply them to the special camera viewport to visualize
* that the tracking of the 3D mesh (triangle) works. The result will be a white box snapped to origin of the triangle.
* Alternatively the coordinates can be linked to an another logic node (e.g. LuaScript) to be processed further, perhaps
* end up transforming another mesh (e.g. text or 2D element).
*/
const rlogic::vec2f coords = *anchorPoint->getOutputs()->getChild("viewportCoords")->get<rlogic::vec2f>();
const rlogic::vec2i coords2d{ static_cast<int32_t>(std::lround(coords[0])), static_cast<int32_t>(std::lround(coords[1])) };
cameraSimulating2d->setViewport(coords2d[0], coords2d[1], cameraSimulating2d->getViewportWidth(), cameraSimulating2d->getViewportHeight());
/**
* In order to commit the changes to Ramses scene caused by animations logic we need to "flush" them.
*/
scene->flush();
/**
* Process window events, check if window was closed
*/
renderer.processEvents();
/**
* Throttle the simulation loop by sleeping for a bit.
*/
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}