Forum

quake2xp weird bug

Discuss programming topics for the various GPL'd game engine sources.

Moderator: InsideQC Admins

Postby Barnes » Fri Dec 25, 2009 9:38 am

i can give to you svn access, if you want
User avatar
Barnes
 
Posts: 226
Joined: Thu Dec 24, 2009 2:26 pm
Location: Russia, Moscow

Postby revelator » Fri Dec 25, 2009 12:06 pm

sure :)
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby revelator » Tue Apr 26, 2011 4:49 pm

i found the bugger causing playermodels to not show.

the skins were set to disable if no bumpmap were found for them so i changed the code a bit (bumpmaps should not be needed for basic engine functionality).

also there was a bug with the version of windows sdk i used causing _findnext to use the 64 bit type if 32 bit was not explicitly defined (nope the 64 bit type does not work).

everything works now :)
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby Barnes » Thu Apr 28, 2011 9:02 am

reckless wrote:i found the bugger causing playermodels to not show.

the skins were set to disable if no bumpmap were found for them so i changed the code a bit (bumpmaps should not be needed for basic engine functionality).

also there was a bug with the version of windows sdk i used causing _findnext to use the 64 bit type if 32 bit was not explicitly defined (nope the 64 bit type does not work).

everything works now :)


I have long time a smooth procedural bump, in case there is no regular normal map. All the newest now on sourceforge.net now
User avatar
Barnes
 
Posts: 226
Joined: Thu Dec 24, 2009 2:26 pm
Location: Russia, Moscow

Postby revelator » Thu Apr 28, 2011 9:07 am

yep had a look at the new version pretty nice i must say :) i keep the old one just in case now that i got things working like i wanted to though.
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby Barnes » Thu Apr 28, 2011 9:49 am

I do not see any reason to keep the old, at least by the fact that earlier it was much worse.
User avatar
Barnes
 
Posts: 226
Joined: Thu Dec 24, 2009 2:26 pm
Location: Russia, Moscow

Postby revelator » Sun May 01, 2011 12:57 pm

i can understand that but i made a lot of changes which still apply so i keep it for reference :)

btw heres a few slight modifications.

