~ubuntu-branches/debian/stretch/assaultcube-data/stretch

« back to all changes in this revision

Viewing changes to source/src/worldocull.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gonéri Le Bouder, Ansgar Burchardt, Gonéri Le Bouder
  • Date: 2010-04-02 23:37:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100402233755-kf74fxwlu634o6vg
Tags: 1.0.4+repack1-1
[ Ansgar Burchardt ]
* debian/control: fix typo in short description

[ Gonéri Le Bouder ]
* Upgrade to 1.0.4
* bump standards-version to 3.8.4
* Add Depends: ${misc:Depends} just to avoid a lintian warning
* Add a debian/source/format file for the same reason

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// worldocull.cpp: occlusion map and occlusion test
 
2
 
 
3
#include "pch.h"
 
4
#include "cube.h"
 
5
 
 
6
#define NUMRAYS 512
 
7
 
 
8
float rdist[NUMRAYS];
 
9
bool ocull = true;
 
10
float odist = 256;
 
11
 
 
12
void toggleocull() { ocull = !ocull; }
 
13
 
 
14
COMMAND(toggleocull, ARG_NONE);
 
15
 
 
16
// constructs occlusion map: cast rays in all directions on the 2d plane and record distance.
 
17
// done exactly once per frame.
 
18
 
 
19
void disableraytable()
 
20
{
 
21
    odist = 1e16f;
 
22
    loopi(NUMRAYS) rdist[i] = 1e16f;
 
23
}
 
24
 
 
25
void computeraytable(float vx, float vy, float fov)
 
26
{
 
27
    if(!ocull) { disableraytable(); return; }
 
28
 
 
29
    odist = getvar("fog")*1.5f;
 
30
 
 
31
    float apitch = (float)fabs(camera1->pitch);
 
32
    float af = fov/2+apitch/1.5f+3;
 
33
    float byaw = (camera1->yaw-90+af)/360*PI2;
 
34
    float syaw = (camera1->yaw-90-af)/360*PI2;
 
35
 
 
36
    loopi(NUMRAYS)
 
37
    {
 
38
        float angle = i*PI2/NUMRAYS;
 
39
        if((apitch>45 // must be bigger if fov>120
 
40
        || (angle<byaw && angle>syaw)
 
41
        || (angle<byaw-PI2 && angle>syaw-PI2)
 
42
        || (angle<byaw+PI2 && angle>syaw+PI2))
 
43
        && !OUTBORD(vx, vy)
 
44
        && !SOLID(S(int(vx), int(vy))))       // try to avoid tracing ray if outside of frustrum
 
45
        {
 
46
            float ray = i*8/(float)NUMRAYS;
 
47
            float dx, dy;
 
48
            if(ray>1 && ray<3) { dx = -(ray-2); dy = 1; }
 
49
            else if(ray>=3 && ray<5) { dx = -1; dy = -(ray-4); }
 
50
            else if(ray>=5 && ray<7) { dx = ray-6; dy = -1; }
 
51
            else { dx = 1; dy = ray>4 ? ray-8 : ray; }
 
52
            float sx = vx;
 
53
            float sy = vy;
 
54
            for(;;)
 
55
            {
 
56
                sx += dx;
 
57
                sy += dy;
 
58
                if(SOLID(S(int(sx), int(sy))))    // 90% of time spend in this function is on this line
 
59
                {
 
60
                    rdist[i] = (float)(fabs(sx-vx)+fabs(sy-vy));
 
61
                    break;
 
62
                }
 
63
            }
 
64
        }
 
65
        else
 
66
        {
 
67
            rdist[i] = 2;
 
68
        }
 
69
    }
 
70
}
 
71
 
 
72
// test occlusion for a cube... one of the most computationally expensive functions in the engine
 
73
// as its done for every cube and entity, but its effect is more than worth it!
 
74
 
 
75
#ifdef __GNUC__
 
76
// GCC seems to have trouble inlining these
 
