Jump to content


[OpenGL-2d camera]Having trouble culling invisible objects


1 reply to this topic

#1 HateCoolNicks

    New Member

  • Members
  • Pip
  • 5 posts

Posted 15 October 2008 - 11:24 AM

Hi everyone , im (yet)another beginner "game developer"( i know , i need to improve alot ) , and
just started with opengl(well , i've been playing around with it for...about 15 days).

I decided to program a simple tile game , but im getting bad results when "culling" invisible objects
(objects that are outside camera).

Some objects(tiles) are visible , some other aren't ... and i just can't figure out what's wrong...


Im posting my code here , and hopefuly someone might be able to help me ...


Well , here's (pretty much) everything ... ->


Building the map:

//generate a large map
CCustomArray2d<CTile> mapData(app.window.getWidth() * 6,app.window.getHeight() * 6);

for ( register int y = 0; y < mapData.getHeight(); y++)
{
  for ( register int x = 0; x < mapData.getWidth(); x++)
  {
     mapData.set(y,x,CTile(x*32,y*32,32,32,TILE_TYPES::WALKABLE,TILE_NAMES::NO_TEXTURE));
  }
}

Main loop:


//setup camera 2d vector object 
//(used for collision detection with tiles AND scolling of course)
app.renderer.camera.setupVector(0,0,app.window.getWidth(),app.window.getHeight());

//temp variable to count visible objects:
int  temp__visible__objects = 0;

while ( app.running() )
{
  temp__visible__objects = 0;

  app.updateTimers();
  app.renderer.clear(); 

  //set view by mouse...
  glPushMatrix();
  app.renderer.camera.setViewByMouse( app.getDelta() , app.events.getMouseX() ,  app.events.getMouseY() );
  app.renderer.camera.translate();// inlined function - code can be found in next  code block

  //render all tiles
  for ( register int y = 0; y < mapData.getHeight(); y+=1)
  {
    for ( register int x = 0; x < mapData.getWidth(); x+=1)
    {
       //jump table
       switch(mapData.get(y,x).getType())
       {
          case TILE_NAMES::NO_TEXTURE:
          {
            CTile* tile = &mapData.get(y,x);
            if ( ! COMMON::collidesWith( tile->getVector() , app.renderer.camera.getVector() ) ) 
            break;
            app.renderer.textureManager.bind("TILE_NO_TEXTURE");
            glPushMatrix();
            app.renderer.renderTexturedQuad( tile->getVector() );
            glPopMatrix();
            temp__visible__objects++;
            break;
          }//case
       }//switch
    }//for x
  }//for y

  glPopMatrix();//camera transformations
  app.renderer.present();
  app.renderer.forceFinishCommands();
}


Camera translation code:

    inline void translate()
    {
        handleZoom();
        //glTranslatef(-(m_Vec.w/2) + m_Vec.x,-(m_Vec.h/2)+m_Vec.y,0);
        glTranslatef( m_Vec.x, m_Vec.y,0);
        resetZoom();
    }

Setting view by mouse:
	inline void setViewByMouse(const float dt,const int mouse_x,const int mouse_y)
	{
        float old_speed = m_Speed;

        m_Speed = 140.0f;

		if ( mouse_x > m_Vec.w - 10)
		{
			moveRight(dt);
		}
        else
		if ( mouse_x < 10)
		{
			moveLeft(dt);
		}
        else
		if ( mouse_y > m_Vec.h - 10)
		{
			moveDown(dt);
		}
        else
		if ( mouse_y < 10)
		{
			moveUp(dt);
		}

        m_Speed = old_speed;

	}

Rendering textured quad :

	inline void renderTexturedQuad(const CVector2& v)
	{
		glTranslatef(  v.x, v.y  ,0);
		glBegin(GL_QUADS);
		glTexCoord2f(0.0f,1.0f); glVertex2f(0,0);
		glTexCoord2f(0.0f,0.0f); glVertex2f(-v.w,0);
		glTexCoord2f(1.0f,0.0f); glVertex2f(-v.w,-v.h);
		glTexCoord2f(1.0f,1.0f); glVertex2f(0,-v.h);
		glEnd();
	}

Collision detection:
bool collidesWith(const CVector2& v1,const CVector2& v2)
{
    /*static*/float leftside[2]={0},rightside[2]={0},topside[2]={0},bottomside[2]={0};

    //box 1
    leftside[0] = v1.x;
    rightside[0]= (v1.x+v1.w);
    topside[0] = v1.y;
    bottomside[0] = (v1.y + v1.h);

    //box 2
    leftside[1] = v2.x;
    rightside[1]= (v2.x+v2.w);
    topside[1] = v2.y;
    bottomside[1] = (v2.y + v2.h);

    //return something
    if (bottomside[0] <= topside[1]) return false;
    if (topside[0] >= bottomside[1]) return false;
    if (rightside[0] <= leftside[1]) return false;
    if (leftside[0] >= rightside[1]) return false;
    return true;
}


#2 HateCoolNicks

    New Member

  • Members
  • Pip
  • 5 posts

Posted 18 October 2008 - 04:32 PM

FYI , i didn't kill Kenny , i just only hate foo bar examples , and im just watching
a little p*rn...lol , joking of course(and maybe the other word starting with j :P).

Anyway , i found the solution , i just had to separate camera <-> tile collision detection so i can take account negative gl translations , and it works fine.

I would like to ask just one question(and i hope it will get answered) :

Im trying to think of a way looping through only tiles that are in range,and
im thinking to ...

A)
To copy(sort) all tiles that are in range to a second tile buffer , and then
doing the usual stuff there.
This change will only occur when there's an event(in each frame its just overkill).

B)
This method i think is much faster and more efficient than the first , but i can't figure
out how to do it ... so experts at math , please tell me how...

We have 2 nested loops to render the map & perform events to a specific tile... :

for ( int y = 0 ; y < map height ; y++ )
{
    for ( int x = 0 ; x < map width ; x++ )
    {
	CTile& t_ref = map.get(y,x);//reference to tile
    }
}

My idea is to start looping from camera's relative position ...

I've tried the following , but it just crashes:

//size of each tile = 32 
int start_x = 0,start_y = 0,end_x=mapData.getWidth(),end_y=mapData.getHeight();

if ( (int)app.renderer.camera.getVector().x >0 )
{
    start_x = (int)app.renderer.camera.getVector().x/32;
    end_x = (int)(start_x + ((1+(int)app.renderer.camera.getVector().w)/32));
}
if ( (int)app.renderer.camera.getVector().y >0 )
{
    start_y = (int)app.renderer.camera.getVector().y/32;
    end_y = (int)(start_y + ((1+(int)app.renderer.camera.getVector().h)/32));
}

//now , do the loop
for ( int y = start_y ; y < end_y ; y++ )
{
    for ( int x = start_x ; x < end_x ; x++ )
    {
	CTile& t_ref = map.get(y,x);//reference to tile
    }
}


...Any ideas what im doing wrong (except from messing with game development) ???

Thanks...





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users