Code: Select all
void R_DrawBrushModel(entity_t * e)
{
   vec3_t      mins, maxs;
   int         contentsAND, contentsOR;
   qboolean   rotated, viewInWater;
   int         cont[5];
   vec3_t      org;

   if (currentmodel->nummodelsurfaces == 0) return;

   currententity = e;

   gl_state.currenttextures[0] = gl_state.currenttextures[1] = -1;

   if (e->angles[0] || e->angles[1] || e->angles[2])
   {
      rotated = true;

      if (!r_noCull->value)
      {
         if (R_CullSphere (e->origin, currentmodel->radius)) return;
      }
   }
   else
   {
      rotated = false;

      VectorAdd(e->origin, currentmodel->mins, mins);
      VectorAdd(e->origin, currentmodel->maxs, maxs);

      if (!r_noCull->value)
      {
         if (R_CullBox(mins, maxs)) return;
      }
   }
   qglColor3f(1, 1, 1);

   memset(gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces));

   VectorSubtract(r_newrefdef.vieworg, e->origin, r_modelorigin);

   if (rotated)
   {
      vec3_t temp;
      vec3_t forward, right, up;

      VectorCopy(r_modelorigin, temp);
      AngleVectors(e->angles, forward, right, up);
      r_modelorigin[0] = DotProduct(temp, forward);
      r_modelorigin[1] = -DotProduct(temp, right);
      r_modelorigin[2] = DotProduct(temp, up);
   }
   qglPushMatrix();
   e->angles[0] = -e->angles[0];   // stupid quake bug
   e->angles[2] = -e->angles[2];   // stupid quake bug
   R_RotateForEntity(e);
   e->angles[0] = -e->angles[0];   // stupid quake bug
   e->angles[2] = -e->angles[2];   // stupid quake bug

   // ==================================
   // detect underwater position
   // for bmodels caustics by Berserker
   // modified a bit by reckless.
   // ==================================
   currententity->minmax[0] = mins[0];
   currententity->minmax[1] = mins[1];
   currententity->minmax[2] = mins[2];
   currententity->minmax[3] = maxs[0];
   currententity->minmax[4] = maxs[1];
   currententity->minmax[5] = maxs[2];

   VectorSet(org, currententity->minmax[0], currententity->minmax[1], currententity->minmax[5]);
   cont[0] = CL_PMpointcontents2(org, currentmodel);
   VectorSet(org, currententity->minmax[3], currententity->minmax[1], currententity->minmax[5]);
   cont[1] = CL_PMpointcontents2(org, currentmodel);
   VectorSet(org, currententity->minmax[0], currententity->minmax[4], currententity->minmax[5]);
   cont[2] = CL_PMpointcontents2(org, currentmodel);
   VectorSet(org, currententity->minmax[3], currententity->minmax[4], currententity->minmax[5]);
   cont[3] = CL_PMpointcontents2(org, currentmodel);
   org[0] = (currententity->minmax[0] + currententity->minmax[3]) * 0.5;
   org[1] = (currententity->minmax[1] + currententity->minmax[4]) * 0.5;
   org[2] = (currententity->minmax[2] + currententity->minmax[5]) * 0.5;
   cont[4] = CL_PMpointcontents2(org, currentmodel);
   contentsAND = (cont[0] & cont[1] & cont[2] & cont[3] & cont[4]);
   contentsOR = (cont[0] | cont[1] | cont[2] | cont[3] | cont[4]);
   viewInWater = (CL_PMpointcontents(r_newrefdef.vieworg) & MASK_WATER);

   //Put camera into model space view angle for bmodels parallax
   if (currententity->angles[0] || currententity->angles[1] || currententity->angles[2])
   {
      vec3_t   forward, right, up, temp;
      VectorSubtract(r_origin, currententity->origin, temp);
      AngleVectors (currententity->angles, forward, right, up);
      BmodelViewOrg[0] = DotProduct (temp, forward);
      BmodelViewOrg[1] = -DotProduct (temp, right);
      BmodelViewOrg[2] = DotProduct (temp, up);
   }
   else
   {
      VectorSubtract(r_origin, currententity->origin, BmodelViewOrg);
   }

   //diffuse
   GL_SelectTexture(GL_TEXTURE0_ARB);
   qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
   qglTexCoordPointer(2, GL_FLOAT, 0, wTexArray);

   //lighmap
   GL_SelectTexture(GL_TEXTURE1_ARB);
   qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
   qglTexCoordPointer(2, GL_FLOAT, 0, wLMArray);
   qglEnable(GL_TEXTURE_2D);

   //addative map
   GL_SelectTexture(GL_TEXTURE2_ARB);
   qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
   qglTexCoordPointer(3, GL_FLOAT, 0, wTexArray);
   qglEnable(GL_TEXTURE_2D);

   //caustics map
   GL_SelectTexture(GL_TEXTURE3_ARB);
   qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
   qglTexCoordPointer(2, GL_FLOAT, 0, wTexArray);
   qglEnable(GL_TEXTURE_2D);

   //normal
   qglEnableClientState(GL_NORMAL_ARRAY);
   qglNormalPointer(GL_FLOAT, 0, nTexArray);

   qglEnableClientState(GL_VERTEX_ARRAY);
   qglVertexPointer(3, GL_FLOAT, 0, wVertexArray);

   qglEnableVertexAttribArray(10);
   qglEnableVertexAttribArray(11);

   // tangent & binormal
   qglVertexAttribPointer(10, 3, GL_FLOAT, false, 0, tTexArray);
   qglVertexAttribPointer(11, 3, GL_FLOAT, false, 0, bTexArray);

   num_scene_surfaces = 0;

   R_DrawInlineBModel();

   // all types = valid if one or all of these match
   if ((contentsAND & MASK_WATER) || ((contentsOR & MASK_WATER) && viewInWater))
   {
      // sanity checking since we newer have all the types above.
      if ((contentsOR & CONTENTS_LAVA) || (contentsOR & CONTENTS_SLIME) || (contentsOR & CONTENTS_WATER))
      {
         GL_BatchLightmappedPoly(true, true);
      }
      else
      {
         GL_BatchLightmappedPoly(true, false);
      }
   }
   else
   {
      GL_BatchLightmappedPoly(true, false);
   }
   GL_SelectTexture(GL_TEXTURE3_ARB);
   qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
   qglDisable(GL_TEXTURE_2D);

   GL_SelectTexture(GL_TEXTURE2_ARB);
   qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
   qglDisable(GL_TEXTURE_2D);

   GL_SelectTexture(GL_TEXTURE1_ARB);
   qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
   qglDisable(GL_TEXTURE_2D);

   GL_SelectTexture(GL_TEXTURE0_ARB);
   qglDisableClientState(GL_TEXTURE_COORD_ARRAY);

   qglDisableClientState(GL_VERTEX_ARRAY);
   qglDisableClientState(GL_NORMAL_ARRAY);

   qglDisableVertexAttribArray(10);
   qglDisableVertexAttribArray(11);

   qglPopMatrix();
   qglDisable(GL_BLEND);
   qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}




