diff options
Diffstat (limited to 'src/engine/physics.cpp')
| -rw-r--r-- | src/engine/physics.cpp | 200 |
1 files changed, 85 insertions, 115 deletions
diff --git a/src/engine/physics.cpp b/src/engine/physics.cpp index f7e5342..5fa7c3f 100644 --- a/src/engine/physics.cpp +++ b/src/engine/physics.cpp @@ -95,38 +95,35 @@ extern void entselectionbox(const entity &e, vec &eo, vec &es); float hitentdist; int hitent, hitorient; -static float disttoent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) { - vec eo, es; - int orient = -1; - float dist = radius, f = 0.0f; - const vector<extentity *> &ents = entities::getents(); - #define entintersect(mask, type, func) {\ - if((mode&(mask))==(mask)) loopv(oc->type) { \ - \ - extentity &e = *ents[oc->type[i]]; \ - if(!(e.flags&EF_OCTA) || &e==t) continue; \ - func; \ - if(f<dist && f>0 && vec(ray).mul(f).add(o).insidebb(oc->o, oc->size)) { \ - \ - hitentdist = dist = f; \ - hitent = oc->type[i]; \ - hitorient = orient; \ - } \ - } \ - } - entintersect(RAY_POLY, mapmodels, - if(!mmintersect(e, o, ray, radius, mode, f)) continue; - ); - entintersect(RAY_ENTS, other, - entselectionbox(e, eo, es); - if(!rayboxintersect(eo, es, o, ray, f, orient)) continue; - ); - entintersect(RAY_ENTS, mapmodels, - entselectionbox(e, eo, es); - if(!rayboxintersect(eo, es, o, ray, f, orient)) continue; - ); - return dist; -} +//~static float disttoent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) { + //~vec eo, es; + //~int orient = -1; + //~float dist = radius, f = 0.0f; + //~const vector<extentity *> &ents = entities::getents(); + //~#define entintersect(mask, type, func) {\ + //~if((mode&(mask))==(mask)) loopv(oc->type) { \ + //~\ + //~extentity &e = *ents[oc->type[i]]; \ + //~if(!(e.flags&EF_OCTA) || &e==t) continue; \ + //~func; \ + //~if(f<dist && f>0 && vec(ray).mul(f).add(o).insidebb(oc->o, oc->size)) { \ + //~\ + //~hitentdist = dist = f; \ + //~hitent = oc->type[i]; \ + //~hitorient = orient; \ + //~} \ + //~} \ + //~} + //~entintersect(RAY_ENTS, other, + //~entselectionbox(e, eo, es); + //~if(!rayboxintersect(eo, es, o, ray, f, orient)) continue; + //~); + //~entintersect(RAY_ENTS, mapmodels, + //~entselectionbox(e, eo, es); + //~if(!rayboxintersect(eo, es, o, ray, f, orient)) continue; + //~); + //~return dist; +//~} static float disttooutsideent(const vec &o, const vec &ray, float radius, extentity *t) { vec eo, es; @@ -147,19 +144,6 @@ static float disttooutsideent(const vec &o, const vec &ray, float radius, extent return dist; } -// optimized shadow version -static float shadowent(octaentities *oc, const vec &o, const vec &ray, float radius, int mode, extentity *t) { - float dist = radius, f = 0.0f; - const vector<extentity *> &ents = entities::getents(); - loopv(oc->mapmodels) { - extentity &e = *ents[oc->mapmodels[i]]; - if(!(e.flags&EF_OCTA) || &e==t) continue; - if(!mmintersect(e, o, ray, radius, mode, f)) continue; - if(f>0 && f<dist) dist = f; - } - return dist; -} - #define INITRAYCUBE \ float dist = 0, dent = radius > 0 ? radius : 1e16f; \ vec v(o), invray(ray.x ? 1/ray.x : 1e16f, ray.y ? 1/ray.y : 1e16f, ray.z ? 1/ray.z : 1e16f); \ @@ -167,6 +151,7 @@ static float shadowent(octaentities *oc, const vec &o, const vec &ray, float rad levels[worldscale] = worldroot; \ int lshift = worldscale, elvl = mode&RAY_BB ? worldscale : 0; \ ivec lsizemask(invray.x>0 ? 1 : 0, invray.y>0 ? 1 : 0, invray.z>0 ? 1 : 0); \ + (void) elvl; (void) dent; #define CHECKINSIDEWORLD \ if(!insideworld(o)) { \ @@ -189,26 +174,25 @@ static float shadowent(octaentities *oc, const vec &o, const vec &ray, float rad dist += disttoworld; \ } -#define DOWNOCTREE(disttoent, earlyexit) \ - cube *lc = levels[lshift]; \ - for(;;) { \ - \ - lshift--; \ - lc += octastep(x, y, z, lshift); \ - if(lc->ext && lc->ext->ents && lshift < elvl) { \ - \ - float edist = disttoent(lc->ext->ents, o, ray, dent, mode, t); \ - if(edist < dent) { \ - \ - earlyexit return min(edist, dist); \ - elvl = lshift; \ - dent = min(dent, edist); \ - } \ - } \ - if(lc->children==NULL) break; \ - lc = lc->children; \ - levels[lshift] = lc; \ - } +//~#define DOWNOCTREE(disttoent, earlyexit) \ + //~cube *lc = levels[lshift]; \ + //~for(;;) { \ + //~lshift--; \ + //~lc += octastep(x, y, z, lshift); \ + //~if(lc->ext && lc->ext->ents && lshift < elvl) { \ + //~\ + //~float edist = disttoent(lc->ext->ents, o, ray, dent, mode, t); \ + //~if(edist < dent) { \ + //~\ + //~earlyexit return min(edist, dist); \ + //~elvl = lshift; \ + //~dent = min(dent, edist); \ + //~} \ + //~} \ + //~if(lc->children==NULL) break; \ + //~lc = lc->children; \ + //~levels[lshift] = lc; \ + //~} #define FINDCLOSEST(xclosest, yclosest, zclosest) \ float dx = (lo.x+(lsizemask.x<<lshift)-v.x)*invray.x, \ @@ -242,7 +226,23 @@ float raycube(const vec &o, const vec &ray, float radius, int mode, int size, ex CHECKINSIDEWORLD; int closest = -1, x = int(v.x), y = int(v.y), z = int(v.z); for(;;) { - DOWNOCTREE(disttoent, if(mode&RAY_SHADOW)); + cube *lc = levels[lshift]; + for(;;) { + lshift--; + lc += octastep(x, y, z, lshift); + //~if(lc->ext && lc->ext->ents && lshift < elvl) { + //~float edist = disttoent(lc->ext->ents, o, ray, dent, mode, t); + //~if(edist < dent) { + //~return min(edist, dist); + //~elvl = lshift; + //~dent = min(dent, edist); + //~} + //~} + if(lc->children==NULL) break; + lc = lc->children; + levels[lshift] = lc; + } + int lsize = 1<<lshift; cube &c = *lc; if((dist>0 || !(mode&RAY_SKIPFIRST)) && @@ -267,60 +267,31 @@ float raycube(const vec &o, const vec &ray, float radius, int mode, int size, ex } // optimized version for lightmap shadowing... every cycle here counts!!! + float shadowray(const vec &o, const vec &ray, float radius, int mode, extentity *t) { INITRAYCUBE; CHECKINSIDEWORLD; int side = O_BOTTOM, x = int(v.x), y = int(v.y), z = int(v.z); (void) side; for(;;) { - DOWNOCTREE(shadowent, ); - cube &c = *lc; - ivec lo(x&(~0U<<lshift), y&(~0U<<lshift), z&(~0U<<lshift)); - if(!isempty(c) && !(c.material&MAT_ALPHA)) { - if(isentirelysolid(c)) { - return dist; - } - else { - const clipplanes &p = getclipplanes(c, lo, 1<<lshift, false, 1); - INTERSECTPLANES(side = p.side[i], goto nextcube); - INTERSECTBOX(side = (i<<1) + 1 - lsizemask[i], goto nextcube); - if(exitdist >= 0) { - return dist+max(enterdist+0.1f, 0.0f); - } - } + //~DOWNOCTREE(shadowent, ); + + cube *lc = levels[lshift]; + for(;;) { + lshift--; + lc += octastep(x, y, z, lshift); + //~if(lc->ext && lc->ext->ents && lshift < elvl) { + //~float edist = shadowent(lc->ext->ents, o, ray, dent, mode, t); + //~if(edist < dent) { + //~return min(edist, dist); + //~elvl = lshift; + //~dent = min(dent, edist); + //~} + //~} + if(lc->children==NULL) break; + lc = lc->children; + levels[lshift] = lc; } - nextcube: - FINDCLOSEST(side = O_RIGHT - lsizemask.x, side = O_FRONT - lsizemask.y, side = O_TOP - lsizemask.z); - if(dist>=radius) return dist; - UPOCTREE(return radius); - } -} - -// thread safe version -struct ShadowRayCache { - clipplanes clipcache[MAXCLIPPLANES]; - int version; - ShadowRayCache() : version(-1) {} -}; - -ShadowRayCache *newshadowraycache() { return new ShadowRayCache; } - -void freeshadowraycache(ShadowRayCache *&cache) { delete cache; cache = NULL; } - -void resetshadowraycache(ShadowRayCache *cache) { - cache->version++; - if(!cache->version) { - memclear(cache->clipcache); - cache->version = 1; - } -} - -float shadowray(ShadowRayCache *cache, const vec &o, const vec &ray, float radius, int mode, extentity *t) { - INITRAYCUBE; - CHECKINSIDEWORLD; - int side = O_BOTTOM, x = int(v.x), y = int(v.y), z = int(v.z); (void) side; - for(;;) { - DOWNOCTREE(shadowent, ); cube &c = *lc; ivec lo(x&(~0U<<lshift), y&(~0U<<lshift), z&(~0U<<lshift)); if(!isempty(c) && !(c.material&MAT_ALPHA)) { @@ -328,8 +299,7 @@ float shadowray(ShadowRayCache *cache, const vec &o, const vec &ray, float radiu return dist; } else { - clipplanes &p = cache->clipcache[int(&c - worldroot)&(MAXCLIPPLANES-1)]; - if(p.owner != &c || p.version != cache->version) { p.owner = &c; p.version = cache->version; genclipplanes(c, lo, 1<<lshift, p, false); } + const clipplanes &p = getclipplanes(c, lo, 1<<lshift, false, 1); INTERSECTPLANES(side = p.side[i], goto nextcube); INTERSECTBOX(side = (i<<1) + 1 - lsizemask[i], goto nextcube); if(exitdist >= 0) { |
