// 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 "stdpch.h" #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