bit cleaner now :)

Code: Select all
static void R_RecursiveWorldNode(mnode_t * node, int clipflags)
{
    int         c, clipped, side, sidebit;
    cplane_t   *plane;
    msurface_t   *surf, **mark;
    mleaf_t      *pleaf;
    float      dot;
    image_t      *fx, *image;

    if (node->contents == CONTENTS_SOLID) return;               // solid
    if (node->visframe != r_visframecount) return;

   if (clipflags)
   {
      for (c=0, plane=frustum ; c<4 ; c++, plane++)
      {
         if (!(clipflags & (1 << c))) continue;

         clipped = BOX_ON_PLANE_SIDE(node->minmaxs, node->minmaxs + 3, plane);

         if (clipped == 2) return;               // fully clipped

         if (clipped == 1)
         {
            clipflags &= ~(1 << c);               // node is entirely on screen
         }
      }
   }

    // if a leaf node, draw stuff
    if (node->contents != -1)
    {
        pleaf = (mleaf_t *) node;

        // check for door connected areas
        if (r_newrefdef.areabits)
        {
            if (!(r_newrefdef.areabits[pleaf->area >> 3] & (1 << (pleaf->area & 7)))) return; // not visible
        }
        mark = pleaf->firstmarksurface;
        c = pleaf->nummarksurfaces;

        if (c)
        {
            do
            {
                if (SurfInFrustum(*mark))
            {
                    (*mark)->visframe = r_framecount;
            }
                (*mark)->ent = NULL;
                mark++;
            } while (--c);
        } return;
    }

    // node is just a decision point, so go down the apropriate sides
    // find which side of the node we are on
    plane = node->plane;

    switch (plane->type)
    {
    case PLANE_X:
        dot = r_modelorigin[0] - plane->dist;
        break;
    case PLANE_Y:
        dot = r_modelorigin[1] - plane->dist;
        break;
    case PLANE_Z:
        dot = r_modelorigin[2] - plane->dist;
        break;
    default:
        dot = DotProduct(r_modelorigin, plane->normal) - plane->dist;
        break;
    }

    if (dot >= 0)
    {
        side = 0;
        sidebit = 0;
    }
    else
    {
        side = 1;
        sidebit = SURF_PLANEBACK;
    }

    // recurse down the children, front side first
    R_RecursiveWorldNode(node->children[side], clipflags);

    // draw stuff
    for (c = node->numsurfaces, surf = r_worldmodel->surfaces + node->firstsurface; c; c--, surf++)
    {
        if (surf->visframe != r_framecount) continue;
        if ((surf->flags & SURF_PLANEBACK) != sidebit) continue;         // wrong side

        if (surf->texinfo->flags & SURF_SKY)     // just adds to visible sky bounds
        {
            R_AddSkySurface(surf);
        }
        else if (surf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66))     // add to the translucent chain
        {
         // not sure what to make of this flag ?
         if (surf->texinfo->flags & SURF_NODRAW) continue;

            surf->texturechain = r_alpha_surfaces;
            r_alpha_surfaces = surf;
        }
        else
        {
         // not sure what to make of this flag ?
         if (surf->texinfo->flags & SURF_NODRAW) continue;

            if (!(surf->flags & SURF_DRAWTURB))
            {
                r_scene_surfaces[num_scene_surfaces++] = surf;
            }
            else
            {
                // the polygon is visible, so add it to the texture
                // sorted chain
                // FIXME: this is a hack for animation
                image = R_TextureAnimation(surf->texinfo);
                fx = R_TextureAnimationFx(surf->texinfo); // fix glow hack
                surf->texturechain = image->texturechain;
                image->texturechain = surf;
            }
        }
    }

    // recurse down the back side
    R_RecursiveWorldNode(node->children[!side], clipflags);
}


