// NeL - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#include "std3d.h"
#include "nel/3d/landscape_collision_grid.h"
#include "nel/misc/fast_floor.h"
#include
using namespace std;
using namespace NLMISC;
namespace NL3D
{
// ***************************************************************************
CLandscapeCollisionGrid::CLandscapeCollisionGrid(CVisualCollisionManager *owner)
{
_Owner= owner;
// reset list to NULL.
memset(_Grid, 0, NL_COLGRID_SIZE*NL_COLGRID_SIZE * sizeof(CVisualTileDescNode*));
_Cleared= true;
// sizepower.
nlassert(isPowerOf2(NL_COLGRID_SIZE));
_SizePower= getPowerOf2(NL_COLGRID_SIZE);
}
// ***************************************************************************
CLandscapeCollisionGrid::~CLandscapeCollisionGrid()
{
clear();
}
// ***************************************************************************
void CLandscapeCollisionGrid::clear()
{
// already cleared? do nothing.
if(_Cleared)
return;
// Parse all quads.
sint i;
for(i=0;iNext;
_Owner->deleteVisualTileDescNode(ptr);
ptr= next;
}
// reset root.
_Grid[i]= NULL;
}
_Cleared= true;
}
// ***************************************************************************
struct CVector2i
{
sint x,y;
};
// ***************************************************************************
void CLandscapeCollisionGrid::build(const std::vector &quadBlocks, const CVector &delta)
{
sint x,y;
static CVector2i floorVals[NL_PATCH_BLOCK_MAX_VERTEX*NL_PATCH_BLOCK_MAX_VERTEX];
// first clear
clear();
// init for fast floor.
OptFastFloorBegin();
// then fill.
_Cleared= false;
_Delta= delta;
// parse all quad blocks.
for(sint i=0; i<(sint)quadBlocks.size();i++)
{
CPatchQuadBlock &qb= *quadBlocks[i];
sint lenS= qb.PatchBlockId.S1 - qb.PatchBlockId.S0;
sint lenT= qb.PatchBlockId.T1 - qb.PatchBlockId.T0;
// First, floor all vertices of interest.
for(y=0; y=0 && x1>=x0);
nlassert(y0>=0 && y1>=y0);
// first, transform coordinate (in meters) in quadgrid eltSize (ie 2 meters).
x0= (x0>>1); // floor().
x1= (x1>>1) + 1; // equivalent of ceil().
y0= (y0>>1); // floor().
y1= (y1>>1) + 1; // equivalent of ceil().
// setup bounds in quadgrid coordinate.
if(x1-x0>=NL_COLGRID_SIZE)
x0=0, x1= NL_COLGRID_SIZE;
else
{
x0&= NL_COLGRID_SIZE-1;
x1&= NL_COLGRID_SIZE-1;
if(x1<=x0)
x1+=NL_COLGRID_SIZE;
}
if(y1-y0>=NL_COLGRID_SIZE)
y0=0, y1= NL_COLGRID_SIZE;
else
{
y0&= NL_COLGRID_SIZE-1;
y1&= NL_COLGRID_SIZE-1;
if(y1<=y0)
y1+=NL_COLGRID_SIZE;
}
// fill all cases with element.
sint x,y;
for(y= y0;ynewVisualTileDescNode();
// fill elt.
elt->PatchQuadBlocId= paBlockId;
elt->QuadId= quadId;
// bind elt to the list.
elt->Next= _Grid[gridId];
_Grid[gridId]= elt;
}
}
}
// ***************************************************************************
CVisualTileDescNode *CLandscapeCollisionGrid::select(const NLMISC::CVector &pos)
{
// compute pos in the quadgrid.
CVector localPos;
localPos= pos + _Delta;
// cases are 2x2 meters.
localPos/=2;
// floor, bound in quadgrid coordinate.
sint x,y;
x= (sint)floor(localPos.x);
y= (sint)floor(localPos.y);
x&= NL_COLGRID_SIZE-1;
y&= NL_COLGRID_SIZE-1;
return _Grid[y*NL_COLGRID_SIZE+x];
}
} // NL3D