void Categorizer::Categorize(std::vector<CorrelationAircraft *> *aircraft) { CDTIReport *report = new CDTIReport(); int64_t t = 1; report->set_timestamp(t); CDTIPlane* ownship = new CDTIPlane(); Vector* pv = new Vector(); printf("printCategorizereport\n"); pv->set_d(0); pv->set_e(0); pv->set_n(0); ownship->set_allocated_position(pv); ownship->set_allocated_velocity(pv); ownship->set_id("2"); ownship->set_severity(CDTIPlane_Severity_PROXIMATE); report->set_allocated_ownship(ownship); report->set_advisorymessage("message"); report->set_advisorylevel(CDTIReport_Severity_PROXIMATE); // report->mutable_planes()->AddAllocated(plane); //call something to translate whatever is given into a list of CDTIplanes for (int i = 0; i < aircraft->size(); i++) { CDTIPlane plane = MakeCDTIPlane(aircraft->at(i)); plane.set_severity(CategorizePlane(plane)); CDTIPlane *set = report->add_planes(); *set = plane; } cout << ownship->id(); _client_socket << *report; }
/* * R_TraceLine */ static msurface_t *R_TransformedTraceLine( rtrace_t *tr, const vec3_t start, const vec3_t end, entity_t *test, int surfumask ) { model_t *model; r_traceframecount++; // for multi-check avoidance // fill in a default trace memset( tr, 0, sizeof( *tr ) ); trace_surface = NULL; trace_umask = surfumask; trace_fraction = 1; VectorCopy( end, trace_impact ); memset( &trace_plane, 0, sizeof( trace_plane ) ); ClearBounds( trace_absmins, trace_absmaxs ); AddPointToBounds( start, trace_absmins, trace_absmaxs ); AddPointToBounds( end, trace_absmins, trace_absmaxs ); model = test->model; if( model ) { if( model->type == mod_brush ) { mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata; vec3_t temp, start_l, end_l; mat3_t axis; bool rotated = !Matrix3_Compare( test->axis, axis_identity ); // transform VectorSubtract( start, test->origin, start_l ); VectorSubtract( end, test->origin, end_l ); if( rotated ) { VectorCopy( start_l, temp ); Matrix3_TransformVector( test->axis, temp, start_l ); VectorCopy( end_l, temp ); Matrix3_TransformVector( test->axis, temp, end_l ); } VectorCopy( start_l, trace_start ); VectorCopy( end_l, trace_end ); // world uses a recursive approach using BSP tree, submodels // just walk the list of surfaces linearly if( test->model == rsh.worldModel ) { R_RecursiveHullCheck( bmodel->nodes, start_l, end_l ); } else if( BoundsIntersect( model->mins, model->maxs, trace_absmins, trace_absmaxs ) ) { R_TraceAgainstBmodel( bmodel ); } // transform back if( rotated && trace_fraction != 1 ) { Matrix3_Transpose( test->axis, axis ); VectorCopy( tr->plane.normal, temp ); Matrix3_TransformVector( axis, temp, trace_plane.normal ); } } } // calculate the impact plane, if any if( trace_fraction < 1 && trace_surface != NULL ) { VectorNormalize( trace_plane.normal ); trace_plane.dist = DotProduct( trace_plane.normal, trace_impact ); CategorizePlane( &trace_plane ); tr->shader = trace_surface->shader; tr->plane = trace_plane; tr->surfFlags = trace_surface->flags; tr->ent = R_ENT2NUM( test ); } tr->fraction = trace_fraction; VectorCopy( trace_impact, tr->endpos ); return trace_surface; }
/* * R_AddPortalSurface */ portalSurface_t *R_AddPortalSurface( const entity_t *ent, const mesh_t *mesh, const vec3_t mins, const vec3_t maxs, const shader_t *shader ) { unsigned int i; float dist; cplane_t plane, untransformed_plane; vec3_t v[3]; portalSurface_t *portalSurface; if( !mesh ) { return NULL; } if( R_FASTSKY() && !( shader->flags & (SHADER_PORTAL_CAPTURE|SHADER_PORTAL_CAPTURE2) ) ) { // r_fastsky doesn't affect portalmaps return NULL; } for( i = 0; i < 3; i++ ) { VectorCopy( mesh->xyzArray[mesh->elems[i]], v[i] ); } PlaneFromPoints( v, &untransformed_plane ); untransformed_plane.dist += DotProduct( ent->origin, untransformed_plane.normal ); CategorizePlane( &untransformed_plane ); if( shader->flags & SHADER_AUTOSPRITE ) { vec3_t centre; // autosprites are quads, facing the viewer if( mesh->numVerts < 4 ) { return NULL; } // compute centre as average of 4 vertices VectorCopy( mesh->xyzArray[mesh->elems[3]], centre ); for( i = 0; i < 3; i++ ) VectorAdd( centre, v[i], centre ); VectorMA( ent->origin, 0.25, centre, centre ); VectorNegate( &rn.viewAxis[AXIS_FORWARD], plane.normal ); plane.dist = DotProduct( plane.normal, centre ); CategorizePlane( &plane ); } else { vec3_t temp; mat3_t entity_rotation; // regular surfaces if( !Matrix3_Compare( ent->axis, axis_identity ) ) { Matrix3_Transpose( ent->axis, entity_rotation ); for( i = 0; i < 3; i++ ) { VectorCopy( v[i], temp ); Matrix3_TransformVector( entity_rotation, temp, v[i] ); VectorMA( ent->origin, ent->scale, v[i], v[i] ); } PlaneFromPoints( v, &plane ); CategorizePlane( &plane ); } else { plane = untransformed_plane; } } if( ( dist = PlaneDiff( rn.viewOrigin, &plane ) ) <= BACKFACE_EPSILON ) { // behind the portal plane if( !( shader->flags & SHADER_PORTAL_CAPTURE2 ) ) { return NULL; } // we need to render the backplane view } // check if portal view is opaque due to alphagen portal if( shader->portalDistance && dist > shader->portalDistance ) { return NULL; } // find the matching portal plane for( i = 0; i < rn.numPortalSurfaces; i++ ) { portalSurface = &rn.portalSurfaces[i]; if( portalSurface->entity == ent && portalSurface->shader == shader && DotProduct( portalSurface->plane.normal, plane.normal ) > 0.99f && fabs( portalSurface->plane.dist - plane.dist ) < 0.1f ) { goto addsurface; } } if( i == MAX_PORTAL_SURFACES ) { // not enough space return NULL; } portalSurface = &rn.portalSurfaces[rn.numPortalSurfaces++]; portalSurface->entity = ent; portalSurface->plane = plane; portalSurface->shader = shader; portalSurface->untransformed_plane = untransformed_plane; ClearBounds( portalSurface->mins, portalSurface->maxs ); memset( portalSurface->texures, 0, sizeof( portalSurface->texures ) ); addsurface: AddPointToBounds( mins, portalSurface->mins, portalSurface->maxs ); AddPointToBounds( maxs, portalSurface->mins, portalSurface->maxs ); VectorAdd( portalSurface->mins, portalSurface->maxs, portalSurface->centre ); VectorScale( portalSurface->centre, 0.5, portalSurface->centre ); return portalSurface; }
/* * R_DrawPortalSurface * * Renders the portal view and captures the results from framebuffer if * we need to do a $portalmap stage. Note that for $portalmaps we must * use a different viewport. */ static void R_DrawPortalSurface( portalSurface_t *portalSurface ) { unsigned int i; int x, y, w, h; float dist, d, best_d; vec3_t viewerOrigin; vec3_t origin; mat3_t axis; entity_t *ent, *best; const entity_t *portal_ent = portalSurface->entity; cplane_t *portal_plane = &portalSurface->plane, *untransformed_plane = &portalSurface->untransformed_plane; const shader_t *shader = portalSurface->shader; vec_t *portal_mins = portalSurface->mins, *portal_maxs = portalSurface->maxs; vec_t *portal_centre = portalSurface->centre; qboolean mirror, refraction = qfalse; image_t *captureTexture; int captureTextureId = -1; int prevRenderFlags = 0; qboolean doReflection, doRefraction; image_t *portalTexures[2] = { NULL, NULL }; doReflection = doRefraction = qtrue; if( shader->flags & SHADER_PORTAL_CAPTURE ) { shaderpass_t *pass; captureTexture = NULL; captureTextureId = 0; for( i = 0, pass = shader->passes; i < shader->numpasses; i++, pass++ ) { if( pass->program_type == GLSL_PROGRAM_TYPE_DISTORTION ) { if( ( pass->alphagen.type == ALPHA_GEN_CONST && pass->alphagen.args[0] == 1 ) ) doRefraction = qfalse; else if( ( pass->alphagen.type == ALPHA_GEN_CONST && pass->alphagen.args[0] == 0 ) ) doReflection = qfalse; break; } } } else { captureTexture = NULL; captureTextureId = -1; } x = y = 0; w = rn.refdef.width; h = rn.refdef.height; dist = PlaneDiff( rn.viewOrigin, portal_plane ); if( dist <= BACKFACE_EPSILON || !doReflection ) { if( !( shader->flags & SHADER_PORTAL_CAPTURE2 ) || !doRefraction ) return; // even if we're behind the portal, we still need to capture // the second portal image for refraction refraction = qtrue; captureTexture = NULL; captureTextureId = 1; if( dist < 0 ) { VectorInverse( portal_plane->normal ); portal_plane->dist = -portal_plane->dist; } } if( !(rn.renderFlags & RF_NOVIS) && !R_ScissorForEntity( portal_ent, portal_mins, portal_maxs, &x, &y, &w, &h ) ) return; mirror = qtrue; // default to mirror view // it is stupid IMO that mirrors require a RT_PORTALSURFACE entity best = NULL; best_d = 100000000; for( i = 1; i < rsc.numEntities; i++ ) { ent = R_NUM2ENT(i); if( ent->rtype != RT_PORTALSURFACE ) continue; d = PlaneDiff( ent->origin, untransformed_plane ); if( ( d >= -64 ) && ( d <= 64 ) ) { d = Distance( ent->origin, portal_centre ); if( d < best_d ) { best = ent; best_d = d; } } } if( best == NULL ) { if( captureTextureId < 0 ) return; } else { if( !VectorCompare( best->origin, best->origin2 ) ) // portal mirror = qfalse; best->rtype = NUM_RTYPES; } prevRenderFlags = rn.renderFlags; if( !R_PushRefInst() ) { return; } VectorCopy( rn.viewOrigin, viewerOrigin ); setup_and_render: if( refraction ) { VectorInverse( portal_plane->normal ); portal_plane->dist = -portal_plane->dist - 1; CategorizePlane( portal_plane ); VectorCopy( rn.viewOrigin, origin ); Matrix3_Copy( rn.refdef.viewaxis, axis ); VectorCopy( viewerOrigin, rn.pvsOrigin ); rn.renderFlags = RF_PORTALVIEW; if( !mirror ) rn.renderFlags |= RF_PVSCULL; } else if( mirror ) { VectorReflect( rn.viewOrigin, portal_plane->normal, portal_plane->dist, origin ); VectorReflect( &rn.viewAxis[AXIS_FORWARD], portal_plane->normal, 0, &axis[AXIS_FORWARD] ); VectorReflect( &rn.viewAxis[AXIS_RIGHT], portal_plane->normal, 0, &axis[AXIS_RIGHT] ); VectorReflect( &rn.viewAxis[AXIS_UP], portal_plane->normal, 0, &axis[AXIS_UP] ); Matrix3_Normalize( axis ); VectorCopy( viewerOrigin, rn.pvsOrigin ); rn.renderFlags = RF_MIRRORVIEW|RF_FLIPFRONTFACE; } else { vec3_t tvec; mat3_t A, B, C, rot; // build world-to-portal rotation matrix VectorNegate( portal_plane->normal, tvec ); NormalVectorToAxis( tvec, A ); // build portal_dest-to-world rotation matrix ByteToDir( best->frame, tvec ); NormalVectorToAxis( tvec, B ); Matrix3_Transpose( B, C ); // multiply to get world-to-world rotation matrix Matrix3_Multiply( C, A, rot ); // translate view origin VectorSubtract( rn.viewOrigin, best->origin, tvec ); Matrix3_TransformVector( rot, tvec, origin ); VectorAdd( origin, best->origin2, origin ); Matrix3_Transpose( A, B ); Matrix3_Multiply( rn.viewAxis, B, rot ); Matrix3_Multiply( best->axis, rot, B ); Matrix3_Transpose( C, A ); Matrix3_Multiply( B, A, axis ); // set up portal_plane VectorCopy( &axis[AXIS_FORWARD], portal_plane->normal ); portal_plane->dist = DotProduct( best->origin2, portal_plane->normal ); CategorizePlane( portal_plane ); // for portals, vis data is taken from portal origin, not // view origin, because the view point moves around and // might fly into (or behind) a wall rn.renderFlags = RF_PORTALVIEW|RF_PVSCULL; VectorCopy( best->origin2, rn.pvsOrigin ); VectorCopy( best->origin2, rn.lodOrigin ); // ignore entities, if asked politely if( best->renderfx & RF_NOPORTALENTS ) rn.renderFlags |= RF_NOENTS; } rn.renderFlags |= (prevRenderFlags & RF_SOFT_PARTICLES); rn.refdef.rdflags &= ~( RDF_UNDERWATER|RDF_CROSSINGWATER ); rn.shadowGroup = NULL; rn.meshlist = &r_portallist; rn.renderFlags |= RF_CLIPPLANE; rn.clipPlane = *portal_plane; rn.farClip = R_DefaultFarClip(); rn.clipFlags |= ( 1<<5 ); rn.frustum[5] = *portal_plane; CategorizePlane( &rn.frustum[5] ); // if we want to render to a texture, initialize texture // but do not try to render to it more than once if( captureTextureId >= 0 ) { int texFlags = shader->flags & SHADER_NO_TEX_FILTERING ? IT_NOFILTERING : 0; captureTexture = R_GetPortalTexture( rsc.refdef.width, rsc.refdef.height, texFlags, rsc.frameCount ); portalTexures[captureTextureId] = captureTexture; if( !captureTexture ) { // couldn't register a slot for this plane goto done; } x = y = 0; w = captureTexture->upload_width; h = captureTexture->upload_height; rn.refdef.width = w; rn.refdef.height = h; rn.refdef.x = 0; rn.refdef.y = 0; rn.fbColorAttachment = captureTexture; // no point in capturing the depth buffer due to oblique frustum messing up // the far plane and depth values rn.fbDepthAttachment = NULL; Vector4Set( rn.viewport, rn.refdef.x + x, rn.refdef.y + y, w, h ); Vector4Set( rn.scissor, rn.refdef.x + x, rn.refdef.y + y, w, h ); } else { // no point in capturing the depth buffer due to oblique frustum messing up // the far plane and depth values rn.fbDepthAttachment = NULL; Vector4Set( rn.scissor, rn.refdef.x + x, rn.refdef.y + y, w, h ); } VectorCopy( origin, rn.refdef.vieworg ); Matrix3_Copy( axis, rn.refdef.viewaxis ); R_RenderView( &rn.refdef ); if( doRefraction && !refraction && ( shader->flags & SHADER_PORTAL_CAPTURE2 ) ) { refraction = qtrue; captureTexture = NULL; captureTextureId = 1; goto setup_and_render; } done: portalSurface->texures[0] = portalTexures[0]; portalSurface->texures[1] = portalTexures[1]; R_PopRefInst( rn.fbDepthAttachment != NULL ? 0 : GL_DEPTH_BUFFER_BIT ); }
/* * R_UpdatePortalSurface */ void R_UpdatePortalSurface( portalSurface_t *portalSurface, const mesh_t *mesh, const vec3_t mins, const vec3_t maxs, const shader_t *shader ) { unsigned int i; float dist; cplane_t plane, untransformed_plane; vec3_t v[3]; const entity_t *ent; if( !mesh || !portalSurface ) { return; } ent = portalSurface->entity; for( i = 0; i < 3; i++ ) { VectorCopy( mesh->xyzArray[mesh->elems[i]], v[i] ); } PlaneFromPoints( v, &untransformed_plane ); untransformed_plane.dist += DotProduct( ent->origin, untransformed_plane.normal ); untransformed_plane.dist += 1; // nudge along the normal a bit CategorizePlane( &untransformed_plane ); if( shader->flags & SHADER_AUTOSPRITE ) { vec3_t centre; // autosprites are quads, facing the viewer if( mesh->numVerts < 4 ) { return; } // compute centre as average of 4 vertices VectorCopy( mesh->xyzArray[mesh->elems[3]], centre ); for( i = 0; i < 3; i++ ) VectorAdd( centre, v[i], centre ); VectorMA( ent->origin, 0.25, centre, centre ); VectorNegate( &rn.viewAxis[AXIS_FORWARD], plane.normal ); plane.dist = DotProduct( plane.normal, centre ); CategorizePlane( &plane ); } else { vec3_t temp; mat3_t entity_rotation; // regular surfaces if( !Matrix3_Compare( ent->axis, axis_identity ) ) { Matrix3_Transpose( ent->axis, entity_rotation ); for( i = 0; i < 3; i++ ) { VectorCopy( v[i], temp ); Matrix3_TransformVector( entity_rotation, temp, v[i] ); VectorMA( ent->origin, ent->scale, v[i], v[i] ); } PlaneFromPoints( v, &plane ); CategorizePlane( &plane ); } else { plane = untransformed_plane; } } if( ( dist = PlaneDiff( rn.viewOrigin, &plane ) ) <= BACKFACE_EPSILON ) { // behind the portal plane if( !( shader->flags & SHADER_PORTAL_CAPTURE2 ) ) { return; } // we need to render the backplane view } // check if portal view is opaque due to alphagen portal if( shader->portalDistance && dist > shader->portalDistance ) { return; } portalSurface->plane = plane; portalSurface->untransformed_plane = untransformed_plane; AddPointToBounds( mins, portalSurface->mins, portalSurface->maxs ); AddPointToBounds( maxs, portalSurface->mins, portalSurface->maxs ); VectorAdd( portalSurface->mins, portalSurface->maxs, portalSurface->centre ); VectorScale( portalSurface->centre, 0.5, portalSurface->centre ); }
/* * R_DrawPortalSurface * * Renders the portal view and captures the results from framebuffer if * we need to do a $portalmap stage. Note that for $portalmaps we must * use a different viewport. */ static void R_DrawPortalSurface( portalSurface_t *portalSurface ) { unsigned int i; int x, y, w, h; float dist, d, best_d; vec3_t viewerOrigin; vec3_t origin; mat3_t axis; entity_t *ent, *best; cplane_t *portal_plane = &portalSurface->plane, *untransformed_plane = &portalSurface->untransformed_plane; const shader_t *shader = portalSurface->shader; vec_t *portal_centre = portalSurface->centre; bool mirror, refraction = false; image_t *captureTexture; int captureTextureId = -1; int prevRenderFlags = 0; bool prevFlipped; bool doReflection, doRefraction; image_t *portalTexures[2] = { NULL, NULL }; doReflection = doRefraction = true; if( shader->flags & SHADER_PORTAL_CAPTURE ) { shaderpass_t *pass; captureTexture = NULL; captureTextureId = 0; for( i = 0, pass = shader->passes; i < shader->numpasses; i++, pass++ ) { if( pass->program_type == GLSL_PROGRAM_TYPE_DISTORTION ) { if( ( pass->alphagen.type == ALPHA_GEN_CONST && pass->alphagen.args[0] == 1 ) ) { doRefraction = false; } else if( ( pass->alphagen.type == ALPHA_GEN_CONST && pass->alphagen.args[0] == 0 ) ) { doReflection = false; } break; } } } else { captureTexture = NULL; captureTextureId = -1; } x = y = 0; w = rn.refdef.width; h = rn.refdef.height; dist = PlaneDiff( rn.viewOrigin, portal_plane ); if( dist <= BACKFACE_EPSILON || !doReflection ) { if( !( shader->flags & SHADER_PORTAL_CAPTURE2 ) || !doRefraction ) { return; } // even if we're behind the portal, we still need to capture // the second portal image for refraction refraction = true; captureTexture = NULL; captureTextureId = 1; if( dist < 0 ) { VectorInverse( portal_plane->normal ); portal_plane->dist = -portal_plane->dist; } } mirror = true; // default to mirror view // it is stupid IMO that mirrors require a RT_PORTALSURFACE entity best = NULL; best_d = 100000000; for( i = 0; i < rn.numEntities; i++ ) { ent = R_NUM2ENT( rn.entities[i] ); if( ent->rtype != RT_PORTALSURFACE ) { continue; } d = PlaneDiff( ent->origin, untransformed_plane ); if( ( d >= -64 ) && ( d <= 64 ) ) { d = Distance( ent->origin, portal_centre ); if( d < best_d ) { best = ent; best_d = d; } } } if( best == NULL ) { if( captureTextureId < 0 ) { // still do a push&pop because to ensure the clean state if( R_PushRefInst() ) { R_PopRefInst(); } return; } } else { if( !VectorCompare( best->origin, best->origin2 ) ) { // portal mirror = false; } best->rtype = NUM_RTYPES; } prevRenderFlags = rn.renderFlags; prevFlipped = ( rn.refdef.rdflags & RDF_FLIPPED ) != 0; if( !R_PushRefInst() ) { return; } VectorCopy( rn.viewOrigin, viewerOrigin ); if( prevFlipped ) { VectorInverse( &rn.viewAxis[AXIS_RIGHT] ); } setup_and_render: if( refraction ) { VectorInverse( portal_plane->normal ); portal_plane->dist = -portal_plane->dist; CategorizePlane( portal_plane ); VectorCopy( rn.viewOrigin, origin ); Matrix3_Copy( rn.refdef.viewaxis, axis ); VectorCopy( viewerOrigin, rn.pvsOrigin ); rn.renderFlags |= RF_PORTALVIEW; if( prevFlipped ) { rn.renderFlags |= RF_FLIPFRONTFACE; } } else if( mirror ) { VectorReflect( rn.viewOrigin, portal_plane->normal, portal_plane->dist, origin ); VectorReflect( &rn.viewAxis[AXIS_FORWARD], portal_plane->normal, 0, &axis[AXIS_FORWARD] ); VectorReflect( &rn.viewAxis[AXIS_RIGHT], portal_plane->normal, 0, &axis[AXIS_RIGHT] ); VectorReflect( &rn.viewAxis[AXIS_UP], portal_plane->normal, 0, &axis[AXIS_UP] ); Matrix3_Normalize( axis ); VectorCopy( viewerOrigin, rn.pvsOrigin ); rn.renderFlags = ( prevRenderFlags ^ RF_FLIPFRONTFACE ) | RF_MIRRORVIEW; } else { vec3_t tvec; mat3_t A, B, C, rot; // build world-to-portal rotation matrix VectorNegate( portal_plane->normal, tvec ); NormalVectorToAxis( tvec, A ); // build portal_dest-to-world rotation matrix ByteToDir( best->frame, tvec ); NormalVectorToAxis( tvec, B ); Matrix3_Transpose( B, C ); // multiply to get world-to-world rotation matrix Matrix3_Multiply( C, A, rot ); // translate view origin VectorSubtract( rn.viewOrigin, best->origin, tvec ); Matrix3_TransformVector( rot, tvec, origin ); VectorAdd( origin, best->origin2, origin ); Matrix3_Transpose( A, B ); Matrix3_Multiply( rn.viewAxis, B, rot ); Matrix3_Multiply( best->axis, rot, B ); Matrix3_Transpose( C, A ); Matrix3_Multiply( B, A, axis ); // set up portal_plane VectorCopy( &axis[AXIS_FORWARD], portal_plane->normal ); portal_plane->dist = DotProduct( best->origin2, portal_plane->normal ); CategorizePlane( portal_plane ); // for portals, vis data is taken from portal origin, not // view origin, because the view point moves around and // might fly into (or behind) a wall VectorCopy( best->origin2, rn.pvsOrigin ); VectorCopy( best->origin2, rn.lodOrigin ); rn.renderFlags |= RF_PORTALVIEW; // ignore entities, if asked politely if( best->renderfx & RF_NOPORTALENTS ) { rn.renderFlags |= RF_ENVVIEW; } if( prevFlipped ) { rn.renderFlags |= RF_FLIPFRONTFACE; } } rn.refdef.rdflags &= ~( RDF_UNDERWATER | RDF_CROSSINGWATER | RDF_FLIPPED ); rn.meshlist = &r_portallist; rn.portalmasklist = NULL; rn.renderFlags |= RF_CLIPPLANE; rn.renderFlags &= ~RF_SOFT_PARTICLES; rn.clipPlane = *portal_plane; rn.nearClip = Z_NEAR; rn.farClip = R_DefaultFarClip(); rn.polygonFactor = POLYOFFSET_FACTOR; rn.polygonUnits = POLYOFFSET_UNITS; rn.clipFlags |= 16; rn.frustum[4] = *portal_plane; // nearclip CategorizePlane( &rn.frustum[4] ); // if we want to render to a texture, initialize texture // but do not try to render to it more than once if( captureTextureId >= 0 ) { int texFlags = shader->flags & SHADER_NO_TEX_FILTERING ? IT_NOFILTERING : 0; captureTexture = R_GetPortalTexture( rsc.refdef.width, rsc.refdef.height, texFlags, rsc.frameCount ); portalTexures[captureTextureId] = captureTexture; if( !captureTexture ) { // couldn't register a slot for this plane goto done; } x = y = 0; w = captureTexture->upload_width; h = captureTexture->upload_height; rn.refdef.width = w; rn.refdef.height = h; rn.refdef.x = 0; rn.refdef.y = 0; rn.renderTarget = captureTexture->fbo; rn.renderFlags |= RF_PORTAL_CAPTURE; Vector4Set( rn.viewport, rn.refdef.x + x, rn.refdef.y + y, w, h ); Vector4Set( rn.scissor, rn.refdef.x + x, rn.refdef.y + y, w, h ); } else { rn.renderFlags &= ~RF_PORTAL_CAPTURE; } VectorCopy( origin, rn.refdef.vieworg ); Matrix3_Copy( axis, rn.refdef.viewaxis ); R_SetupViewMatrices( &rn.refdef ); R_SetupFrustum( &rn.refdef, rn.nearClip, rn.farClip, rn.frustum, rn.frustumCorners ); R_SetupPVS( &rn.refdef ); R_RenderView( &rn.refdef ); if( doRefraction && !refraction && ( shader->flags & SHADER_PORTAL_CAPTURE2 ) ) { rn.renderFlags = prevRenderFlags; refraction = true; captureTexture = NULL; captureTextureId = 1; goto setup_and_render; } done: portalSurface->texures[0] = portalTexures[0]; portalSurface->texures[1] = portalTexures[1]; R_PopRefInst(); }
/* ================= R_TraceLine ================= */ msurface_t *R_TransformedTraceLine( trace_t *tr, const vec3_t start, const vec3_t end, ref_entity_t *test, int umask ) { ref_model_t *model; r_fragmentframecount++; // for multi-check avoidance // fill in a default trace Mem_Set( tr, 0, sizeof( trace_t )); trace_surface = NULL; trace_umask = umask; trace_fraction = 1; VectorCopy( end, trace_impact ); Mem_Set( &trace_plane, 0, sizeof( trace_plane )); ClearBounds( trace_absmins, trace_absmaxs ); AddPointToBounds( start, trace_absmins, trace_absmaxs ); AddPointToBounds( end, trace_absmins, trace_absmaxs ); model = test->model; if( model ) { if( model->type == mod_world || model->type == mod_brush ) { mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata; vec3_t temp, start_l, end_l, axis[3]; bool rotated = !Matrix3x3_Compare( test->axis, matrix3x3_identity ); // transform VectorSubtract( start, test->origin, start_l ); VectorSubtract( end, test->origin, end_l ); if( rotated ) { VectorCopy( start_l, temp ); Matrix3x3_Transform( test->axis, temp, start_l ); VectorCopy( end_l, temp ); Matrix3x3_Transform( test->axis, temp, end_l ); } VectorCopy( start_l, trace_start ); VectorCopy( end_l, trace_end ); // world uses a recursive approach using BSP tree, submodels // just walk the list of surfaces linearly if( test->model->type == mod_world ) R_RecursiveHullCheck( bmodel->nodes, start_l, end_l ); else if( BoundsIntersect( model->mins, model->maxs, trace_absmins, trace_absmaxs ) ) R_TraceAgainstBmodel( bmodel ); // transform back if( rotated && trace_fraction != 1 ) { Matrix3x3_Transpose( axis, test->axis ); VectorCopy( tr->vecPlaneNormal, temp ); Matrix3x3_Transform( axis, temp, trace_plane.normal ); } } } // calculate the impact plane, if any if( trace_fraction < 1.0f ) { VectorNormalize( trace_plane.normal ); trace_plane.dist = DotProduct( trace_plane.normal, trace_impact ); CategorizePlane( &trace_plane ); tr->flPlaneDist = trace_plane.dist; VectorCopy( trace_plane.normal, tr->vecPlaneNormal ); tr->iContents = trace_surface->contents; tr->pHit = (edict_t *)test; } tr->flFraction = trace_fraction; VectorCopy( trace_impact, tr->vecEndPos ); return trace_surface; }