Skip to content

Commit 15c56ce

Browse files
authored
Various fixes (#87)
1 parent a0bc6ff commit 15c56ce

19 files changed

Lines changed: 352 additions & 276 deletions

File tree

include/NavKit/Resource.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@
152152
#define IDC_CHECK_SKIP_RPKG_EXTRACT 30414
153153
#define IDC_CHECK_EXTRACT_TEXTURE_FILES 30415
154154
#define IDC_CHECK_APPLY_TEXTURES 30416
155+
#define IDC_BUTTON_SELECT_ALL_LODS 30417
156+
#define IDC_BUTTON_DESELECT_ALL_LODS 30418
155157

156158
#define IDD_EXTRACT_NAVP_DIALOG 30500
157159
#define IDC_COMBOBOX_NAVP 30501

include/NavKit/adapter/RecastAdapter.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class Sample;
2323
class BuildContext;
2424
class InputGeom;
2525
class DebugDrawGL;
26+
class SceneMeshHitTestResult;
2627

2728
class RecastAdapter {
2829
RecastAdapter();
@@ -101,7 +102,9 @@ class RecastAdapter {
101102

102103
dtPolyRef getAdjacentPoly(dtPolyRef poly, int edgeIndex) const;
103104

104-
void doHitTest(int mx, int my);
105+
void setMarker(const SceneMeshHitTestResult& result);
106+
107+
SceneMeshHitTestResult doHitTest(int mx, int my);
105108

106109
void loadSettings() const;
107110

@@ -111,11 +114,11 @@ class RecastAdapter {
111114

112115
static Vec3 convertFromRecastToNavPower(Vec3 pos);
113116

114-
std::vector<Vec3> getEdges(dtPolyRef polyRef) const;
117+
static std::vector<Vec3> getEdges(const dtNavMeshQuery* navQuery, dtPolyRef polyRef) ;
115118

116-
Vec3 calculateNormal(dtPolyRef polyRef) const;
119+
Vec3 calculateNormal(dtNavMeshQuery* navQuery, dtPolyRef polyRef) const;
117120

118-
Vec3 calculateCentroid(dtPolyRef polyRef) const;
121+
Vec3 calculateCentroid(dtNavMeshQuery* navQuery, dtPolyRef polyRef) const;
119122

120123
const dtNavMesh* getNavMesh() const;
121124

include/NavKit/module/Renderer.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@ class HitTestResult {
2727
int selectedIndex;
2828
};
2929

30+
class SceneMeshHitTestResult {
31+
public:
32+
SceneMeshHitTestResult() : hitTime(0.0f), hitIndex(-1) {
33+
rayStart[0] = rayStart[1] = rayStart[2] = 0.0f;
34+
rayEnd[0] = rayEnd[1] = rayEnd[2] = 0.0f;
35+
}
36+
37+
float rayStart[3];
38+
float rayEnd[3];
39+
float hitTime;
40+
int hitIndex;
41+
};
42+
3043
class Renderer {
3144
public:
3245
Renderer();

include/NavKit/util/Pathfinding.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ namespace Pathfinding {
3232

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

35-
Vec3* GetClosestPosInArea2d_G2_EdgeIndex(Vec3* navPowerResult,
35+
Vec3* GetClosestPosInArea2d_G2_EdgeIndex(dtNavMeshQuery* navQuery,
36+
Vec3* navPowerResult,
3637
dtPolyRef poly, const Vec3* navPowerPos,
3738
int* edgeIndex);
3839

3940
Vec3* GetClosestPosInArea2d_G2_ClosestPos(
41+
dtNavMeshQuery* navQuery,
4042
Vec3* resultNavPower,
4143
dtPolyRef polyRef,
4244
const Vec3* posWCoordNavPower,

lib/Debug/NavWeakness.dll

-4 KB
Binary file not shown.

lib/Release/NavWeakness.dll

-1.5 KB
Binary file not shown.

src/NavKit.rc

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -291,14 +291,18 @@ BEGIN
291291
CONTROL "Prim",IDC_RADIO_MESH_TYPE_PRIM,"Button",BS_AUTORADIOBUTTON,64,20,40,10
292292

293293
GROUPBOX "Prim Level of Detail",IDC_STATIC,7,50,246,75
294-
AUTOCHECKBOX "LOD 1", IDC_CHECK_PRIM_LOD_1, 14, 65, 50, 8
295-
AUTOCHECKBOX "LOD 2", IDC_CHECK_PRIM_LOD_2, 14, 80, 50, 8
296-
AUTOCHECKBOX "LOD 3", IDC_CHECK_PRIM_LOD_3, 14, 95, 50, 8
297-
AUTOCHECKBOX "LOD 4", IDC_CHECK_PRIM_LOD_4, 14, 110, 50, 8
298-
AUTOCHECKBOX "LOD 5", IDC_CHECK_PRIM_LOD_5, 84, 65, 50, 8
299-
AUTOCHECKBOX "LOD 6", IDC_CHECK_PRIM_LOD_6, 84, 80, 50, 8
300-
AUTOCHECKBOX "LOD 7", IDC_CHECK_PRIM_LOD_7, 84, 95, 50, 8
301-
AUTOCHECKBOX "LOD 8", IDC_CHECK_PRIM_LOD_8, 84, 110, 50, 8
294+
PUSHBUTTON "Select All",IDC_BUTTON_SELECT_ALL_LODS,14,65,60,14
295+
PUSHBUTTON "Deselect All",IDC_BUTTON_DESELECT_ALL_LODS,84,65,60,14
296+
297+
AUTOCHECKBOX "LOD 1 (Highest)", IDC_CHECK_PRIM_LOD_1, 14, 85, 70, 8
298+
AUTOCHECKBOX "LOD 2", IDC_CHECK_PRIM_LOD_2, 84, 85, 40, 8
299+
AUTOCHECKBOX "LOD 3", IDC_CHECK_PRIM_LOD_3, 134, 85, 40, 8
300+
AUTOCHECKBOX "LOD 4", IDC_CHECK_PRIM_LOD_4, 184, 85, 40, 8
301+
302+
AUTOCHECKBOX "LOD 5", IDC_CHECK_PRIM_LOD_5, 14, 105, 40, 8
303+
AUTOCHECKBOX "LOD 6", IDC_CHECK_PRIM_LOD_6, 84, 105, 40, 8
304+
AUTOCHECKBOX "LOD 7", IDC_CHECK_PRIM_LOD_7, 134, 105, 40, 8
305+
AUTOCHECKBOX "LOD 8", IDC_CHECK_PRIM_LOD_8, 184, 105, 40, 8
302306

303307
GROUPBOX "Build Type for Blender File",IDC_STATIC,7,135,246,35
304308
CONTROL "Copy",IDC_RADIO_BUILD_TYPE_COPY,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,14,150,40,10

src/adapter/RecastAdapter.cpp

Lines changed: 71 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ void RecastAdapter::renderRecastNavmesh(const bool isAirgInstance) const {
442442
if (!mesh) {
443443
return;
444444
}
445+
dtNavMeshQuery* navQuery = sample->getNavMeshQuery();
445446
for (int tileIndex = 0; tileIndex < mesh->getMaxTiles(); tileIndex++) {
446447
const dtMeshTile* tile = mesh->getTile(tileIndex);
447448
if (!tile || !tile->header) {
@@ -474,14 +475,14 @@ void RecastAdapter::renderRecastNavmesh(const bool isAirgInstance) const {
474475

475476
for (int polyIndex = 0; polyIndex < tile->header->polyCount; polyIndex++) {
476477
const dtPolyRef polyRef = getPoly(tileIndex, polyIndex);
477-
auto edges = getEdges(polyRef);
478+
auto edges = getEdges(navQuery, polyRef);
478479
glBegin(GL_LINE_LOOP);
479480
glVertex3f(edges[0].X, edges[0].Y, edges[0].Z);
480481
glVertex3f(edges[1].X, edges[1].Y, edges[1].Z);
481482
glVertex3f(edges[2].X, edges[2].Y, edges[2].Z);
482483
glEnd();
483-
auto centroid = calculateCentroid(polyRef);
484-
renderer.drawText(("ref: " + std::to_string(polyRef) + " idx: " + std::to_string(polyIndex)).c_str(),
484+
auto centroid = calculateCentroid(navQuery, polyRef);
485+
renderer.drawText("ref: " + std::to_string(polyRef) + " idx: " + std::to_string(polyIndex),
485486
{centroid.X, centroid.Y, centroid.Z}, color);
486487
}
487488
}
@@ -952,7 +953,35 @@ dtPolyRef RecastAdapter::getAdjacentPoly(const dtPolyRef polyRef, const int edge
952953
return 0;
953954
}
954955

955-
void RecastAdapter::doHitTest(const int mx, const int my) {
956+
void RecastAdapter::setMarker(const SceneMeshHitTestResult& result) {
957+
markerPositionSet = true;
958+
markerPosition[0] = result.rayStart[0] + (result.rayEnd[0] - result.rayStart[0]) * result.hitTime;
959+
markerPosition[1] = result.rayStart[1] + (result.rayEnd[1] - result.rayStart[1]) * result.hitTime;
960+
markerPosition[2] = result.rayStart[2] + (result.rayEnd[2] - result.rayStart[2]) * result.hitTime;
961+
for (auto [object, vertexRange] : SceneMesh::getInstance().objectTriangleRanges) {
962+
if (result.hitIndex >= vertexRange.first && result.hitIndex < vertexRange.second) {
963+
selectedObject = object;
964+
break;
965+
}
966+
}
967+
std::string meshNameString;
968+
std::string roomString;
969+
if (Scene::getInstance().sceneLoaded) {
970+
if (const auto mesh = Scene::getInstance().findMeshByHashAndIdAndPos(
971+
selectedObject.substr(0, 16), selectedObject.substr(17, 16), markerPosition); mesh != nullptr) {
972+
meshNameString = mesh->entity.name;
973+
roomString = " Room Folder: " + mesh->roomFolderName + " Room: " + mesh->roomName;
974+
}
975+
}
976+
Logger::log(
977+
NK_INFO,
978+
("Selected Object: '" + meshNameString + "' Mesh: '" + selectedObject + "' Obj vertex: " +
979+
std::to_string(result.hitIndex) + roomString +
980+
". Setting marker position to: " + std::to_string(markerPosition[0]) + ", " +
981+
std::to_string(markerPosition[1]) + ", " + std::to_string(markerPosition[2])).c_str());
982+
}
983+
984+
SceneMeshHitTestResult RecastAdapter::doHitTest(const int mx, const int my) {
956985
float rayStart[3];
957986
float rayEnd[3];
958987
float hitTime;
@@ -966,40 +995,23 @@ void RecastAdapter::doHitTest(const int mx, const int my) {
966995
rayEnd[0] = (float)x;
967996
rayEnd[1] = (float)y;
968997
rayEnd[2] = (float)z;
969-
const int hit = inputGeom->raycastMesh(rayStart, rayEnd, hitTime);
970-
if (hit != -1) {
971-
// Marker
972-
markerPositionSet = true;
973-
markerPosition[0] = rayStart[0] + (rayEnd[0] - rayStart[0]) * hitTime;
974-
markerPosition[1] = rayStart[1] + (rayEnd[1] - rayStart[1]) * hitTime;
975-
markerPosition[2] = rayStart[2] + (rayEnd[2] - rayStart[2]) * hitTime;
976-
for (auto [object, vertexRange] : SceneMesh::getInstance().objectTriangleRanges) {
977-
if (hit >= vertexRange.first && hit < vertexRange.second) {
978-
selectedObject = object;
979-
break;
980-
}
981-
}
982-
std::string meshNameString;
983-
std::string roomString;
984-
if (Scene::getInstance().sceneLoaded) {
985-
if (const auto mesh = Scene::getInstance().findMeshByHashAndIdAndPos(
986-
selectedObject.substr(0, 16), selectedObject.substr(17, 16), markerPosition); mesh != nullptr) {
987-
meshNameString = mesh->entity.name;
988-
roomString = " Room Folder: " + mesh->roomFolderName + " Room: " + mesh->roomName;
989-
}
990-
}
991-
Logger::log(
992-
NK_INFO,
993-
("Selected Object: '" + meshNameString + "' Mesh: '" + selectedObject + "' Obj vertex: " +
994-
std::to_string(hit) + roomString +
995-
". Setting marker position to: " + std::to_string(markerPosition[0]) + ", " +
996-
std::to_string(markerPosition[1]) + ", " + std::to_string(markerPosition[2])).c_str());
997-
} else {
998-
if (SDL_GetModState()) {
999-
// Marker
1000-
markerPositionSet = false;
1001-
}
998+
SceneMeshHitTestResult result;
999+
if (const int hitIndex = inputGeom->raycastMesh(rayStart, rayEnd, hitTime); hitIndex != -1) {
1000+
result.hitIndex = hitIndex;
1001+
result.rayStart[0] = rayStart[0];
1002+
result.rayStart[1] = rayStart[1];
1003+
result.rayStart[2] = rayStart[2];
1004+
result.rayEnd[0] = rayEnd[0];
1005+
result.rayEnd[1] = rayEnd[1];
1006+
result.rayEnd[2] = rayEnd[2];
1007+
result.hitTime = hitTime;
1008+
return result;
1009+
}
1010+
result.hitIndex = -1;
1011+
if (SDL_GetModState()) {
1012+
markerPositionSet = false;
10021013
}
1014+
return result;
10031015
}
10041016

10051017
void RecastAdapter::loadSettings() const {
@@ -1085,8 +1097,16 @@ Vec3 RecastAdapter::convertFromRecastToNavPower(Vec3 pos) {
10851097
return {pos.X, -pos.Z, pos.Y};
10861098
}
10871099

1088-
std::vector<Vec3> RecastAdapter::getEdges(const dtPolyRef polyRef) const {
1089-
const dtNavMesh* mesh = sample->getNavMesh();
1100+
std::vector<Vec3> RecastAdapter::getEdges(const dtNavMeshQuery* navQuery, const dtPolyRef polyRef) {
1101+
if (!navQuery) {
1102+
return {};
1103+
}
1104+
1105+
const dtNavMesh* mesh = navQuery->getAttachedNavMesh();
1106+
if (!mesh) {
1107+
return {};
1108+
}
1109+
10901110
unsigned int salt = 0;
10911111
unsigned int tileIndex = 0;
10921112
unsigned int polyIndex = 0;
@@ -1106,8 +1126,11 @@ std::vector<Vec3> RecastAdapter::getEdges(const dtPolyRef polyRef) const {
11061126
return edges;
11071127
}
11081128

1109-
Vec3 RecastAdapter::calculateNormal(const dtPolyRef polyRef) const {
1110-
const std::vector<Vec3> edges = getEdges(polyRef);
1129+
Vec3 RecastAdapter::calculateNormal(dtNavMeshQuery* navQuery, const dtPolyRef polyRef) const {
1130+
const std::vector<Vec3> edges = getEdges(navQuery, polyRef);
1131+
if (edges.size() < 3) {
1132+
return {0.0f, 1.0f, 0.0f};
1133+
}
11111134
const Vec3 v0 = edges.at(0);
11121135
const Vec3 v1 = edges.at(1);
11131136
const Vec3 v2 = edges.at(2);
@@ -1118,9 +1141,13 @@ Vec3 RecastAdapter::calculateNormal(const dtPolyRef polyRef) const {
11181141
return cross.GetUnitVec();
11191142
}
11201143

1121-
Vec3 RecastAdapter::calculateCentroid(const dtPolyRef polyRef) const {
1122-
const std::vector<Vec3> edges = getEdges(polyRef);
1123-
const Vec3 normal = calculateNormal(polyRef);
1144+
Vec3 RecastAdapter::calculateCentroid(dtNavMeshQuery* navQuery, const dtPolyRef polyRef) const {
1145+
const std::vector<Vec3> edges = getEdges(navQuery, polyRef);
1146+
if (edges.empty()) {
1147+
return {0.0f, 0.0f, 0.0f};
1148+
}
1149+
1150+
const Vec3 normal = calculateNormal(navQuery, polyRef);
11241151
const Vec3 v0 = edges.at(0);
11251152
const Vec3 v1 = edges.at(1);
11261153

src/model/Json.cpp

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "../../include/NavKit/model/Json.h"
22

3+
#include <algorithm>
4+
#include <type_traits>
35
#include "../../include/NavKit/module/Logger.h"
46
#include "../../include/NavKit/module/Scene.h"
57

@@ -22,9 +24,31 @@ std::string Json::toString(std::string_view val) {
2224
template <typename t, typename> Json::JsonValueProxy::operator t() {
2325
using simdT = typename SimdJsonTypeMap<t>::type;
2426
simdT val;
25-
if (json[field].get(val) == simdjson::SUCCESS) {
27+
28+
if (simdjson::ondemand::value jsonValue = json[field]; jsonValue.get(val) == simdjson::SUCCESS) {
2629
Logger::log(NK_DEBUG, "Field: %s value: %s", field.c_str(), toString(val).c_str());
2730
return static_cast<t>(val);
31+
} else if constexpr (std::is_arithmetic_v<t>) {
32+
std::string_view strVal;
33+
if (simdjson::error_code err; (err = jsonValue.get_string().get(strVal)) == simdjson::SUCCESS) {
34+
try {
35+
if constexpr (std::is_integral_v<t>) {
36+
val = static_cast<simdT>(std::stoll(std::string(strVal)));
37+
} else if constexpr (std::is_floating_point_v<t>) {
38+
val = static_cast<simdT>(std::stod(std::string(strVal)));
39+
}
40+
Logger::log(NK_DEBUG, "Field: %s value (from string conversion): %s", field.c_str(),
41+
toString(val).c_str());
42+
return static_cast<t>(val);
43+
} catch (const std::exception& e) {
44+
Logger::log(NK_ERROR, "Error converting string '%s' to numeric type for field: %s. Exception: %s",
45+
std::string(strVal).c_str(), field.c_str(), e.what());
46+
}
47+
} else {
48+
Logger::log(
49+
NK_ERROR, "Error getting value for field: %s. Not a direct numeric or string value. Simdjson error: %s",
50+
field.c_str(), simdjson::error_message(err));
51+
}
2852
}
2953
Logger::log(NK_ERROR, "Error getting value for field: %s", field.c_str());
3054
return {};
@@ -125,12 +149,12 @@ void Json::Mesh::writeJson(std::ostream& f) const {
125149
R"(","roomFolderName":")" << roomFolderName <<
126150
R"(","entity":{"id":")" << entity.id <<
127151
R"(","name":")" << entity.name << R"(",)";
128-
entity.position.writeJson(f);
129-
f << ",";
130-
entity.rotation.writeJson(f);
131-
f << ",";
132-
entity.scale.writeJson(f);
133-
f << "}}";
152+
entity.position.writeJson(f);
153+
f << ",";
154+
entity.rotation.writeJson(f);
155+
f << ",";
156+
entity.scale.writeJson(f);
157+
f << "}}";
134158
}
135159

136160
Json::Meshes::Meshes(simdjson::ondemand::array meshesJson) {
@@ -180,7 +204,21 @@ void Json::PfBoxes::readPathfindingBBoxes() {
180204
Vec3 s = entity.scale.data;
181205
Rotation r = entity.rotation;
182206
PfBoxType type = entity.type;
183-
scene.includeBox = {id, name, p, s, r, type};
207+
if (scene.includeBox.id.empty()) {
208+
scene.includeBox = {id, name, p, s, r, type};
209+
} else {
210+
// Set scene.includeBox pos, scale, and rotation to be the span of the two boxes
211+
float minX = std::min(scene.includeBox.pos.x - scene.includeBox.scale.x / 2.0f, p.x - s.x / 2.0f);
212+
float minY = std::min(scene.includeBox.pos.y - scene.includeBox.scale.y / 2.0f, p.y - s.y / 2.0f);
213+
float minZ = std::min(scene.includeBox.pos.z - scene.includeBox.scale.z / 2.0f, p.z - s.z / 2.0f);
214+
float maxX = std::max(scene.includeBox.pos.x + scene.includeBox.scale.x / 2.0f, p.x + s.x / 2.0f);
215+
float maxY = std::max(scene.includeBox.pos.y + scene.includeBox.scale.y / 2.0f, p.y + s.y / 2.0f);
216+
float maxZ = std::max(scene.includeBox.pos.z + scene.includeBox.scale.z / 2.0f, p.z + s.z / 2.0f);
217+
218+
scene.includeBox.pos = {(minX + maxX) / 2.0f, (minY + maxY) / 2.0f, (minZ + maxZ) / 2.0f};
219+
scene.includeBox.scale = {maxX - minX, maxY - minY, maxZ - minZ};
220+
scene.includeBox.rotation = {0, 0, 0, 1};
221+
}
184222
includeBoxFound = true;
185223
}
186224
if (entity.type.data == EXCLUDE_TYPE) {

0 commit comments

Comments
 (0)