pixelcity/Visible.cpp

133 lines
4.0 KiB
C++

/*-----------------------------------------------------------------------------
Visible.cpp
2009 Shamus Young
-------------------------------------------------------------------------------
This module runs the visibility grid, a 2-dimensional array that aids in
culling objects during rendering.
There are many ways this could be refined or sped up, although tests indicate
it's not a huge drain on performance.
-----------------------------------------------------------------------------*/
#include <windows.h>
#include <math.h>
#include "glTypes.h"
#include "camera.h"
#include "macro.h"
#include "math.h"
#include "visible.h"
#include "world.h"
#include "win.h"
static bool vis_grid[GRID_SIZE][GRID_SIZE];
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
bool Visible (GLvector pos)
{
return vis_grid[WORLD_TO_GRID(pos.x)][WORLD_TO_GRID(pos.z)];
}
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
bool Visible (int x, int z)
{
return vis_grid[x][z];
}
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
void VisibleUpdate (void)
{
GLvector angle;
GLvector position;
int x, y, grid_x, grid_z;
int left, right, front, back;
float angle_to;
float angle_diff;
float target_x, target_z;
//Clear the visibility table
ZeroMemory (vis_grid, sizeof (vis_grid));
//Calculate which cell the camera is in
angle = CameraAngle ();
position = CameraPosition ();
grid_x = WORLD_TO_GRID(position.x);
grid_z = WORLD_TO_GRID(position.z);
//Cells directly adjactent to the camera might technically fall out of the fov,
//but still have a few objects poking into screenspace when looking up or down.
//Rather than obsess over sorting those objects properly, it's more efficient to
//just mark them visible.
left = right = front = back = 3;
//Looking north, can't see south.
if (angle.y < 45.0f || angle.y > 315.0f)
front = 0;
//Looking south, can't see north
if (angle.y > 135.0f && angle.y < 225.0f)
back = 0;
//Looking east, can't see west
if (angle.y > 45.0f && angle.y < 135.0f)
left = 0;
//Looking west, can't see east
if (angle.y > 225.0f && angle.y < 315.0f)
right = 0;
//Now mark the block around us the might be visible
for (x = grid_x - left; x <= grid_x + right; x++) {
if (x < 0 || x >= GRID_SIZE) //just in case the camera leaves the world map
continue;
for (y = grid_z - back; y <= grid_z + front; y++) {
if (y < 0 || y >= GRID_SIZE) //just in case the camera leaves the world map
continue;
vis_grid[x][y] = true;
}
}
//Doesn't matter where we are facing, objects in current cell are always visible
vis_grid[grid_x][grid_z] = true;
//Here, we look at the angle from the current camera position to the cell
//on the grid, and how much that angle deviates from the current view angle.
for (x = 0; x < GRID_SIZE; x++) {
for (y = 0; y < GRID_SIZE; y++) {
//if we marked it visible earlier, skip all this math
if (vis_grid[x][y])
continue;
//if the camera is to the left of this cell, use the left edge
if (grid_x < x)
target_x = (float)x * GRID_RESOLUTION;
else
target_x = (float)(x + 1) * GRID_RESOLUTION;
if (grid_z < y)
target_z = (float)y * GRID_RESOLUTION;
else
target_z = (float)(y + 1) * GRID_RESOLUTION;
angle_to = 180 - MathAngle (target_x, target_z, position.x, position.z);
//Store how many degrees the cell is to the
angle_diff = (float)fabs (MathAngleDifference (angle.y, angle_to));
vis_grid[x][y] = angle_diff < 45;
}
}
}