Question The IsVisibleInCamera() function in D3D11Client

dumbo2007

Crazy about real time sims
Joined
Nov 29, 2009
Messages
675
Reaction score
0
Points
0
Location
India
I am trying to figure out some of the D3D11Client code for my own education and to write a wiki page on it for others. I understand most of it except when it gets really mathematical and if I am unaware of the algorithm used for rendering certain things.

For example during scene rendering, the render loop calls Scene::Render_0()

https://bitbucket.org/face/ovp/src/...k/D3D11Client/Scene.cpp?at=D3D11Client#cl-401

There is a line there :
//background
CB->Render();

which render the celestial background. I am trying to understand the algorithm behind rendering just the celestial background for now.

So CB->Render is this function :

https://bitbucket.org/face/ovp/src/...lient/CelBackground.cpp?at=D3D11Client#cl-104

The main part of the function which renders is this :
Code:
void CelBackground::Render( /*int level, int bglvl*/ ) {
..
......
 for( hemisphere = idx = 0; hemisphere < 2; hemisphere++ ) {
                if( hemisphere )
                        D3DXMatrixMultiply( &RP.mWorld, &TileManager::RSouth, &RP.mWorld );
                for( ilat = nlat-1; ilat >= 0; ilat-- ) {
                        for( ilng = 0; ilng < nlng[ilat]; ilng++ ) {
                                ProcessTile( hemisphere, startlvl, ilat, nlat, ilng, nlng[ilat], td+idx,
                                        range, td[idx].tex );
                                idx++;
                        }
                }
        }
        dCtx->RSSetState( RS_Back_Solid );
}

void CelBackground::ProcessTile( int hemisphere, int lvl, int ilat, int nlat, int ilng, int nlng, TILEDESC *tile,
                const TEXCRDRANGE &range, ID3D11ShaderResourceView *tex )
{
        static const double rad0 = sqrt(2.0)*PI05;
        VECTOR3 cnt = GetTileCenter( hemisphere, ilat, nlat, ilng, nlng);
        double rad = rad0/(double)nlat;
        double adist = acos( dotp( RP.CamDir, cnt ) ) - rad;
        if( adist > RP.viewap )
                return;

        SetWorldMatrix( ilat, nlat, ilng, nlng );

        if( !IsTileInView( lvl, ilat ) )
                return;

        RenderTile( hemisphere, lvl, ilat, nlat, ilng, nlng, tile, range, tex );
}

The part that I am unable to understand clearly is IsTileInView() :
Code:
bool CelBackground::IsTileInView( int lvl, int ilat ) {
	TILEMESH &mesh = TPL[lvl][ilat];

	float rad = mesh.bsRad*2000.0f;
	D3DXVECTOR3 vP;
	D3DXVec3TransformCoord( &vP, &mesh.bsCnt, &mWorld );
	return SC->IsVisibleInCamera( &vP, rad );
}

Specifically the

Code:
bool Scene::IsVisibleInCamera( D3DXVECTOR3 *pCnt, float radius ) {
//tilemanger, cloudmanager:
	float z = camera_z.x*pCnt->x + camera_z.y*pCnt->y + camera_z.z*pCnt->z;
	if( z < (-radius) ) return false; 
	if( z < 0) z=-z;
	float y = camera_y.x*pCnt->x + camera_y.y*pCnt->y + camera_y.z*pCnt->z;
	if( y < 0) y=-y;
	if( y - (radius*vhf) > (vh*z) ) return false; 
	float x = camera_x.x*pCnt->x + camera_x.y*pCnt->y + camera_x.z*pCnt->z;
	if( x < 0 ) x=-x;
	if( x - (radius*vwf) > (vw*z) ) return false;
	return true;
}

Basically what all the above functions do is divide up the entire celestial sphere into patches decided by the gaps between the lats and longitudes. Each patch is a tile I guess. Each tile's center is found. Then to decide the visibility of the tile through the camera, the position vector of the center of the tile in world space and the camera's forward direction in world space should be dotted (dot product-ed) and that should give a clue.

But it seems a lot more is going on here. Anyone has a clue ?

---------- Post added at 11:30 PM ---------- Previous post was at 11:11 PM ----------

It seems to be related to culling meshes based on the bounding sphere of the mesh and the camera aperture information. There is a part just before a D3D11 mesh is rendered where I can see similar logic :

Code:
void D3D11Mesh::Render( vObject *vobj, D3DXMATRIX *mOfsWorld, bool mesh_cull, bool grp_cull ) {
	D3D11Material *Mat;
	DWORD pSDR, SDR, p_TEX, _TEX, BLND, p_BLND;
	const UINT MeshVertexStride = 44, VBOffset = 0;

//
//check mesh visibility and cull invisible meshes:
	float
		ap = (float)SC->GetCamAperture(),
		h = tan( ap ),
		dfr = 0.0015f*h,
		hf = 1.0f/cos( ap ),
		as = cfg->Aspect,
		w = h*as,
		wf = hf*as;

	if( mesh_cull ) 
	{
		D3DXVECTOR3 vP;
		D3DXMATRIX mWorldView = *mOfsWorld * *SC->GetV();
		D3DXVec3TransformCoord( &vP, &bsPos, &mWorldView );
		float r = bsRad;
	
		if( r < 0 )		r = -r;
		if( vP.z < (-r) )	return;
		if( vP.z < 0 )	vP.z = -vP.z;
		if( vP.y < 0 )	vP.y = -vP.y;
		if( vP.x < 0 )	vP.x = -vP.x;
		if( (r/vP.z) < dfr )    return;
		if( vP.y - (r*hf) > (h*vP.z) )	return;
		if( vP.x - (r*wf) > (w*vP.z) )	return;
	}


.......
.............

Hmmm, for some reason the tan of the aperture angle gives the height of the viewport and the width is got from this using the aspect ratio 'as'
But what is :

hf = 1.0f/cos( ap ),

A wild guess...but maybe its the height of the far plane of the view frustum ? Probably got to read up on view frustum culling.
 
Last edited:
Top