/**
* This example demonstrates how to use RamsesMeshNodeBinding in a simple scene.
*/
struct SceneAndMesh
{
ramses::Scene* scene;
ramses::MeshNode* mesh;
};
/**
* Helper method which creates a simple ramses scene. For more ramses
* examples, check the ramses docs at https://bmwcarit.github.io/ramses
*/
SceneAndMesh CreateSceneWithTriangles(ramses::RamsesClient& client);
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 a simple mesh.
* We will then apply vertex skinning on this mesh.
*/
auto [scene, meshNode] = CreateSceneWithTriangles(*renderer.getClient());
/**
* Skin binding requires feature level 05 or higher.
*/
rlogic::LogicEngine logicEngine{ rlogic::EFeatureLevel_05 };
/**
* Show the scene on the renderer.
*/
renderer.showScene(scene->getSceneId());
/**
* Create control script which will output values meaningful for some of the RamsesMeshNodeBinding inputs.
* This script takes in time ticker and adjusts mesh parameters so that it cycles through up to 3 instances
* of it also cycles through subsets of vertices to be used to render it.
*/
rlogic::LuaConfig scriptConfig;
scriptConfig.addStandardModuleDependency(rlogic::EStandardModule::Math);
rlogic::LuaScript* controlScript = logicEngine.createLuaScript(R"(
function interface(IN,OUT)
IN.ticker = Type:Int64()
OUT.vertexOffset = Type:Int32()
OUT.indexCount = Type:Int32()
OUT.instanceCount = Type:Int32()
end
function run(IN,OUT)
local tickerMs = IN.ticker / 1000
OUT.vertexOffset = 4 - (math.floor(tickerMs / 333.333333) % 3) * 2
OUT.indexCount = 8 - OUT.vertexOffset
OUT.instanceCount = math.floor(tickerMs / 1000) % 3 + 1
end
)", scriptConfig);
/**
* As mentioned above the control script requires time ticker, here we create it and link it to the script.
*/
rlogic::TimerNode* timer = logicEngine.createTimerNode();
logicEngine.link(
*timer->getOutputs()->getChild("ticker_us"),
*controlScript->getInputs()->getChild("ticker"));
/**
* Finally we create the RamsesMeshNodeBinding which binds to our mesh.
* Each control script output is linked to the corresponding RamsesMeshNodeBinding's input.
*/
const auto meshNodeBinding = logicEngine.createRamsesMeshNodeBinding(*meshNode, "meshNodeBinding");
logicEngine.link(
*controlScript->getOutputs()->getChild("vertexOffset"),
*meshNodeBinding->getInputs()->getChild("vertexOffset"));
logicEngine.link(
*controlScript->getOutputs()->getChild("indexCount"),
*meshNodeBinding->getInputs()->getChild("indexCount"));
logicEngine.link(
*controlScript->getOutputs()->getChild("instanceCount"),
*meshNodeBinding->getInputs()->getChild("instanceCount"));
/**
* Note that we do not link all the RamsesMeshNodeBinding input properties (e.g. 'indexOffset' is not used here),
* meaning it will be initialized by Ramses and not modified in any way by Ramses logic.
*/
/**
* Simulate an application loop.
*/
while (!renderer.isWindowClosed())
{
/**
* Update the LogicEngine. This will apply changes to Ramses scene from any running script.
*/
logicEngine.update();
/**
* In order to commit the changes to Ramses scene 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));
}