#ifndef SENSORCELLMAP_HPP #define SENSORCELLMAP_HPP #pragma warning(disable : 4284) #pragma warning(push) #include #include #pragma warning(pop) class SensorCellMap { public: SensorCellMap() { } ~SensorCellMap() { } typedef stlport::slist list_type; typedef stlport::vector checksum_type; class Cell { public: Cell() : m_Checksum(0) { } list_type::const_iterator begin() { return (entries.begin()); } list_type::const_iterator end() { return (entries.end()); } void Add(MechWarrior4::MWObject* ptr) { Verify(std::find(begin(),end(),ptr) == end()); entries.insert(entries.begin(),ptr); RecalcChecksum(); } void Remove(MechWarrior4::MWObject* ptr) { Verify(std::find(begin(),end(),ptr) != end()); entries.remove(ptr); RecalcChecksum(); } void RecalcChecksum() { m_Checksum = entries.size() << 24; {for (list_type::const_iterator i = begin(); i != end(); ++i) { m_Checksum += ((*i)->objectID & 0x00FFFFFF); }} } int GetChecksum() const { return (m_Checksum); } private: stlport::slist entries; int m_Checksum; }; Cell& GetCell(int x, int z) { Verify(x >= 0); Verify(x < WIDTH); Verify(z >= 0); Verify(z < HEIGHT); return (m_Entries[x][z]); } void Fill(int x1, int z1, int x2, int z2, list_type& output, checksum_type& checksums) { {for (int i_x = x1; i_x <= x2; ++i_x) { {for (int i_z = z1; i_z <= z2; ++i_z) { Cell& cell = GetCell(i_x,i_z); {for (list_type::const_iterator i = cell.begin(); i != cell.end(); ++i) { output.insert(output.begin(),*i); }} checksums.push_back(cell.GetChecksum()); }} }} } int CellIndex(Stuff::Scalar pos) { Verify(CELL_WIDTH == 256); Verify(CELL_HEIGHT == 256); int p((int)(pos + (Scalar)COORD_ADD)); return (p >> 8); } void ClampIndex(int& index, int min, int max) { if (index < min) { index = min; } else { if (index > max) { index = max; } } } void GetCellPos(int& x, int& z, const Stuff::LinearMatrix4D& local_to_world) { x = CellIndex(local_to_world(W_Axis, X_Axis)); z = CellIndex(local_to_world(W_Axis, Z_Axis)); ClampIndex(x,0,WIDTH - 1); ClampIndex(z,0,HEIGHT - 1); } void GetRect(int& x1, int& z1, int& x2, int& z2, const Stuff::LinearMatrix4D& local_to_world, Stuff::Scalar radius) { Scalar x = local_to_world(W_Axis, X_Axis); Scalar z = local_to_world(W_Axis, Z_Axis); Scalar _x1 = x - radius; if (_x1 < (Stuff::Scalar)LEFT_BOUNDS) { _x1 = (Stuff::Scalar)LEFT_BOUNDS; } x1 = CellIndex(_x1); Scalar _x2 = x + radius; if (_x2 >= (Stuff::Scalar)RIGHT_BOUNDS) { _x2 = (Stuff::Scalar)RIGHT_BOUNDS; } x2 = CellIndex(_x2); Scalar _z1 = z - radius; if (_z1 < (Stuff::Scalar)TOP_BOUNDS) { _z1 = (Stuff::Scalar)TOP_BOUNDS; } z1 = CellIndex(_z1); Scalar _z2 = z + radius; if (_z2 >= (Stuff::Scalar)BOTTOM_BOUNDS) { _z2 = (Stuff::Scalar)BOTTOM_BOUNDS; } z2 = CellIndex(_z2); } void Fill(const Stuff::LinearMatrix4D& local_to_world, Stuff::Scalar radius, list_type& output, checksum_type& checksums) { checksums.clear(); int x1, z1, x2, z2; GetRect(x1,z1,x2,z2,local_to_world,radius); Fill(x1,z1,x2,z2,output,checksums); } bool ChecksumMatches(const Stuff::LinearMatrix4D& local_to_world, Stuff::Scalar radius, checksum_type& checksums) { int x1, z1, x2, z2; GetRect(x1,z1,x2,z2,local_to_world,radius); if (checksums.size() != (x2 - x1 + 1) * (z2 - z1 + 1)) { return (false); } checksum_type::const_iterator i_checksum = checksums.begin(); {for (int i_x = x1; i_x <= x2; ++i_x) { {for (int i_z = z1; i_z <= z2; ++i_z) { // TODO: REWRITE THIS BEFORE CHECKING IN!!! Cell& cell = GetCell(i_x,i_z); if (cell.GetChecksum() != *(i_checksum)) { return (false); } ++i_checksum; }} }} return (true); } void Add(MechWarrior4::MWObject* ptr, int x, int z) { Cell& cell = GetCell(x,z); cell.Add(ptr); } void Add(MechWarrior4::MWObject* ptr, const Stuff::LinearMatrix4D& local_to_world) { int x, z; GetCellPos(x,z,local_to_world); Add(ptr,x,z); } void Remove(MechWarrior4::MWObject* ptr, int x, int z) { Cell& cell = GetCell(x,z); cell.Remove(ptr); } void Remove(MechWarrior4::MWObject* ptr, const Stuff::LinearMatrix4D& local_to_world) { int x, z; GetCellPos(x,z,local_to_world); Remove(ptr,x,z); } private: enum { CELL_WIDTH = 256 }; enum { CELL_HEIGHT = CELL_WIDTH }; enum { WIDTH = 20 }; enum { HEIGHT = 20 }; enum { COORD_ADD = 2560 }; enum { GRID_WIDTH = WIDTH * CELL_WIDTH }; enum { GRID_HEIGHT = HEIGHT * CELL_HEIGHT }; enum { LEFT_BOUNDS = -COORD_ADD + 1 }; enum { TOP_BOUNDS = -COORD_ADD + 1 }; enum { RIGHT_BOUNDS = COORD_ADD - 1 }; enum { BOTTOM_BOUNDS = COORD_ADD - 1 }; Cell m_Entries[WIDTH][HEIGHT]; }; #endif // SENSORCELLMAP_HPP