当前位置: 首页>>代码示例>>C++>>正文


C++ rcVcopy函数代码示例

本文整理汇总了C++中rcVcopy函数的典型用法代码示例。如果您正苦于以下问题:C++ rcVcopy函数的具体用法?C++ rcVcopy怎么用?C++ rcVcopy使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。


在下文中一共展示了rcVcopy函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: while

// Calculates convex hull on xz-plane of points on 'pts'
ConvexVolume::ConvexVolume(InputGeom* geom, float offset)
{
// TODO protect against too many vectors!

    int hullVertIndices[MAX_CONVEXVOL_PTS];
    float* pts = geom->getVerts();
    int npts = geom->getVertCount();

    // Find lower-leftmost point.
    int hull = 0;
    for (int i = 1; i < npts; ++i)
        if (ConvexVolume::cmppt(&pts[i*3], &pts[hull*3]))
            hull = i;
    // Gift wrap hull.
    int endpt = 0;
    int i = 0;
    do
    {
        hullVertIndices[i++] = hull;
        endpt = 0;
        for (int j = 1; j < npts; ++j)
            if (hull == endpt || ConvexVolume::left(&pts[hull*3], &pts[endpt*3], &pts[j*3]))
                endpt = j;
        hull = endpt;
    }
    while (endpt != hullVertIndices[0] && i < MAX_CONVEXVOL_PTS/2);   // TODO: number of hull points is limited, but in a naive way. In large meshes the best candidate points for the hull might not be selected
                                            // Leave the other half of the points for expanding the hull

    nverts = i;


    // Copy geometry vertices to convex hull
    for (int i = 0; i < nverts; i++)
        rcVcopy(&verts[i*3], &pts[hullVertIndices[i]*3]);



    area = SAMPLE_POLYAREA_DOOR;   // You can choose whatever flag you assing to the poly area

    // Find min and max height of convex hull
    hmin = geom->getMeshBoundsMin()[1];
    hmax = geom->getMeshBoundsMax()[1];

    // 3D mesh min and max bounds
    rcVcopy(bmin, geom->getMeshBoundsMin());
    rcVcopy(bmax, geom->getMeshBoundsMax());

//TODO offsetting is still broken for a lot of shapes! Fix this!
    // Offset convex hull if needed
    if(offset > 0.01f) {
        float offsetVerts[MAX_CONVEXVOL_PTS * 3]; // An offset hull is allowed twice the number of vertices
        int nOffsetVerts = rcOffsetPoly(verts, nverts, offset, offsetVerts, MAX_CONVEXVOL_PTS);

        if (nOffsetVerts <= 0)
            return;

        for(int i = 0; i < nOffsetVerts; i++)
            rcVcopy(&verts[i*3], &offsetVerts[i*3]);

        nverts = nOffsetVerts;

        // Modify the bounds with offset (except height)
        bmin[0] = bmin[0]-offset;
        bmin[2] = bmin[2]-offset;
        bmax[0] = bmax[0]+offset;
        bmax[2] = bmax[2]+offset;
    }

}
开发者ID:k300021,项目名称:OgreFireworksimulation,代码行数:70,代码来源:RecastConvexHull.cpp

示例2: rcVcopy

