Creating a c++ standalone simulation


#include <iostream>
#include <Atoms/Initialize.h>
#include <Atoms/AgentsSimulation.h>
#include <Atoms/AgentsSimulations.h>
#include <Atoms/SimulationTime.h>
#include <Atoms/AgentGroup.h>
#include <AtomsModules/Initialize.h>
#include <Atoms/BehaviourModules.h>
#include <chrono>
#include <Atoms/AnimationClip.h>
#include <Atoms/AnimationClips.h>
#include <Atoms/SimulationEvents.h>
#include <Atoms/GlobalNames.h>
#include <Atoms/SimulationEvent.h>
#include <AtomsCore/Metadata/Vector3Metadata.h>
#include <AtomsCore/Metadata/IntMetadata.h>
#include <AtomsCore/Metadata/BoolMetadata.h>
#include <AtomsCore/Metadata/DoubleMetadata.h>
#include <AtomsCore/Metadata/MapMetadata.h>
#include <AtomsCore/Metadata/StringMetadata.h>

/////////////////////////
// REGISTER CLIPS
/////////////////////////

template<const char* NAME, const char* CLIPNAME, int START, int END, int LOOP_BLEND, bool LOOP, bool IDLE>
class AtomsRobotClip : public Atoms::SimulationEvent
{
public:
	AtomsRobotClip() : Atoms::SimulationEvent()
	{
		setName(NAME);
	}

	virtual ~AtomsRobotClip()
	{

	}

	void load()
	{
		//CLIP = GLOBAL_NAMES.CLIP
		const char* eventName = NAME;
		const char* clipNameFile = CLIPNAME;
		const int blendFramesAfterFootUp = 4;
		const bool loop = LOOP;
		const int loopStart = START;
		const int loopEnd = END;
		const int loopBlend = 4;
		const bool idle = IDLE;
		const double direction[3] = { 1.0, 0.0, 0.0 };
		const int directionType = 1;
		const int directionFromJoints[2] = { 0, 1 };

		std::string clipPath = "";
		if (getenv("ATOMS_DATA"))
		{
			std::string dataPath = getenv("ATOMS_DATA");
			clipPath = dataPath + "/" + clipNameFile;
		}

		Atoms::AnimationClips& aClips = Atoms::AnimationClips::instance();
		aClips.addAnimationClip(eventName, clipPath, true);
		Atoms::AnimationClipPtr acPtr = aClips.animationClip(eventName);
		if (!acPtr)
			return;

		AtomsCore::MapMetadata& metadataMap = acPtr->metadata();

		metadataMap.addEntry(ATOMS_CLIP_BLEND_FRAMES_AFTER_FOOT_UP, &AtomsCore::IntMetadata(blendFramesAfterFootUp));
		metadataMap.addEntry(ATOMS_CLIP_LOOP, &AtomsCore::BoolMetadata(loop));
		metadataMap.addEntry(ATOMS_CLIP_LOOP_START, &AtomsCore::IntMetadata(loopStart));
		metadataMap.addEntry(ATOMS_CLIP_LOOP_END, &AtomsCore::IntMetadata(loopEnd));
		metadataMap.addEntry(ATOMS_CLIP_LOOP_NUM_BLEND_FRAMES, &AtomsCore::IntMetadata(loopBlend));

		if (directionType)
		{
			acPtr->setDirectionType(Atoms::AnimationClip::DirectionType::kStatic);
		}
		else if (directionType == 0)
		{
			acPtr->setDirectionType(Atoms::AnimationClip::DirectionType::kPelvis);
		}
		else
		{
			acPtr->setDirectionType(Atoms::AnimationClip::DirectionType::kJoints);
		}
		acPtr->setDirection(AtomsCore::Vector3(direction[0], direction[1], direction[2]));
		acPtr->setDirectionFromJoints(directionFromJoints[0], directionFromJoints[1]);
		acPtr->setIdle(idle);
	}

	static Atoms::SimulationEvent* creator(const std::string& parameter)
	{
		return new AtomsRobotClip();
	}
};

extern const char robotIdleName[] = "atomsRobotIdle";
extern const char robotIdleClip[] = "atomsRobot_idle.fbx";
typedef AtomsRobotClip<robotIdleName, robotIdleClip, 0, 1, 0, true, false> AtomsRobotIdleClip;

extern const char robotWalkName[] = "atomsRobotWalk";
extern const char robotWalkClip[] = "atomsRobot_walk.fbx";
typedef AtomsRobotClip<robotWalkName, robotWalkClip, 21, 50, 4, true, false> AtomsRobotWalkClip;

extern const char robotRunName[] = "atomsRobotRun";
extern const char robotRunClip[] = "atomsRobot_run.fbx";
typedef AtomsRobotClip<robotRunName, robotRunClip, 6, 26, 4, true, false> AtomsRobotRunClip;

extern const char robotIdleToWalkName[] = "atomsRobotIdleToWalk";
extern const char robotIdleToWalkClip[] = "atomsRobot_idleToWalk.fbx";
typedef AtomsRobotClip<robotIdleToWalkName, robotIdleToWalkClip, 17, 66, 6, false, false> AtomsRobotIdleToWalkClip;

extern const char robotWalkToRunName[] = "atomsRobotWalkToRun";
extern const char robotWalkToRunClip[] = "atomsRobot_walkToRun.fbx";
typedef AtomsRobotClip<robotWalkToRunName, robotWalkToRunClip, 0, 45, 3, false, false> AtomsRobotWalkToRunClip;

void registerAtomsClips(Atoms::AgentsSimulation& sim)
{
	Atoms::SimulationEvents& events = Atoms::SimulationEvents::instance();
	events.registerSimulationEvent(robotIdleName, AtomsRobotIdleClip::creator, Atoms::SimulationEvent::kAnimClipNative);
	events.registerSimulationEvent(robotWalkName, AtomsRobotWalkClip::creator, Atoms::SimulationEvent::kAnimClipNative);
	events.registerSimulationEvent(robotRunName, AtomsRobotRunClip::creator, Atoms::SimulationEvent::kAnimClipNative);
	events.registerSimulationEvent(robotIdleToWalkName, AtomsRobotIdleToWalkClip::creator, Atoms::SimulationEvent::kAnimClipNative);
	events.registerSimulationEvent(robotWalkToRunName, AtomsRobotWalkToRunClip::creator, Atoms::SimulationEvent::kAnimClipNative);
	
	sim.addAnimationClipEvent(events.createSimulationEvent(robotIdleName));
	sim.addAnimationClipEvent(events.createSimulationEvent(robotWalkName));
	sim.addAnimationClipEvent(events.createSimulationEvent(robotRunName));
	sim.addAnimationClipEvent(events.createSimulationEvent(robotIdleToWalkName));
	sim.addAnimationClipEvent(events.createSimulationEvent(robotWalkToRunName));
}

/////////////////////////
// REGISTER AGENT TYPE
/////////////////////////

template<
	const char* NAME,
	const char* SKEL_PATH,
	const char* GEO_PATH,
	const char* SKIN_PATH,
	const char* STATE_MACHINE>
class SimTestAgentType : public Atoms::SimulationEvent
{
public:
	

	SimTestAgentType() : Atoms::SimulationEvent()
	{
		setName(NAME);
	}

	virtual ~SimTestAgentType()
	{

	}

	void load()
	{
		const char* stateMachine = STATE_MACHINE;
		const double scaleMultiplier = 1.0;

		std::string skeletonPath = "";
		std::string geoPath = "";
		std::string skinPath = "";
		if (getenv("ATOMS_DATA"))
		{
			std::string dataPath = getenv("ATOMS_DATA");
			skeletonPath = dataPath + "/" + SKEL_PATH;
			geoPath = dataPath + "/" + GEO_PATH;
			skinPath = dataPath + "/" + SKIN_PATH;
		}

		AtomsCore::Skeleton skel(1);
		AtomsCore::Archive	skeletonArchive;
		if (skeletonArchive.readFromFile(skeletonPath))
		{
			skeletonArchive >> skel;
		}
		else
		{
			return;
		}

		Atoms::AgentType aType;
		aType.setSkeleton(skel);

		AtomsCore::MapMetadata meshMap;
		AtomsCore::Archive typeArchive;
		if (typeArchive.readFromFile(geoPath))
		{
			meshMap.deserialise(typeArchive);
			aType.metadata().addEntry(ATOMS_AGENT_TYPE_LOW_GEO, &meshMap);
		}

		AtomsCore::MapMetadata skinMap;
		AtomsCore::Archive skinArchive;
		if (skinArchive.readFromFile(skinPath))
		{
			skinMap.deserialise(skinArchive);
			aType.metadata().addEntry(ATOMS_AGENT_TYPE_SKIN_GEO, &skinMap);
		}


		aType.metadata().addEntry(ATOMS_AGENT_TYPE_STATE_MACHINE, &AtomsCore::StringMetadata(stateMachine));
		aType.metadata().addEntry(ATOMS_AGENT_TYPE_SCALE_MULTIPLIER, &AtomsCore::DoubleMetadata(scaleMultiplier));

		Atoms::AgentTypes::instance().addAgentType(NAME, aType);
	}

	void unload()
	{
		Atoms::AgentTypes::instance().removeAgentType(NAME);
	}

	static Atoms::SimulationEvent* creator(const std::string& parameter)
	{
		return new SimTestAgentType();
	}
};

extern const char atomsRobotName[] = "atomsRobot";
extern const char atomsRobotSkel[] = "atomsRobot.atomsskel";
extern const char atomsRobotGeo[] = "atomsRobot.geos";
extern const char atomsRobotSkin[] = "atomsRobot_skin.geos";
extern const char atomsRobotStateMachineName[] = "atomsRobotStateMachine";
typedef SimTestAgentType<atomsRobotName, atomsRobotSkel, atomsRobotGeo, atomsRobotSkin, atomsRobotStateMachineName> AtomsRobotAgentType;

