From d2b4b09e16c597cd09e95adb86304f015e65e47c Mon Sep 17 00:00:00 2001 From: Mikko Mononen Date: Sat, 2 Jun 2012 10:13:59 +0000 Subject: [PATCH] - Added rcOffsetPoly() helper function to expand polygon areas --- Recast/Include/Recast.h | 10 ++++ Recast/Source/RecastArea.cpp | 78 ++++++++++++++++++++++++++ RecastDemo/Include/ConvexVolumeTool.h | 1 + RecastDemo/Source/ConvexVolumeTool.cpp | 16 +++++- 4 files changed, 103 insertions(+), 2 deletions(-) diff --git a/Recast/Include/Recast.h b/Recast/Include/Recast.h index a9032e1..1ea40a3 100644 --- a/Recast/Include/Recast.h +++ b/Recast/Include/Recast.h @@ -935,6 +935,16 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, const float hmin, const float hmax, unsigned char areaId, rcCompactHeightfield& chf); +/// Helper function to offset voncex polygons for rcMarkConvexPolyArea. +/// @ingroup recast +/// @param[in] verts The vertices of the polygon [Form: (x, y, z) * @p nverts] +/// @param[in] nverts The number of vertices in the polygon. +/// @param[out] outVerts The offset vertices (should hold up to 2 * @p nverts) [Form: (x, y, z) * return value] +/// @param[in] maxOutVerts The max number of vertices that can be stored to @p outVerts. +/// @returns Number of vertices in the offset polygon or 0 if too few vertices in @p outVerts. +int rcOffsetPoly(const float* verts, const int nverts, const float offset, + float* outVerts, const int maxOutVerts); + /// Applies the area id to all spans within the specified cylinder. /// @ingroup recast /// @param[in,out] ctx The build context to use during the operation. diff --git a/Recast/Source/RecastArea.cpp b/Recast/Source/RecastArea.cpp index d0465b3..1a338cd 100644 --- a/Recast/Source/RecastArea.cpp +++ b/Recast/Source/RecastArea.cpp @@ -452,6 +452,84 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA); } +int rcOffsetPoly(const float* verts, const int nverts, const float offset, + float* outVerts, const int maxOutVerts) +{ + const float MITER_LIMIT = 1.20f; + + int n = 0; + + for (int i = 0; i < nverts; i++) + { + const int a = (i+nverts-1) % nverts; + const int b = i; + const int c = (i+1) % nverts; + const float* va = &verts[a*3]; + const float* vb = &verts[b*3]; + const float* vc = &verts[c*3]; + float dx0 = vb[0] - va[0]; + float dy0 = vb[2] - va[2]; + float d0 = dx0*dx0 + dy0*dy0; + if (d0 > 1e-6f) + { + d0 = 1.0f/rcSqrt(d0); + dx0 *= d0; + dy0 *= d0; + } + float dx1 = vc[0] - vb[0]; + float dy1 = vc[2] - vb[2]; + float d1 = dx1*dx1 + dy1*dy1; + if (d1 > 1e-6f) + { + d1 = 1.0f/rcSqrt(d1); + dx1 *= d1; + dy1 *= d1; + } + const float dlx0 = -dy0; + const float dly0 = dx0; + const float dlx1 = -dy1; + const float dly1 = dx1; + float cross = dx1*dy0 - dx0*dy1; + float dmx = (dlx0 + dlx1) * 0.5f; + float dmy = (dly0 + dly1) * 0.5f; + float dmr2 = dmx*dmx + dmy*dmy; + bool bevel = dmr2 * MITER_LIMIT*MITER_LIMIT < 1.0f; + if (dmr2 > 1e-6f) + { + const float scale = 1.0f / dmr2; + dmx *= scale; + dmy *= scale; + } + + if (bevel && cross < 0.0f) + { + if (n+2 >= maxOutVerts) + return 0; + float d = (1.0f - (dx0*dx1 + dy0*dy1))*0.5f; + outVerts[n*3+0] = vb[0] + (-dlx0+dx0*d)*offset; + outVerts[n*3+1] = vb[1]; + outVerts[n*3+2] = vb[2] + (-dly0+dy0*d)*offset; + n++; + outVerts[n*3+0] = vb[0] + (-dlx1-dx1*d)*offset; + outVerts[n*3+1] = vb[1]; + outVerts[n*3+2] = vb[2] + (-dly1-dy1*d)*offset; + n++; + } + else + { + if (n+1 >= maxOutVerts) + return 0; + outVerts[n*3+0] = vb[0] - dmx*offset; + outVerts[n*3+1] = vb[1]; + outVerts[n*3+2] = vb[2] - dmy*offset; + n++; + } + } + + return n; +} + + /// @par /// /// The value of spacial parameters are in world units. diff --git a/RecastDemo/Include/ConvexVolumeTool.h b/RecastDemo/Include/ConvexVolumeTool.h index e338230..fea8776 100644 --- a/RecastDemo/Include/ConvexVolumeTool.h +++ b/RecastDemo/Include/ConvexVolumeTool.h @@ -27,6 +27,7 @@ class ConvexVolumeTool : public SampleTool { Sample* m_sample; int m_areaType; + float m_polyOffset; float m_boxHeight; float m_boxDescent; diff --git a/RecastDemo/Source/ConvexVolumeTool.cpp b/RecastDemo/Source/ConvexVolumeTool.cpp index a401384..2d6963b 100644 --- a/RecastDemo/Source/ConvexVolumeTool.cpp +++ b/RecastDemo/Source/ConvexVolumeTool.cpp @@ -101,6 +101,7 @@ static int pointInPoly(int nvert, const float* verts, const float* p) ConvexVolumeTool::ConvexVolumeTool() : m_sample(0), m_areaType(SAMPLE_POLYAREA_GRASS), + m_polyOffset(0.0f), m_boxHeight(6.0f), m_boxDescent(1.0f), m_npts(0), @@ -127,6 +128,7 @@ void ConvexVolumeTool::handleMenu() { imguiSlider("Shape Height", &m_boxHeight, 0.1f, 20.0f, 0.1f); imguiSlider("Shape Descent", &m_boxDescent, 0.1f, 20.0f, 0.1f); + imguiSlider("Poly Offset", &m_polyOffset, 0.0f, 10.0f, 0.1f); imguiSeparator(); @@ -195,8 +197,18 @@ void ConvexVolumeTool::handleClick(const float* /*s*/, const float* p, bool shif minh = rcMin(minh, verts[i*3+1]); minh -= m_boxDescent; maxh = minh + m_boxHeight; - - geom->addConvexVolume(verts, m_nhull, minh, maxh, (unsigned char)m_areaType); + + if (m_polyOffset > 0.01f) + { + float offset[MAX_PTS*2*3]; + int noffset = rcOffsetPoly(verts, m_nhull, m_polyOffset, offset, MAX_PTS*2); + if (noffset > 0) + geom->addConvexVolume(offset, noffset, minh, maxh, (unsigned char)m_areaType); + } + else + { + geom->addConvexVolume(verts, m_nhull, minh, maxh, (unsigned char)m_areaType); + } } m_npts = 0;