77
#define ca(xv, yv) ({ float x = (xv), y = (yv); x>y ? y/x : 2-x/y; })
 
78
#define ma(xv, yv) ({ float x = (xv), y = (yv); x==0 ? (y>0 ? 2 : -2) : y/x; })
 
79
#else
 
80
static inline float ca(float x, float y) { return x>y ? y/x : 2-x/y; } 
 
81
static inline float ma(float x, float y) { return x==0 ? (y>0 ? 2 : -2) : y/x; }
 
82
#endif
 
83
 
 
84
int isoccluded(float vx, float vy, float cx, float cy, float csize)     // v = viewer, c = cube to test 
 
85
{
 
86
    // ABC
 
87
    // D E
 
88
    // FGH
 
89
 
 
90
    // - check middle cube? BG
 
91
 
 
92
    // find highest and lowest angle in the occlusion map that this cube spans, based on its most left and right
 
93
    // points on the border from the viewer pov... I see no easier way to do this than this silly code below
 
94
 
 
95
    float xdist = 0, ydist = 0, h, l;
 
96
    if(cx<=vx)              // ABDFG
 
97
    {
 
98
        if(cx+csize<vx)     // ADF
 
99
        {
 
100
            if((xdist = vx-(cx+csize)) > odist) return 2;
 
101
            if(cy<=vy)      // AD
 
102
            {
 
103
                if(cy+csize<vy) { if((ydist = vy-(cy+csize)) > odist) return 2; h = ca(-(cx-vx), ydist)+4; l = ca(xdist, -(cy-vy))+4; }        // A
 
104
                else            {                                               h = ma(xdist, -(cy+csize-vy))+4; l = ma(xdist, -(cy-vy))+4; }  // D
 
105
            }
 
106
            else                { if((ydist = cy-vy) > odist) return 2;         h = ca(cy+csize-vy, xdist)+2; l = ca(ydist, -(cx-vx))+2; }     // F
 
107
        }
 
108
        else                // BG
 
109
        {
 
110
            if(cy<=vy)
 
111
            {
 
112
                if(cy+csize<vy) { if((ydist = vy-(cy+csize)) > odist) return 2; h = ma(ydist, cx-vx)+6; l = ma(ydist, cx+csize-vx)+6; }        // B
 
113
                else return 0;
 
114
            }
 
115
            else                { if((ydist = cy-vy) > odist) return 2;         h = ma(ydist, -(cx+csize-vx))+2; l = ma(ydist, -(cx-vx))+2; }  // G
 
116
        }
 
117
    }
 
118
    else                    // CEH
 
119
    {
 
120
        if((xdist = cx-vx) > odist) return 2;
 
121
        if(cy<=vy)          // CE
 
122
        {
 
123
            if(cy+csize<vy) { if((ydist = vy-(cy+csize)) > odist) return 2;     h = ca(-(cy-vy), xdist)+6; l = ca(ydist, cx+csize-vx)+6; }     // C
 
124
            else            {                                                   h = ma(xdist, cy-vy); l = ma(xdist, cy+csize-vy); }            // E
 
125
        }
 
126
        else                { if((ydist = cy-vy) > odist) return 2;             h = ca(cx+csize-vx, ydist); l = ca(xdist, cy+csize-vy); }      // H
 
127
    }
 
128
 
 
129
    float dist = xdist+ydist-1; // 1 needed?
 
130
    int si = int(h*(NUMRAYS/8))+NUMRAYS;     // get indexes into occlusion map from angles
 
131
    int ei = int(l*(NUMRAYS/8))+NUMRAYS+1; 
 
132
    if(ei<=si) ei += NUMRAYS;
 
133
 
 
134
    for(int i = si; i<=ei; i++)
 
135
    {
 
136
        if(dist<rdist[i&(NUMRAYS-1)]) return 0;     // if any value in this segment of the occlusion map is further away then cube is not occluded
 
137
    }
 
138
 
 
139
    return 1;                                       // cube is entirely occluded
 
140
}
 
141