관심 지점은 지정된 위치에서 사용자 정의 데이터를 NavMesh에 공간화하고 특정 공간 영역 내에 있는 점을 신속하게 검색할 수 있는 오브젝트입니다.
PointOfInterest 클래스의 각 인스턴스는 게임에서 나타내는 오브젝트 또는 데이터의 유형을 식별(즉, 은폐 지점, 저격점 등)하기 위해 설정할 수 있는 정수 ID와 게임에서 특정 오브젝트(즉, 무기 또는 탄약 오브젝트, 헬스 팩 등)를 참조하도록 설정할 수 있는 빈 포인터를 유지합니다.
관심 지점은 전적으로 런타임에서 관리되며, 현재 지형에 대한 NavMesh를 사전 생성하는 데이터 생성 프로세스의 일부가 아닙니다. 필요할 때마다 언제든지 런타임에 관심 지점을 생성하고, 필요한 경우 이를 새 위치로 이동하며, 공간 쿼리를 사용하여 검색할 수 있습니다.
게임에서 PointOfInterest 초기화 및 파괴를 관리하는 클래스를 설정할 수 있습니다. PointOfInterest가 Gameware Navigation World 내에서 나타내는 오브젝트의 수명을 관리하는 클래스가 게임에 이미 있을 수도 있습니다. 이 경우 해당 클래스를 사용할 수 있습니다.
예: [Tutorial_PointOfInterest.cpp의 코드]
class MyGamePointOfInterest
{
public:
MyGamePointOfInterest() : m_navPointOfInterest(KY_NULL) {}
void Initialize(Kaim::World* world, const Kaim::Vec3f& position);
void Destroy();
void SetPosition(const Kaim::Vec3f& newPosition);
Kaim::Ptr<Kaim::PointOfInterest> m_navPointOfInterest;
...
};PointOfInterest를 초기화하려면 PointOfInterest에 필요한 데이터를 사용하여 설정하는 PointOfInterestInitConfig 구성 클래스의 인스턴스를 제공해야 합니다. 적어도 다음을 설정해야 합니다.
예: [Tutorial_PointOfInterest.cpp의 코드]
void MyGamePointOfInterest::Initialize(Kaim::World* world, const Kaim::Vec3f& position)
{
...
// Set up the PointOfInterestInitConfig
Kaim::PointOfInterestInitConfig pointOfInterestInitConfig;
pointOfInterestInitConfig.m_world = world;
pointOfInterestInitConfig.m_startPosition = position;
pointOfInterestInitConfig.m_poiType = Kaim::PointOfInterestType_FirstClient;
// Create and initialize the point of interest, and add it to its World
m_navPointOfInterest = *KY_NEW Kaim::PointOfInterest;
m_navPointOfInterest->Init(pointOfInterestInitConfig);
m_navPointOfInterest->AddToWorld();
// Set a pointer to your own data
m_navPointOfInterest->SetUserData(this);
...
}PointOfInterest가 나타내는 오브젝트가 해당 위치 또는 게임 내 다른 데이터를 변경할 때마다 PointOfInterest를 업데이트하여 새 상태를 반영해야 합니다. PointofInterest::SetPosition() 함수를 사용하면 새 상태를 반영할 수 있습니다.
이 경우 PointOfInterest가 즉시 수정되는 것은 아닙니다. 다음에 World가 업데이트될 때까지 업데이트가 지연됩니다.
예: [Tutorial_PointOfInterest.cpp의 코드]
void MyGamePointOfInterest::SetPosition(const Kaim::Vec3f& newPosition)
{
m_navPointOfInterest->SetPosition(newPosition);
}PointOfInterest를 파괴하려면
예: [Tutorial_PointOfInterest.cpp의 코드]
void MyGamePointOfInterest::Destroy()
{
m_navPointOfInterest->RemoveFromWorld();
m_navPointOfInterest = KY_NULL;
}관심 지점은 Bot 및 동적 장애물과 같은 공간화된 WorldElements의 다른 클래스에서 사용하는 메커니즘과 마찬가지로, 내부 SpatializedPoint 오브젝트를 사용하여 NavMesh에 공간화됩니다. SpatializedPointCollectorInAABBQuery 클래스의 인스턴스를 만들고 실행하여 지정된 경계 상자 내에서 공간화된 점을 검색할 수 있습니다.
기본적으로 쿼리에서는 모든 종류의 공간화된 점을 검색하지만, 결과에 관심 지점만 포함되도록 쿼리에 대한 필터를 제공할 수 있습니다.
예: [Tutorial_PointOfInterest.cpp의 코드]
void CollectAndRenderNearbyPointsOfInterest(Kaim::Database* database, const Kaim::Vec3f& collectorBoxCenter, KyFloat32 collectorBoxHalfExtentFloat)
{
...
// Set up a filter
Kaim::SpatializedPointCollectorFilter_SelectiveCollect selectiveCollect;
selectiveCollect.Select(Kaim::SpatializedPointObjectType_PointOfInterest);
// Instantiate the query
Kaim::SpatializedPointCollectorInAABBQuery<Kaim::SpatializedPointCollectorFilter_SelectiveCollect> query(selectiveCollect);
query.BindToDatabase(database);
// Set up the query parameters
const Kaim::Vec3f collectorBoxHalfExtentVec3f(collectorBoxHalfExtentFloat, collectorBoxHalfExtentFloat, collectorBoxHalfExtentFloat);
const Kaim::Box3f collectorBoxExtent(collectorBoxHalfExtentVec3f, collectorBoxHalfExtentVec3f);
query.Initialize(collectorBoxCenter, collectorBoxExtent);
// Perform the query
query.PerformQueryBlocking();
...
쿼리가 완료되면 결과를 반복하여 검색된 점을 처리할 수 있습니다. 예를 들어 다음 코드는 각 관심 지점의 ID를 Navigation Lab에서 렌더링하도록 시각적 디버깅 프레임워크로 푸시합니다. [Tutorial_PointOfInterest.cpp의 코드]
...
Kaim::ScopedDisplayList displayList(database->GetWorld(), Kaim::DisplayList_Enable);
displayList.InitSingleFrameLifespan("Nearby POIs", "Tutorial_PointOfInterest");
Kaim::VisualShapeColor displayColor;
displayColor.m_lineColor = Kaim::VisualColor::Magenta;
displayList.PushBox(query.ComputeAABB(), displayColor);
if (query.GetResult() == Kaim::SPATIALIZEDPOINTCOLLECTOR_DONE)
{
Kaim::QueryDynamicOutput* queryDynamicOutput = query.GetQueryDynamicOutput();
if (queryDynamicOutput)
{
for(KyUInt32 i = 0; i < queryDynamicOutput->GetSpatializedPointCount(); ++i)
{
Kaim::SpatializedPoint* spatializedPoint = queryDynamicOutput->GetSpatializedPoint(i);
if (spatializedPoint)
{
const Kaim::Vec3f& position = spatializedPoint->GetPosition();
displayList.PushArrow(position + Kaim::Vec3f::UnitZ(), position, 0.1f, displayColor);
if (spatializedPoint->GetObjectType() == Kaim::SpatializedPointObjectType_PointOfInterest)
{
Kaim::StringStream displayText;
Kaim::PointOfInterest* pointOfInterest = (Kaim::PointOfInterest*)spatializedPoint->GetObject();
MyGamePointOfInterest* myGamePointOfInterest = (MyGamePointOfInterest*)pointOfInterest->GetUserData();
displayText << " POI #" << myGamePointOfInterest->m_id;
displayList.PushText(position + Kaim::Vec3f::UnitZ(), Kaim::VisualColor::White, displayText.CStr());
}
}
}
}
}
}