Forum

Easy Bounding Box Fix

Post tutorials on how to do certain tasks within game or engine code here.

Moderator: InsideQC Admins

Easy Bounding Box Fix

Postby Stroggos » Sat Oct 03, 2009 11:50 am

Easy Bounding Box Fix:
I found this by accident and it seemed to work. I'm really not sure how it works
so maybe someone could tell me.

There is only one change in one file throughout the whole tutorial. First find
R_CullBox(). It should look like this:
Code: Select all
qboolean R_CullBox (vec3_t mins, vec3_t maxs)
{
   int      i;

   for (i=0 ; i<4 ; i++)
      if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
         return true;
   return false;
}


Then change the line:
Code: Select all
if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)

to
Code: Select all
if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 5)


Compile and run. Goto the final map (end.bsp) and look up at the Shub-Niggurath.
Stroggos
 
Posts: 50
Joined: Tue Apr 14, 2009 11:40 am
Location: Australia

Postby frag.machine » Sat Oct 03, 2009 5:15 pm

And what is exactly fixed with this code snippet ? The fact that Shub's bound box does not fit to its model ?
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
User avatar
frag.machine
 
Posts: 2090
Joined: Sat Nov 25, 2006 1:49 pm

Postby Team Xlink » Sat Oct 03, 2009 5:45 pm

He is makeing it so it returns 5 and makes it always visible.
Last edited by Team Xlink on Sat Oct 03, 2009 8:47 pm, edited 1 time in total.
Team Xlink
 
Posts: 368
Joined: Thu Jun 25, 2009 4:45 am
Location: Michigan

Postby Spike » Sat Oct 03, 2009 6:17 pm

It 'fixes' it by disabling culling entirely.

BoxOnPlaneSide returns 1 if part of the box is fully in view, 2 if none of it is (thus cull), and 3 if part of it is. 0 is possible if the box is inside out...

5 will never happen. Thus the box (read: model) will never be culled, and will always be visible.
Note that the BSP culling code also uses this function to cull things. So if you do apply that change, you'll more than double the amount of data sent to the graphics card every frame.



The bug is that the model loader loads every single mdl file with mins & max as '-16 -16 -16' & '16 16 16'. Thus the box sizes used in the call to R_CullBox are wrong.

A better, but still lazy, 'fix' is to remove the condition+call+return in R_DrawAliasModel instead. Just comment out the two lines.

The proper fix is to fix the mdl loader to set the size to model_header->origin & (model_header->origin_scale*255).

And to then maybe hack PF_setmodel so QC still sees models as the old -16 & 16 size (quakerally for one breaks).
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby Team Xlink » Sat Oct 03, 2009 8:46 pm

Spike, the quakerc.org tutorial at:

http://www.quake-1.com/docs/quakesrc.org/71.html

Says to add:
Code: Select all
   aliasbboxmins[0] = aliasbboxmins[1] = aliasbboxmins[2] =  99999;

   aliasbboxmaxs[0] = aliasbboxmaxs[1] = aliasbboxmaxs[2] = -99999;



After this:

Code: Select all
   //

   // load the frames

   //



   posenum = 0;

   pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];


In this:

Code: Select all
   Mod_LoadAliasModel



So instead of doing this:
Code: Select all
   aliasbboxmins[0] = aliasbboxmins[1] = aliasbboxmins[2] =  99999;

   aliasbboxmaxs[0] = aliasbboxmaxs[1] = aliasbboxmaxs[2] = -99999;


I should do this:
Code: Select all
   aliasbboxmins[0] = aliasbboxmins[1] = aliasbboxmins[2] = 255;
   aliasbboxmaxs[0] = aliasbboxmaxs[1] = aliasbboxmaxs[2] = 0;


That is correct, right?
Team Xlink
 
Posts: 368
Joined: Thu Jun 25, 2009 4:45 am
Location: Michigan

Postby Spike » Sat Oct 03, 2009 9:01 pm

The important bit is this code:
// FIXME: do this right
mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;


The whole aliasbboxmins / aliasbboxmaxs part of that tutorial you linked is to try to get as small a bounds as possible.
Although that's probably overkill, as the model will generally be expanded to consume the full 0-255 range anyway, in which case mins is 0 and maxs is 255.

But yeah, that tutorial should fix it properly and efficiently.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby r00k » Mon Oct 05, 2009 9:02 pm

Rich Whitehouse fixed it in his model loader
Code: Select all
   //rww - doing this right (get the max extents of the verts for all poses).
   //could also use a mins/maxs for culling for each pose uniquely, but who cares.
   //continue using 32 as the minimum extent size
   mod->mins[0] = mod->mins[1] = mod->mins[2] = -16.0f;
   mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16.0f;
   for (i = 0; i < pheader->numposes; i++)
   {
      int j;
      for (j = 0; j < pheader->numverts; j++) {
         byte *vert = poseverts[i][j].v;
         float v;
         for (k = 0; k < 3; k++)
         {
            v = (float)vert[k];
            v *= pheader->scale[k];
            v += pheader->scale_origin[k];

            if (v < mod->mins[k])
            {
               mod->mins[k] = v;
            }
            if (v > mod->maxs[k])
            {
               mod->maxs[k] = v;
            }
         }
      }
   }
   for (k = 0; k < 3; k++)
   {
      mod->mins[k] -= 32.0f;
      mod->maxs[k] += 32.0f;
   }

   if (mod->maxs[1] > mod->maxs[0])
   {
      mod->maxs[0] = mod->maxs[1];
   }
   else
   {
      mod->maxs[1] = mod->maxs[0];
   }
   if (mod->maxs[2] > mod->maxs[0])
   {
      mod->maxs[0] = mod->maxs[2];
      mod->maxs[1] = mod->maxs[2];
   }
   else
   {
      mod->maxs[2] = mod->maxs[0];
   }
   if (mod->mins[1] < mod->mins[0])
   {
      mod->mins[0] = mod->mins[1];
   }
   else
   {
      mod->mins[1] = mod->mins[0];
   }
   if (mod->mins[2] < mod->mins[0])
   {
      mod->mins[0] = mod->mins[2];
      mod->mins[1] = mod->mins[2];
   }
   else
   {
      mod->mins[2] = mod->mins[0];
   }

   mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
r00k
 
Posts: 1110
Joined: Sat Nov 13, 2004 10:39 pm

Postby FrikaC » Thu Oct 08, 2009 10:00 pm

Weird bit of code. He's got it starting at 32x32x32, finds the maximum extents of the model, extends a further 64x64x64 (to cover up rotations exiting the bounds no doubt (better would be to multiply by the square root of 2), then takes the greatest extent encountered and copies it everywhere (again, rotation).
FrikaC
Site Admin
 
Posts: 1026
Joined: Fri Oct 08, 2004 11:19 pm


Return to Programming Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest