public int RecursiveLightPoint(int idx_node, Vector3 start, Vector3 end) { float front; float back; float frac; int side; CShared.SCPlane plane; Vector3 mid; int surf; int s, t; int ds, dt; CModel.SMTexInfo tex; int lightmap; int r; CModel.SMNode node; node = CQ2BSP.SWorldData.nodes[idx_node]; if (node.contents != -1) { return(-1); // didn't hit anything } // calculate mid point // FIXME: optimize for axial plane = CQ2BSP.SWorldData.planes[node.plane]; front = Vector3.Dot(start, plane.normal) - plane.dist; back = Vector3.Dot(end, plane.normal) - plane.dist; side = Convert.ToInt32(front < 0); if (Convert.ToInt32(back < 0) == side) { return(RecursiveLightPoint(node.children[side], start, end)); } frac = front / (front - back); mid.X = start.X + (end.X - start.X) * frac; mid.Y = start.Y + (end.Y - start.Y) * frac; mid.Z = start.Z + (end.Z - start.Z) * frac; // go down front side r = RecursiveLightPoint(node.children[side], start, mid); if (r >= 0) { return(r); // hit something } if (Convert.ToInt32(back < 0) == side) { return(-1); // didn't hit anything } // check for impact on this node lightspot.X = mid.X; lightspot.Y = mid.Y; lightspot.Z = mid.Z; lightplane = plane; surf = node.firstsurface; for (int i = 0; i < node.numsurfaces; i++, surf++) { Vector3 vecs; if ((CQ2BSP.SWorldData.surfaces[surf].flags & CModel.EMSurface.SURF_DRAWTURB) == CModel.EMSurface.SURF_DRAWTURB) { continue; // no lightmaps } if ((CQ2BSP.SWorldData.surfaces[surf].flags & CModel.EMSurface.SURF_DRAWSKY) == CModel.EMSurface.SURF_DRAWSKY) { continue; // no lightmaps } tex = CQ2BSP.SWorldData.texinfo[CQ2BSP.SWorldData.surfaces[surf].texinfo]; vecs.X = tex.vecs[0].X; vecs.Y = tex.vecs[0].Y; vecs.Z = tex.vecs[0].Z; s = (int)(Vector3.Dot(mid, vecs) + tex.vecs[0].W); vecs.X = tex.vecs[1].X; vecs.Y = tex.vecs[1].Y; vecs.Z = tex.vecs[1].Z; t = (int)(Vector3.Dot(mid, vecs) + tex.vecs[1].W); if (s < CQ2BSP.SWorldData.surfaces[surf].texturemins[0] || t < CQ2BSP.SWorldData.surfaces[surf].texturemins[1]) { continue; } ds = s - CQ2BSP.SWorldData.surfaces[surf].texturemins[0]; dt = t - CQ2BSP.SWorldData.surfaces[surf].texturemins[1]; if (ds > CQ2BSP.SWorldData.surfaces[surf].extents[0] || dt > CQ2BSP.SWorldData.surfaces[surf].extents[1]) { continue; } if (CQ2BSP.SWorldData.surfaces[surf].samples == -1) { return(0); } ds >>= 4; dt >>= 4; lightmap = CQ2BSP.SWorldData.surfaces[surf].samples; pointcolor.X = CShared.vec3_origin.X; pointcolor.Y = CShared.vec3_origin.Y; pointcolor.Z = CShared.vec3_origin.Z; if (lightmap != -1) { Vector3 scale; lightmap += 3 * (dt * ((CQ2BSP.SWorldData.surfaces[surf].extents[0] >> 4) + 1) + ds); for (int maps = 0; maps < CQ2BSP.MAXLIGHTMAPS && CQ2BSP.SWorldData.surfaces[surf].styles[maps] != 255; maps++) { scale = Vector3.Zero; for (i = 0; i < 3; i++) { // jkrige ?? //scale.X = CLocal.gl_modulate * CClient.cl.RefDef.lightstyles[CQ2BSP.SWorldData.surfaces[surf].styles[maps]].rgb[0]; //scale.Y = CLocal.gl_modulate * CClient.cl.RefDef.lightstyles[CQ2BSP.SWorldData.surfaces[surf].styles[maps]].rgb[1]; //scale.Z = CLocal.gl_modulate * CClient.cl.RefDef.lightstyles[CQ2BSP.SWorldData.surfaces[surf].styles[maps]].rgb[2]; scale.X = 1.0f; scale.Y = 1.0f; scale.Z = 1.0f; // jkrige ?? } pointcolor.X += CQ2BSP.SWorldData.lightdata[lightmap + 0] * scale.X * (1.0f / 255); pointcolor.Y += CQ2BSP.SWorldData.lightdata[lightmap + 1] * scale.Y * (1.0f / 255); pointcolor.Z += CQ2BSP.SWorldData.lightdata[lightmap + 2] * scale.Z * (1.0f / 255); lightmap += 3 * ((CQ2BSP.SWorldData.surfaces[surf].extents[0] >> 4) + 1) * ((CQ2BSP.SWorldData.surfaces[surf].extents[1] >> 4) + 1); } } return(1); } // go down back side return(RecursiveLightPoint(node.children[Convert.ToInt32(side == 0)], mid, end)); }
public int RecursiveLightPoint(int idx_node, Vector3 start, Vector3 end) { float front; float back; float frac; int side; CShared.SCPlane plane; Vector3 mid; int surf; int s, t; int ds, dt; CModel.SMTexInfo tex; int lightmap; int r; CModel.SMNode node; node = CQ2BSP.SWorldData.nodes[idx_node]; if (node.contents != -1) return -1; // didn't hit anything // calculate mid point // FIXME: optimize for axial plane = CQ2BSP.SWorldData.planes[node.plane]; front = Vector3.Dot(start, plane.normal) - plane.dist; back = Vector3.Dot(end, plane.normal) - plane.dist; side = Convert.ToInt32(front < 0); if (Convert.ToInt32(back < 0) == side) return RecursiveLightPoint(node.children[side], start, end); frac = front / (front - back); mid.X = start.X + (end.X - start.X) * frac; mid.Y = start.Y + (end.Y - start.Y) * frac; mid.Z = start.Z + (end.Z - start.Z) * frac; // go down front side r = RecursiveLightPoint(node.children[side], start, mid); if (r >= 0) return r; // hit something if (Convert.ToInt32(back < 0) == side) return -1; // didn't hit anything // check for impact on this node lightspot.X = mid.X; lightspot.Y = mid.Y; lightspot.Z = mid.Z; lightplane = plane; surf = node.firstsurface; for (int i = 0; i < node.numsurfaces; i++, surf++) { Vector3 vecs; if ((CQ2BSP.SWorldData.surfaces[surf].flags & CModel.EMSurface.SURF_DRAWTURB) == CModel.EMSurface.SURF_DRAWTURB) continue; // no lightmaps if ((CQ2BSP.SWorldData.surfaces[surf].flags & CModel.EMSurface.SURF_DRAWSKY) == CModel.EMSurface.SURF_DRAWSKY) continue; // no lightmaps tex = CQ2BSP.SWorldData.texinfo[CQ2BSP.SWorldData.surfaces[surf].texinfo]; vecs.X = tex.vecs[0].X; vecs.Y = tex.vecs[0].Y; vecs.Z = tex.vecs[0].Z; s = (int)(Vector3.Dot(mid, vecs) + tex.vecs[0].W); vecs.X = tex.vecs[1].X; vecs.Y = tex.vecs[1].Y; vecs.Z = tex.vecs[1].Z; t = (int)(Vector3.Dot(mid, vecs) + tex.vecs[1].W); if (s < CQ2BSP.SWorldData.surfaces[surf].texturemins[0] || t < CQ2BSP.SWorldData.surfaces[surf].texturemins[1]) continue; ds = s - CQ2BSP.SWorldData.surfaces[surf].texturemins[0]; dt = t - CQ2BSP.SWorldData.surfaces[surf].texturemins[1]; if (ds > CQ2BSP.SWorldData.surfaces[surf].extents[0] || dt > CQ2BSP.SWorldData.surfaces[surf].extents[1]) continue; if (CQ2BSP.SWorldData.surfaces[surf].samples == -1) return 0; ds >>= 4; dt >>= 4; lightmap = CQ2BSP.SWorldData.surfaces[surf].samples; pointcolor.X = CShared.vec3_origin.X; pointcolor.Y = CShared.vec3_origin.Y; pointcolor.Z = CShared.vec3_origin.Z; if (lightmap != -1) { Vector3 scale; lightmap += 3 * (dt * ((CQ2BSP.SWorldData.surfaces[surf].extents[0] >> 4) + 1) + ds); for (int maps = 0; maps < CQ2BSP.MAXLIGHTMAPS && CQ2BSP.SWorldData.surfaces[surf].styles[maps] != 255; maps++) { scale = Vector3.Zero; for (i = 0; i < 3; i++) { // jkrige ?? //scale.X = CLocal.gl_modulate * CClient.cl.RefDef.lightstyles[CQ2BSP.SWorldData.surfaces[surf].styles[maps]].rgb[0]; //scale.Y = CLocal.gl_modulate * CClient.cl.RefDef.lightstyles[CQ2BSP.SWorldData.surfaces[surf].styles[maps]].rgb[1]; //scale.Z = CLocal.gl_modulate * CClient.cl.RefDef.lightstyles[CQ2BSP.SWorldData.surfaces[surf].styles[maps]].rgb[2]; scale.X = 1.0f; scale.Y = 1.0f; scale.Z = 1.0f; // jkrige ?? } pointcolor.X += CQ2BSP.SWorldData.lightdata[lightmap + 0] * scale.X * (1.0f / 255); pointcolor.Y += CQ2BSP.SWorldData.lightdata[lightmap + 1] * scale.Y * (1.0f / 255); pointcolor.Z += CQ2BSP.SWorldData.lightdata[lightmap + 2] * scale.Z * (1.0f / 255); lightmap += 3 * ((CQ2BSP.SWorldData.surfaces[surf].extents[0] >> 4) + 1) * ((CQ2BSP.SWorldData.surfaces[surf].extents[1] >> 4) + 1); } } return 1; } // go down back side return RecursiveLightPoint(node.children[Convert.ToInt32(side == 0)], mid, end); }