From d7f2b7d319fb05ad7ab33dae0ffbd9cc961a3dec Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:05:44 +0200 Subject: [PATCH] Recast: implement off-mesh connection editor Allows the user to modify core attributes of any off-mesh connection in the world. --- src/naveditor/InputGeom.cpp | 34 ++-- src/naveditor/OffMeshConnectionTool.cpp | 163 ++++++++++++++++-- src/naveditor/include/InputGeom.h | 30 ++-- src/naveditor/include/OffMeshConnectionTool.h | 22 +++ .../DebugUtils/Source/DetourDebugDraw.cpp | 3 +- .../recast/Detour/Include/DetourNavMesh.h | 2 +- .../recast/Detour/Source/DetourNavMesh.cpp | 8 +- 7 files changed, 215 insertions(+), 47 deletions(-) diff --git a/src/naveditor/InputGeom.cpp b/src/naveditor/InputGeom.cpp index 0dce3d59..ca728306 100644 --- a/src/naveditor/InputGeom.cpp +++ b/src/naveditor/InputGeom.cpp @@ -266,6 +266,13 @@ bool InputGeom::loadGeomSet(rcContext* ctx, const std::string& filepath) &yaw, &bidir, &jump, &order, &area, &flags); + if (std::isnan(yaw)) + { + const float offset[3] = { 0.0f,0.0f,rad }; + yaw = dtCalcOffMeshRefYaw(&verts[0], &verts[3]); + dtCalcOffMeshRefPos(verts, yaw, offset, refs); + } + m_offMeshConRads[m_offMeshConCount] = rad; m_offMeshConRefYaws[m_offMeshConCount] = yaw; m_offMeshConDirs[m_offMeshConCount] = (unsigned char)bidir; @@ -613,11 +620,11 @@ bool InputGeom::raycastMesh(const float* src, const float* dst, const unsigned i return hit; } -void InputGeom::addOffMeshConnection(const float* spos, const float* epos, const float rad, +int InputGeom::addOffMeshConnection(const float* spos, const float* epos, const float rad, unsigned char bidir, unsigned char jump, unsigned char order, unsigned char area, unsigned short flags) { - if (m_offMeshConCount >= MAX_OFFMESH_CONNECTIONS) return; + if (m_offMeshConCount >= MAX_OFFMESH_CONNECTIONS) return -1; rdAssert(jump < DT_MAX_TRAVERSE_TYPES); float* verts = &m_offMeshConVerts[m_offMeshConCount*3*2]; @@ -626,7 +633,8 @@ void InputGeom::addOffMeshConnection(const float* spos, const float* epos, const float* refs = &m_offMeshConRefPos[m_offMeshConCount*3]; const float yaw = dtCalcOffMeshRefYaw(spos, epos); - dtCalcOffMeshRefPos(spos, yaw, DT_OFFMESH_CON_REFPOS_OFFSET, refs); + const float offset[3] = { 0.0f,0.0f,rad }; + dtCalcOffMeshRefPos(spos, yaw, offset, refs); m_offMeshConRads[m_offMeshConCount] = rad; m_offMeshConRefYaws[m_offMeshConCount] = yaw; @@ -636,7 +644,8 @@ void InputGeom::addOffMeshConnection(const float* spos, const float* epos, const m_offMeshConAreas[m_offMeshConCount] = area; m_offMeshConFlags[m_offMeshConCount] = flags; m_offMeshConId[m_offMeshConCount] = 1000 + m_offMeshConCount; - m_offMeshConCount++; + + return m_offMeshConCount++; } void InputGeom::deleteOffMeshConnection(int i) @@ -661,10 +670,9 @@ void InputGeom::deleteOffMeshConnection(int i) m_offMeshConFlags[i] = m_offMeshConFlags[m_offMeshConCount]; } -void InputGeom::drawOffMeshConnections(duDebugDraw* dd, const float* offset, bool hilight) +void InputGeom::drawOffMeshConnections(duDebugDraw* dd, const float* offset, const int hilightIdx) { - unsigned int conColor = duRGBA(192,0,128,192); - unsigned int baseColor = duRGBA(0,0,0,64); + const unsigned int baseColor = duRGBA(0,0,0,64); dd->depthMask(false); dd->begin(DU_DRAW_LINES, 2.0f, offset); @@ -681,16 +689,16 @@ void InputGeom::drawOffMeshConnections(duDebugDraw* dd, const float* offset, boo duAppendCircle(dd, v[0],v[1],v[2]+5.0f, m_offMeshConRads[i], baseColor); duAppendCircle(dd, v[3],v[4],v[5]+5.0f, m_offMeshConRads[i], baseColor); - if (hilight) - { - duAppendArc(dd, v[0],v[1],v[2], v[3],v[4],v[5], 0.25f, - (m_offMeshConDirs[i]&DT_OFFMESH_CON_BIDIR) ? 30.0f : 0.0f, 30.0f, conColor); - } + const unsigned int conColor = hilightIdx == i ? duRGBA(192,0,128,192) : duRGBA(152,0,78,192); + + duAppendArc(dd, v[0], v[1], v[2], v[3], v[4], v[5], 0.25f, + (m_offMeshConDirs[i] & DT_OFFMESH_CON_BIDIR) ? 30.0f : 0.0f, 30.0f, conColor); float* r = &m_offMeshConRefPos[i*3]; float refPosDir[3]; - dtCalcOffMeshRefPos(r, m_offMeshConRefYaws[i], DT_OFFMESH_CON_REFPOS_OFFSET, refPosDir); + const float arrowLength[3] = { 35.f, 35.f, 0.f }; + dtCalcOffMeshRefPos(r, m_offMeshConRefYaws[i], arrowLength, refPosDir); duAppendArrow(dd, r[0],r[1],r[2], refPosDir[0],refPosDir[1],refPosDir[2], 0.f, 10.f, duRGBA(255,255,0,255)); } diff --git a/src/naveditor/OffMeshConnectionTool.cpp b/src/naveditor/OffMeshConnectionTool.cpp index 8a6ee897..a4e065f1 100644 --- a/src/naveditor/OffMeshConnectionTool.cpp +++ b/src/naveditor/OffMeshConnectionTool.cpp @@ -35,9 +35,13 @@ OffMeshConnectionTool::OffMeshConnectionTool() : m_bidir(true), m_invertVertexLookupOrder(false), m_traverseType(0), - m_oldFlags(0) + m_oldFlags(0), + m_selectedOffMeshIndex(-1), + m_copiedOffMeshIndex(-1) { rdVset(m_hitPos, 0.0f,0.0f,0.0f); + rdVset(m_refOffset, 0.0f,0.0f,0.0f); + memset(&m_copyOffMeshInstance, 0, sizeof(OffMeshConnection)); } OffMeshConnectionTool::~OffMeshConnectionTool() @@ -63,6 +67,8 @@ void OffMeshConnectionTool::init(Editor* editor) const float agentRadius = m_editor->getAgentRadius(); m_radius = agentRadius; m_lastSelectedAgentRadius = agentRadius; + + rdVset(m_refOffset, 0.0f,0.0f, agentRadius); } } @@ -74,18 +80,149 @@ void OffMeshConnectionTool::reset() m_hitPosSet = false; } -void OffMeshConnectionTool::handleMenu() +#define VALUE_ADJUST_WINDOW 200 + +void OffMeshConnectionTool::renderModifyMenu() { + InputGeom* geom = m_editor->getInputGeom(); + if (!geom) return; + + ImGui::Separator(); + ImGui::Text("Modify Off-Mesh Connection"); + + ImGui::SliderInt("Selected##OffMeshConnectionModify", &m_selectedOffMeshIndex, -1, geom->getOffMeshConnectionCount()-1); + + if (m_selectedOffMeshIndex == -1) + return; + + float* verts = &geom->getOffMeshConnectionVerts()[m_selectedOffMeshIndex*6]; + float* refs = &geom->getOffMeshConnectionRefPos()[m_selectedOffMeshIndex*3]; + float& rad = geom->getOffMeshConnectionRads()[m_selectedOffMeshIndex]; + float& yaw = geom->getOffMeshConnectionRefYaws()[m_selectedOffMeshIndex]; + unsigned char& dir = geom->getOffMeshConnectionDirs()[m_selectedOffMeshIndex]; + unsigned char& jump = geom->getOffMeshConnectionJumps()[m_selectedOffMeshIndex]; + unsigned char& order = geom->getOffMeshConnectionOrders()[m_selectedOffMeshIndex]; + unsigned char& area = geom->getOffMeshConnectionAreas()[m_selectedOffMeshIndex]; + unsigned short& flags = geom->getOffMeshConnectionFlags()[m_selectedOffMeshIndex]; + + if (m_copiedOffMeshIndex != m_selectedOffMeshIndex) + { + rdVcopy(&m_copyOffMeshInstance.pos[0], &verts[0]); + rdVcopy(&m_copyOffMeshInstance.pos[3], &verts[3]); + rdVcopy(m_copyOffMeshInstance.refPos, refs); + + rdVset(m_refOffset, 0.f,0.f,rad); + + m_copyOffMeshInstance.rad = rad; + m_copyOffMeshInstance.refYaw = yaw; + m_copyOffMeshInstance.dir = dir; + m_copyOffMeshInstance.jump = jump; + m_copyOffMeshInstance.order = order; + m_copyOffMeshInstance.area = area; + m_copyOffMeshInstance.flags = flags; + + m_copiedOffMeshIndex = m_selectedOffMeshIndex; + } + + ImGui::PushItemWidth(60); + + ImGui::SliderFloat("##OffMeshConnectionModifyStartX", &verts[0], m_copyOffMeshInstance.pos[0]-VALUE_ADJUST_WINDOW, m_copyOffMeshInstance.pos[0]+VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::SliderFloat("##OffMeshConnectionModifyStartY", &verts[1], m_copyOffMeshInstance.pos[1]-VALUE_ADJUST_WINDOW, m_copyOffMeshInstance.pos[1]+VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::SliderFloat("##OffMeshConnectionModifyStartZ", &verts[2], m_copyOffMeshInstance.pos[2]-VALUE_ADJUST_WINDOW, m_copyOffMeshInstance.pos[2]+VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::Text("Start"); + + ImGui::SliderFloat("##OffMeshConnectionModifyEndX", &verts[3], m_copyOffMeshInstance.pos[3]-VALUE_ADJUST_WINDOW, m_copyOffMeshInstance.pos[3]+VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::SliderFloat("##OffMeshConnectionModifyEndY", &verts[4], m_copyOffMeshInstance.pos[4]-VALUE_ADJUST_WINDOW, m_copyOffMeshInstance.pos[4]+VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::SliderFloat("##OffMeshConnectionModifyEndZ", &verts[5], m_copyOffMeshInstance.pos[5]-VALUE_ADJUST_WINDOW, m_copyOffMeshInstance.pos[5]+VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::Text("End"); + + ImGui::SliderFloat("##OffMeshConnectionModifyRefX", &refs[0], m_copyOffMeshInstance.refPos[0]-VALUE_ADJUST_WINDOW, m_copyOffMeshInstance.refPos[0]+VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::SliderFloat("##OffMeshConnectionModifyRefY", &refs[1], m_copyOffMeshInstance.refPos[1]-VALUE_ADJUST_WINDOW, m_copyOffMeshInstance.refPos[1]+VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::SliderFloat("##OffMeshConnectionModifyRefZ", &refs[2], m_copyOffMeshInstance.refPos[2]-VALUE_ADJUST_WINDOW, m_copyOffMeshInstance.refPos[2]+VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::Text("Ref"); + + ImGui::PopItemWidth(); + // On newer navmesh sets, off-mesh links are always bidirectional. #if DT_NAVMESH_SET_VERSION < 7 - ImGui::Checkbox("Bidirectional", &m_bidir); + ImGui::Checkbox("Bidirectional##OffMeshConnectionModify", (bool*)&dir); #endif - ImGui::Checkbox("Invert Lookup Order", &m_invertVertexLookupOrder); + + ImGui::SliderFloat("Radius##OffMeshConnectionModify", &rad, 0, 512); + ImGui::SliderFloat("Yaw##OffMeshConnectionModify", &yaw, -180, 180); + + int traverseType = jump; + ImGui::SliderInt("Jump##OffMeshConnectionModify", &traverseType, 0, DT_MAX_TRAVERSE_TYPES-1, "%d", ImGuiSliderFlags_NoInput); + + if (traverseType != jump) + jump = (unsigned char)traverseType; + + ImGui::PushItemWidth(60); + ImGui::SliderFloat("##OffMeshConnectionModifyRefOffsetX", &m_refOffset[0], -VALUE_ADJUST_WINDOW, VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::SliderFloat("##OffMeshConnectionModifyRefOffsetY", &m_refOffset[1], -VALUE_ADJUST_WINDOW, VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::SliderFloat("##OffMeshConnectionModifyRefOffsetZ", &m_refOffset[2], -VALUE_ADJUST_WINDOW, VALUE_ADJUST_WINDOW); + ImGui::SameLine(); + ImGui::Text("Ref Offset"); + ImGui::PopItemWidth(); + + if (ImGui::Button("Recalculate Reference##OffMeshConnectionModify")) + { + yaw = dtCalcOffMeshRefYaw(&verts[0], &verts[3]); + dtCalcOffMeshRefPos(verts, yaw, m_refOffset, refs); + } + + if (ImGui::Button("Reset Connection##OffMeshConnectionModify")) + { + rdVcopy(&verts[0], &m_copyOffMeshInstance.pos[0]); + rdVcopy(&verts[3], &m_copyOffMeshInstance.pos[3]); + rdVcopy(refs, m_copyOffMeshInstance.refPos); + + rad = m_copyOffMeshInstance.rad; + yaw = m_copyOffMeshInstance.refYaw; + dir = m_copyOffMeshInstance.dir; + jump = m_copyOffMeshInstance.jump; + order = m_copyOffMeshInstance.order; + area = m_copyOffMeshInstance.area; + flags = m_copyOffMeshInstance.flags; + } + + if (ImGui::Button("Delete Connection##OffMeshConnectionModify")) + { + geom->deleteOffMeshConnection(m_selectedOffMeshIndex); + m_selectedOffMeshIndex = -1; + m_copiedOffMeshIndex = -1; + + return; + } +} + +void OffMeshConnectionTool::handleMenu() +{ + ImGui::Text("Create Off-Mesh Connection"); + + // On newer navmesh sets, off-mesh links are always bidirectional. +#if DT_NAVMESH_SET_VERSION < 7 + ImGui::Checkbox("Bidirectional##OffMeshConnectionCreate", &m_bidir); +#endif + ImGui::Checkbox("Invert Lookup Order##OffMeshConnectionCreate", &m_invertVertexLookupOrder); ImGui::PushItemWidth(140); - ImGui::SliderInt("Traverse Type##OffMeshConnectionTool", &m_traverseType, 0, DT_MAX_TRAVERSE_TYPES-1, "%d", ImGuiSliderFlags_NoInput); - ImGui::SliderFloat("Radius##OffMeshConnectionTool", &m_radius, 0, 512); + ImGui::SliderInt("Jump##OffMeshConnectionCreate", &m_traverseType, 0, DT_MAX_TRAVERSE_TYPES-1, "%d", ImGuiSliderFlags_NoInput); + ImGui::SliderFloat("Radius##OffMeshConnectionCreate", &m_radius, 0, 512); ImGui::PopItemWidth(); + + renderModifyMenu(); } void OffMeshConnectionTool::handleClick(const float* /*s*/, const float* p, const int /*v*/, bool shift) @@ -96,7 +233,7 @@ void OffMeshConnectionTool::handleClick(const float* /*s*/, const float* p, cons if (shift) { - // Delete + // Select // Find nearest link end-point float nearestDist = FLT_MAX; int nearestIndex = -1; @@ -104,18 +241,18 @@ void OffMeshConnectionTool::handleClick(const float* /*s*/, const float* p, cons for (int i = 0; i < geom->getOffMeshConnectionCount()*2; ++i) { const float* v = &verts[i*3]; - float d = rdVdistSqr(p, v); + float d = rdVdist2DSqr(p, v); if (d < nearestDist) { nearestDist = d; nearestIndex = i/2; // Each link has two vertices. } } - // If end point close enough, delete it. + // If end point close enough, select it it. if (nearestIndex != -1 && - sqrtf(nearestDist) < m_radius) + rdMathSqrtf(nearestDist) < m_radius) { - geom->deleteOffMeshConnection(nearestIndex); + m_selectedOffMeshIndex = nearestIndex; } } else @@ -135,7 +272,7 @@ void OffMeshConnectionTool::handleClick(const float* /*s*/, const float* p, cons #else ; #endif; - geom->addOffMeshConnection(m_hitPos, p, m_radius, m_bidir ? 1 : 0, + m_selectedOffMeshIndex = geom->addOffMeshConnection(m_hitPos, p, m_radius, m_bidir ? 1 : 0, (unsigned char)m_traverseType, m_invertVertexLookupOrder ? 1 : 0, area, flags); m_hitPosSet = false; } @@ -171,7 +308,7 @@ void OffMeshConnectionTool::handleRender() InputGeom* geom = m_editor->getInputGeom(); if (geom) - geom->drawOffMeshConnections(&dd, m_editor->getRecastDrawOffset(), true); + geom->drawOffMeshConnections(&dd, m_editor->getRecastDrawOffset(), m_selectedOffMeshIndex); } void OffMeshConnectionTool::handleRenderOverlay(double* proj, double* model, int* view) diff --git a/src/naveditor/include/InputGeom.h b/src/naveditor/include/InputGeom.h index 5a306ba3..56c5e5f5 100644 --- a/src/naveditor/include/InputGeom.h +++ b/src/naveditor/include/InputGeom.h @@ -174,28 +174,28 @@ public: /// @name Off-Mesh connections. ///@{ - int getOffMeshConnectionCount() const { return m_offMeshConCount; } - const float* getOffMeshConnectionVerts() const { return m_offMeshConVerts; } - const float* getOffMeshConnectionRads() const { return m_offMeshConRads; } - const unsigned char* getOffMeshConnectionDirs() const { return m_offMeshConDirs; } - const unsigned char* getOffMeshConnectionJumps() const { return m_offMeshConJumps; } - const unsigned char* getOffMeshConnectionOrders() const { return m_offMeshConOrders; } - const unsigned char* getOffMeshConnectionAreas() const { return m_offMeshConAreas; } - const unsigned short* getOffMeshConnectionFlags() const { return m_offMeshConFlags; } - const unsigned short* getOffMeshConnectionId() const { return m_offMeshConId; } - const float* getOffMeshConnectionRefPos() const { return m_offMeshConRefPos; } - const float* getOffMeshConnectionRefYaws() const { return m_offMeshConRefYaws; } - void addOffMeshConnection(const float* spos, const float* epos, const float rad, + int getOffMeshConnectionCount() { return m_offMeshConCount; } + float* getOffMeshConnectionVerts() { return m_offMeshConVerts; } + float* getOffMeshConnectionRads() { return m_offMeshConRads; } + unsigned char* getOffMeshConnectionDirs() { return m_offMeshConDirs; } + unsigned char* getOffMeshConnectionJumps() { return m_offMeshConJumps; } + unsigned char* getOffMeshConnectionOrders() { return m_offMeshConOrders; } + unsigned char* getOffMeshConnectionAreas() { return m_offMeshConAreas; } + unsigned short* getOffMeshConnectionFlags() { return m_offMeshConFlags; } + unsigned short* getOffMeshConnectionId() { return m_offMeshConId; } + float* getOffMeshConnectionRefPos() { return m_offMeshConRefPos; } + float* getOffMeshConnectionRefYaws() { return m_offMeshConRefYaws; } + int addOffMeshConnection(const float* spos, const float* epos, const float rad, unsigned char bidir, unsigned char jump, unsigned char order, unsigned char area, unsigned short flags); void deleteOffMeshConnection(int i); - void drawOffMeshConnections(struct duDebugDraw* dd, const float* offset, bool hilight = false); + void drawOffMeshConnections(struct duDebugDraw* dd, const float* offset, const int hilightIdx = -1); ///@} /// @name Shape Volumes. ///@{ - int getShapeVolumeCount() const { return m_volumeCount; } // todo(amos): rename to 'getShapeVolumeCount' - ShapeVolume* getShapeVolumes() { return m_volumes; } // todo(amos): rename to 'getShapeVolumes' + int getShapeVolumeCount() const { return m_volumeCount; } + ShapeVolume* getShapeVolumes() { return m_volumes; } int addBoxVolume(const float* bmin, const float* bmax, unsigned short flags, unsigned char area); int addCylinderVolume(const float* pos, const float radius, diff --git a/src/naveditor/include/OffMeshConnectionTool.h b/src/naveditor/include/OffMeshConnectionTool.h index 49f4d09d..3175ea12 100644 --- a/src/naveditor/include/OffMeshConnectionTool.h +++ b/src/naveditor/include/OffMeshConnectionTool.h @@ -23,10 +23,25 @@ // Tool to create off-mesh connection for InputGeom +// TODO: eventually this needs to be the type for off-mesh connections in InputGeom! +struct OffMeshConnection +{ + float pos[6]; + float refPos[3]; + float rad; + float refYaw; + unsigned char dir; + unsigned char jump; + unsigned char order; + unsigned char area; + unsigned short flags; +}; + class OffMeshConnectionTool : public EditorTool { Editor* m_editor; float m_hitPos[3]; + float m_refOffset[3]; float m_lastSelectedAgentRadius; float m_radius; bool m_hitPosSet; @@ -34,10 +49,17 @@ class OffMeshConnectionTool : public EditorTool bool m_invertVertexLookupOrder; int m_traverseType; unsigned int m_oldFlags; + + int m_selectedOffMeshIndex; + int m_copiedOffMeshIndex; + + OffMeshConnection m_copyOffMeshInstance; public: OffMeshConnectionTool(); ~OffMeshConnectionTool(); + + void renderModifyMenu(); virtual int type() { return TOOL_OFFMESH_CONNECTION; } virtual void init(Editor* editor); diff --git a/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp b/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp index 3ca0bb6f..de830eaf 100644 --- a/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp +++ b/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp @@ -413,7 +413,8 @@ static void drawTileBounds(duDebugDraw* dd, const dtMeshTile* tile, const float* static void drawOffMeshConnectionRefPosition(duDebugDraw* dd, const dtOffMeshConnection* con) { float refPosDir[3]; - dtCalcOffMeshRefPos(con->refPos, con->refYaw, DT_OFFMESH_CON_REFPOS_OFFSET, refPosDir); + const float arrowLength[3] = { 35.f, 35.f, 0.f }; + dtCalcOffMeshRefPos(con->refPos, con->refYaw, arrowLength, refPosDir); duAppendArrow(dd, con->refPos[0], con->refPos[1], con->refPos[2], refPosDir[0], refPosDir[1], refPosDir[2], 0.f, 10.f, duRGBA(255,255,0,255)); diff --git a/src/thirdparty/recast/Detour/Include/DetourNavMesh.h b/src/thirdparty/recast/Detour/Include/DetourNavMesh.h index 33e74325..7fb747ec 100644 --- a/src/thirdparty/recast/Detour/Include/DetourNavMesh.h +++ b/src/thirdparty/recast/Detour/Include/DetourNavMesh.h @@ -530,7 +530,7 @@ extern float dtCalcOffMeshRefYaw(const float* spos, const float* epos); /// @param yawRad[in] The yaw angle of the off-mesh connection in radians. /// @param offset[in] The desired offset from the start position. /// @param res[in] The output ref position. -extern void dtCalcOffMeshRefPos(const float* spos, float yawRad, float offset, float* res); +extern void dtCalcOffMeshRefPos(const float* spos, const float yawDeg, const float* offset, float* res); /// Provides high level information related to a dtMeshTile object. /// @ingroup detour diff --git a/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp b/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp index e94f3c87..0d68256e 100644 --- a/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp +++ b/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp @@ -2206,16 +2206,16 @@ float dtCalcOffMeshRefYaw(const float* spos, const float* epos) return rdRadToDeg(yawRad); } -void dtCalcOffMeshRefPos(const float* spos, float yawDeg, float offset, float* res) +void dtCalcOffMeshRefPos(const float* spos, const float yawDeg, const float* offset, float* res) { const float yawRad = rdDegToRad(yawDeg); - const float dx = offset*rdMathCosf(yawRad); - const float dy = offset*rdMathSinf(yawRad); + const float dx = offset[0]*rdMathCosf(yawRad); + const float dy = offset[1]*rdMathSinf(yawRad); res[0] = spos[0]+dx; res[1] = spos[1]+dy; - res[2] = spos[2]; + res[2] = spos[2]+offset[2]; } int dtGetNavMeshVersionForSet(const int setVersion)