void NavMeshPruneTool::handleClick(const float* s, const float* p, bool shift)
{
	rcIgnoreUnused(s);
	rcIgnoreUnused(shift);

	if (!m_sample) return;
	InputGeom* geom = m_sample->getInputGeom();
	if (!geom) return;
	dtNavMesh* nav = m_sample->getNavMesh();
	if (!nav) return;
	dtNavMeshQuery* query = m_sample->getNavMeshQuery();
	if (!query) return;
	
	dtVcopy(m_hitPos, p);
	m_hitPosSet = true;
	
	if (!m_flags)
	{
		m_flags = new NavmeshFlags;
		m_flags->init(nav);
	}
	
	const float ext[3] = {2,4,2};
	dtQueryFilter filter;
	dtPolyRef ref = 0;
	query->findNearestPoly(p, ext, &filter, &ref, 0);

	floodNavmesh(nav, m_flags, ref, 1);
}
void CrowdTool::handleRenderOverlay(double* proj, double* model, int* view)
{
	rcIgnoreUnused(model);
	rcIgnoreUnused(proj);

	// Tool help
	const int h = view[3];
	int ty = h-40;
	
	if (m_mode == TOOLMODE_CREATE)
	{
		imguiDrawText(280, ty, IMGUI_ALIGN_LEFT, "LMB: add agent.  Shift+LMB: remove agent.", imguiRGBA(255,255,255,192));	
	}
	else if (m_mode == TOOLMODE_MOVE_TARGET)
	{
		imguiDrawText(280, ty, IMGUI_ALIGN_LEFT, "LMB: set move target.  Shift+LMB: adjust set velocity.", imguiRGBA(255,255,255,192));	
		ty -= 20;
		imguiDrawText(280, ty, IMGUI_ALIGN_LEFT, "Setting velocity will move the agents without pathfinder.", imguiRGBA(255,255,255,192));	
	}
	else if (m_mode == TOOLMODE_SELECT)
	{
		imguiDrawText(280, ty, IMGUI_ALIGN_LEFT, "LMB: select agent.", imguiRGBA(255,255,255,192));	
	}
	ty -= 20;
	imguiDrawText(280, ty, IMGUI_ALIGN_LEFT, "SPACE: Run/Pause simulation.  1: Step simulation.", imguiRGBA(255,255,255,192));	
	ty -= 20;

	if (m_state && m_state->isRunning())
		imguiDrawText(280, ty, IMGUI_ALIGN_LEFT, "- RUNNING -", imguiRGBA(255,32,16,255));	
	else 
		imguiDrawText(280, ty, IMGUI_ALIGN_LEFT, "- PAUSED -", imguiRGBA(255,255,255,128));	
}
void NavMeshPruneTool::handleRenderOverlay(double* proj, double* model, int* view)
{
	rcIgnoreUnused(model);
	rcIgnoreUnused(proj);

	// Tool help
	const int h = view[3];

	imguiDrawText(280, h-40, IMGUI_ALIGN_LEFT, "LMB: Click fill area.", imguiRGBA(255,255,255,192));
}
void NavMeshPruneTool::handleRenderOverlay(double* proj, double* model, int* view)
{
	rcIgnoreUnused(model);
	rcIgnoreUnused(proj);

	// Tool help
	const int h = view[3];

	ImGui::RenderTextRight(-330, -(h - 40), ImVec4(255, 255, 255, 192),
		"LMB: Click fill area.");
}
Example #5
0
/// @par
///
/// Only sets the area id's for the walkable triangles.  Does not alter the
/// area id's for unwalkable triangles.
/// 
/// See the #rcConfig documentation for more information on the configuration parameters.
/// 
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
							 const float* verts, int nv,
							 const int* tris, int nt,
							 unsigned char* areas)
{
	rcIgnoreUnused(ctx);
	rcIgnoreUnused(nv);
	
	const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI);

	float norm[3];
	
	for (int i = 0; i < nt; ++i)
	{
		const int* tri = &tris[i*3];
		calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm);
		// Check if the face is walkable.
		if (norm[1] > walkableThr)
			areas[i] = RC_WALKABLE_AREA;
	}
}
Example #6
0
/// @par
///
/// See the #rcConfig documentation for more information on the configuration parameters.
/// 
/// @see rcAllocHeightfield, rcHeightfield 
bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height,
						 const dtCoordinates& bmin, const dtCoordinates& bmax,
						 float cs, float ch)
{
	rcIgnoreUnused(ctx);
	
	hf.width = width;
	hf.height = height;
	rcVcopy(hf.bmin, bmin);
	rcVcopy(hf.bmax, bmax);
	hf.cs = cs;
	hf.ch = ch;
	hf.spans = (rcSpan**)rcAlloc(sizeof(rcSpan*)*hf.width*hf.height, RC_ALLOC_PERM);
	if (!hf.spans)
		return false;
	memset(hf.spans, 0, sizeof(rcSpan*)*hf.width*hf.height);
	return true;
}
Example #7
0
int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf)
{
	rcIgnoreUnused(ctx);
	
	const int w = hf.width;
	const int h = hf.height;
	int spanCount = 0;
	for (int y = 0; y < h; ++y)
	{
		for (int x = 0; x < w; ++x)
		{
			for (rcSpan* s = hf.spans[x + y*w]; s; s = s->next)
			{
				if( rcCanMovableArea( s->area ) )
					spanCount++;
			}
		}
	}
	return spanCount;
}
Example #8
0
/// @par
///
/// Only sets the aread id's for the unwalkable triangles.  Does not alter the
/// area id's for walkable triangles.
/// 
/// See the #rcConfig documentation for more information on the configuration parameters.
/// 
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
								const dtCoordinates* verts, int /*nv*/,
								const int* tris, int nt,
								unsigned char* areas)
{
	rcIgnoreUnused(ctx);
	
	const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI);
	
	dtCoordinates norm;
	
	for (int i = 0; i < nt; ++i)
	{
		const int* tri = &tris[i*3];
		calcTriNormal(verts[tri[0]], verts[tri[1]], verts[tri[2]], norm);
		// Check if the face is walkable.
		if (norm.Y() <= walkableThr)
			areas[i] = RC_NULL_AREA;
	}
}
Example #9
0
/// @par
///
/// Only sets the aread id's for the walkable triangles.  Does not alter the
/// area id's for unwalkable triangles.
/// 
/// See the #rcConfig documentation for more information on the configuration parameters.
/// 
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle,
							 const dtCoordinates* verts, int /*nv*/,
							 const int* tris, int nt,
							 unsigned char* areas)
{
	rcIgnoreUnused(ctx);
	
	const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI);
	dtCoordinates norm;
	
	for (int i = 0; i < nt; ++i)
	{
		const int* tri = &tris[i*3];
		calcTriNormal(verts[tri[0]], verts[tri[1]], verts[tri[2]], norm);
//#ifdef MODIFY_VOXEL_FLAG
		const bool terrain = tri[0] < RC_MAX_GROUND_FLOOR_VERTICES && tri[1] < RC_MAX_GROUND_FLOOR_VERTICES && tri[2] < RC_MAX_GROUND_FLOOR_VERTICES;
//#endif // MODIFY_VOXEL_FLAG
		// Check if the face is walkable.
#ifdef MODIFY_VOXEL_FLAG
		if( walkableThr < norm.Y() ) {
			areas[i] = terrain ? RC_TERRAIN_AREA | RC_WALKABLE_AREA : RC_OBJECT_AREA | RC_WALKABLE_AREA;
		}
		else {
			areas[i] = terrain ? RC_TERRAIN_AREA | RC_WALKABLE_AREA : RC_OBJECT_AREA | RC_UNWALKABLE_AREA;;
		}
#else // MODIFY_VOXEL_FLAG
		if (norm[1] > walkableThr) {
			//areas[i] = RC_WALKABLE_AREA;
			areas[i] = terrain ? RC_WALKABLE_AREA : 1;
		}
		else {
			areas[i] = terrain ? RC_NULL_AREA : 2;
		}
#endif // MODIFY_VOXEL_FLAG
	}
}
Example #10
0
static void getHeightData(const rcCompactHeightfield& chf,
						  const unsigned short* poly, const int npoly,
						  const unsigned short* verts, const int bs,
						  rcHeightPatch& hp, rcIntArray& stack,
						  int region)
{
	rcIgnoreUnused( verts );
	rcIgnoreUnused( npoly );
	rcIgnoreUnused( poly );
	// Note: Reads to the compact heightfield are offset by border size (bs)
	// since border size offset is already removed from the polymesh vertices.
	
	stack.resize(0);
	memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height);
	
	bool empty = true;

	// Copy the height from the same region, and mark region borders
	// as seed points to fill the rest.
	for (int hy = 0; hy < hp.height; hy++)
	{
		int y = hp.ymin + hy + bs;
		for (int hx = 0; hx < hp.width; hx++)
		{
			int x = hp.xmin + hx + bs;
			const rcCompactCell& c = chf.cells[x+y*chf.width];
			//////////////////////////////////////////////////////////////////////////
			bool b = false;
			//////////////////////////////////////////////////////////////////////////
			for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
			{
				const rcCompactSpan& s = chf.spans[i];
				if (s.reg == region)
				{
					//////////////////////////////////////////////////////////////////////////
					b = true;
					//////////////////////////////////////////////////////////////////////////
					// Store height
					hp.data[hx + hy*hp.width] = s.y;
					empty = false;

					// If any of the neighbours is not in same region,
					// add the current location as flood fill start
					bool border = false;
					for (int dir = 0; dir < 4; ++dir)
					{
						if( rcIsConnectedWalkableArea( s, dir ) )
						{
							const int ax = x + rcGetDirOffsetX(dir);
							const int ay = y + rcGetDirOffsetY(dir);
							const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir);
							const rcCompactSpan& as = chf.spans[ai];
							if (as.reg != region)
							{
								border = true;
								break;
							}
						}
					}
					if (border)
					{
						stack.push(x);
						stack.push(y);
						stack.push(i);
					}
					break;
				}
			}
			//////////////////////////////////////////////////////////////////////////
// 			if( !b ) {
// 				const rcCompactSpan& s = chf.spans[c.index];
// 				hp.data[hx + hy*hp.width] = s.y;
// 			}
			//////////////////////////////////////////////////////////////////////////
		}
	}

	// if the polygon does not contian any points from the current region (rare, but happens)
	// then use the cells closest to the polygon vertices as seeds to fill the height field
	if (empty)
		getHeightDataSeedsFromVertices(chf, poly, npoly, verts, bs, hp, stack);
	
	static const int RETRACT_SIZE = 256;
	int head = 0;
	
	while (head*3 < stack.size())
	{
		int cx = stack[head*3+0];
		int cy = stack[head*3+1];
		int ci = stack[head*3+2];
		head++;
		if (head >= RETRACT_SIZE)
		{
			head = 0;
			if (stack.size() > RETRACT_SIZE*3)
				memmove(&stack[0], &stack[RETRACT_SIZE*3], sizeof(int)*(stack.size()-RETRACT_SIZE*3));
			stack.resize(stack.size()-RETRACT_SIZE*3);
		}

		const rcCompactSpan& cs = chf.spans[ci];
		for (int dir = 0; dir < 4; ++dir)
		{
			if( !rcIsConnectedWalkableArea( cs, dir ) ) {
				continue;
			}
			
			const int ax = cx + rcGetDirOffsetX(dir);
			const int ay = cy + rcGetDirOffsetY(dir);
			const int hx = ax - hp.xmin - bs;
			const int hy = ay - hp.ymin - bs;
			
			if (hx < 0 || hx >= hp.width || hy < 0 || hy >= hp.height)
				continue;
			
			if (hp.data[hx + hy*hp.width] != RC_UNSET_HEIGHT)
				continue;
			
			const int ai = (int)chf.cells[ax + ay*chf.width].index + rcGetCon(cs, dir);
			const rcCompactSpan& as = chf.spans[ai];
			
			hp.data[hx + hy*hp.width] = as.y;

			stack.push(ax);
			stack.push(ay);
			stack.push(ai);
		}
	}
}
void CrowdTool::handleUpdate(const float dt)
{
	rcIgnoreUnused(dt);
}