Heres quadtree pvs system
#ifndef ocean_pvs_systemH
#define ocean_pvs_systemH
#include "DxcMath.h"
#include "DxcMatrix.h"
#include "frustum.h"
#include "glwrapper.h"
#include "shaderclass.h"
struct TOceanPVSCell
{
Pushort * indices; //each row corresponds to each row in the ocean
int len; //both dimensions of an array
int ilen;
unsigned int * elementbuff;
bool add2;
int x;
int z;
//points of grid (adding translation will give correct worldspace pos)
vec3 A;
vec3 B;
vec3 C;
vec3 D;
TOceanPVSCell()
{
add2 = false;
indices = NULL;
elementbuff = NULL;
len = 0;
}
~TOceanPVSCell()
{
if (indices != NULL)
{
delete [] indices;
for (int i=0; i < len; i++)
glDeleteBuffers(1, &elementbuff[i]);
delete [] elementbuff;
}
}
};
struct TOceanPVS
{
float pvs_cell_size;
TFrustum EYE;
TOceanPVSCell * cells;
int sectors;
int sim_grid_size;
int * vis[9]; //each direction, that stores visible pvs cells, because i first determine which i see then i draw them
int vislen[9];
bool visvis[9];
float ocean_grid_size;
int cells_in_sector;
vec3 A;
vec3 B;
vec3 C;
vec3 D;
TOceanPVS()
{
cells = NULL;
}
~TOceanPVS()
{
if (cells != NULL)
{
delete [] cells;
for (int i=0; i < 9; i++) delete [] vis[i];
}
}
bool TGridVisible(int translation_index, int X, int Z)
{
float DirX[9] = {0.0, -1.0, 1.0, 0.0, 0.0, -1.0, 1.0, -1.0, 1.0};
float DirY[9] = {0.0, 0.0, 0.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0};
vec3 t = vec3(ocean_grid_size*float(X), 0.0, ocean_grid_size*float(Z));
vec3 v[4];
v[0] = A + vec3(ocean_grid_size*DirX[translation_index], 0.0, ocean_grid_size*DirY[translation_index]) + t;
v[1] = B + vec3(ocean_grid_size*DirX[translation_index], 0.0, ocean_grid_size*DirY[translation_index]) + t;
v[2] = C + vec3(ocean_grid_size*DirX[translation_index], 0.0, ocean_grid_size*DirY[translation_index]) + t;
v[3] = D + vec3(ocean_grid_size*DirX[translation_index], 0.0, ocean_grid_size*DirY[translation_index]) + t;
return EYE.BoxIsVisible(v, 4);
}
bool PVSCellVisible(int index, int translation_index, int X, int Z)
{
float DirX[9] = {0.0, -1.0, 1.0, 0.0, 0.0, -1.0, 1.0, -1.0, 1.0};
float DirY[9] = {0.0, 0.0, 0.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0};
vec3 t = vec3(ocean_grid_size*float(X), 0.0, ocean_grid_size*float(Z));
vec3 v[4];
v[0] = cells[index].A + vec3(ocean_grid_size*DirX[translation_index], 0.0, ocean_grid_size*DirY[translation_index]) + t;
v[1] = cells[index].B + vec3(ocean_grid_size*DirX[translation_index], 0.0, ocean_grid_size*DirY[translation_index]) + t;
v[2] = cells[index].C + vec3(ocean_grid_size*DirX[translation_index], 0.0, ocean_grid_size*DirY[translation_index]) + t;
v[3] = cells[index].D + vec3(ocean_grid_size*DirX[translation_index], 0.0, ocean_grid_size*DirY[translation_index]) + t;
return EYE.BoxIsVisible(v, 4);
}
void CalculatePVS(int X, int Z, TSpecCamera * FPP_CAM, mat4 CAM_VIEW, int sw, int sh, float fovy, float z_near, float z_far, float aspect)
{
EYE.CalcFrustum(FPP_CAM,CAM_VIEW, sw, sh, fovy, z_near, z_far, aspect);
vec3 v[4];
v[0] = vec3(0.0, 0.0, 0.0);
v[1] = vec3(400.0, 0.0, 0.0);
v[2] = vec3(400.0, 0.0, 400.0);
v[3] = vec3(0.0, 0.0, 400.0);
int h = 0;
//ALOG("NEW PVS FRAME");
for (int i=0; i < 9; i++)
{
visvis[i] = TGridVisible(i, X, Z);
// if (visvis) h = h + 1;
vislen[i] = -1;
}
for (int i=0; i < 9; i++)
if (visvis[i])
{
for (int n=0; n < sectors*sectors; n++)
if (PVSCellVisible(n, i, X, Z))
{
vislen[i] = vislen[i] + 1;
vis[i][vislen[i]] = n;
}
}
for (int i=0; i < 9; i++) vislen[i] = vislen[i] + 1;
//for (int i=0; i < 9; i++)
//ALOG("VIS: "+IntToStr(i) + " "+IntToStr(vislen)+ " pvs cells visible");
}
void DrawOceanPVS(TShaderObject * shader, int X, int Z)
{
float DirX[9] = {0.0, -1.0, 1.0, 0.0, 0.0, -1.0, 1.0, -1.0, 1.0};
float DirY[9] = {0.0, 0.0, 0.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0};
for (int i=0; i < 9; i++)
if (visvis[i])
{
vec3 t = vec3(DirX[i]*float(ocean_grid_size), 0.0, DirY[i]*float(ocean_grid_size)) +
vec3(float(X)*ocean_grid_size, 0.0, float(Z)*ocean_grid_size);
mat4 wrld;
wrld.LoadIdentity();
wrld.TranslateP(t);
shader->SendWorldMatrixtoShader(wrld);
mat4 MVP = (wrld * ACTUAL_VIEW) * ACTUAL_PROJECTION;
shader->SendMVPtoShader(MVP);
for (int n=0; n < vislen[i]; n++)
{
int celli = vis[i][n];
int len = cells[celli].len * 2;
if (cells[celli].add2) len = len + 2;
for (int k=0; k < cells[celli].len; k++)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cells[celli].elementbuff[k]);
glDrawElements(GL_TRIANGLE_STRIP, GLsizei(len), GL_UNSIGNED_SHORT,
(void*)( 0 ) );
}
}
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
int ArrI(int x, int y)
{
return y*sim_grid_size + x;
}
int pvsI(int x, int y)
{
return y*sectors + x;
}
void Initialize(int sections, float oc_grid_size, int sim_grd_size)
{
CAN_LOG = false;
sim_grid_size = sim_grd_size;
ocean_grid_size = oc_grid_size;
// OCEAN_TEX_GRID_SIZE
for (int i=0; i < 9; i++)
{
vislen[i] = 0;
visvis[i] = false;
vis[i] = new int[sections*sections];
}
sectors = sections;
cells_in_sector = sim_grid_size / sections; //64 / 8 = 8
cells = new TOceanPVSCell[sections * sections]; //8 * 8 = 64
B.x = oc_grid_size;
C.x = oc_grid_size;
C.z = oc_grid_size;
D.z = oc_grid_size;
ALOG("1");
pvs_cell_size = float(oc_grid_size) / sectors;
for (int y = 0; y < sim_grid_size; y++)
for (int x = 0; x < sim_grid_size; x++)
{
int sectionX = x / cells_in_sector;
int sectionY = y / cells_in_sector;
int row = y % cells_in_sector;
int col = x % cells_in_sector;
int pvsi = pvsI(sectionX, sectionY);
cells[pvsi].x = sectionX;
cells[pvsi].z = sectionY;
}
//ALOG("2");
for (int y = 0; y < sections; y++)
for (int x = 0; x < sections; x++)
{
float xper = float(x) / float(sections);
float yper = float(y) / float(sections);
float x2per = float(x+1) / float(sections);
float y2per = float(y+1) / float(sections);
int pvsi = pvsI(x, y);
//ALOG("VXX: "+IntToStr(cells[pvsi].x)+ " y: "+IntToStr(cells[pvsi].z));
cells[pvsi].A.x = xper * ocean_grid_size;
cells[pvsi].A.z = yper * ocean_grid_size;
cells[pvsi].B.x = x2per * ocean_grid_size;
cells[pvsi].B.z = yper * ocean_grid_size;
cells[pvsi].C.x = x2per * ocean_grid_size;
cells[pvsi].C.z = y2per * ocean_grid_size;
cells[pvsi].D.x = xper * ocean_grid_size;
cells[pvsi].D.z = y2per * ocean_grid_size;
}
//ALOG("3");
for (int i=0; i < sections*sections; i++)
{
int alen = cells_in_sector;
// if (cells.z == sections-1) alen = alen - 1;
cells[i].len = alen;
cells[i].indices = new Pushort[cells[i].len];
cells[i].elementbuff = new unsigned int[cells[i].len];
bool add2 = true;
if (cells[i].x == sections-1) add2 = false;
int k = 2;
if (!add2) k = 0;
cells[i].ilen = cells_in_sector*2+k;
for (int n=0; n < cells[i].len; n++)
{
cells[i].indices[n] = new unsigned short[cells[i].ilen];
cells[i].add2 = add2;
}
}
for (int n=0; n < sectors*sectors; n++)
for (int i=0; i < cells[n].len; i++)
for (int j=0; j < cells[n].ilen; j++)
cells[n].indices[i][j] = 0;
//ALOG("4");
for (int y = 0; y < sim_grid_size-1; y++)
for (int x = 0; x < sim_grid_size; x++)
{
int sectionX = x / cells_in_sector;
int sectionY = y / cells_in_sector;
int row = y % cells_in_sector;
int col = x % cells_in_sector;
int pvsi = pvsI(sectionX, sectionY);
cells[pvsi].x = sectionX;
cells[pvsi].z = sectionY;
cells[pvsi].indices[row][col*2] = (unsigned short)ArrI(x,y+1);
cells[pvsi].indices[row][col*2+1] = (unsigned short)ArrI(x,y);
//ArrI(x,y);
//return y*sim_grid_size + x;
//ALOG("CXX x: "+IntToStr(x)+ " y: "+IntToStr(y));
//last element needs additional 2 indices from next first, do not do that for last column
if ( (col == cells_in_sector-1) && (sectionX != sectors - 1) )
{
if (!cells[pvsi].add2) ALOG("SOMETHING BAD IS HAPPENING");
cells[pvsi].indices[row][col*2 + 2] = (unsigned short)ArrI(x+1,y+1);
cells[pvsi].indices[row][col*2+1 + 2] = (unsigned short)ArrI(x+1,y);
// ALOG("BXX: x2y2"+IntToStr(ArrI(x+1,y+1)) + " x2y1 :"+IntToStr(ArrI(x+1,y)) +" x: "+IntToStr(x+1)+ " y: "+IntToStr(y+1));
}
}
//ALOG("5");
//flush to gpu
for (int n=0; n < sectors*sectors; n++)
{
int k = 0;
if (cells[n].add2) k = 2;
for (int i=0; i < cells[n].len; i++)
{
glGenBuffers(1, &cells[n].elementbuff[i]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cells[n].elementbuff[i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, cells[n].ilen * sizeof(unsigned short), cells[n].indices[i], GL_STATIC_DRAW);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//ALOG("6");
for (int n=0; n < sectors*sectors; n++)
{
// ALOG("cell len: "+IntToStr(cells[n].len) + " additional 2: "+booltostring(cells[n].add2));
AnsiString indi;
for (int i=0; i < cells[n].len; i++)
{
indi = "";
int ylen = cells[n].len * 2;
if (cells[n].add2) ylen = ylen + 2;
for (int j=0; j < ylen; j++)
indi = indi + " " + IntToStr(int(cells[n].indices[i][j]));
//ALOG("cx: "+IntToStr(cells[n].x)+ " cy: "+IntToStr(cells[n].z)+ " Indices: "+indi);
}
}
}
};
#endif