// returns surfID SurfaceHandle_t RecursiveLightPoint (mnode_t *node, float start, float end, Vector& c, LightVecState_t& state ) { // didn't hit anything if (node->contents >= 0) { // FIXME: Should we always do this? It could get expensive... // Check all the faces at the leaves return FindIntersectionSurfaceAtLeaf( (mleaf_t*)node, start, end, c, state ); } // Determine which side of the node plane our points are on // FIXME: optimize for axial cplane_t* plane = node->plane; float startDotN = DotProduct( state.m_Ray.m_Start, plane->normal ); float deltaDotN = DotProduct( state.m_Ray.m_Delta, plane->normal ); float front = startDotN + start * deltaDotN - plane->dist; float back = startDotN + end * deltaDotN - plane->dist; int side = front < 0; // If they're both on the same side of the plane, don't bother to split // just check the appropriate child SurfaceHandle_t surfID; if ( (back < 0) == side ) { surfID = RecursiveLightPoint (node->children[side], start, end, c, state); return surfID; } // calculate mid point float frac = front / (front-back); float mid = start * (1.0f - frac) + end * frac; // go down front side surfID = RecursiveLightPoint (node->children[side], start, mid, c, state ); if ( IS_SURF_VALID( surfID ) ) return surfID; // hit something // check for impact on this node surfID = FindIntersectionSurfaceAtNode( node, mid, c, state ); if ( IS_SURF_VALID( surfID ) ) return surfID; // go down back side surfID = RecursiveLightPoint (node->children[!side], mid, end, c, state ); return surfID; }
//----------------------------------------------------------------------------- // returns light in range from 0 to 1. // lightmapS/T is in [0,1] within the space of the surface. // returns surfID //----------------------------------------------------------------------------- SurfaceHandle_t R_LightVec (const Vector& start, const Vector& end, bool bUseLightStyles, Vector& c, float *textureS, float *textureT, float *lightmapS, float *lightmapT ) { VPROF_INCREMENT_COUNTER( "R_LightVec", 1 ); SurfaceHandle_t retSurfID; SurfaceHandle_t dispSurfID; // We're using the vis frame here for lightvec tests // to make sure we test each displacement only once ++r_surfacevisframe; LightVecState_t state; state.m_HitFrac = 1.0f; state.m_Ray.Init( start, end ); state.m_pTextureS = textureS; state.m_pTextureT = textureT; state.m_pLightmapS = lightmapS; state.m_pLightmapT = lightmapT; state.m_nSkySurfID = SURFACE_HANDLE_INVALID; state.m_bUseLightStyles = bUseLightStyles; c[0] = c[1] = c[2] = 0.0f; model_t* model = s_pLightVecModel ? s_pLightVecModel : host_state.worldmodel; retSurfID = RecursiveLightPoint(&model->brush.pShared->nodes[model->brush.firstnode], 0.0f, 1.0f, c, state ); // While doing recursive light point, we built a list of all // displacement surfaces which we need to test, so let's test them dispSurfID = R_LightVecDisplacementChain( state, bUseLightStyles, c ); if( r_visualizelighttraces.GetBool() ) { if( r_visualizelighttracesshowfulltrace.GetBool() ) { CDebugOverlay::AddLineOverlay( start, end, 0, 255, 0, 255, true, -1.0f ); } else { CDebugOverlay::AddLineOverlay( start, start + ( end - start ) * state.m_HitFrac, 0, 255, 0, 255, true, -1.0f ); } } if ( IS_SURF_VALID( dispSurfID ) ) retSurfID = dispSurfID; // ConMsg( "R_LightVec: %f %f %f\n", c[0], c[1], c[2] ); // If we didn't hit anything else, but we hit a sky surface at // some point along the ray cast, return the sky id. if ( ( retSurfID == SURFACE_HANDLE_INVALID ) && ( state.m_nSkySurfID != SURFACE_HANDLE_INVALID ) ) return state.m_nSkySurfID; return retSurfID; }
void R_ShadowLight(vec3_t pos, vec3_t lightAdd) { vec3_t end; float r; int lnum; dlight_t *dl; float len; vec3_t dist, angle; float add; if (!r_worldmodel->lightdata) /* keep old lame shadow */ return; end[0] = pos[0]; end[1] = pos[1]; end[2] = pos[2] - 2048; r = RecursiveLightPoint(r_worldmodel->nodes, pos, end); VectorClear(lightAdd); // /* add dynamic light shadow angles */ // dl = r_refdef.dlights; for (lnum = 0; lnum < r_refdef.num_dlights; lnum++, dl++) { if (dl->spotlight) /* spotlights */ continue; VectorSubtract(dl->origin, pos, dist); add = sqrt(dl->intensity - VectorLength(dist)); VectorNormalize(dist); if (add > 0) { VectorScale(dist, add, dist); VectorAdd(lightAdd, dist, lightAdd); } } len = VectorNormalize(lightAdd); if (len > 2048) len = 2048; if (len <= 0) return; /* now rotate according to model yaw */ vectoangles(lightAdd, angle); /* e->angles */ angle[YAW] = -(currententity->angles[YAW] - angle[YAW]); AngleVectors(angle, dist, NULL, NULL); VectorScale(dist, len, lightAdd); }
int R_LightPoint (vec3_t &p, vec3_t &outcolor) { vec3_t end; // int r; model_t* world = gEngfuncs.GetEntityByIndex(0)->model; if (!world->lightdata) { outcolor[0] = outcolor[1] = outcolor[2] = 1; return 255; } end[0] = p[0]; end[1] = p[1]; end[2] = p[2] - 2048; return RecursiveLightPoint (world->nodes, p, end, outcolor); }
//----------------------------------------------------------------------------- // returns light in range from 0 to 1. // lightmapS/T is in [0,1] within the space of the surface. // returns surfID //----------------------------------------------------------------------------- int R_LightVec (const Vector& start, const Vector& end, bool bUseLightStyles, Vector& c, float *textureS, float *textureT, float *lightmapS, float *lightmapT ) { int retSurfID; int dispSurfID; // We're using the vis frame here for lightvec tests // to make sure we test each displacement only once ++r_surfacevisframe; LightVecState_t state; state.m_HitFrac = 1.0f; state.m_Ray.Init( start, end ); state.m_pTextureS = textureS; state.m_pTextureT = textureT; state.m_pLightmapS = lightmapS; state.m_pLightmapT = lightmapT; state.m_nSkySurfID = -1; state.m_bUseLightStyles = bUseLightStyles; c[0] = c[1] = c[2] = 0.0f; model_t* model = s_pLightVecModel ? s_pLightVecModel : host_state.worldmodel; retSurfID = RecursiveLightPoint(&model->brush.nodes[model->brush.firstnode], 0.0f, 1.0f, c, state ); // While doing recursive light point, we built a list of all // displacement surfaces which we need to test, so let's test them dispSurfID = R_LightVecDisplacementChain( state, bUseLightStyles, c ); if ( IS_SURF_VALID( dispSurfID ) ) retSurfID = dispSurfID; // Con_Printf( "R_LightVec: %f %f %f\n", c[0], c[1], c[2] ); // If we didn't hit anything else, but we hit a sky surface at // some point along the ray cast, return the sky id. if ( ( retSurfID == -1 ) && ( state.m_nSkySurfID != -1 ) ) return state.m_nSkySurfID; return retSurfID; }
// 0 - success // -1 - failed int RecursiveLightPoint (mnode_t *node, const vec3_t &start, const vec3_t &end, vec3_t &outcolor) { int r; float front, back, frac; int side; mplane_t *plane; vec3_t mid; msurface_t *surf; int s, t, ds, dt; int i; mtexinfo_t *tex; // byte *lightmap; color24 *lightmap; // unsigned scale; // int maps; if (node->contents < 0) return -1; // didn't hit anything // calculate mid point // FIXME: optimize for axial plane = node->plane; front = DotProduct (start, plane->normal) - plane->dist; back = DotProduct (end, plane->normal) - plane->dist; side = front < 0; if ( (back < 0) == side) return RecursiveLightPoint (node->children[side], start, end, outcolor); frac = front / (front-back); mid[0] = start[0] + (end[0] - start[0])*frac; mid[1] = start[1] + (end[1] - start[1])*frac; mid[2] = start[2] + (end[2] - start[2])*frac; // go down front side r = RecursiveLightPoint (node->children[side], start, mid, outcolor); if (r >= 0) return r; // hit something if ( (back < 0) == side ) return -1; // didn't hit anuthing // check for impact on this node model_t* world = gEngfuncs.GetEntityByIndex(0)->model; surf = world->surfaces + node->firstsurface; for (i=0 ; i<node->numsurfaces ; i++, surf++) { if (surf->flags & SURF_DRAWTILED) continue; // no lightmaps tex = surf->texinfo; s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; if (s < surf->texturemins[0] || t < surf->texturemins[1]) continue; ds = s - surf->texturemins[0]; dt = t - surf->texturemins[1]; if ( ds > surf->extents[0] || dt > surf->extents[1] ) continue; if (!surf->samples) return 0; ds >>= 4; dt >>= 4; lightmap = surf->samples; r = 0; if (lightmap) { lightmap += dt * ((surf->extents[0]>>4)+1) + ds; outcolor[0] = (float)lightmap->r / 255.0f; outcolor[1] = (float)lightmap->g / 255.0f; outcolor[2] = (float)lightmap->b / 255.0f; /* for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; maps++) { scale = d_lightstylevalue[surf->styles[maps]]; r += *lightmap * scale; lightmap += ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1); } r >>= 8;*/ } return r; } // go down back side return RecursiveLightPoint (node->children[!side], mid, end, outcolor); }