Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/NavKit/Resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@
#define IDC_CHECK_SKIP_RPKG_EXTRACT 30414
#define IDC_CHECK_EXTRACT_TEXTURE_FILES 30415
#define IDC_CHECK_APPLY_TEXTURES 30416
#define IDC_BUTTON_SELECT_ALL_LODS 30417
#define IDC_BUTTON_DESELECT_ALL_LODS 30418

#define IDD_EXTRACT_NAVP_DIALOG 30500
#define IDC_COMBOBOX_NAVP 30501
Expand Down
11 changes: 7 additions & 4 deletions include/NavKit/adapter/RecastAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Sample;
class BuildContext;
class InputGeom;
class DebugDrawGL;
class SceneMeshHitTestResult;

class RecastAdapter {
RecastAdapter();
Expand Down Expand Up @@ -101,7 +102,9 @@ class RecastAdapter {

dtPolyRef getAdjacentPoly(dtPolyRef poly, int edgeIndex) const;

void doHitTest(int mx, int my);
void setMarker(const SceneMeshHitTestResult& result);

SceneMeshHitTestResult doHitTest(int mx, int my);

void loadSettings() const;

Expand All @@ -111,11 +114,11 @@ class RecastAdapter {

static Vec3 convertFromRecastToNavPower(Vec3 pos);

std::vector<Vec3> getEdges(dtPolyRef polyRef) const;
static std::vector<Vec3> getEdges(const dtNavMeshQuery* navQuery, dtPolyRef polyRef) ;

Vec3 calculateNormal(dtPolyRef polyRef) const;
Vec3 calculateNormal(dtNavMeshQuery* navQuery, dtPolyRef polyRef) const;

Vec3 calculateCentroid(dtPolyRef polyRef) const;
Vec3 calculateCentroid(dtNavMeshQuery* navQuery, dtPolyRef polyRef) const;

const dtNavMesh* getNavMesh() const;

Expand Down
13 changes: 13 additions & 0 deletions include/NavKit/module/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ class HitTestResult {
int selectedIndex;
};

class SceneMeshHitTestResult {
public:
SceneMeshHitTestResult() : hitTime(0.0f), hitIndex(-1) {
rayStart[0] = rayStart[1] = rayStart[2] = 0.0f;
rayEnd[0] = rayEnd[1] = rayEnd[2] = 0.0f;
}

float rayStart[3];
float rayEnd[3];
float hitTime;
int hitIndex;
};

class Renderer {
public:
Renderer();
Expand Down
4 changes: 3 additions & 1 deletion include/NavKit/util/Pathfinding.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ namespace Pathfinding {

NavPower::BBox calculateBBox(const NavPower::Area* area);

Vec3* GetClosestPosInArea2d_G2_EdgeIndex(Vec3* navPowerResult,
Vec3* GetClosestPosInArea2d_G2_EdgeIndex(dtNavMeshQuery* navQuery,
Vec3* navPowerResult,
dtPolyRef poly, const Vec3* navPowerPos,
int* edgeIndex);

Vec3* GetClosestPosInArea2d_G2_ClosestPos(
dtNavMeshQuery* navQuery,
Vec3* resultNavPower,
dtPolyRef polyRef,
const Vec3* posWCoordNavPower,
Expand Down
Binary file modified lib/Debug/NavWeakness.dll
Binary file not shown.
Binary file modified lib/Release/NavWeakness.dll
Binary file not shown.
20 changes: 12 additions & 8 deletions src/NavKit.rc
Original file line number Diff line number Diff line change
Expand Up @@ -291,14 +291,18 @@ BEGIN
CONTROL "Prim",IDC_RADIO_MESH_TYPE_PRIM,"Button",BS_AUTORADIOBUTTON,64,20,40,10

GROUPBOX "Prim Level of Detail",IDC_STATIC,7,50,246,75
AUTOCHECKBOX "LOD 1", IDC_CHECK_PRIM_LOD_1, 14, 65, 50, 8
AUTOCHECKBOX "LOD 2", IDC_CHECK_PRIM_LOD_2, 14, 80, 50, 8
AUTOCHECKBOX "LOD 3", IDC_CHECK_PRIM_LOD_3, 14, 95, 50, 8
AUTOCHECKBOX "LOD 4", IDC_CHECK_PRIM_LOD_4, 14, 110, 50, 8
AUTOCHECKBOX "LOD 5", IDC_CHECK_PRIM_LOD_5, 84, 65, 50, 8
AUTOCHECKBOX "LOD 6", IDC_CHECK_PRIM_LOD_6, 84, 80, 50, 8
AUTOCHECKBOX "LOD 7", IDC_CHECK_PRIM_LOD_7, 84, 95, 50, 8
AUTOCHECKBOX "LOD 8", IDC_CHECK_PRIM_LOD_8, 84, 110, 50, 8
PUSHBUTTON "Select All",IDC_BUTTON_SELECT_ALL_LODS,14,65,60,14
PUSHBUTTON "Deselect All",IDC_BUTTON_DESELECT_ALL_LODS,84,65,60,14

AUTOCHECKBOX "LOD 1 (Highest)", IDC_CHECK_PRIM_LOD_1, 14, 85, 70, 8
AUTOCHECKBOX "LOD 2", IDC_CHECK_PRIM_LOD_2, 84, 85, 40, 8
AUTOCHECKBOX "LOD 3", IDC_CHECK_PRIM_LOD_3, 134, 85, 40, 8
AUTOCHECKBOX "LOD 4", IDC_CHECK_PRIM_LOD_4, 184, 85, 40, 8

AUTOCHECKBOX "LOD 5", IDC_CHECK_PRIM_LOD_5, 14, 105, 40, 8
AUTOCHECKBOX "LOD 6", IDC_CHECK_PRIM_LOD_6, 84, 105, 40, 8
AUTOCHECKBOX "LOD 7", IDC_CHECK_PRIM_LOD_7, 134, 105, 40, 8
AUTOCHECKBOX "LOD 8", IDC_CHECK_PRIM_LOD_8, 184, 105, 40, 8

GROUPBOX "Build Type for Blender File",IDC_STATIC,7,135,246,35
CONTROL "Copy",IDC_RADIO_BUILD_TYPE_COPY,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,14,150,40,10
Expand Down
115 changes: 71 additions & 44 deletions src/adapter/RecastAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ void RecastAdapter::renderRecastNavmesh(const bool isAirgInstance) const {
if (!mesh) {
return;
}
dtNavMeshQuery* navQuery = sample->getNavMeshQuery();
for (int tileIndex = 0; tileIndex < mesh->getMaxTiles(); tileIndex++) {
const dtMeshTile* tile = mesh->getTile(tileIndex);
if (!tile || !tile->header) {
Expand Down Expand Up @@ -474,14 +475,14 @@ void RecastAdapter::renderRecastNavmesh(const bool isAirgInstance) const {

for (int polyIndex = 0; polyIndex < tile->header->polyCount; polyIndex++) {
const dtPolyRef polyRef = getPoly(tileIndex, polyIndex);
auto edges = getEdges(polyRef);
auto edges = getEdges(navQuery, polyRef);
glBegin(GL_LINE_LOOP);
glVertex3f(edges[0].X, edges[0].Y, edges[0].Z);
glVertex3f(edges[1].X, edges[1].Y, edges[1].Z);
glVertex3f(edges[2].X, edges[2].Y, edges[2].Z);
glEnd();
auto centroid = calculateCentroid(polyRef);
renderer.drawText(("ref: " + std::to_string(polyRef) + " idx: " + std::to_string(polyIndex)).c_str(),
auto centroid = calculateCentroid(navQuery, polyRef);
renderer.drawText("ref: " + std::to_string(polyRef) + " idx: " + std::to_string(polyIndex),
{centroid.X, centroid.Y, centroid.Z}, color);
}
}
Expand Down Expand Up @@ -952,7 +953,35 @@ dtPolyRef RecastAdapter::getAdjacentPoly(const dtPolyRef polyRef, const int edge
return 0;
}

void RecastAdapter::doHitTest(const int mx, const int my) {
void RecastAdapter::setMarker(const SceneMeshHitTestResult& result) {
markerPositionSet = true;
markerPosition[0] = result.rayStart[0] + (result.rayEnd[0] - result.rayStart[0]) * result.hitTime;
markerPosition[1] = result.rayStart[1] + (result.rayEnd[1] - result.rayStart[1]) * result.hitTime;
markerPosition[2] = result.rayStart[2] + (result.rayEnd[2] - result.rayStart[2]) * result.hitTime;
for (auto [object, vertexRange] : SceneMesh::getInstance().objectTriangleRanges) {
if (result.hitIndex >= vertexRange.first && result.hitIndex < vertexRange.second) {
selectedObject = object;
break;
}
}
std::string meshNameString;
std::string roomString;
if (Scene::getInstance().sceneLoaded) {
if (const auto mesh = Scene::getInstance().findMeshByHashAndIdAndPos(
selectedObject.substr(0, 16), selectedObject.substr(17, 16), markerPosition); mesh != nullptr) {
meshNameString = mesh->entity.name;
roomString = " Room Folder: " + mesh->roomFolderName + " Room: " + mesh->roomName;
}
}
Logger::log(
NK_INFO,
("Selected Object: '" + meshNameString + "' Mesh: '" + selectedObject + "' Obj vertex: " +
std::to_string(result.hitIndex) + roomString +
". Setting marker position to: " + std::to_string(markerPosition[0]) + ", " +
std::to_string(markerPosition[1]) + ", " + std::to_string(markerPosition[2])).c_str());
}

SceneMeshHitTestResult RecastAdapter::doHitTest(const int mx, const int my) {
float rayStart[3];
float rayEnd[3];
float hitTime;
Expand All @@ -966,40 +995,23 @@ void RecastAdapter::doHitTest(const int mx, const int my) {
rayEnd[0] = (float)x;
rayEnd[1] = (float)y;
rayEnd[2] = (float)z;
const int hit = inputGeom->raycastMesh(rayStart, rayEnd, hitTime);
if (hit != -1) {
// Marker
markerPositionSet = true;
markerPosition[0] = rayStart[0] + (rayEnd[0] - rayStart[0]) * hitTime;
markerPosition[1] = rayStart[1] + (rayEnd[1] - rayStart[1]) * hitTime;
markerPosition[2] = rayStart[2] + (rayEnd[2] - rayStart[2]) * hitTime;
for (auto [object, vertexRange] : SceneMesh::getInstance().objectTriangleRanges) {
if (hit >= vertexRange.first && hit < vertexRange.second) {
selectedObject = object;
break;
}
}
std::string meshNameString;
std::string roomString;
if (Scene::getInstance().sceneLoaded) {
if (const auto mesh = Scene::getInstance().findMeshByHashAndIdAndPos(
selectedObject.substr(0, 16), selectedObject.substr(17, 16), markerPosition); mesh != nullptr) {
meshNameString = mesh->entity.name;
roomString = " Room Folder: " + mesh->roomFolderName + " Room: " + mesh->roomName;
}
}
Logger::log(
NK_INFO,
("Selected Object: '" + meshNameString + "' Mesh: '" + selectedObject + "' Obj vertex: " +
std::to_string(hit) + roomString +
". Setting marker position to: " + std::to_string(markerPosition[0]) + ", " +
std::to_string(markerPosition[1]) + ", " + std::to_string(markerPosition[2])).c_str());
} else {
if (SDL_GetModState()) {
// Marker
markerPositionSet = false;
}
SceneMeshHitTestResult result;
if (const int hitIndex = inputGeom->raycastMesh(rayStart, rayEnd, hitTime); hitIndex != -1) {
result.hitIndex = hitIndex;
result.rayStart[0] = rayStart[0];
result.rayStart[1] = rayStart[1];
result.rayStart[2] = rayStart[2];
result.rayEnd[0] = rayEnd[0];
result.rayEnd[1] = rayEnd[1];
result.rayEnd[2] = rayEnd[2];
result.hitTime = hitTime;
return result;
}
result.hitIndex = -1;
if (SDL_GetModState()) {
markerPositionSet = false;
}
return result;
}

void RecastAdapter::loadSettings() const {
Expand Down Expand Up @@ -1085,8 +1097,16 @@ Vec3 RecastAdapter::convertFromRecastToNavPower(Vec3 pos) {
return {pos.X, -pos.Z, pos.Y};
}

std::vector<Vec3> RecastAdapter::getEdges(const dtPolyRef polyRef) const {
const dtNavMesh* mesh = sample->getNavMesh();
std::vector<Vec3> RecastAdapter::getEdges(const dtNavMeshQuery* navQuery, const dtPolyRef polyRef) {
if (!navQuery) {
return {};
}

const dtNavMesh* mesh = navQuery->getAttachedNavMesh();
if (!mesh) {
return {};
}

unsigned int salt = 0;
unsigned int tileIndex = 0;
unsigned int polyIndex = 0;
Expand All @@ -1106,8 +1126,11 @@ std::vector<Vec3> RecastAdapter::getEdges(const dtPolyRef polyRef) const {
return edges;
}

Vec3 RecastAdapter::calculateNormal(const dtPolyRef polyRef) const {
const std::vector<Vec3> edges = getEdges(polyRef);
Vec3 RecastAdapter::calculateNormal(dtNavMeshQuery* navQuery, const dtPolyRef polyRef) const {
const std::vector<Vec3> edges = getEdges(navQuery, polyRef);
if (edges.size() < 3) {
return {0.0f, 1.0f, 0.0f};
}
const Vec3 v0 = edges.at(0);
const Vec3 v1 = edges.at(1);
const Vec3 v2 = edges.at(2);
Expand All @@ -1118,9 +1141,13 @@ Vec3 RecastAdapter::calculateNormal(const dtPolyRef polyRef) const {
return cross.GetUnitVec();
}

Vec3 RecastAdapter::calculateCentroid(const dtPolyRef polyRef) const {
const std::vector<Vec3> edges = getEdges(polyRef);
const Vec3 normal = calculateNormal(polyRef);
Vec3 RecastAdapter::calculateCentroid(dtNavMeshQuery* navQuery, const dtPolyRef polyRef) const {
const std::vector<Vec3> edges = getEdges(navQuery, polyRef);
if (edges.empty()) {
return {0.0f, 0.0f, 0.0f};
}

const Vec3 normal = calculateNormal(navQuery, polyRef);
const Vec3 v0 = edges.at(0);
const Vec3 v1 = edges.at(1);

Expand Down
54 changes: 46 additions & 8 deletions src/model/Json.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "../../include/NavKit/model/Json.h"

#include <algorithm>
#include <type_traits>
#include "../../include/NavKit/module/Logger.h"
#include "../../include/NavKit/module/Scene.h"

Expand All @@ -22,9 +24,31 @@ std::string Json::toString(std::string_view val) {
template <typename t, typename> Json::JsonValueProxy::operator t() {
using simdT = typename SimdJsonTypeMap<t>::type;
simdT val;
if (json[field].get(val) == simdjson::SUCCESS) {

if (simdjson::ondemand::value jsonValue = json[field]; jsonValue.get(val) == simdjson::SUCCESS) {
Logger::log(NK_DEBUG, "Field: %s value: %s", field.c_str(), toString(val).c_str());
return static_cast<t>(val);
} else if constexpr (std::is_arithmetic_v<t>) {
std::string_view strVal;
if (simdjson::error_code err; (err = jsonValue.get_string().get(strVal)) == simdjson::SUCCESS) {
try {
if constexpr (std::is_integral_v<t>) {
val = static_cast<simdT>(std::stoll(std::string(strVal)));
} else if constexpr (std::is_floating_point_v<t>) {
val = static_cast<simdT>(std::stod(std::string(strVal)));
}
Logger::log(NK_DEBUG, "Field: %s value (from string conversion): %s", field.c_str(),
toString(val).c_str());
return static_cast<t>(val);
} catch (const std::exception& e) {
Logger::log(NK_ERROR, "Error converting string '%s' to numeric type for field: %s. Exception: %s",
std::string(strVal).c_str(), field.c_str(), e.what());
}
} else {
Logger::log(
NK_ERROR, "Error getting value for field: %s. Not a direct numeric or string value. Simdjson error: %s",
field.c_str(), simdjson::error_message(err));
}
}
Logger::log(NK_ERROR, "Error getting value for field: %s", field.c_str());
return {};
Expand Down Expand Up @@ -125,12 +149,12 @@ void Json::Mesh::writeJson(std::ostream& f) const {
R"(","roomFolderName":")" << roomFolderName <<
R"(","entity":{"id":")" << entity.id <<
R"(","name":")" << entity.name << R"(",)";
entity.position.writeJson(f);
f << ",";
entity.rotation.writeJson(f);
f << ",";
entity.scale.writeJson(f);
f << "}}";
entity.position.writeJson(f);
f << ",";
entity.rotation.writeJson(f);
f << ",";
entity.scale.writeJson(f);
f << "}}";
}

Json::Meshes::Meshes(simdjson::ondemand::array meshesJson) {
Expand Down Expand Up @@ -180,7 +204,21 @@ void Json::PfBoxes::readPathfindingBBoxes() {
Vec3 s = entity.scale.data;
Rotation r = entity.rotation;
PfBoxType type = entity.type;
scene.includeBox = {id, name, p, s, r, type};
if (scene.includeBox.id.empty()) {
scene.includeBox = {id, name, p, s, r, type};
} else {
// Set scene.includeBox pos, scale, and rotation to be the span of the two boxes
float minX = std::min(scene.includeBox.pos.x - scene.includeBox.scale.x / 2.0f, p.x - s.x / 2.0f);
float minY = std::min(scene.includeBox.pos.y - scene.includeBox.scale.y / 2.0f, p.y - s.y / 2.0f);
float minZ = std::min(scene.includeBox.pos.z - scene.includeBox.scale.z / 2.0f, p.z - s.z / 2.0f);
float maxX = std::max(scene.includeBox.pos.x + scene.includeBox.scale.x / 2.0f, p.x + s.x / 2.0f);
float maxY = std::max(scene.includeBox.pos.y + scene.includeBox.scale.y / 2.0f, p.y + s.y / 2.0f);
float maxZ = std::max(scene.includeBox.pos.z + scene.includeBox.scale.z / 2.0f, p.z + s.z / 2.0f);

scene.includeBox.pos = {(minX + maxX) / 2.0f, (minY + maxY) / 2.0f, (minZ + maxZ) / 2.0f};
scene.includeBox.scale = {maxX - minX, maxY - minY, maxZ - minZ};
scene.includeBox.rotation = {0, 0, 0, 1};
}
includeBoxFound = true;
}
if (entity.type.data == EXCLUDE_TYPE) {
Expand Down
Loading
Loading