Code: Select all
static void R_DrawInlineBModel(void)
{
    int         i, k;
    cplane_t   *pplane;
    float      dot;
    msurface_t   *psurf;
    dlight_t   *lt;

    // calculate dynamic lighting for bmodel
    if (!r_flashBlend->value)
    {
        lt = r_newrefdef.dlights;

        for (k = 0; k < r_newrefdef.num_dlights; k++, lt++)
        {
            R_MarkLights(lt, 1 << k, currentmodel->nodes + currentmodel->firstnode);
        }
    }
    psurf = &currentmodel->surfaces[currentmodel->firstmodelsurface];

    //
    // draw texture
    //
    for (i = 0; i < currentmodel->nummodelsurfaces; i++, psurf++)
    {
        // find which side of the node we are on
        pplane = psurf->plane;

        dot = DotProduct(r_modelorigin, pplane->normal) - pplane->dist;

        // draw the polygon
        if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
        {
            /*===============================
            berserker - flares for brushmodels
            =================================*/
            psurf->visframe = r_framecount;
            psurf->ent = currententity;
            // ================================

            if (psurf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66))
            {
            qboolean   duplicate = false;
            msurface_t   *s;

             // Don't allow surface to be added twice (fixes hang)
            for (s = r_alpha_surfaces; s; s = s->texturechain)
            {
               if (s == psurf)
               {   
                  duplicate = true;   
                  break;   
               }
            }

            if (!duplicate)
            {
               psurf->texturechain = r_alpha_surfaces;
               r_alpha_surfaces = psurf;
            }
            }
            else if (!(psurf->flags & SURF_DRAWTURB))
            {
                r_scene_surfaces[num_scene_surfaces++] = psurf;
            }
            else
            {
                R_RenderBrushPoly(psurf);
                qglDisable(GL_BLEND);
            }
        }
    }

    if (!(currententity->flags & RF_TRANSLUCENT))
    {
        qglDisable(GL_BLEND);
        qglColor4f(1, 1, 1, 1);
        GL_TexEnv(GL_REPLACE);
    }
    qglDisable(GL_BLEND);
    qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}


some of these are fixes knightmare made in kmquake2
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby mh » Sun May 01, 2011 2:08 pm

Instead of the duplicate test, why not just set and check surf->visframe in R_DrawInlineBModel?
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby revelator » Sun May 01, 2011 7:12 pm

also a possibility :) this was just a crude attempt to get rid of some boolean checks (nothing against those but its a bit overdone in some places).

