Ejemplo n.º 1
0
void AwarenessVisualizer::createRecastPolyMesh(const std::string& name, const unsigned short *verts, const int nverts, const unsigned short *polys, const int npolys, const unsigned char *areas, const int maxpolys, const unsigned short *regions, const int nvp, const float cs, const float ch, const float *orig, bool colorRegions)
{

	// Demo specific parameters
	float m_navMeshOffsetFromGround = 0.2; //ch / 5;         // Distance above ground for drawing navmesh polygons
	float m_navMeshEdgesOffsetFromGround = 0.5; //ch / 3;    // Distance above ground for drawing edges of navmesh (should be slightly higher than navmesh polygons)
//	float m_pathOffsetFromGround = 1 + m_navMeshOffsetFromGround; // Distance above ground for drawing path debug lines relative to cellheight (should be higher than navmesh polygons)

	// Colors for navmesh debug drawing
	static Ogre::ColourValue m_navmeshNeighbourEdgeCol(0.9, 0.9, 0.9);   // Light Grey
	static Ogre::ColourValue m_navmeshOuterEdgeCol(0, 0, 0);         // Black
	static Ogre::ColourValue m_navmeshGroundPolygonCol(0, 0.7, 0);       // Green
	static Ogre::ColourValue m_navmeshOtherPolygonCol(0, 0.175, 0);     // Dark green
	static Ogre::ColourValue m_pathCol(1, 0, 0);         // Red

	// When drawing regions choose different random colors for each region
	Ogre::ColourValue* regionColors = NULL;
	if (colorRegions) {
		regionColors = new Ogre::ColourValue[maxpolys];
		for (int i = 0; i < maxpolys; ++i) {
			regionColors[i] = Ogre::ColourValue(Ogre::Math::RangeRandom(0, 1), Ogre::Math::RangeRandom(0, 1), Ogre::Math::RangeRandom(0, 1), 1);
		}
	}

	int nIndex = 0;

	if (npolys) {
		// start defining the manualObject with the navmesh planes
		Ogre::ManualObject* pRecastMOWalk;
		if (mSceneManager.hasManualObject("RecastMOWalk_" + name)) {
			pRecastMOWalk = mSceneManager.getManualObject("RecastMOWalk_" + name);
			pRecastMOWalk->clear();
		} else {
			pRecastMOWalk = mSceneManager.createManualObject("RecastMOWalk_" + name);
			//Remove from the overhead map.
			pRecastMOWalk->setVisibilityFlags(pRecastMOWalk->getVisibilityFlags() & ~Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK);
			mTileSceneNode->attachObject(pRecastMOWalk);
		}
		pRecastMOWalk->begin("/common/base/authoring/awareness", Ogre::RenderOperation::OT_TRIANGLE_LIST);
		for (int i = 0; i < npolys; ++i) {    // go through all polygons
			if (areas[i] == Navigation::POLYAREA_GROUND || areas[i] == DT_TILECACHE_WALKABLE_AREA) {
				const unsigned short* p = &polys[i * nvp * 2];

				unsigned short vi[3];
				for (int j = 2; j < nvp; ++j) // go through all verts in the polygon
						{
					if (p[j] == RC_MESH_NULL_IDX)
						break;
					vi[0] = p[0];
					vi[1] = p[j - 1];
					vi[2] = p[j];
					for (int k = 0; k < 3; ++k) // create a 3-vert triangle for each 3 verts in the polygon.
							{
						const unsigned short* v = &verts[vi[k] * 3];
						const float x = orig[0] + v[0] * cs;
						const float y = orig[1] + (v[1]/*+1*/) * ch;
						const float z = -orig[2] - v[2] * cs;

						pRecastMOWalk->position(x, y + m_navMeshOffsetFromGround, z);

						if (colorRegions) {
							pRecastMOWalk->colour(regionColors[regions[i]]);  // Assign vertex color
						} else {
							if (areas[i] == Navigation::POLYAREA_GROUND)
								pRecastMOWalk->colour(m_navmeshGroundPolygonCol);
							else
								pRecastMOWalk->colour(m_navmeshOtherPolygonCol);
						}

					}
					pRecastMOWalk->triangle(nIndex, nIndex + 2, nIndex + 1);
					nIndex += 3;
				}
			}
		}
		pRecastMOWalk->end();

		// Define manualObject with the navmesh edges between neighbouring polygons
		Ogre::ManualObject* pRecastMONeighbour;
		if (mSceneManager.hasManualObject("RecastMONeighbour_" + name)) {
			pRecastMONeighbour = mSceneManager.getManualObject("RecastMONeighbour_" + name);
			pRecastMONeighbour->clear();
		} else {
			pRecastMONeighbour = mSceneManager.createManualObject("RecastMONeighbour_" + name);
			//Remove from the overhead map.
			pRecastMONeighbour->setVisibilityFlags(pRecastMONeighbour->getVisibilityFlags() & ~Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK);
			mTileSceneNode->attachObject(pRecastMONeighbour);
		}

		pRecastMONeighbour->begin("/common/base/authoring/awareness", Ogre::RenderOperation::OT_LINE_LIST);

		for (int i = 0; i < npolys; ++i) {
			const unsigned short* p = &polys[i * nvp * 2];
			for (int j = 0; j < nvp; ++j) {
				if (p[j] == RC_MESH_NULL_IDX)
					break;
				if (p[nvp + j] == RC_MESH_NULL_IDX)
					continue;
				int vi[2];
				vi[0] = p[j];
				if (j + 1 >= nvp || p[j + 1] == RC_MESH_NULL_IDX)
					vi[1] = p[0];
				else
					vi[1] = p[j + 1];
				for (int k = 0; k < 2; ++k) {
					const unsigned short* v = &verts[vi[k] * 3];
					const float x = orig[0] + v[0] * cs;
					const float y = orig[1] + (v[1]/*+1*/) * ch /*+ 0.1f*/;
					const float z = -orig[2] - v[2] * cs;
					//dd->vertex(x, y, z, coln);
					pRecastMONeighbour->position(x, y + m_navMeshEdgesOffsetFromGround, z);
					pRecastMONeighbour->colour(m_navmeshNeighbourEdgeCol);

				}
			}
		}

		pRecastMONeighbour->end();

		// Define manualObject with navmesh outer edges (boundaries)
		Ogre::ManualObject* pRecastMOBoundary;
		if (mSceneManager.hasManualObject("RecastMOBoundary_" + name)) {
			pRecastMOBoundary = mSceneManager.getManualObject("RecastMOBoundary_" + name);

			pRecastMOBoundary->clear();
		} else {
			pRecastMOBoundary = mSceneManager.createManualObject("RecastMOBoundary_" + name);
			//Remove from the overhead map.
			pRecastMOBoundary->setVisibilityFlags(pRecastMOBoundary->getVisibilityFlags() & ~Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK);
			mTileSceneNode->attachObject(pRecastMOBoundary);
		}

		pRecastMOBoundary->begin("/common/base/authoring/awareness", Ogre::RenderOperation::OT_LINE_LIST);

		for (int i = 0; i < npolys; ++i) {
			const unsigned short* p = &polys[i * nvp * 2];
			for (int j = 0; j < nvp; ++j) {
				if (p[j] == RC_MESH_NULL_IDX)
					break;
				if (p[nvp + j] != RC_MESH_NULL_IDX)
					continue;
				int vi[2];
				vi[0] = p[j];
				if (j + 1 >= nvp || p[j + 1] == RC_MESH_NULL_IDX)
					vi[1] = p[0];
				else
					vi[1] = p[j + 1];
				for (int k = 0; k < 2; ++k) {
					const unsigned short* v = &verts[vi[k] * 3];
					const float x = orig[0] + v[0] * cs;
					const float y = orig[1] + (v[1]/*+1*/) * ch /*+ 0.1f*/;
					const float z = -orig[2] - v[2] * cs;
					//dd->vertex(x, y, z, colb);

					pRecastMOBoundary->position(x, y + m_navMeshEdgesOffsetFromGround, z);
					pRecastMOBoundary->colour(m_navmeshOuterEdgeCol);
				}
			}
		}

		pRecastMOBoundary->end();

//		if (STATIC_GEOM_DEBUG) {
//			// Render navmesh tiles more efficiently using staticGeometry
//
//			// Early out if empty meshes drawn
//			if (m_pRecastMOWalk->getNumSections() == 0)
//				return;
//
//			if (!m_sg) {
//				m_sg = m_pSceneMgr->createStaticGeometry("NavmeshDebugStaticGeom");
//				Ogre::Vector3 bmin;
//				Ogre::Vector3 bmax;
//				Ogre::Vector3 bsize;
//				FloatAToOgreVect3(m_cfg.bmin, bmin);
//				FloatAToOgreVect3(m_cfg.bmax, bmax);
//				bsize = bmax - bmin;
//				m_sg->setRegionDimensions(bsize);
//				m_sg->setOrigin(bmin);
//			}
//
//			m_pRecastMOWalk->convertToMesh("mesh_" + m_pRecastMOWalk->getName());
//			Ogre::Entity *walkEnt = m_pSceneMgr->createEntity("ent_" + m_pRecastMOWalk->getName(), "mesh_" + m_pRecastMOWalk->getName());
//			m_sg->addEntity(walkEnt, Ogre::Vector3::ZERO);
//
//// TODO line drawing does not work with staticGeometry
//			if (false && m_pRecastMONeighbour->getNumSections() > 0) {
//				m_pRecastMONeighbour->convertToMesh("mesh_" + m_pRecastMONeighbour->getName());     // Creating meshes from manualobjects without polygons is not a good idea!
//				Ogre::Entity *neighbourEnt = m_pSceneMgr->createEntity("ent_" + m_pRecastMONeighbour->getName(), "mesh_" + m_pRecastMONeighbour->getName());
//				m_sg->addEntity(neighbourEnt, Ogre::Vector3::ZERO);
//			}
//
//			if (false && m_pRecastMOBoundary->getNumSections() > 0) {
//				m_pRecastMOBoundary->convertToMesh("mesh_" + m_pRecastMOBoundary->getName());
//				Ogre::Entity *boundaryEnt = m_pSceneMgr->createEntity("ent_" + m_pRecastMOBoundary->getName(), "mesh_" + m_pRecastMOBoundary->getName());
//				m_sg->addEntity(boundaryEnt, Ogre::Vector3::ZERO);
//			}
//
//			// Set dirty flag of solid geometry so it will be rebuilt next update()
//			m_rebuildSg = true;
//		} else {
		// Add manualobjects directly to scene (can be slow for lots of tiles)
//		}

	}     // end areacount

	delete[] regionColors;

}