本文整理汇总了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;
}
}
示例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);
//.........这里部分代码省略.........
示例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);
示例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(¶ms);
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;
//.........这里部分代码省略.........
示例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];
//.........这里部分代码省略.........
示例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;
}
}
示例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;
//.........这里部分代码省略.........
示例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(¶ms, 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(¶ms);
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))
//.........这里部分代码省略.........
示例9: handleClick
virtual void handleClick(const float* /*s*/, const float* p, bool /*shift*/)
{
m_hitPosSet = true;
rcVcopy(m_hitPos,p);
}
示例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;
}
示例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.
//.........这里部分代码省略.........
示例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)
//.........这里部分代码省略.........
示例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)
{
示例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)
{
示例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();
}