most of the code was copied of kmquake2 but a few differences made it nesseary to do some workarounds.

atm im hunting a bug where it crashes in the map with the black hole generator ill post a fix to barnes if i find whats causing it (having some slight trouble with me jit debugger :S )

p.s this bug is not caused by the above code the unmodified version also does it :(
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby revelator » Sun May 01, 2011 11:37 pm

something like this ?

Code: Select all
            if (psurf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66))
            {
            if (psurf->visframe != r_framecount)   continue;
            psurf->texturechain = r_alpha_surfaces;
            r_alpha_surfaces = psurf;
            }
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby revelator » Mon May 02, 2011 12:25 am

oh shiny i think i got it.

before this

Code: Select all
            /*===============================
            berserker - flares for brushmodels
            =================================*/
            psurf->visframe = r_framecount;
            psurf->ent = currententity;
            // ================================


add this if (psurf->visframe == r_framecount) continue;

it works a treat even speed up the code some :)

i have to commend echon for this one.

quite a bit simpler i must say.
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby Barnes » Mon May 02, 2011 9:44 am

reckless, mh
Thx, im add this fixes in code :)

also i'm don't draw caustics for lava or slime contents :wink:
User avatar
Barnes
 
Posts: 226
Joined: Thu Dec 24, 2009 2:26 pm
Location: Russia, Moscow

Postby Barnes » Mon May 02, 2011 10:56 am

and
in R_RecursiveWorldNode
Code: Select all
 
if (clipflags)
   {
      for (c=0, plane=frustum ; c<4 ; c++, plane++)
      {
         if (!(clipflags & (1 << c))) continue;

         clipped = BOX_ON_PLANE_SIDE(node->minmaxs, node->minmaxs + 3, plane);

         if (clipped == 2) return;               // fully clipped

         if (clipped == 1)
         {
            clipflags &= ~(1 << c);               // node is entirely on screen
         }
      }
   }

is a variant of
Code: Select all
if (R_CullBox(node->minmaxs, node->minmaxs + 3))
      return;

I think this is too much :)
User avatar
Barnes
 
Posts: 226
Joined: Thu Dec 24, 2009 2:26 pm
Location: Russia, Moscow

Postby revelator » Mon May 02, 2011 2:56 pm

np m8 :)

the cull check above is old vic code i newer quite figure out the difference but it works great no visual difference i could notice though
so the simple version might be just fine.

id argue about caustics in slime but in lava i think the user has other problems (extra crispy) hehe ;).
User avatar
revelator
 
Posts: 2567
Joined: Thu Jan 24, 2008 12:04 pm
Location: inside tha debugger

Postby mh » Mon May 02, 2011 3:25 pm

Sometimes it's useful to know if a node is fully onscreen or fully offscreen. A node that's fully offscreen can have all of it's children rejected in the frustum cull check, but a node that's fully onscreen can also have all of it's children accepted without needing a test. Only nodes that intersect the frustum need to have their child nodes tested. This can reduce CPU load for more complex BSP trees, and standard R_CullBox won't give you that info.

You can get useful reductions in surface submission by also running R_CullBox on surfaces; normally this is CPU heavy, but making use of the fully onscreen/fully offscreen info for the node containing the surface helps. Only nodes that intersect the frustum need to have their surfaces tested; if the node is fully onscreen then it's surfaces are also fully onscreen (nodes that are fully offscreen don't get their surfaces added so this doesn't apply to them).

Another interesting thing about R_RecursiveWorldNode is that it only needs to run if the view origin or angles change. If they don't you can just reuse the results of the last run. You may need to add extra handling for texture animation, lightmap updates and static entities (not a problem for Q2, is a problem for Q1) depending on the structure of your renderer. This can get very useful reductions in overhead CPU-side, doubling framerates in some cases (depending on where your bottleneck is, of course).
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

PreviousNext

Return to Engine Programming

Who is online

Users browsing this forum: No registered users and 1 guest