# calculating visibility

This topic is 4987 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

void CalculateVisTable() {

bool cl, cr, cu, cd, cur, cul, cdr, cdl;
int NextID = 0;

register int f;
register int x;
register int y;
register int x2;
register int y2;

for (f = 0; f < Dungeon[0].NumFloors; f++) {
for (y = 0; y < DungeonH; y++) {
for (x = 0; x < DungeonW; x++) {
NextID = 0;

if (VisTable[f][y][x].VisList != NULL)
free(VisTable[f][y][x].VisList);

VisTable[f][y][x].VisList = (Co2D*)malloc(sizeof(Co2D));

//Check for valid map co-ordinates in each direction of the current map section
if (IsValidMC(x - 1)) cl = true; else cl = false;
if (IsValidMC(x + 1)) cr = true; else cr = false;
if (IsValidMC(y - 1)) cu = true; else cu = false;
if (IsValidMC(y + 1)) cd = true; else cd = false;

if (cl && cu) cul = true; else cul = false;
if (cr && cu) cur = true; else cur = false;
if (cl && cd) cdl = true; else cdl = false;
if (cr && cd) cdr = true; else cdr = false;

//first check all squares visable from this exact location

for (y2 = 0; y2 < 100; y2 ++) {
for (x2 = 0; x2 < 100; x2 ++) {

if (IsFloor(f, x, y)) {
if (Get3dDistance(x * TileSize, 0, y * TileSize, x2 * TileSize, 0, y * TileSize) < MAX_DRAW_RANGE + TileSize/2) {
if (GetLOS(f, x, y, x2, y2)) {// || Dungeon[f].Data[y2][x2].id == 2) {
//If the object is visable, add its object id to the vis list

VisTable[f][y][x].VisList = (Co2D*)realloc(VisTable[f][y][x].VisList, sizeof(Co2D) * (NextID + 1));
VisTable[f][y][x].VisList[NextID].x = x2;
VisTable[f][y][x].VisList[NextID].y = y2;
VisTable[f][y][x].VisList[0].s = NextID;
NextID++;

//here I add all the adjencent squares to the one that finally hit, to avoid clipping when
//looking around part of a corner.. I know, this is NOT good.

if (cl) {
if (!VisIdExist(f, x - 1, y, x2, y2)) {
VisTable[f][y][x].VisList = (Co2D*)realloc(VisTable[f][y][x].VisList, sizeof(Co2D) * (NextID + 1));
VisTable[f][y][x].VisList[NextID].x = x2 - 1;
VisTable[f][y][x].VisList[NextID].y = y2;
VisTable[f][y][x].VisList[0].s = NextID;
NextID++;
}
}

if (cr) {
if (!VisIdExist(f, x, y, x2 + 1, y2)) {
VisTable[f][y][x].VisList = (Co2D*)realloc(VisTable[f][y][x].VisList, sizeof(Co2D) * (NextID + 1));
VisTable[f][y][x].VisList[NextID].x = x2 + 1;
VisTable[f][y][x].VisList[NextID].y = y2;
VisTable[f][y][x].VisList[0].s = NextID;
NextID++;
}
}

if (cu) {
if (!VisIdExist(f, x, y, x2, y2 - 1)) {
VisTable[f][y][x].VisList = (Co2D*)realloc(VisTable[f][y][x].VisList, sizeof(Co2D) * (NextID + 1));
VisTable[f][y][x].VisList[NextID].x = x2;
VisTable[f][y][x].VisList[NextID].y = y2 - 1;
VisTable[f][y][x].VisList[0].s = NextID;
NextID++;
}
}

if (cd) {
if (!VisIdExist(f, x, y, x2, y2 + 1)) {
VisTable[f][y][x].VisList = (Co2D*)realloc(VisTable[f][y][x].VisList, sizeof(Co2D) * (NextID + 1));
VisTable[f][y][x].VisList[NextID].x = x2;
VisTable[f][y][x].VisList[NextID].y = y2 + 1;
VisTable[f][y][x].VisList[0].s = NextID;
NextID++;
}
}

if (cul) {
if (!VisIdExist(f, x, y, x2 - 1, y2 - 1)) {
VisTable[f][y][x].VisList = (Co2D*)realloc(VisTable[f][y][x].VisList, sizeof(Co2D) * (NextID + 1));
VisTable[f][y][x].VisList[NextID].x = x2 - 1;
VisTable[f][y][x].VisList[NextID].y = y2 - 1;
VisTable[f][y][x].VisList[0].s = NextID;
NextID++;
}
}

if (cur) {
if (!VisIdExist(f, x, y, x2 + 1, y2 - 1)) {
VisTable[f][y][x].VisList = (Co2D*)realloc(VisTable[f][y][x].VisList, sizeof(Co2D) * (NextID + 1));
VisTable[f][y][x].VisList[NextID].x = x2 + 1;
VisTable[f][y][x].VisList[NextID].y = y2 - 1;
VisTable[f][y][x].VisList[0].s = NextID;
NextID++;
}
}

if (cdl) {
if (!VisIdExist(f, x, y, x2 - 1, y2 + 1)) {
VisTable[f][y][x].VisList = (Co2D*)realloc(VisTable[f][y][x].VisList, sizeof(Co2D) * (NextID + 1));
VisTable[f][y][x].VisList[NextID].x = x2 - 1;
VisTable[f][y][x].VisList[NextID].y = y2 + 1;
VisTable[f][y][x].VisList[0].s = NextID;
NextID++;
}
}

if (cdr) {
if (!VisIdExist(f, x, y, x2 + 1, y2 + 1)) {
VisTable[f][y][x].VisList = (Co2D*)realloc(VisTable[f][y][x].VisList, sizeof(Co2D) * (NextID + 1));
VisTable[f][y][x].VisList[NextID].x = x2 + 1;
VisTable[f][y][x].VisList[NextID].y = y2 + 1;
VisTable[f][y][x].VisList[0].s = NextID;
NextID++;
}
}

} else {
if (x2 == LosHitX && y2 == LosHitY) {

if (Get3dDistance(x * TileSize, 0, y * TileSize, x2 * TileSize, 0, y * TileSize) < MAX_DRAW_RANGE + TileSize/2) {
if (!VisIdExist(f, x, y, x2, y2)) {
VisTable[f][y][x].VisList = (Co2D*)realloc(VisTable[f][y][x].VisList, sizeof(Co2D) * (NextID + 1));
VisTable[f][y][x].VisList[NextID].x = x2;
VisTable[f][y][x].VisList[NextID].y = y2;
VisTable[f][y][x].VisList[0].s = NextID;
NextID++;
}
}
}
}//*/
}
}

}
}
}
}
}

}


