#include "GwNavTestFwk/GwNavTestFwk.h"
#include "common/oneworldenv.h"
#include "LabEngine/gamebot.h"
#include "LabEngine/utils/labengineutils.h"
namespace
{
class RigidBodyPhysics
{
public:
RigidBodyPhysics()
: m_oscillationPhase(0.0f)
, m_oscillationVelocityFactor(1.0f)
{}
{
m_transform.m_translation = position;
m_linearVelocity = linearVelocity;
m_angularVelocity = angularVelocity;
}
void Update(
KyFloat32 simulationStepsInSeconds)
{
m_oscillationPhase += simulationStepsInSeconds;
m_oscillationVelocityFactor = cosf(m_oscillationPhase);
const Kaim::Vec3f velocity = m_oscillationVelocityFactor * m_linearVelocity;
m_transform.m_translation += velocity * simulationStepsInSeconds;
if (m_angularVelocity.IsZero() == false)
{
const Kaim::Matrix3x3f rotationMatrix(rotationAxis, rotationSpeedRadPerSecond * simulationStepsInSeconds);
m_transform.m_rotationMatrix = rotationMatrix * m_transform.m_rotationMatrix;
}
}
void SetLinearVelocity(
const Kaim::Vec3f& linearVelocity) { m_linearVelocity = linearVelocity; }
void SetAngularVelocity(
const Kaim::Vec3f& angularVelocity) { m_angularVelocity = angularVelocity; }
const Kaim::Vec3f& GetPosition()
const {
return m_transform.m_translation; }
const Kaim::Vec3f GetLinearVelocity()
const {
return m_oscillationVelocityFactor * m_linearVelocity; }
const Kaim::Vec3f& GetAngularVelocity()
const {
return m_angularVelocity; }
bool IsSleeping() const { return (m_linearVelocity.IsZero() && m_angularVelocity.IsZero()); }
private:
};
class MyGameCylinderObstacle
{
public:
MyGameCylinderObstacle() : m_navCylinderObstacle(
KY_NULL) {}
void Destroy();
void Update(
KyFloat32 simulationStepsInSeconds);
RigidBodyPhysics m_rigidBodyPhysics;
Kaim::Ptr<Kaim::CylinderObstacle> m_navCylinderObstacle;
};
{
m_rigidBodyPhysics.Initialize(position, linearVelocity);
cylinderObstacleInitConfig.
m_world = world;
cylinderObstacleInitConfig.
m_radius = radius;
cylinderObstacleInitConfig.
m_height = height;
cylinderObstacleInitConfig.
m_startPosition = m_rigidBodyPhysics.GetPosition();
cylinderObstacleInitConfig.
m_navTag.SetAsExclusive();
m_navCylinderObstacle->
Init(cylinderObstacleInitConfig);
m_navCylinderObstacle->SetCurrentVisualDebugLOD(Kaim::VisualDebugLOD_Maximal);
}
void MyGameCylinderObstacle::Destroy()
{
m_navCylinderObstacle->RemoveFromWorld();
}
void MyGameCylinderObstacle::Update(
KyFloat32 simulationStepsInSeconds)
{
const bool isStopped = m_rigidBodyPhysics.IsSleeping();
m_navCylinderObstacle->SetDoesTriggerTagVolume(isStopped);
if (isStopped)
return;
m_rigidBodyPhysics.Update(simulationStepsInSeconds);
m_navCylinderObstacle->SetPosition(m_rigidBodyPhysics.GetPosition());
m_navCylinderObstacle->SetVelocity(m_rigidBodyPhysics.GetLinearVelocity());
}
class MyGameBoxObstacle
{
public:
MyGameBoxObstacle(): m_navBoxObstacle(
KY_NULL) {}
void Destroy();
void Update(
KyFloat32 simulationStepsInSeconds);
RigidBodyPhysics m_rigidBodyPhysics;
Kaim::Ptr<Kaim::BoxObstacle> m_navBoxObstacle;
};
{
m_rigidBodyPhysics.Initialize(position, linearVelocity, angularVelocity);
boxObstacleInitConfig.
m_world = world;
boxObstacleInitConfig.
m_localHalfExtents = boxHalfExtents;
boxObstacleInitConfig.
m_startPosition = m_rigidBodyPhysics.GetPosition();
boxObstacleInitConfig.
m_navTag.SetAsExclusive();
m_navBoxObstacle->
Init(boxObstacleInitConfig);
m_navBoxObstacle->AddToWorld();
m_navBoxObstacle->SetCurrentVisualDebugLOD(Kaim::VisualDebugLOD_Maximal);
}
void MyGameBoxObstacle::Destroy()
{
m_navBoxObstacle->RemoveFromWorld();
}
void MyGameBoxObstacle::Update(
KyFloat32 simulationStepsInSeconds)
{
const bool isStopped = m_rigidBodyPhysics.IsSleeping();
m_navBoxObstacle->SetDoesTriggerTagVolume(isStopped);
if (isStopped)
return;
m_rigidBodyPhysics.Update(simulationStepsInSeconds);
m_navBoxObstacle->SetTransform(m_rigidBodyPhysics.GetTransform());
m_navBoxObstacle->SetLinearVelocity(m_rigidBodyPhysics.GetLinearVelocity());
m_navBoxObstacle->SetAngularVelocity(m_rigidBodyPhysics.GetAngularVelocity());
}
class MyGameTagVolume
{
public:
MyGameTagVolume(): m_navTagVolume(
KY_NULL) {}
void Destroy();
Kaim::Ptr<Kaim::TagVolume> m_navTagVolume;
};
{
m_navTagVolume->
Init(navTagVolumeInitConfig);
m_navTagVolume->SetCurrentVisualDebugLOD(Kaim::VisualDebugLOD_Maximal);
m_navTagVolume->AddToWorld();
}
void MyGameTagVolume::Destroy()
{
m_navTagVolume->RemoveFromWorld();
}
void UpdateScenario(
KyUInt32 frameIndex, MyGameCylinderObstacle& cylinderObstacle, MyGameBoxObstacle& boxObstacle,
{
static const KyUInt32 scenarioCycleLength = 1000;
const KyUInt32 scenarioCycleIdx = frameIndex / scenarioCycleLength;
const KyUInt32 scenarioFrameIdx = frameIndex % scenarioCycleLength;
if (scenarioFrameIdx == 200)
{
return;
}
if (scenarioFrameIdx == 300)
{
return;
}
if (scenarioFrameIdx == 600)
{
tagVolume.Destroy();
return;
}
if (scenarioFrameIdx == 700)
{
cylinderObstacle.m_rigidBodyPhysics.SetLinearVelocity(
Kaim::Vec3f(3.0f, 0.0f, 0.0f));
return;
}
if (scenarioFrameIdx == 800)
{
boxObstacle.m_rigidBodyPhysics.SetLinearVelocity(linearVelocity);
boxObstacle.m_rigidBodyPhysics.SetAngularVelocity(angularVelocity);
return;
}
if (scenarioFrameIdx == 900)
{
if (scenarioCycleIdx % 2 == 0)
navTagVolumeInitConfig.
m_navTag.SetAsWalkable();
else
navTagVolumeInitConfig.
m_navTag.SetAsExclusive();
navTagVolumeInitConfig.
m_navTag.m_blindDataArray[0] = scenarioCycleIdx;
const Kaim::Vec2f positionOffset(cosf(direction), sinf(direction));
const KyUInt32 pointCount = navTagVolumeInitConfig.
m_points.GetCount();
for (
KyUInt32 i = 0; i < pointCount; ++i)
navTagVolumeInitConfig.m_points[i] += positionOffset;
tagVolume.Initialize(navTagVolumeInitConfig);
return;
}
}
#define TEST_ENV_CLASS OneWorldEnv
TEST_ENV {}
TUTORIAL
{
KT_LOG_TITLE_BEGIN("TUTORIAL - Obstacle Integration");
const KyUInt32 simulationFrameCount = 60;
const KyFloat32 simulationDeltaTimeInSeconds = 0.016f;
CHECK(env.LoadAndAddNavData(
"GeneratedNavData/opencastle/opencastle.NavData") !=
KY_NULL);
env.StartVisualDebugUsingLab();
LabEngine::GameBotInitConfig gameBotInitConfig;
gameBotInitConfig.m_botInitConfig.m_database = navDatabase;
gameBotInitConfig.m_botInitConfig.m_startPosition.Set(-38.7f, -9.1f, 8.7f);
LabEngine::GameBot* gameBot = env.AddBotFromConfig(gameBotInitConfig);
gameBot->PushWayPoint(
Kaim::Vec3f(-38.7f, -9.1f, 8.7f));
gameBot->PushWayPoint(
Kaim::Vec3f(-10.8f, 7.8f, 10.9f));
const Kaim::Vec3f cylinderPosition(-29.6941f, 2.0931f, 9.53431f);
const Kaim::Vec3f cylinderLinearVelocity(3.0f, 0.0f, 0.0f);
MyGameCylinderObstacle myGameCylinderObstacle;
myGameCylinderObstacle.Initialize(navWorld, cylinderRadius, cylinderHeight, cylinderPosition, cylinderLinearVelocity);
const Kaim::Vec3f boxPosition(-24.5504f, 5.5223f, 10.3989f);
const Kaim::Vec3f boxAngularVelocity(0.0f, 0.0f, 1.0f);
MyGameBoxObstacle myGameBoxObstacle;
myGameBoxObstacle.Initialize(navWorld, boxHalfExtents, boxPosition, boxLinearVelocity, boxAngularVelocity);
navTagVolumeInitConfig.
m_world = navWorld;
navTagVolumeInitConfig.
m_altitudeMin = 10.0f;
navTagVolumeInitConfig.
m_altitudeMax = 11.0f;
navTagVolumeInitConfig.m_points.PushBack(
Kaim::Vec2f(-19.0967f, 7.93156f));
navTagVolumeInitConfig.m_points.PushBack(
Kaim::Vec2f(-15.3928f, 4.77404f));
navTagVolumeInitConfig.m_points.PushBack(
Kaim::Vec2f(-11.9082f, 9.46633f));
navTagVolumeInitConfig.m_points.PushBack(
Kaim::Vec2f(-14.6730f, 16.2140f));
navTagVolumeInitConfig.m_points.PushBack(
Kaim::Vec2f(-14.5526f, 10.8631f));
navTagVolumeInitConfig.m_points.PushBack(
Kaim::Vec2f(-18.5613f, 10.9361f));
navTagVolumeInitConfig.
m_navTag.SetAsExclusive();
navTagVolumeInitConfig.
m_navTag.m_blindDataArray.PushBack(0);
MyGameTagVolume myGameTagVolume;
myGameTagVolume.Initialize(navTagVolumeInitConfig);
for (
KyUInt32 frameIdx = 0; frameIdx < simulationFrameCount; ++frameIdx)
{
myGameCylinderObstacle.Update(simulationDeltaTimeInSeconds);
myGameBoxObstacle.Update(simulationDeltaTimeInSeconds);
env.Update(simulationDeltaTimeInSeconds);
LabEngine::Utils::TimedBusyWait(1000.0f * simulationDeltaTimeInSeconds);
UpdateScenario(frameIdx, myGameCylinderObstacle, myGameBoxObstacle, myGameTagVolume, navTagVolumeInitConfig);
}
myGameCylinderObstacle.Destroy();
myGameBoxObstacle.Destroy();
myGameTagVolume.Destroy();
env.CleanUpWorld();
}
}