void registerAgentType(Atoms::AgentsSimulation& sim)
{
	Atoms::SimulationEvents& events = Atoms::SimulationEvents::instance();
	events.registerSimulationEvent(atomsRobotName, AtomsRobotAgentType::creator, Atoms::SimulationEvent::kAgentTypeNative);
	sim.addAgentTypeEvent(events.createSimulationEvent(atomsRobotName));
}

/////////////////////////////////
// Register state machine
/////////////////////////////////

void registerStateMachine(Atoms::AgentsSimulation& sim)
{
	Atoms::StateMachines& stateMachineManager = Atoms::StateMachines::instance();
	Atoms::StateMachine stateMachine;
	Atoms::AnimationState currentAnimState("idle", 0, AtomsCore::Vector3(0.200000, 0.200000, 0.200000), 3, 3);
	currentAnimState.addClip(Atoms::AnimationStateClip("atomsRobotIdle", 0, 0, 0.000000, 0.000000));
	stateMachine.addAnimationState(currentAnimState);
	currentAnimState = Atoms::AnimationState("walk", 1, AtomsCore::Vector3(0.200000, 0.200000, 0.200000), 3, 3);
	currentAnimState.addClip(Atoms::AnimationStateClip("atomsRobotWalk", 0, 0, 0.000000, 0.000000));
	stateMachine.addAnimationState(currentAnimState);
	currentAnimState = Atoms::AnimationState("run", 2, AtomsCore::Vector3(0.200000, 0.200000, 0.200000), 3, 3);
	currentAnimState.addClip(Atoms::AnimationStateClip("atomsRobotRun", 0, 0, 0.000000, 0.000000));
	stateMachine.addAnimationState(currentAnimState);
	currentAnimState = Atoms::AnimationState("idleToWalk", -1, AtomsCore::Vector3(0.200000, 0.200000, 0.200000), 3, 3);
	currentAnimState.addClip(Atoms::AnimationStateClip("atomsRobotIdleToWalk", 0, 0, 0.000000, 0.000000));
	stateMachine.connect("idle", "walk", currentAnimState);
	currentAnimState = Atoms::AnimationState("walkToRun", -1, AtomsCore::Vector3(0.200000, 0.200000, 0.200000), 3, 3);
	currentAnimState.addClip(Atoms::AnimationStateClip("atomsRobotWalkToRun", 0, 0, 0.000000, 0.000000));
	stateMachine.connect("walk", "run", currentAnimState);
	stateMachineManager.addStateMachine("atomsRobotStateMachine", stateMachine, true);
}

//////////////////////////////////
// Main simulation
//////////////////////////////////

int main()
{
	Atoms::initAtoms();
	AtomsModules::initAtomsModules();
	

	Atoms::AgentsSimulation simulation;
	Atoms::AgentsSimulations::instance().addAgentsSimulation("main", &simulation);

	registerAtomsClips(simulation);
	registerStateMachine(simulation);
	registerAgentType(simulation);


	Atoms::BehaviourModules& modulesFactory = Atoms::BehaviourModules::instance();
	AtomsPtr<Atoms::AgentGroup> agGroup(new Atoms::AgentGroup());
	agGroup->setMultithread(true);
	simulation.addAgentGroup(agGroup);

	auto gridLayout = modulesFactory.createBehaviourModule("gridLayout");
	gridLayout->attributes().getTypedEntry<AtomsCore::StringMetadata>("agentType")->set("atomsRobot");
	gridLayout->attributes().getTypedEntry<AtomsCore::Vector3Metadata>("size")->set(AtomsCore::Vector3(50,0,50));
	auto stateMachine = modulesFactory.createBehaviourModule("stateMachine");
	stateMachine->attributes().getTypedEntry<AtomsCore::IntMetadata>("state")->set(1);
	agGroup->addBehaviourModule("gridLayout", gridLayout);
	agGroup->addBehaviourModule("stateMachine", stateMachine);
	
	Atoms::SimulationTime& atomsTime = Atoms::SimulationTime::instance();
	atomsTime.set(0);
	atomsTime.setFps(24.0);

	
	simulation.initSimulation();

	for (unsigned int i = 0; i < 50; i++)
	{
		atomsTime.set(i);
		auto start = std::chrono::high_resolution_clock::now();
		simulation.initFrame();
		simulation.computeFrame();
		simulation.endFrame();
		auto end = std::chrono::high_resolution_clock::now();
		auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
		std::cout << "Frame " << i << " " << elapsed <<"ms " << 1.0 /(static_cast<double>(elapsed)*0.001) <<"fps" << std::endl;
	}

	simulation.endSimulation();
	return 0;
}

Copyright © 2017, Toolchefs LTD.