and its two helper functions:
//line of sight inside the map array using breshams
bool GetLOS(int f, int x1, int y1, int x2, int y2) {
int u = 0;
int dx, dy, c, M, xinc = 1, yinc = 1;
int hits=0;
int x = x1;
int y = y1;
dx = x2 - x1;
dy = y2 - y1;

if (dx < 0) { xinc = -1; dx = -dx; }
if (dy < 0) { yinc = -1; dy = -dy; }

if (dy < dx) {
c = 2 * dx;
M = 2 * dy;

while (x != x2) {

if (d(f, x, y) != 1 && d(f, x, y) != 3) {
LosHitX = x;
LosHitY = y;
hits++;

if (hits > LOS_TOLERANCE)
return false;
}

x += xinc;
u += M;

if (u > dx) { y += yinc; u -= c; }
}

} else {

c = 2 * dy;
M = 2 * dx;

while(y != y2) {
if (d(f, x, y) != 1 && d(f, x, y) != 3) {
LosHitX = x;
LosHitY = y;
hits++;

if (hits > LOS_TOLERANCE)
return false;
}

y += yinc;
u += M;

if(u > dy) { x += xinc; u -= c; }
}
}

return true;
}

//This code returns wether or not an id has already been added to the vislist so I dont add duplicates
//its written in asm because I was interested in learning it so it was an exercise.  It uses a hashing technique.

bool VisIdExist(int f, int x, int y, int x2, int y2) {

bool r;

int ThisSize = VisTable[f][y][x].VisList[0].s;
__asm {

mov eax, 0						;set eax to 0 (array index)
mov ecx, 0						;holder for second half of array calcs (hashing)
mov edx, 0						;holder for first half
mov esi, 0						;im sure i shouldnt be using this register but what the hell. its eax * 2

lp:
mov edx, [eax * 4 + ebx]	;store the value of the current index of the array in edx
cmp edx, [x2]				;compare edx (array value) to the value we are looking for

mov esi, eax				;second half of the array
mov ecx, [esi * 4 + ebx]
cmp ecx, [x2]
je checkY2

cmp edx, [-1]
je rt2

cont:
inc eax						;increase eax
cmp eax, [ThisSize]			;compare eax against max size of the array
jge rt2						;jump to "rt2" lable if eax was greater than or equal to maxsize

jmp lp							;jump back to "lp"

checkY:
mov edx, [eax * 4 + 4 + ebx]
cmp edx, [y2]
je rt

jmp cont

checkY2:
mov ecx, [esi * 4 + 4 + ebx]
cmp ecx, [y2]
je rt

jmp cont

rt:
mov [r], 1			;set return result to 1 (true)
jmp end

rt2:
mov [r], 0			;value wasnt found.

end:
};

return r;
}


Well, thats all my code for what good it is. There has -got- to be a better and more accurate way of doing things than this, but i'm all out of ideas :/

##### Share on other sites
Look up "occlusion culling".

In the meantime, how about this: each tile has max_height and occluder_height. max_height is of course the highest visible point of a tile and occluder_height is the height below which nothing can be seen beyond it. As you cast your ray, you compare the max_height of a tile to the highest occluder_height so far. Something like this:
    occlusion_tangent = 0;    while ( ... )    {        ...        occluded_height = occlusion_tangent * ray_distance;                if ( tile->max_height > occluded_height )        {            tile->draw();                        if ( tile->occluder_height > occluded_height )            {                occlusion_tangent = tile->occluder_height / ray_distance;            }        }        ...    }

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 11
• 15
• 11
• 11
• 9
• ### Forum Statistics

• Total Topics
634151
• Total Posts
3015825
×