// Ryzom - 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 "patat_grid.h"
#include "nel/misc/aabbox.h"
#include "nel/misc/file.h"
#include "nel/misc/i_xml.h"
#include "nel/misc/path.h"
#include "nel/ligo/ligo_config.h"
using namespace std;
using namespace NLMISC;
using namespace NLLIGO;
extern NLLIGO::CLigoConfig LigoConfig;
/*
* Constructor
*/
CPatatGrid::CPatatGrid()
{
}
/*
* Destructor
*/
CPatatGrid::~CPatatGrid()
{
}
/*
* Init patat grid
*/
void CPatatGrid::init()
{
// allocate 1 free entry (for no zone entry)
_PrimZones.resize(1);
_EntryTable.resize(1);
_SelectGrid.clear();
_ZoneMap.clear();
_FlagTable.clear();
_EntryMap.clear();
_FreeEntries.clear();
nlinfo("Initialized CPatatGrid, move grid is 1024x1024 uint16 (%.2f Mb)", (float)(sizeof(TEntryIndex)*1024*1024)/(1024.0f*1024.0f));
}
void CPatatGrid::readPrimitive(IPrimitive *primitive, std::vector &inFile)
{
if (dynamic_cast(primitive) != NULL)
{
// check good class
string primName;
string className;
if (primitive->getPropertyByName("name", primName) &&
primitive->getPropertyByName("class", className) &&
_PrimZoneFilters.find(className) != _PrimZoneFilters.end())
{
_ZoneMap.insert(TZoneMap::value_type(primName, (sint32)_PrimZones.size()));
inFile.push_back((uint32)_PrimZones.size());
_PrimZones.push_back(static_cast(*primitive));
// _PrimZones.back().Name = primName;
}
}
// parse children
uint i;
for (i=0; igetNumChildren(); ++i)
{
IPrimitive *child;
if (!primitive->getChild(child, i))
continue;
readPrimitive(child, inFile);
}
}
/*
* Use patat prim file
*/
void CPatatGrid::usePrim(const string &primFile, std::vector &inFile)
{
/*
CIFile f(CPath::lookup(primFile));
CPrimRegion region;
CIXml xml;
xml.init(f);
region.serial(xml);
nlinfo("Loaded prim file '%s'", primFile.c_str());
uint i;
uint firstPrimZone = _PrimZones.size();
inFile.clear();
for (i=0; i xmax) xmax = zone.VPoints[j].x;
if (zone.VPoints[j].y > ymax) ymax = zone.VPoints[j].y;
}
xmin = _SelectGrid.round(xmin);
ymin = _SelectGrid.round(ymin);
xmax = _SelectGrid.round(xmax);
ymax = _SelectGrid.round(ymax);
nlinfo("Sampling %d/%d (%d samples)", i-firstPrimZone+1, _PrimZones.size()-firstPrimZone, (sint)((xmax-xmin)/PatatGridResolution * (ymax-ymin)/PatatGridResolution));
// sample zone
for (y=ymin; y<=ymax; y+=PatatGridResolution)
{
for (x=xmin; x<=xmax; x+=PatatGridResolution)
{
CVector v((float)x, (float)y, 0.0f);
// check sampled point belongs to the patat
if (!zone.contains(v))
continue;
// get the entry index for this point
TEntryIndex index = (TEntryIndex)getEntryIndex(v);
CEntry &entry = _EntryTable[index];
// compute the new hash code for this point
// basically, hash is previous hash code times zone number
//uint32 hash = (index == 0) ? i : entry.HashCode * i;
// other hash function, assuming index0 entry has 0 hashcode.
uint32 hash = (entry.HashCode<<4) + (entry.HashCode>>28) + i;
pair range;
TEntryMap::iterator it;
// get all entries with this hash code
range = _EntryMap.equal_range(hash);
// check if selected entries match the new point
for (it=range.first; it!=range.second; ++it)
{
CEntry &selected = _EntryTable[(*it).second];
// selected must have one zone more than entry
if (selected.Zones.size() != entry.Zones.size()+1)
continue;
uint k;
for (k=0; k= maxGridEntryIndex)
{
nlerror("Error in PatatGrid build, type 'TEntryIndex' too short (%d bytes), use wider type !", sizeof(TEntryIndex));
}
CEntry &newEntry = _EntryTable[newIndex];
// inits new entry
newEntry.EntryIndex = (TEntryIndex)newIndex;
newEntry.HashCode = hash;
newEntry.NumSamples = 1;
newEntry.Zones = entry.Zones;
newEntry.Zones.push_back(i);
// add entry to map
_EntryMap.insert(TEntryMap::value_type(hash, (TEntryIndex)newIndex));
// points point to new entry
setEntryIndex(v, newEntry.EntryIndex);
}
}
}
}
}
/*
* build patat grid
*/
bool CPatatGrid::diff(TEntryIndex previous, TEntryIndex next, vector &in, vector &out)
{
if (previous >= _EntryTable.size())
{
nlwarning("Entry index %d out of bounds, assume empty zone", previous);
previous = 0;
}
if (next >= _EntryTable.size())
{
nlwarning("Entry index %d out of bounds, assume empty zone", next);
next = 0;
}
in.clear();
out.clear();
if (previous == next)
return false;
CEntry &p = _EntryTable[previous];
CEntry &n = _EntryTable[next];
uint i;
// flag all of previous
for (i=0; i