Hi,
I'm trying to create 'bit keys' for my renderables, to be able to sort them in an order I want.
I got so far that I can create the keys and retrieve information from them, they're even sorted.
Unfortunately thery're sorted on 'mesh'.
Can someome try to help me out on how to sort them based on:
1 - matgroup, then
2 - material
3 - then mesh
4 - then distance
Any input is appreciated, here's the test app source.
#include <Windows.h>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <string>
#include <vector>
typedef struct Q_RENDERABLE
{
int MatGroup;
int Material;
int Mesh;
int Instance;
int Id;
bool Visible;
float DistToCamSqr;
// testing
int DistToCamConv;
} Q_RENDERABLE;
std::vector<Q_RENDERABLE> tRenderables;
std::vector<int> tIndexUnsorted;
std::vector<int> tIndexSorted;
std::vector<UINT64> tBitKeys;
bool Setup(const std::string pFilename);
bool CreateIndexUnsorted();
bool CreateBitKeys();
bool SortKeys();
bool OutputResults(const std::string pFilename);
bool loaded = false;
bool created = false;
bool bitKeysCreated = false;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
if(!Setup("testbucket.txt")) return 0;
if(!CreateIndexUnsorted()) return 0;
if(!CreateBitKeys()) return 0;
if(!SortKeys()) return 0;
if(!OutputResults("indices.txt")) return 0;
return 1;
}
/*** LOAD THE TEST RENDERABLES'S DATA - ASSUMING ALL VISIBLE FOR TESTING ***/
bool Setup(const std::string pFilename)
{
std::ifstream readFile(pFilename);
if(!readFile) return false;
Q_RENDERABLE tempRend;
tRenderables.resize(0);
char temp[255];
for(int j=0;j<6;++j) readFile >> temp;
bool done = false;
while(!done)
{
readFile >> tempRend.Id;
if(tempRend.Id == 9999) break;
readFile >> tempRend.MatGroup;
readFile >> tempRend.Material;
readFile >> tempRend.Mesh;
readFile >> tempRend.Instance;
readFile >> tempRend.DistToCamSqr;
tempRend.Visible = true;
tRenderables.push_back(tempRend);
}
readFile.close();
loaded = true;
return true;
}
/*** ADD INDICIES OF ALL VISIBLE RENDERABLES TO 'UNSORTED' INDEX OF RENDERABLES = BUCKET ***/
bool CreateIndexUnsorted()
{
if(!loaded) return false;
tIndexUnsorted.resize(0);
for(size_t rend=0;rend<tRenderables.size();++rend)
{
if(tRenderables[rend].Visible) tIndexUnsorted.push_back(rend);
}
created = true;
return true;
}
bool CreateBitKeys()
{
if(!loaded) return false;
// USE A 64 BIT SORTING KEY: 44 BITS NEEDED FOR NOW
// 4 bits: material group (range 0 - 16)
// 8 bits: materal ID (range 0 - 255)
// 8 bits: mesh ID (range 0 - 255)
// 16 bits: mesh inst ID (range 0 - 2048)
// 8 bits: dist to cam (range 0 - 255) => needs conversion
// convert dists to cam, testing (define max and then convert)
float maxDist = tRenderables[0].DistToCamSqr;
for(size_t rend=1;rend<tRenderables.size();++rend)
{
if(tRenderables[rend].DistToCamSqr > maxDist) maxDist = tRenderables[rend].DistToCamSqr;
}
// maxDist == 250
for(size_t rend=0;rend<tRenderables.size();++rend) tRenderables[rend].DistToCamConv = (int((250 * tRenderables[rend].DistToCamSqr) / maxDist));
// SET THE BITS AND CREATE THE SORTING KEYS
/* 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
MGRP MAT MESH INST INST DIST
MGRP << 40; 4 bits
MAT << 32; 8 bits
MESH << 24; 8 bits
INST << 8; 16 bits
DIST << 0; 8 bits
makeKey = ((0xFF & tr.MatGroup) << 40) | ((0xFF & tr.Mesh) << 32) | ((0xFF & tr.Instance) << 16) | ((0xFF & tr.DistToCamConv) << 8) | (0xFF & tr.Material);
*/
for(size_t rend=0;rend<tIndexUnsorted.size();++rend)
{
auto &tr = tRenderables[tIndexUnsorted[rend]];
UINT64 makeKey = 0;
makeKey = ((0xFF & tr.MatGroup) << 40) | ((0xFF & tr.Material) << 32) | ((0xFF & tr.Mesh) << 24) | ((0xFF & tr.Instance) << 8) | (0xFF & tr.DistToCamConv);
tBitKeys.push_back(makeKey);
}
bitKeysCreated = true;
return true;
}
/*** SORT THE KEYS AND CREATE A NEW SORTED INDEX ***/
bool SortKeys()
{
if(!bitKeysCreated) return false;
std::vector<int> tSortIndexTemp;
std::vector<UINT64> tSortKeysTemp;
tSortIndexTemp.resize(tIndexUnsorted.size());
for(size_t tIndex=0;tIndex<tIndexUnsorted.size();++tIndex) tSortIndexTemp[tIndex] = tIndex;
std::sort(tSortIndexTemp.begin(), tSortIndexTemp.end(), [&](int a, int b)
{ return tBitKeys[a] < tBitKeys[b]; } );
tIndexSorted.resize(tIndexUnsorted.size());
for(size_t sorted=0;sorted<tIndexUnsorted.size();++sorted)
tIndexSorted[sorted] = tSortIndexTemp[tIndexUnsorted[sorted]];
return true;
}
/*** SAVE ALL TEST RESULTS TO ASCII FILE ***/
bool OutputResults(const std::string pFilename)
{
if(!loaded || !created) return false;
std::ofstream oResult(pFilename);
// UNSORTED VISIBLE INDEX
oResult << "Unsorted (visible) index: " << std::endl;
for(size_t rend=0;rend<tIndexUnsorted.size();++rend)
{
oResult << tIndexUnsorted[rend] << std::endl;
}
// TESTING BITKEYS STORING & RETRIEVING
oResult << "Checking visible renderable 5" << std::endl;
oResult << tRenderables[tIndexUnsorted[5]].MatGroup << ", ";
oResult << tRenderables[tIndexUnsorted[5]].Material << ", ";
oResult << tRenderables[tIndexUnsorted[5]].Mesh << ", ";
oResult << tRenderables[tIndexUnsorted[5]].Instance << ", ";
oResult << tRenderables[tIndexUnsorted[5]].DistToCamConv << std::endl;
Q_RENDERABLE retrTest;
retrTest.MatGroup = (tBitKeys[tIndexUnsorted[5]] >> 40 & 0xFF);
retrTest.Material = (tBitKeys[tIndexUnsorted[5]] >> 32 & 0xFF);
retrTest.Mesh = (tBitKeys[tIndexUnsorted[5]] >> 24 & 0xFF);
retrTest.Instance = (tBitKeys[tIndexUnsorted[5]] >> 8 & 0xFF);
retrTest.DistToCamConv = (tBitKeys[tIndexUnsorted[5]] & 0xFF);
oResult << "Retrieved renderable 5: " << std::endl;
oResult << retrTest.MatGroup << ", ";
oResult << retrTest.Material << ", ";
oResult << retrTest.Mesh << ", ";
oResult << retrTest.Instance << ", ";
oResult << retrTest.DistToCamConv << std::endl;
oResult << std::endl;
oResult << "Sorted renderables using bit keys:" << std::endl;
oResult << "ID\tmatgrp\tmatl\tmesh\tinst\tdistsqr" << std::endl;
for(size_t rend=0;rend<tIndexSorted.size();++rend)
{
oResult << tRenderables[tIndexSorted[rend]].Id << "\t";
oResult << tRenderables[tIndexSorted[rend]].MatGroup << "\t";
oResult << tRenderables[tIndexSorted[rend]].Material << "\t";
oResult << tRenderables[tIndexSorted[rend]].Mesh << "\t";
oResult << tRenderables[tIndexSorted[rend]].Instance << "\t";
oResult << tRenderables[tIndexSorted[rend]].DistToCamSqr << std::endl;
}
oResult.close();
return true;
}
(it's actually just one cpp and will compile if you try:))