Ejemplo n.º 1
0
/*
* RB_ScissorForBounds
*/
bool RB_ScissorForBounds( vec3_t bbox[8], int *x, int *y, int *w, int *h )
{
    int i;
    int ix1, iy1, ix2, iy2;
    float x1, y1, x2, y2;
    vec4_t corner = { 0, 0, 0, 1 }, proj = { 0, 0, 0, 1 }, v = { 0, 0, 0, 1 };
    mat4_t cameraProjectionMatrix;

    Matrix4_Multiply( rb.projectionMatrix, rb.cameraMatrix, cameraProjectionMatrix );

    x1 = y1 = 999999;
    x2 = y2 = -999999;
    for( i = 0; i < 8; i++ )
    {
        // compute and rotate the full bounding box
        VectorCopy( bbox[i], corner );

        Matrix4_Multiply_Vector( cameraProjectionMatrix, corner, proj );

        if( proj[3] ) {
            v[0] = ( proj[0] / proj[3] + 1.0f ) * 0.5f * rb.gl.viewport[2];
            v[1] = ( proj[1] / proj[3] + 1.0f ) * 0.5f * rb.gl.viewport[3];
            v[2] = ( proj[2] / proj[3] + 1.0f ) * 0.5f; // [-1..1] -> [0..1]
        } else {
            v[0] = 999999.0f;
            v[1] = 999999.0f;
            v[2] = 999999.0f;
        }

        x1 = min( x1, v[0] );
        y1 = min( y1, v[1] );
        x2 = max( x2, v[0] );
        y2 = max( y2, v[1] );
    }

    ix1 = max( x1 - 1.0f, 0 );
    ix2 = min( x2 + 1.0f, rb.gl.viewport[2] );
    if( ix1 >= ix2 )
        return false; // FIXME

    iy1 = max( y1 - 1.0f, 0 );
    iy2 = min( y2 + 1.0f, rb.gl.viewport[3] );
    if( iy1 >= iy2 )
        return false; // FIXME

    *x = ix1;
    *y = rb.gl.viewport[3] - iy2;
    *w = ix2 - ix1;
    *h = iy2 - iy1;

    return true;
}
Ejemplo n.º 2
0
/*
* Matrix4_Modelview
*/
void Matrix4_Modelview( const vec3_t viewOrg, const mat3_t viewAxis, mat4_t m )
{
	mat3_t axis;
	mat4_t flip, view;

#if 0
	Matrix4_Identity( flip );
	Matrix4_Rotate( flip, -90, 1, 0, 0 );
	Matrix4_Rotate( flip, 90, 0, 0, 1 );
#else
	Vector4Set( &flip[0], 0, 0, -1, 0 );
	Vector4Set( &flip[4], -1, 0, 0, 0 );
	Vector4Set( &flip[8], 0, 1, 0, 0 );
	Vector4Set( &flip[12], 0, 0, 0, 1 );
#endif

	Matrix3_Copy( viewAxis, axis );

	view[0 ] = axis[0];
	view[4 ] = axis[1];
	view[8 ] = axis[2];
	view[12] = -viewOrg[0] * view[0] + -viewOrg[1] * view[4] + -viewOrg[2] * view[8];

	view[1 ] = axis[3];
	view[5 ] = axis[4];
	view[9 ] = axis[5];
	view[13] = -viewOrg[0] * view[1] + -viewOrg[1] * view[5] + -viewOrg[2] * view[9];

	view[2 ] = axis[6];
	view[6 ] = axis[7];
	view[10] = axis[8];
	view[14] = -viewOrg[0] * view[2] + -viewOrg[1] * view[6] + -viewOrg[2] * view[10];

	view[3] = 0;
	view[7] = 0;
	view[11] = 0;
	view[15] = 1;

	Matrix4_Multiply( flip, view, m );
}
Ejemplo n.º 3
0
/*
* RB_LoadProjectionMatrix
*/
void RB_LoadProjectionMatrix( const mat4_t m )
{
    Matrix4_Copy( m, rb.projectionMatrix );
    Matrix4_Multiply( m, rb.modelviewMatrix, rb.modelviewProjectionMatrix );
}
Ejemplo n.º 4
0
/*
* RB_LoadObjectMatrix
*/
void RB_LoadObjectMatrix( const mat4_t m )
{
    Matrix4_Copy( m, rb.objectMatrix );
    Matrix4_MultiplyFast( rb.cameraMatrix, m, rb.modelviewMatrix );
    Matrix4_Multiply( rb.projectionMatrix, rb.modelviewMatrix, rb.modelviewProjectionMatrix );
}
Ejemplo n.º 5
0
/*
* R_FitOccluder
*
* returns farclip value
*/
static float R_FitOccluder( const shadowGroup_t *group, refdef_t *refdef ) {
	int i;
	float x1, x2, y1, y2, z1, z2;
	int ix1, ix2, iy1, iy2, iz1, iz2;
	int sizex = refdef->width, sizey = refdef->height;
	int diffx, diffy;
	mat4_t cameraMatrix, projectionMatrix, cameraProjectionMatrix;
	bool useOrtho = refdef->rdflags & RDF_USEORTHO ? true : false;

	Matrix4_Modelview( refdef->vieworg, refdef->viewaxis, cameraMatrix );

	// use current view settings for first approximation
	if( useOrtho ) {
		Matrix4_OrthogonalProjection( -refdef->ortho_x, refdef->ortho_x, -refdef->ortho_y, refdef->ortho_y,
									  -group->projDist, group->projDist, projectionMatrix );
	} else {
		Matrix4_PerspectiveProjection( refdef->fov_x, refdef->fov_y,
									   Z_NEAR, group->projDist, rf.cameraSeparation, projectionMatrix );
	}

	Matrix4_Multiply( projectionMatrix, cameraMatrix, cameraProjectionMatrix );

	// compute optimal fov to increase depth precision (so that shadow group objects are
	// as close to the nearplane as possible)
	// note that it's suboptimal to use bbox calculated in worldspace (FIXME)
	x1 = y1 = z1 = 999999;
	x2 = y2 = z2 = -999999;
	for( i = 0; i < 8; i++ ) {
		// compute and rotate a full bounding box
		vec3_t v;
		vec4_t temp, temp2;

		temp[0] = ( ( i & 1 ) ? group->mins[0] : group->maxs[0] );
		temp[1] = ( ( i & 2 ) ? group->mins[1] : group->maxs[1] );
		temp[2] = ( ( i & 4 ) ? group->mins[2] : group->maxs[2] );
		temp[3] = 1.0f;

		// transform to screen space
		Matrix4_Multiply_Vector( cameraProjectionMatrix, temp, temp2 );

		if( temp2[3] ) {
			v[0] = ( temp2[0] / temp2[3] + 1.0f ) * 0.5f * refdef->width;
			v[1] = ( temp2[1] / temp2[3] + 1.0f ) * 0.5f * refdef->height;
			v[2] = ( temp2[2] / temp2[3] + 1.0f ) * 0.5f * group->projDist;
		} else {
			v[0] = 999999;
			v[1] = 999999;
			v[2] = 999999;
		}

		x1 = min( x1, v[0] ); y1 = min( y1, v[1] ); z1 = min( z1, v[2] );
		x2 = max( x2, v[0] ); y2 = max( y2, v[1] ); z2 = max( z2, v[2] );
	}

	// give it 1 pixel gap on both sides
	ix1 = x1 - 1.0f; ix2 = x2 + 1.0f;
	iy1 = y1 - 1.0f; iy2 = y2 + 1.0f;
	iz1 = z1 - 1.0f; iz2 = z2 + 1.0f;

	diffx = sizex - min( ix1, sizex - ix2 ) * 2;
	diffy = sizey - min( iy1, sizey - iy2 ) * 2;

	// adjust fov (for perspective projection)
	refdef->fov_x = 2 * RAD2DEG( atan( (float)diffx / (float)sizex ) );
	refdef->fov_y = 2 * RAD2DEG( atan( (float)diffy / (float)sizey ) );

	// adjust ortho clipping settings
	refdef->ortho_x = ix2 - ix1 + SHADOWMAP_ORTHO_NUDGE;
	refdef->ortho_y = iy2 - iy1 + SHADOWMAP_ORTHO_NUDGE;

	return useOrtho ? max( iz1, iz2 ) : group->projDist;
}