bool OgreRecast::NavMeshBuild(InputGeom* input)
{
    // TODO: clean up unused variables


   m_pLog->logMessage("NavMeshBuild Start");


   //
   // Step 1. Initialize build config.
   //

   // Reset build times gathering.
   m_ctx->resetTimers();

   // Start the build process.
   m_ctx->startTimer(RC_TIMER_TOTAL);






   //
   // Step 2. Rasterize input polygon soup.
   //

   InputGeom *inputGeom = input;
   rcVcopy(m_cfg.bmin, inputGeom->getMeshBoundsMin());
   rcVcopy(m_cfg.bmax, inputGeom->getMeshBoundsMax());
   rcCalcGridSize(m_cfg.bmin, m_cfg.bmax, m_cfg.cs, &m_cfg.width, &m_cfg.height);

   int nverts = inputGeom->getVertCount();
   int ntris = inputGeom->getTriCount();
   Ogre::Vector3 min; FloatAToOgreVect3(inputGeom->getMeshBoundsMin(), min);
   Ogre::Vector3 max; FloatAToOgreVect3(inputGeom->getMeshBoundsMax(), max);

   //Ogre::LogManager::getSingletonPtr()->logMessage("Bounds: "+Ogre::StringConverter::toString(min) + "   "+ Ogre::StringConverter::toString(max));


   m_pLog->logMessage("Building navigation:");
   m_pLog->logMessage(" - " + Ogre::StringConverter::toString(m_cfg.width) + " x " + Ogre::StringConverter::toString(m_cfg.height) + " cells");
   m_pLog->logMessage(" - " + Ogre::StringConverter::toString(nverts/1000.0f) + " K verts, " + Ogre::StringConverter::toString(ntris/1000.0f) + " K tris");

   // Allocate voxel heightfield where we rasterize our input data to.
   m_solid = rcAllocHeightfield();
   if (!m_solid)
   {
      m_pLog->logMessage("ERROR: buildNavigation: Out of memory 'solid'.");
      return false;
   }
   if (!rcCreateHeightfield(m_ctx, *m_solid, m_cfg.width, m_cfg.height, m_cfg.bmin, m_cfg.bmax, m_cfg.cs, m_cfg.ch))
   {
      m_pLog->logMessage("ERROR: buildNavigation: Could not create solid heightfield. Possibly it requires too much memory, try setting a higher cellSize and cellHeight value.");
      return false;
   }
   
   // Allocate array that can hold triangle area types.
   // If you have multiple meshes you need to process, allocate
   // an array which can hold the max number of triangles you need to process.
   m_triareas = new unsigned char[ntris];
   if (!m_triareas)
   {
       m_pLog->logMessage("ERROR: buildNavigation: Out of memory 'm_triareas' ("+Ogre::StringConverter::toString(ntris)+").");
      return false;
   }
   
   // Find triangles which are walkable based on their slope and rasterize them.
   // If your input data is multiple meshes, you can transform them here, calculate
   // the are type for each of the meshes and rasterize them.
   memset(m_triareas, 0, ntris*sizeof(unsigned char));
   rcMarkWalkableTriangles(m_ctx, m_cfg.walkableSlopeAngle, inputGeom->getVerts(), inputGeom->getVertCount(), inputGeom->getTris(), inputGeom->getTriCount(), m_triareas);
   rcRasterizeTriangles(m_ctx, inputGeom->getVerts(), inputGeom->getVertCount(), inputGeom->getTris(), m_triareas, inputGeom->getTriCount(), *m_solid, m_cfg.walkableClimb);

   if (!m_keepInterResults)
   {
      delete [] m_triareas;
      m_triareas = 0;
   }





   //
   // Step 3. Filter walkables surfaces.
   //
   
   // Once all geoemtry is rasterized, we do initial pass of filtering to
   // remove unwanted overhangs caused by the conservative rasterization
   // as well as filter spans where the character cannot possibly stand.
   rcFilterLowHangingWalkableObstacles(m_ctx, m_cfg.walkableClimb, *m_solid);
   rcFilterLedgeSpans(m_ctx, m_cfg.walkableHeight, m_cfg.walkableClimb, *m_solid);
   rcFilterWalkableLowHeightSpans(m_ctx, m_cfg.walkableHeight, *m_solid);






//.........这里部分代码省略.........
开发者ID:arrian,项目名称:3d-engine,代码行数:101,代码来源:OgreRecast.cpp

示例3: rcBuildHeightfieldLayers


//.........这里部分代码省略.........
    unsigned char remap[256];
    memset(remap, 0, 256);

    // Find number of unique layers.
    layerId = 0;
    for (int i = 0; i < nregs; ++i)
        remap[regs[i].layerId] = 1;
    for (int i = 0; i < 256; ++i)
    {
        if (remap[i])
            remap[i] = layerId++;
        else
            remap[i] = 0xff;
    }
    // Remap ids.
    for (int i = 0; i < nregs; ++i)
        regs[i].layerId = remap[regs[i].layerId];
    
    // No layers, return empty.
    if (layerId == 0)
    {
        ctx->stopTimer(RC_TIMER_BUILD_LAYERS);
        return true;
    }
    
    // Create layers.
    rcAssert(lset.layers == 0);
    
    const int lw = w - borderSize*2;
    const int lh = h - borderSize*2;

    // Build contracted bbox for layers.
    float bmin[3], bmax[3];
    rcVcopy(bmin, chf.bmin);
    rcVcopy(bmax, chf.bmax);
    bmin[0] += borderSize*chf.cs;
    bmin[2] += borderSize*chf.cs;
    bmax[0] -= borderSize*chf.cs;
    bmax[2] -= borderSize*chf.cs;
    
    lset.nlayers = (int)layerId;
    
    lset.layers = (rcHeightfieldLayer*)rcAlloc(sizeof(rcHeightfieldLayer)*lset.nlayers, RC_ALLOC_PERM);
    if (!lset.layers)
    {
        ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'layers' (%d).", lset.nlayers);
        return false;
    }
    memset(lset.layers, 0, sizeof(rcHeightfieldLayer)*lset.nlayers);

    
    // Store layers.
    for (int i = 0; i < lset.nlayers; ++i)
    {
        unsigned char curId = (unsigned char)i;
        
        // Allocate memory for the current layer.
        rcHeightfieldLayer* layer = &lset.layers[i];
        memset(layer, 0, sizeof(rcHeightfieldLayer));

        const int gridSize = sizeof(unsigned char)*lw*lh;

        layer->heights = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM);
        if (!layer->heights)
        {
            ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'heights' (%d).", gridSize);
开发者ID:IonutCava,项目名称:trunk,代码行数:67,代码来源:RecastLayers.cpp

示例4: buildMesh

dtNavMesh* buildMesh(InputGeom* geom, WCellBuildContext* wcellContext, int numCores)
{
	dtNavMesh* mesh = 0;

	if (!geom || !geom->getMesh())
	{
		CleanupAfterBuild();
		wcellContext->log(RC_LOG_ERROR, "buildTiledNavigation: No vertices and triangles.");
		return 0;
	}
	
	mesh = dtAllocNavMesh();
	if (!mesh)
	{
		CleanupAfterBuild();
		wcellContext->log(RC_LOG_ERROR, "buildTiledNavigation: Could not allocate navmesh.");
		return 0;
	}

	// setup some default parameters
	rcConfig cfg;
	memset(&cfg, 0, sizeof(rcConfig));
	const float agentHeight = 2.1f;				// most character toons are about this tall
	const float agentRadius = 0.6f;				// most character toons are about this big around
	const float agentClimb = 1.0f;				// character toons can step up this far. Seems ridiculously high ...
	const float tileSize = 1600.0f/3.0f/16.0f;	// The size of one chunk

	cfg.cs = 0.1f;										// cell size is a sort of resolution -> the bigger the faster
	cfg.ch = 0.05f;										// cell height -> distance from mesh to ground, if too low, recast will not build essential parts of the mesh for some reason
	cfg.walkableSlopeAngle = 50.0f;						// max climbable slope, bigger values won't make much of a change
	cfg.walkableHeight = (int)ceilf(agentHeight/cfg.ch);// minimum space to ceiling
	cfg.walkableClimb = (int)floorf(agentClimb/cfg.ch); // how high the agent can climb in one step
	cfg.walkableRadius = (int)ceilf(agentRadius/cfg.cs);// minimum distance to objects
	cfg.tileSize = (int)(tileSize/cfg.cs + 0.5f);
	cfg.maxEdgeLen = cfg.tileSize/2;;
	cfg.borderSize = cfg.walkableRadius + 3;
	cfg.width = cfg.tileSize + cfg.borderSize*2;
	cfg.height = cfg.tileSize + cfg.borderSize*2;	
	cfg.maxSimplificationError = 1.3f;
	cfg.minRegionArea = (int)rcSqr(8);		// Note: area = size*size
	cfg.mergeRegionArea = (int)rcSqr(20);	// Note: area = size*size
	cfg.maxVertsPerPoly = 3;
	cfg.detailSampleDist = cfg.cs * 9;
	cfg.detailSampleMaxError = cfg.ch * 1.0f;

	// default calculations - for some reason not included in basic recast
	const float* bmin = geom->getMeshBoundsMin();
	const float* bmax = geom->getMeshBoundsMax();
	
	int gw = 0, gh = 0;
	rcCalcGridSize(bmin, bmax, cfg.cs, &gw, &gh);
	const int ts = cfg.tileSize;
	const int tw = (gw + ts-1) / ts;
	const int th = (gh + ts-1) / ts;

	// Max tiles and max polys affect how the tile IDs are caculated.
	// There are 22 bits available for identifying a tile and a polygon.
	int tileBits = rcMin((int)ilog2(nextPow2(tw*th)), 14);
	if (tileBits > 14) tileBits = 14;
	int polyBits = 22 - tileBits;
	int maxTiles = 1 << tileBits;
	int maxPolysPerTile = 1 << polyBits;

	dtNavMeshParams params;
	rcVcopy(params.orig, geom->getMeshBoundsMin());
	params.tileWidth = cfg.tileSize * cfg.cs;
	params.tileHeight = cfg.tileSize * cfg.cs;
	params.maxTiles = maxTiles;
	params.maxPolys = maxPolysPerTile;
	
	dtStatus status;
	
	status = mesh->init(&params);
	if (dtStatusFailed(status))
	{
		CleanupAfterBuild();
		wcellContext->log(RC_LOG_ERROR, "buildTiledNavigation: Could not init navmesh.");
		return 0;
	}
	
	// start building
	const float tcs = cfg.tileSize*cfg.cs;
	wcellContext->startTimer(RC_TIMER_TEMP);
	
	TileAdder Adder;

	dispatcher.Reset();
	dispatcher.maxHeight = th;
	dispatcher.maxWidth = tw;

	int numThreads = 0;
	numThreads = std::min(2*numCores, 8);

	boost::thread *threads[8];
	for(int i = 0; i < numThreads; ++i)
	{
		QuadrantTiler newTiler;
		newTiler.geom = geom;
		newTiler.cfg = cfg;
		newTiler.ctx = *wcellContext;
//.........这里部分代码省略.........
开发者ID:Bootz,项目名称:WCell,代码行数:101,代码来源:WCellRecast.cpp

示例5: rcBuildCompactHeightfield

bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
							   rcHeightfield& hf, rcCompactHeightfield& chf)
{
	rcAssert(ctx);
	
	ctx->startTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD);
	
	const int w = hf.width;
	const int h = hf.height;
	const int spanCount = rcGetHeightFieldSpanCount(ctx, hf);

	// Fill in header.
	chf.width = w;
	chf.height = h;
	chf.spanCount = spanCount;
	chf.walkableHeight = walkableHeight;
	chf.walkableClimb = walkableClimb;
	chf.maxRegions = 0;
	rcVcopy(chf.bmin, hf.bmin);
	rcVcopy(chf.bmax, hf.bmax);
	chf.bmax[1] += walkableHeight*hf.ch;
	chf.cs = hf.cs;
	chf.ch = hf.ch;
	chf.cells = (rcCompactCell*)rcAlloc(sizeof(rcCompactCell)*w*h, RC_ALLOC_PERM);
	if (!chf.cells)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (%d)", w*h);
		return false;
	}
	memset(chf.cells, 0, sizeof(rcCompactCell)*w*h);
	chf.spans = (rcCompactSpan*)rcAlloc(sizeof(rcCompactSpan)*spanCount, RC_ALLOC_PERM);
	if (!chf.spans)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (%d)", spanCount);
		return false;
	}
	memset(chf.spans, 0, sizeof(rcCompactSpan)*spanCount);
	chf.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*spanCount, RC_ALLOC_PERM);
	if (!chf.areas)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.areas' (%d)", spanCount);
		return false;
	}
	memset(chf.areas, RC_NULL_AREA, sizeof(unsigned char)*spanCount);
	
	const int MAX_HEIGHT = 0xffff;
	
	// Fill in cells and spans.
	int idx = 0;
	for (int y = 0; y < h; ++y)
	{
		for (int x = 0; x < w; ++x)
		{
			const rcSpan* s = hf.spans[x + y*w];
			// If there are no spans at this cell, just leave the data to index=0, count=0.
			if (!s) continue;
			rcCompactCell& c = chf.cells[x+y*w];
			c.index = idx;
			c.count = 0;
			while (s)
			{
				if (s->area != RC_NULL_AREA)
				{
					const int bot = (int)s->smax;
					const int top = s->next ? (int)s->next->smin : MAX_HEIGHT;
					chf.spans[idx].y = (unsigned short)rcClamp(bot, 0, 0xffff);
					chf.spans[idx].h = (unsigned char)rcClamp(top - bot, 0, 0xff);
					chf.areas[idx] = s->area;
					idx++;
					c.count++;
				}
				s = s->next;
			}
		}
	}

	// Find neighbour connections.
	const int MAX_LAYERS = RC_NOT_CONNECTED-1;
	int tooHighNeighbour = 0;
	for (int y = 0; y < h; ++y)
	{
		for (int x = 0; x < w; ++x)
		{
			const rcCompactCell& c = chf.cells[x+y*w];
			for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
			{
				rcCompactSpan& s = chf.spans[i];
				
				for (int dir = 0; dir < 4; ++dir)
				{
					rcSetCon(s, dir, RC_NOT_CONNECTED);
					const int nx = x + rcGetDirOffsetX(dir);
					const int ny = y + rcGetDirOffsetY(dir);
					// First check that the neighbour cell is in bounds.
					if (nx < 0 || ny < 0 || nx >= w || ny >= h)
						continue;
						
					// Iterate over all neighbour spans and check if any of the is
					// accessible from current cell.
					const rcCompactCell& nc = chf.cells[nx+ny*w];
//.........这里部分代码省略.........
开发者ID:BlackHell,项目名称:Transmog-2.4.3-OREGON,代码行数:101,代码来源:Recast.cpp

示例6: color

void KX_NavMeshObject::DrawNavMesh(NavMeshRenderMode renderMode)
{
	if (!m_navMesh)
		return;
	MT_Vector3 color(0.f, 0.f, 0.f);
	
	switch (renderMode)
	{
	case RM_POLYS :
	case RM_WALLS : 
		for (int pi=0; pi<m_navMesh->getPolyCount(); pi++)
		{
			const dtStatPoly* poly = m_navMesh->getPoly(pi);

			for (int i = 0, j = (int)poly->nv-1; i < (int)poly->nv; j = i++)
			{
				if (poly->n[j] && renderMode==RM_WALLS) 
					continue;
				const float* vif = m_navMesh->getVertex(poly->v[i]);
				const float* vjf = m_navMesh->getVertex(poly->v[j]);
				MT_Point3 vi(vif[0], vif[2], vif[1]);
				MT_Point3 vj(vjf[0], vjf[2], vjf[1]);
				vi = TransformToWorldCoords(vi);
				vj = TransformToWorldCoords(vj);
				KX_RasterizerDrawDebugLine(vi, vj, color);
			}
		}
		break;
	case RM_TRIS : 
		for (int i = 0; i < m_navMesh->getPolyDetailCount(); ++i)
		{
			const dtStatPoly* p = m_navMesh->getPoly(i);
			const dtStatPolyDetail* pd = m_navMesh->getPolyDetail(i);

			for (int j = 0; j < pd->ntris; ++j)
			{
				const unsigned char* t = m_navMesh->getDetailTri(pd->tbase+j);
				MT_Point3 tri[3];
				for (int k = 0; k < 3; ++k)
				{
					const float* v;
					if (t[k] < p->nv)
						v = m_navMesh->getVertex(p->v[t[k]]);
					else
						v =  m_navMesh->getDetailVertex(pd->vbase+(t[k]-p->nv));
					float pos[3];
					rcVcopy(pos, v);
					flipAxes(pos);
					tri[k].setValue(pos);
				}

				for (int k=0; k<3; k++)
					tri[k] = TransformToWorldCoords(tri[k]);

				for (int k=0; k<3; k++)
					KX_RasterizerDrawDebugLine(tri[k], tri[(k+1)%3], color);
			}
		}
		break;
	default:
		/* pass */
		break;
	}
}
开发者ID:danielmarg,项目名称:blender-main,代码行数:64,代码来源:KX_NavMeshObject.cpp

示例7: buildPolyDetail

static bool buildPolyDetail(const float* in, const int nin,
							const float sampleDist, const float sampleMaxError,
							const rcCompactHeightfield& chf, const rcHeightPatch& hp,
							float* verts, int& nverts, rcIntArray& tris,
							rcIntArray& edges, rcIntArray& samples)
{
	static const int MAX_VERTS = 256;
	static const int MAX_EDGE = 64;
	float edge[(MAX_EDGE+1)*3];
	int hull[MAX_VERTS];
	int nhull = 0;

	nverts = 0;

	for (int i = 0; i < nin; ++i)
		rcVcopy(&verts[i*3], &in[i*3]);
	nverts = nin;
	
	const float cs = chf.cs;
	const float ics = 1.0f/cs;
	
	// Tesselate outlines.
	// This is done in separate pass in order to ensure
	// seamless height values across the ply boundaries.
	if (sampleDist > 0)
	{
		for (int i = 0, j = nin-1; i < nin; j=i++)
		{
			const float* vj = &in[j*3];
			const float* vi = &in[i*3];
			bool swapped = false;
			// Make sure the segments are always handled in same order
			// using lexological sort or else there will be seams.
			if (fabsf(vj[0]-vi[0]) < 1e-6f)
			{
				if (vj[2] > vi[2])
				{
					rcSwap(vj,vi);
					swapped = true;
				}
			}
			else
			{
				if (vj[0] > vi[0])
				{
					rcSwap(vj,vi);
					swapped = true;
				}
			}
			// Create samples along the edge.
			float dx = vi[0] - vj[0];
			float dy = vi[1] - vj[1];
			float dz = vi[2] - vj[2];
			float d = sqrtf(dx*dx + dz*dz);
			int nn = 1 + (int)floorf(d/sampleDist);
			if (nn > MAX_EDGE) nn = MAX_EDGE;
			if (nverts+nn >= MAX_VERTS)
				nn = MAX_VERTS-1-nverts;
			for (int k = 0; k <= nn; ++k)
			{
				float u = (float)k/(float)nn;
				float* pos = &edge[k*3];
				pos[0] = vj[0] + dx*u;
				pos[1] = vj[1] + dy*u;
				pos[2] = vj[2] + dz*u;
				pos[1] = getHeight(pos[0],pos[1],pos[2], cs, ics, chf.ch, hp)*chf.ch;
			}
			// Simplify samples.
			int idx[MAX_EDGE] = {0,nn};
			int nidx = 2;
			for (int k = 0; k < nidx-1; )
			{
				const int a = idx[k];
				const int b = idx[k+1];
				const float* va = &edge[a*3];
				const float* vb = &edge[b*3];
				// Find maximum deviation along the segment.
				float maxd = 0;
				int maxi = -1;
				for (int m = a+1; m < b; ++m)
				{
					float d = distancePtSeg(&edge[m*3],va,vb);
					if (d > maxd)
					{
						maxd = d;
						maxi = m;
					}
				}
				// If the max deviation is larger than accepted error,
				// add new point, else continue to next segment.
				if (maxi != -1 && maxd > rcSqr(sampleMaxError))
				{
					for (int m = nidx; m > k; --m)
						idx[m] = idx[m-1];
					idx[k+1] = maxi;
					nidx++;
				}
				else
				{
					++k;
//.........这里部分代码省略.........
开发者ID:1414648814,项目名称:OpenglESGame,代码行数:101,代码来源:RecastMeshDetail.cpp

示例8: rcCalcGridSize

bool Sample_TempObstacles::handleBuild()
{
	dtStatus status;
	
	if (!m_geom || !m_geom->getMesh())
	{
		m_ctx->log(RC_LOG_ERROR, "buildTiledNavigation: No vertices and triangles.");
		return false;
	}

	m_tmproc->init(m_geom);
	
	// Init cache
	const float* bmin = m_geom->getMeshBoundsMin();
	const float* bmax = m_geom->getMeshBoundsMax();
	int gw = 0, gh = 0;
	rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);
	const int ts = (int)m_tileSize;
	const int tw = (gw + ts-1) / ts;
	const int th = (gh + ts-1) / ts;

	// Generation params.
	rcConfig cfg;
	memset(&cfg, 0, sizeof(cfg));
	cfg.cellSizeXZ = m_cellSize;
	cfg.cellSizeY = m_cellHeight;
	cfg.walkableSlopeAngle = m_agentMaxSlope;
	cfg.walkableHeight = (int)ceilf(m_agentHeight / cfg.cellSizeY);
	cfg.walkableClimb = (int)floorf(m_agentMaxClimb / cfg.cellSizeY);
	cfg.walkableRadius = (int)ceilf(m_agentRadius / cfg.cellSizeXZ);
	cfg.maxEdgeLen = (int)(m_edgeMaxLen / m_cellSize);
	cfg.maxSimplificationError = m_edgeMaxError;
	cfg.minRegionArea = (int)rcSqr(m_regionMinSize);		// Note: area = size*size
	cfg.mergeRegionArea = (int)rcSqr(m_regionMergeSize);	// Note: area = size*size
	cfg.maxVertsPerPoly = (int)m_vertsPerPoly;
	cfg.tileSize = (int)m_tileSize;
	cfg.borderSize = cfg.walkableRadius + 3; // Reserve enough padding.
	cfg.width = cfg.tileSize + cfg.borderSize*2;
	cfg.height = cfg.tileSize + cfg.borderSize*2;
	cfg.detailSampleDist = m_detailSampleDist < 0.9f ? 0 : m_cellSize * m_detailSampleDist;
	cfg.detailSampleMaxError = m_cellHeight * m_detailSampleMaxError;
	rcVcopy(cfg.bmin, bmin);
	rcVcopy(cfg.bmax, bmax);
	
	// Tile cache params.
	dtTileCacheParams tcparams;
	memset(&tcparams, 0, sizeof(tcparams));
	rcVcopy(tcparams.orig, bmin);
	tcparams.cs = m_cellSize;
	tcparams.ch = m_cellHeight;
	tcparams.width = (int)m_tileSize;
	tcparams.height = (int)m_tileSize;
	tcparams.walkableHeight = m_agentHeight;
	tcparams.walkableRadius = m_agentRadius;
	tcparams.walkableClimb = m_agentMaxClimb;
	tcparams.maxSimplificationError = m_edgeMaxError;
	tcparams.maxTiles = tw*th*EXPECTED_LAYERS_PER_TILE;
	tcparams.maxObstacles = 128;

	dtFreeTileCache(m_tileCache);
	
	m_tileCache = dtAllocTileCache();
	if (!m_tileCache)
	{
		m_ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not allocate tile cache.");
		return false;
	}
	status = m_tileCache->init(&tcparams, m_talloc, m_tcomp, m_tmproc);
	if (dtStatusFailed(status))
	{
		m_ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not init tile cache.");
		return false;
	}
	
	dtFreeNavMesh(m_navMesh);
	
	m_navMesh = dtAllocNavMesh();
	if (!m_navMesh)
	{
		m_ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not allocate navmesh.");
		return false;
	}

	dtNavMeshParams params;
	memset(&params, 0, sizeof(params));
	rcVcopy(params.orig, m_geom->getMeshBoundsMin());
	params.tileWidth = m_tileSize*m_cellSize;
	params.tileHeight = m_tileSize*m_cellSize;
	params.maxTiles = m_maxTiles;
	params.maxPolys = m_maxPolysPerTile;
	
	status = m_navMesh->init(&params);
	if (dtStatusFailed(status))
	{
		m_ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not init navmesh.");
		return false;
	}
	
	status = m_navQuery->init(m_navMesh, 2048);
	if (dtStatusFailed(status))
//.........这里部分代码省略.........
开发者ID:rwindegger,项目名称:recastnavigation,代码行数:101,代码来源:Sample_TempObstacles.cpp

示例9: handleClick

	virtual void handleClick(const float* /*s*/, const float* p, bool /*shift*/)
	{
		m_hitPosSet = true;
		rcVcopy(m_hitPos,p);
	}
开发者ID:rwindegger,项目名称:recastnavigation,代码行数:5,代码来源:Sample_TempObstacles.cpp

示例10: rcMergePolyMeshDetails

/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail
bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh)
{
	rcAssert(ctx);
	
	ctx->startTimer(RC_TIMER_MERGE_POLYMESHDETAIL);

	int maxVerts = 0;
	int maxTris = 0;
	int maxMeshes = 0;

	for (int i = 0; i < nmeshes; ++i)
	{
		if (!meshes[i]) continue;
		maxVerts += meshes[i]->nverts;
		maxTris += meshes[i]->ntris;
		maxMeshes += meshes[i]->nmeshes;
	}

	mesh.nmeshes = 0;
	mesh.meshes = (unsigned int*)rcAlloc(sizeof(unsigned int)*maxMeshes*4, RC_ALLOC_PERM);
	if (!mesh.meshes)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'pmdtl.meshes' (%d).", maxMeshes*4);
		return false;
	}

	mesh.ntris = 0;
	mesh.tris = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxTris*4, RC_ALLOC_PERM);
	if (!mesh.tris)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", maxTris*4);
		return false;
	}

	mesh.nverts = 0;
	mesh.verts = (dtCoordinates*)rcAlloc(sizeof(dtCoordinates)*maxVerts, RC_ALLOC_PERM);
	if (!mesh.verts)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", maxVerts*3);
		return false;
	}
	
	// Merge datas.
	for (int i = 0; i < nmeshes; ++i)
	{
		rcPolyMeshDetail* dm = meshes[i];
		if (!dm) continue;
		for (int j = 0; j < dm->nmeshes; ++j)
		{
			unsigned int* dst = &mesh.meshes[mesh.nmeshes*4];
			unsigned int* src = &dm->meshes[j*4];
			dst[0] = (unsigned int)mesh.nverts+src[0];
			dst[1] = src[1];
			dst[2] = (unsigned int)mesh.ntris+src[2];
			dst[3] = src[3];
			mesh.nmeshes++;
		}
			
		for (int k = 0; k < dm->nverts; ++k)
		{
			rcVcopy(mesh.verts[mesh.nverts], dm->verts[k]);
			mesh.nverts++;
		}
		for (int k = 0; k < dm->ntris; ++k)
		{
			mesh.tris[mesh.ntris*4+0] = dm->tris[k*4+0];
			mesh.tris[mesh.ntris*4+1] = dm->tris[k*4+1];
			mesh.tris[mesh.ntris*4+2] = dm->tris[k*4+2];
			mesh.tris[mesh.ntris*4+3] = dm->tris[k*4+3];
			mesh.ntris++;
		}
	}

	ctx->stopTimer(RC_TIMER_MERGE_POLYMESHDETAIL);
	
	return true;
}
开发者ID:infini,项目名称:_task,代码行数:78,代码来源:RecastMeshDetail.cpp

示例11: buildPolyDetail

static bool buildPolyDetail(rcContext* ctx, const dtCoordinates* in, const int nin,
							const float sampleDist, const float sampleMaxError,
							const rcCompactHeightfield& chf, const rcHeightPatch& hp,
							dtCoordinates* verts, int& nverts, rcIntArray& tris,
							rcIntArray& edges, rcIntArray& samples
#ifdef MODIFY_VOXEL_FLAG
							, const char /*area*/
#endif // MODIFY_VOXEL_FLAG
							)
{
	static const int MAX_VERTS = 127;
	static const int MAX_TRIS = 255;	// Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts).
	static const int MAX_VERTS_PER_EDGE = 32;
	dtCoordinates edge[(MAX_VERTS_PER_EDGE+1)];
	int hull[MAX_VERTS];
	int nhull = 0;

	nverts = 0;

	for (int i = 0; i < nin; ++i)
		rcVcopy(verts[i], in[i]);
	nverts = nin;
	
	const float cs = chf.cs;
	const float ics = 1.0f/cs;
	
	// Tessellate outlines.
	// This is done in separate pass in order to ensure
	// seamless height values across the ply boundaries.
#ifdef MODIFY_VOXEL_FLAG
	if( 0 < sampleDist /*&& rcIsTerrainArea( area )*/ )
#else // MODIFY_VOXEL_FLAG
	if (sampleDist > 0)
#endif // MODIFY_VOXEL_FLAG
	{
		for (int i = 0, j = nin-1; i < nin; j=i++)
		{
			const dtCoordinates* vj = &in[j];
			const dtCoordinates* vi = &in[i];
			bool swapped = false;
			// Make sure the segments are always handled in same order
			// using lexological sort or else there will be seams.
			if (fabsf(vj->X()-vi->X()) < 1e-6f)
			{
				if (vj->Z() > vi->Z())
				{
					rcSwap(vj,vi);
					swapped = true;
				}
			}
			else
			{
				if (vj->X() > vi->X())
				{
					rcSwap(vj,vi);
					swapped = true;
				}
			}
			// Create samples along the edge.
			float dx = vi->X() - vj->X();
			float dy = vi->Y() - vj->Y();
			float dz = vi->Z() - vj->Z();
			float d = sqrtf(dx*dx + dz*dz);
			int nn = 1 + (int)floorf(d/sampleDist);
			if (nn >= MAX_VERTS_PER_EDGE) nn = MAX_VERTS_PER_EDGE-1;
			if (nverts+nn >= MAX_VERTS)
				nn = MAX_VERTS-1-nverts;
			
			for (int k = 0; k <= nn; ++k)
			{
				float u = (float)k/(float)nn;
				dtCoordinates* pos = &edge[k];
				pos->SetX( vj->X() + dx*u );
				pos->SetY( vj->Y() + dy*u );
				pos->SetZ( vj->Z() + dz*u );
				pos->SetY( getHeight(pos->X(),pos->Y(),pos->Z(), cs, ics, chf.ch, hp)*chf.ch );
			}
			// Simplify samples.
			int idx[MAX_VERTS_PER_EDGE] = {0,nn};
			int nidx = 2;
			for (int k = 0; k < nidx-1; )
			{
				const int a = idx[k];
				const int b = idx[k+1];
				const dtCoordinates va( edge[a] );
				const dtCoordinates vb( edge[b] );
				// Find maximum deviation along the segment.
				float maxd = 0;
				int maxi = -1;
				for (int m = a+1; m < b; ++m)
				{
					float dev = distancePtSeg(edge[m],va,vb);
					if (dev > maxd)
					{
						maxd = dev;
						maxi = m;
					}
				}
				// If the max deviation is larger than accepted error,
				// add new point, else continue to next segment.
//.........这里部分代码省略.........
开发者ID:infini,项目名称:_task,代码行数:101,代码来源:RecastMeshDetail.cpp

示例12: buildPolyDetail

static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
							const float sampleDist, const float sampleMaxError,
							const int heightSearchRadius, const rcCompactHeightfield& chf,
							const rcHeightPatch& hp, float* verts, int& nverts,
							rcIntArray& tris, rcIntArray& edges, rcIntArray& samples)
{
	static const int MAX_VERTS = 127;
	static const int MAX_TRIS = 255;	// Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts).
	static const int MAX_VERTS_PER_EDGE = 32;
	float edge[(MAX_VERTS_PER_EDGE+1)*3];
	int hull[MAX_VERTS];
	int nhull = 0;
	
	nverts = nin;
	
	for (int i = 0; i < nin; ++i)
		rcVcopy(&verts[i*3], &in[i*3]);
	
	edges.resize(0);
	tris.resize(0);
	
	const float cs = chf.cs;
	const float ics = 1.0f/cs;
	
	// Calculate minimum extents of the polygon based on input data.
	float minExtent = polyMinExtent(verts, nverts);
	
	// Tessellate outlines.
	// This is done in separate pass in order to ensure
	// seamless height values across the ply boundaries.
	if (sampleDist > 0)
	{
		for (int i = 0, j = nin-1; i < nin; j=i++)
		{
			const float* vj = &in[j*3];
			const float* vi = &in[i*3];
			bool swapped = false;
			// Make sure the segments are always handled in same order
			// using lexological sort or else there will be seams.
			if (fabsf(vj[0]-vi[0]) < 1e-6f)
			{
				if (vj[2] > vi[2])
				{
					rcSwap(vj,vi);
					swapped = true;
				}
			}
			else
			{
				if (vj[0] > vi[0])
				{
					rcSwap(vj,vi);
					swapped = true;
				}
			}
			// Create samples along the edge.
			float dx = vi[0] - vj[0];
			float dy = vi[1] - vj[1];
			float dz = vi[2] - vj[2];
			float d = sqrtf(dx*dx + dz*dz);
			int nn = 1 + (int)floorf(d/sampleDist);
			if (nn >= MAX_VERTS_PER_EDGE) nn = MAX_VERTS_PER_EDGE-1;
			if (nverts+nn >= MAX_VERTS)
				nn = MAX_VERTS-1-nverts;
			
			for (int k = 0; k <= nn; ++k)
			{
				float u = (float)k/(float)nn;
				float* pos = &edge[k*3];
				pos[0] = vj[0] + dx*u;
				pos[1] = vj[1] + dy*u;
				pos[2] = vj[2] + dz*u;
				pos[1] = getHeight(pos[0],pos[1],pos[2], cs, ics, chf.ch, heightSearchRadius, hp)*chf.ch;
			}
			// Simplify samples.
			int idx[MAX_VERTS_PER_EDGE] = {0,nn};
			int nidx = 2;
			for (int k = 0; k < nidx-1; )
			{
				const int a = idx[k];
				const int b = idx[k+1];
				const float* va = &edge[a*3];
				const float* vb = &edge[b*3];
				// Find maximum deviation along the segment.
				float maxd = 0;
				int maxi = -1;
				for (int m = a+1; m < b; ++m)
				{
					float dev = distancePtSeg(&edge[m*3],va,vb);
					if (dev > maxd)
					{
						maxd = dev;
						maxi = m;
					}
				}
				// If the max deviation is larger than accepted error,
				// add new point, else continue to next segment.
				if (maxi != -1 && maxd > rcSqr(sampleMaxError))
				{
					for (int m = nidx; m > k; --m)
//.........这里部分代码省略.........
开发者ID:090809,项目名称:TrinityCore,代码行数:101,代码来源:RecastMeshDetail.cpp

示例13: SplitAndStoreLayerRegions


//.........这里部分代码省略.........
		{
			if (!regs[i].remap)
				continue;
			unsigned short oldId = regs[i].layerId;
			unsigned short newId = ++layerId;
			for (int j = i; j < nregs; ++j)
			{
				if (regs[j].layerId == oldId)
				{
					regs[j].layerId = newId;
					regs[j].remap = false;
				}
			}
		}
	}

	// No layers, return empty.
	if (layerId == 0)
	{
		ctx->stopTimer(RC_TIMER_BUILD_LAYERS);
		return true;
	}

	// Create layers.
	rcAssert(lset.layers == 0);

	const int w = chf.width;
	const int h = chf.height;
	const int lw = w - borderSize*2;
	const int lh = h - borderSize*2;

	// Build contracted bbox for layers.
	float bmin[3], bmax[3];
	rcVcopy(bmin, chf.bmin);
	rcVcopy(bmax, chf.bmax);
	bmin[0] += borderSize*chf.cs;
	bmin[2] += borderSize*chf.cs;
	bmax[0] -= borderSize*chf.cs;
	bmax[2] -= borderSize*chf.cs;

	lset.nlayers = (int)layerId;

	lset.layers = (rcHeightfieldLayer*)rcAlloc(sizeof(rcHeightfieldLayer)*lset.nlayers, RC_ALLOC_PERM);
	if (!lset.layers)
	{
		ctx->log(RC_LOG_ERROR, "SplitAndStoreLayerRegions: Out of memory 'layers' (%d).", lset.nlayers);
		return false;
	}
	memset(lset.layers, 0, sizeof(rcHeightfieldLayer)*lset.nlayers);


	// Store layers.
	for (int i = 0; i < lset.nlayers; ++i)
	{
		unsigned short curId = (unsigned short)i;

		// Allocate memory for the current layer.
		rcHeightfieldLayer* layer = &lset.layers[i];
		memset(layer, 0, sizeof(rcHeightfieldLayer));

		const int gridSize = sizeof(unsigned char)*lw*lh;
		const int gridSize2 = sizeof(unsigned short)*lw*lh;

		layer->heights = (unsigned short*)rcAlloc(gridSize2, RC_ALLOC_PERM);
		if (!layer->heights)
		{
开发者ID:RandomDeveloperM,项目名称:UE4_Hairworks,代码行数:67,代码来源:RecastLayers.cpp

示例14: rcBuildHeightfieldLayers


//.........这里部分代码省略.........
	for (int i = 0; i < nreg; ++i)
	{
		if (!regions[i].remap)
			continue;
		unsigned short oldId = regions[i].layerId;
		unsigned short newId = maxLayerId;
		for (int j = i; j < nreg; ++j)
		{
			if (regions[j].layerId == oldId)
			{
				regions[j].layerId = newId;
				regions[j].remap = false;
			}
		}
		maxLayerId++;
	}

	ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER);

	if (maxLayerId == 0)
	{
		ctx->stopTimer(RC_TIMER_BUILD_LAYERS);
		return true;
	}

	// Create layers.
	rcAssert(lset.layers == 0);

	const int lw = w - borderSize*2;
	const int lh = h - borderSize*2;

	// Build contracted bbox for layers.
	float bmin[3], bmax[3];
	rcVcopy(bmin, chf.bmin);
	rcVcopy(bmax, chf.bmax);
	bmin[0] += borderSize*chf.cs;
	bmin[2] += borderSize*chf.cs;
	bmax[0] -= borderSize*chf.cs;
	bmax[2] -= borderSize*chf.cs;

	lset.nlayers = (int)maxLayerId;

	lset.layers = (rcHeightfieldLayer*)rcAlloc(sizeof(rcHeightfieldLayer)*lset.nlayers, RC_ALLOC_PERM);
	if (!lset.layers)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'layers' (%d).", lset.nlayers);
		return false;
	}
	memset(lset.layers, 0, sizeof(rcHeightfieldLayer)*lset.nlayers);


	// Store layers.
	for (int i = 0; i < lset.nlayers; ++i)
	{
		unsigned short curId = (unsigned short)i;

		// Allocate memory for the current layer.
		rcHeightfieldLayer* layer = &lset.layers[i];
		memset(layer, 0, sizeof(rcHeightfieldLayer));

		const int gridSize = sizeof(unsigned char)*lw*lh;
		const int gridSize2 = sizeof(unsigned short)*lw*lh;

		layer->heights = (unsigned short*)rcAlloc(gridSize2, RC_ALLOC_PERM);
		if (!layer->heights)
		{
开发者ID:RandomDeveloperM,项目名称:UE4_Hairworks,代码行数:67,代码来源:RecastLayers.cpp

示例15: rcVcopy

bool OgreDetourTileCache::configure(InputGeom *inputGeom)
{
    m_geom = inputGeom;

    // Reuse OgreRecast context for tiled navmesh building
    m_ctx = m_recast->m_ctx;

    if (!m_geom || m_geom->isEmpty()) {
        m_recast->m_pLog->logMessage("ERROR: OgreDetourTileCache::configure: No vertices and triangles.");
        return false;
    }

    if (!m_geom->getChunkyMesh()) {
        m_recast->m_pLog->logMessage("ERROR: OgreDetourTileCache::configure: Input mesh has no chunkyTriMesh built.");
        return false;
    }

    m_tmproc->init(m_geom);


    // Init cache bounding box
    const float* bmin = m_geom->getMeshBoundsMin();
    const float* bmax = m_geom->getMeshBoundsMax();

    // Navmesh generation params.
    // Use config from recast module
    m_cfg = m_recast->m_cfg;

    // Most params are taken from OgreRecast::configure, except for these:
    m_cfg.tileSize = m_tileSize;
    m_cfg.borderSize = (int) (m_cfg.walkableRadius + BORDER_PADDING); // Reserve enough padding.
    m_cfg.width = m_cfg.tileSize + m_cfg.borderSize*2;
    m_cfg.height = m_cfg.tileSize + m_cfg.borderSize*2;

    // Set mesh bounds
    rcVcopy(m_cfg.bmin, bmin);
    rcVcopy(m_cfg.bmax, bmax);
    // Also define navmesh bounds in recast component
    rcVcopy(m_recast->m_cfg.bmin, bmin);
    rcVcopy(m_recast->m_cfg.bmax, bmax);

    // Cell size navmesh generation property is copied from OgreRecast config
    m_cellSize = m_cfg.cs;

    // Determine grid size (number of tiles) based on bounding box and grid cell size
    int gw = 0, gh = 0;
    rcCalcGridSize(bmin, bmax, m_cellSize, &gw, &gh);   // Calculates total size of voxel grid
    const int ts = m_tileSize;
    const int tw = (gw + ts-1) / ts;    // Tile width
    const int th = (gh + ts-1) / ts;    // Tile height
    m_tw = tw;
    m_th = th;
    Ogre::LogManager::getSingletonPtr()->logMessage("Total Voxels: "+Ogre::StringConverter::toString(gw) + " x " + Ogre::StringConverter::toString(gh));
    Ogre::LogManager::getSingletonPtr()->logMessage("Tilesize: "+Ogre::StringConverter::toString(m_tileSize)+"  Cellsize: "+Ogre::StringConverter::toString(m_cellSize));
    Ogre::LogManager::getSingletonPtr()->logMessage("Tiles: "+Ogre::StringConverter::toString(m_tw)+" x "+Ogre::StringConverter::toString(m_th));


    // Max tiles and max polys affect how the tile IDs are caculated.
    // There are 22 bits available for identifying a tile and a polygon.
    int tileBits = rcMin((int)dtIlog2(dtNextPow2(tw*th*EXPECTED_LAYERS_PER_TILE)), 14);
    if (tileBits > 14) tileBits = 14;
    int polyBits = 22 - tileBits;
    m_maxTiles = 1 << tileBits;
    m_maxPolysPerTile = 1 << polyBits;
    Ogre::LogManager::getSingletonPtr()->logMessage("Max Tiles: " + Ogre::StringConverter::toString(m_maxTiles));
    Ogre::LogManager::getSingletonPtr()->logMessage("Max Polys: " + Ogre::StringConverter::toString(m_maxPolysPerTile));


    // Tile cache params.
    memset(&m_tcparams, 0, sizeof(m_tcparams));
    rcVcopy(m_tcparams.orig, bmin);
    m_tcparams.width = m_tileSize;
    m_tcparams.height = m_tileSize;
    m_tcparams.maxTiles = tw*th*EXPECTED_LAYERS_PER_TILE;
    m_tcparams.maxObstacles = MAX_OBSTACLES;    // Max number of temp obstacles that can be added to or removed from navmesh

    // Copy the rest of the parameters from OgreRecast config
    m_tcparams.cs = m_cfg.cs;
    m_tcparams.ch = m_cfg.ch;
    m_tcparams.walkableHeight = (float) m_cfg.walkableHeight;
    m_tcparams.walkableRadius = (float) m_cfg.walkableRadius;
    m_tcparams.walkableClimb = (float) m_cfg.walkableClimb;
    m_tcparams.maxSimplificationError = m_cfg.maxSimplificationError;

    return initTileCache();
}
开发者ID:k300021,项目名称:OgreFireworksimulation,代码行数:86,代码来源:OgreDetourTileCache.cpp


注:本文中的rcVcopy函数示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。