/* ================ CM_CreateNewFloatPlane ================ */ static int CM_CreateNewFloatPlane( vec4_t plane ) { #ifndef USE_HASHING // add a new plane if( numPlanes == SHADER_MAX_TRIANGLES ) Host_Error( "CM_CreateNewFloatPlane: SHADER_MAX_TRIANGLES limit exceeded\n" ); Vector4Copy( plane, planes[numPlanes].plane ); planes[numPlanes].signbits = SignbitsForPlane( plane ); numPlanes++; return numPlanes - 1; #else cmplane_t *p; // temp; // create a new plane if( numPlanes == SHADER_MAX_TRIANGLES ) Host_Error( "CM_FindPlane: SHADER_MAX_TRIANGLES limit exceeded\n" ); p = &planes[numPlanes]; Vector4Copy( plane, p->plane ); p->signbits = SignbitsForPlane(plane); numPlanes++; CM_AddPlaneToHash( p ); return numPlanes - 1; #endif }
/* * R_SetupFrustum */ void R_SetupFrustum( const refdef_t *rd, float farClip, cplane_t *frustum ) { int i; vec3_t forward, left, up; // 0 - left // 1 - right // 2 - down // 3 - up // 4 - farclip VectorCopy( &rd->viewaxis[AXIS_FORWARD], forward ); VectorCopy( &rd->viewaxis[AXIS_RIGHT], left ); VectorCopy( &rd->viewaxis[AXIS_UP], up ); if( rd->rdflags & RDF_USEORTHO ) { VectorNegate( left, frustum[0].normal ); VectorCopy( left, frustum[1].normal ); VectorNegate( up, frustum[2].normal ); VectorCopy( up, frustum[3].normal ); for( i = 0; i < 4; i++ ) { frustum[i].type = PLANE_NONAXIAL; frustum[i].dist = DotProduct( rd->vieworg, frustum[i].normal ); frustum[i].signbits = SignbitsForPlane( &frustum[i] ); } frustum[0].dist -= rd->ortho_x; frustum[1].dist -= rd->ortho_x; frustum[2].dist -= rd->ortho_y; frustum[3].dist -= rd->ortho_y; } else { vec3_t right; VectorNegate( left, right ); // rotate rn.vpn right by FOV_X/2 degrees RotatePointAroundVector( frustum[0].normal, up, forward, -( 90-rd->fov_x / 2 ) ); // rotate rn.vpn left by FOV_X/2 degrees RotatePointAroundVector( frustum[1].normal, up, forward, 90-rd->fov_x / 2 ); // rotate rn.vpn up by FOV_X/2 degrees RotatePointAroundVector( frustum[2].normal, right, forward, 90-rd->fov_y / 2 ); // rotate rn.vpn down by FOV_X/2 degrees RotatePointAroundVector( frustum[3].normal, right, forward, -( 90 - rd->fov_y / 2 ) ); for( i = 0; i < 4; i++ ) { frustum[i].type = PLANE_NONAXIAL; frustum[i].dist = DotProduct( rd->vieworg, frustum[i].normal ); frustum[i].signbits = SignbitsForPlane( &frustum[i] ); } } // farclip VectorNegate( forward, frustum[4].normal ); frustum[4].type = PLANE_NONAXIAL; frustum[4].dist = DotProduct( rd->vieworg, frustum[4].normal ) - farClip; frustum[4].signbits = SignbitsForPlane( &frustum[4] ); }
void R_SetFrustum (void) { int i; if (r_refdef.fov_x == 90) { // front side is visible VectorAdd (vpn, vright, frustum[0].normal); VectorSubtract (vpn, vright, frustum[1].normal); VectorAdd (vpn, vup, frustum[2].normal); VectorSubtract (vpn, vup, frustum[3].normal); } else { // rotate VPN right by FOV_X/2 degrees RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) ); // rotate VPN left by FOV_X/2 degrees RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 ); // rotate VPN up by FOV_X/2 degrees RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 ); // rotate VPN down by FOV_X/2 degrees RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) ); } for (i=0 ; i<4 ; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (r_origin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane (&frustum[i]); } }
/* =============== R_SetupFrustum =============== */ void R_SetupFrustum( void ) { vec3_t farPoint; int i; // 0 - left // 1 - right // 2 - down // 3 - up // 4 - farclip // 5 - nearclip if( RI.drawOrtho ) { R_SetupFrustumOrtho(); return; } // rotate RI.vforward right by FOV_X/2 degrees RotatePointAroundVector( RI.frustum[0].normal, RI.cull_vup, RI.cull_vforward, -( 90 - RI.refdef.fov_x / 2 )); // rotate RI.vforward left by FOV_X/2 degrees RotatePointAroundVector( RI.frustum[1].normal, RI.cull_vup, RI.cull_vforward, 90 - RI.refdef.fov_x / 2 ); // rotate RI.vforward up by FOV_X/2 degrees RotatePointAroundVector( RI.frustum[2].normal, RI.cull_vright, RI.cull_vforward, 90 - RI.refdef.fov_y / 2 ); // rotate RI.vforward down by FOV_X/2 degrees RotatePointAroundVector( RI.frustum[3].normal, RI.cull_vright, RI.cull_vforward, -( 90 - RI.refdef.fov_y / 2 )); // negate forward vector VectorNegate( RI.cull_vforward, RI.frustum[4].normal ); for( i = 0; i < 4; i++ ) { RI.frustum[i].type = PLANE_NONAXIAL; RI.frustum[i].dist = DotProduct( RI.cullorigin, RI.frustum[i].normal ); RI.frustum[i].signbits = SignbitsForPlane( RI.frustum[i].normal ); } VectorMA( RI.cullorigin, R_GetFarClip(), RI.cull_vforward, farPoint ); RI.frustum[i].type = PLANE_NONAXIAL; RI.frustum[i].dist = DotProduct( farPoint, RI.frustum[i].normal ); RI.frustum[i].signbits = SignbitsForPlane( RI.frustum[i].normal ); }
void FrustumCheck::R_SetFrustum (vec3_t vangles, vec3_t vorigin, float view_hor, float view_ver, float dist) { int i; vec3_t vpn, vright, vup; AngleVectors (vangles, vpn, vright, vup); // rotate VPN right by FOV_X/2 degrees RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-view_hor / 2 ) ); // rotate VPN left by FOV_X/2 degrees RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-view_hor / 2 ); // rotate VPN up by FOV_X/2 degrees RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-(view_ver) / 2 ); // rotate VPN down by FOV_X/2 degrees RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 -(view_ver) / 2 ) ); for (i=0 ; i<4 ; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (vorigin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane (&frustum[i]); } // buz: set also clipping by distance vec3_t farpoint = vorigin + (vpn * dist); farclip.normal = vpn * -1; farclip.type = PLANE_ANYZ; farclip.dist = DotProduct (farpoint, farclip.normal); farclip.signbits = SignbitsForPlane (&farclip); farclipset = 1; // save params for building stencil clipping volume VectorCopy(vorigin, m_origin); VectorCopy(vangles, m_angles); m_fov_hor = view_hor; m_fov_ver = view_ver; m_dist = dist; }
/* =============== R_SetFrustum -- johnfitz -- rewritten =============== */ void R_SetFrustum (float fovx, float fovy) { int i; TurnVector(frustum[0].normal, vpn, vright, fovx/2 - 90); //left plane TurnVector(frustum[1].normal, vpn, vright, 90 - fovx/2); //right plane TurnVector(frustum[2].normal, vpn, vup, 90 - fovy/2); //bottom plane TurnVector(frustum[3].normal, vpn, vup, fovy/2 - 90); //top plane for (i=0 ; i<4 ; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (r_origin, frustum[i].normal); //FIXME: shouldn't this always be zero? frustum[i].signbits = SignbitsForPlane (&frustum[i]); } }
/* =============== R_SetupFrustumOrtho =============== */ static void R_SetupFrustumOrtho( void ) { ref_overview_t *ov = &clgame.overView; float orgOffset; int i; // 0 - left // 1 - right // 2 - down // 3 - up // 4 - farclip // 5 - nearclip // setup the near and far planes. orgOffset = DotProduct( RI.cullorigin, RI.cull_vforward ); VectorNegate( RI.cull_vforward, RI.frustum[4].normal ); RI.frustum[4].dist = -ov->zFar - orgOffset; VectorCopy( RI.cull_vforward, RI.frustum[5].normal ); RI.frustum[5].dist = ov->zNear + orgOffset; // left and right planes... orgOffset = DotProduct( RI.cullorigin, RI.cull_vright ); VectorCopy( RI.cull_vright, RI.frustum[0].normal ); RI.frustum[0].dist = ov->xLeft + orgOffset; VectorNegate( RI.cull_vright, RI.frustum[1].normal ); RI.frustum[1].dist = -ov->xRight - orgOffset; // top and buttom planes... orgOffset = DotProduct( RI.cullorigin, RI.cull_vup ); VectorCopy( RI.cull_vup, RI.frustum[3].normal ); RI.frustum[3].dist = ov->xTop + orgOffset; VectorNegate( RI.cull_vup, RI.frustum[2].normal ); RI.frustum[2].dist = -ov->xBottom - orgOffset; for( i = 0; i < 6; i++ ) { RI.frustum[i].type = PLANE_NONAXIAL; RI.frustum[i].signbits = SignbitsForPlane( RI.frustum[i].normal ); } }
void R_SetFrustum (float fovx, float fovy) { int i; if (r_stereo.value) fovx += 10; //silly hack so that polygons don't drop out becuase of stereo skew TurnVector(frustum[0].normal, vpn, vright, fovx/2 - 90); //left plane TurnVector(frustum[1].normal, vpn, vright, 90 - fovx/2); //right plane TurnVector(frustum[2].normal, vpn, vup, 90 - fovy/2); //bottom plane TurnVector(frustum[3].normal, vpn, vup, fovy/2 - 90); //top plane for (i=0 ; i<4 ; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = Math_DotProduct(r_origin, frustum[i].normal); //FIXME: shouldn't this always be zero? frustum[i].signbits = SignbitsForPlane (&frustum[i]); } }
void FrustumCheck::R_SetFrustum (vec3_t vangles, vec3_t vorigin, float viewsize) { int i; vec3_t vpn, vright, vup; AngleVectors (vangles, vpn, vright, vup); if (viewsize == 90) { // front side is visible VectorAdd (vpn, vright, frustum[0].normal); VectorSubtract (vpn, vright, frustum[1].normal); VectorAdd (vpn, vup, frustum[2].normal); VectorSubtract (vpn, vup, frustum[3].normal); } else { // rotate VPN right by FOV_X/2 degrees RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-viewsize / 2 ) ); // rotate VPN left by FOV_X/2 degrees RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-viewsize / 2 ); // rotate VPN up by FOV_X/2 degrees RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-(viewsize*0.75) / 2 ); // rotate VPN down by FOV_X/2 degrees RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 -(viewsize*0.75) / 2 ) ); } for (i=0 ; i<4 ; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (vorigin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane (&frustum[i]); } farclipset = 0; // buz }
void R_SetFrustum (void) { int i; // rotate VPN right by FOV_X/2 degrees RotatePointAroundVector (frustum[0].normal, vup, vpn, -(90 - r_refdef.fov_x / 2)); // rotate VPN left by FOV_X/2 degrees RotatePointAroundVector (frustum[1].normal, vup, vpn, 90 - r_refdef.fov_x / 2); // rotate VPN up by FOV_Y/2 degrees RotatePointAroundVector (frustum[2].normal, vright, vpn, 90 - r_refdef.fov_y / 2); // rotate VPN down by FOV_Y/2 degrees RotatePointAroundVector (frustum[3].normal, vright, vpn, -(90 - r_refdef.fov_y / 2)); for (i = 0; i < 4; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (r_origin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane (&frustum[i]); } }
/* ================ R_DrawMirrors Draw all viewpasess from mirror position Mirror textures will be drawn in normal pass ================ */ void R_DrawMirrors( void ) { ref_instance_t oldRI; mplane_t plane; msurface_t *surf, *surf2; int i, oldframecount; mextrasurf_t *es, *tmp, *mirrorchain; vec3_t forward, right, up; vec3_t origin, angles; matrix4x4 mirrormatrix; cl_entity_t *e; model_t *m; float d; if( !tr.num_mirror_entities ) return; // mo mirrors for this frame oldRI = RI; // make refinst backup oldframecount = tr.framecount; for( i = 0; i < tr.num_mirror_entities; i++ ) { mirrorchain = tr.mirror_entities[i].chain; for( es = mirrorchain; es != NULL; es = es->mirrorchain ) { RI.currententity = e = tr.mirror_entities[i].ent; RI.currentmodel = m = RI.currententity->model; surf = INFO_SURF( es, m ); ASSERT( RI.currententity != NULL ); ASSERT( RI.currentmodel != NULL ); // NOTE: copy mirrortexture and mirrormatrix from another surfaces // from this entity\world that has same planes and reduce number of viewpasses // make sure what we have one pass at least if( es != mirrorchain ) { for( tmp = mirrorchain; tmp != es; tmp = tmp->mirrorchain ) { surf2 = INFO_SURF( tmp, m ); if( !tmp->mirrortexturenum ) continue; // not filled? if( surf->plane->dist != surf2->plane->dist ) continue; if( !VectorCompare( surf->plane->normal, surf2->plane->normal )) continue; // found surface with same plane! break; } if( tmp != es && tmp && tmp->mirrortexturenum ) { // just copy reflection texture from surface with same plane Matrix4x4_Copy( es->mirrormatrix, tmp->mirrormatrix ); es->mirrortexturenum = tmp->mirrortexturenum; continue; // pass skiped } } R_PlaneForMirror( surf, &plane, mirrormatrix ); d = -2.0f * ( DotProduct( RI.vieworg, plane.normal ) - plane.dist ); VectorMA( RI.vieworg, d, plane.normal, origin ); d = -2.0f * DotProduct( RI.vforward, plane.normal ); VectorMA( RI.vforward, d, plane.normal, forward ); VectorNormalize( forward ); d = -2.0f * DotProduct( RI.vright, plane.normal ); VectorMA( RI.vright, d, plane.normal, right ); VectorNormalize( right ); d = -2.0f * DotProduct( RI.vup, plane.normal ); VectorMA( RI.vup, d, plane.normal, up ); VectorNormalize( up ); VectorsAngles( forward, right, up, angles ); angles[ROLL] = -angles[ROLL]; RI.params = RP_MIRRORVIEW|RP_CLIPPLANE|RP_OLDVIEWLEAF; RI.clipPlane = plane; RI.clipFlags |= ( 1<<5 ); RI.frustum[5] = plane; RI.frustum[5].signbits = SignbitsForPlane( RI.frustum[5].normal ); RI.frustum[5].type = PLANE_NONAXIAL; RI.refdef.viewangles[0] = anglemod( angles[0] ); RI.refdef.viewangles[1] = anglemod( angles[1] ); RI.refdef.viewangles[2] = anglemod( angles[2] ); VectorCopy( origin, RI.refdef.vieworg ); VectorCopy( origin, RI.cullorigin ); // put pvsorigin before the mirror plane to avoid get full visibility on world mirrors if( RI.currententity == clgame.entities ) { VectorMA( es->origin, 1.0f, plane.normal, origin ); } else { Matrix4x4_VectorTransform( mirrormatrix, es->origin, origin ); VectorMA( origin, 1.0f, plane.normal, origin ); } VectorCopy( origin, RI.pvsorigin ); // combine two leafs from client and mirror views r_viewleaf = Mod_PointInLeaf( oldRI.pvsorigin, cl.worldmodel->nodes ); r_viewleaf2 = Mod_PointInLeaf( RI.pvsorigin, cl.worldmodel->nodes ); if( GL_Support( GL_ARB_TEXTURE_NPOT_EXT )) { // allow screen size RI.viewport[2] = bound( 96, RI.viewport[2], 1024 ); RI.viewport[3] = bound( 72, RI.viewport[3], 768 ); } else { RI.viewport[2] = NearestPOW( RI.viewport[2], true ); RI.viewport[3] = NearestPOW( RI.viewport[3], true ); RI.viewport[2] = bound( 128, RI.viewport[2], 1024 ); RI.viewport[3] = bound( 64, RI.viewport[3], 512 ); } tr.framecount++; R_RenderScene( &RI.refdef ); r_stats.c_mirror_passes++; es->mirrortexturenum = R_AllocateMirrorTexture(); // create personal projection matrix for mirror if( VectorIsNull( e->origin ) && VectorIsNull( e->angles )) { Matrix4x4_Copy( es->mirrormatrix, RI.worldviewProjectionMatrix ); } else { Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, mirrormatrix ); Matrix4x4_Concat( es->mirrormatrix, RI.projectionMatrix, RI.modelviewMatrix ); } RI = oldRI; // restore ref instance } // clear chain for this entity for( es = mirrorchain; es != NULL; ) { tmp = es->mirrorchain; es->mirrorchain = NULL; es = tmp; } tr.mirror_entities[i].chain = NULL; // done tr.mirror_entities[i].ent = NULL; } r_oldviewleaf = r_viewleaf = NULL; // force markleafs next frame tr.framecount = oldframecount; // restore real framecount tr.num_mirror_entities = 0; tr.num_mirrors_used = 0; }