private static int RecursiveLightPoint(mnodebase_t node, ref Vector3 start, ref Vector3 end) { if (node.contents < 0) { return(-1); // didn't hit anything } mnode_t n = (mnode_t)node; // calculate mid point // FIXME: optimize for axial mplane_t plane = n.plane; float front = Vector3.Dot(start, plane.normal) - plane.dist; float back = Vector3.Dot(end, plane.normal) - plane.dist; int side = front < 0 ? 1 : 0; if ((back < 0 ? 1 : 0) == side) { return(RecursiveLightPoint(n.children[side], ref start, ref end)); } float frac = front / (front - back); Vector3 mid = start + (end - start) * frac; // go down front side int r = RecursiveLightPoint(n.children[side], ref start, ref mid); if (r >= 0) { return(r); // hit something } if ((back < 0 ? 1 : 0) == side) { return(-1); // didn't hit anuthing } // check for impact on this node _LightSpot = mid; _LightPlane = plane; msurface_t[] surf = client.cl.worldmodel.surfaces; int offset = n.firstsurface; for (int i = 0; i < n.numsurfaces; i++, offset++) { if ((surf[offset].flags & Surf.SURF_DRAWTILED) != 0) { continue; // no lightmaps } mtexinfo_t tex = surf[offset].texinfo; int s = (int)(Vector3.Dot(mid, tex.vecs[0].Xyz) + tex.vecs[0].W); int t = (int)(Vector3.Dot(mid, tex.vecs[1].Xyz) + tex.vecs[1].W); if (s < surf[offset].texturemins[0] || t < surf[offset].texturemins[1]) { continue; } int ds = s - surf[offset].texturemins[0]; int dt = t - surf[offset].texturemins[1]; if (ds > surf[offset].extents[0] || dt > surf[offset].extents[1]) { continue; } if (surf[offset].sample_base == null) { return(0); } ds >>= 4; dt >>= 4; byte[] lightmap = surf[offset].sample_base; int lmOffset = surf[offset].sampleofs; short[] extents = surf[offset].extents; r = 0; if (lightmap != null) { lmOffset += dt * ((extents[0] >> 4) + 1) + ds; for (int maps = 0; maps < bsp_file.MAXLIGHTMAPS && surf[offset].styles[maps] != 255; maps++) { int scale = _LightStyleValue[surf[offset].styles[maps]]; r += lightmap[lmOffset] * scale; lmOffset += ((extents[0] >> 4) + 1) * ((extents[1] >> 4) + 1); } r >>= 8; } return(r); } // go down back side return(RecursiveLightPoint(n.children[side == 0 ? 1 : 0], ref mid, ref end)); }
/// <summary> /// R_AddDynamicLights /// </summary> private static void AddDynamicLights(msurface_t surf) { int smax = (surf.extents[0] >> 4) + 1; int tmax = (surf.extents[1] >> 4) + 1; mtexinfo_t tex = surf.texinfo; dlight_t[] dlights = client.DLights; for (int lnum = 0; lnum < client.MAX_DLIGHTS; lnum++) { if ((surf.dlightbits & (1 << lnum)) == 0) { continue; // not lit by this light } float rad = dlights[lnum].radius; float dist = Vector3.Dot(dlights[lnum].origin, surf.plane.normal) - surf.plane.dist; rad -= Math.Abs(dist); float minlight = dlights[lnum].minlight; if (rad < minlight) { continue; } minlight = rad - minlight; Vector3 impact = dlights[lnum].origin - surf.plane.normal * dist; float local0 = Vector3.Dot(impact, tex.vecs[0].Xyz) + tex.vecs[0].W; float local1 = Vector3.Dot(impact, tex.vecs[1].Xyz) + tex.vecs[1].W; local0 -= surf.texturemins[0]; local1 -= surf.texturemins[1]; for (int t = 0; t < tmax; t++) { int td = (int)(local1 - t * 16); if (td < 0) { td = -td; } for (int s = 0; s < smax; s++) { int sd = (int)(local0 - s * 16); if (sd < 0) { sd = -sd; } if (sd > td) { dist = sd + (td >> 1); } else { dist = td + (sd >> 1); } if (dist < minlight) { _BlockLights[t * smax + s] += (uint)((rad - dist) * 256); } } } } }
/// <summary> /// Mod_LoadTexinfo /// </summary> static void LoadTexInfo(ref lump_t l) { //in = (void *)(mod_base + l->fileofs); if ((l.filelen % texinfo_t.SizeInBytes) != 0) Sys.Error("MOD_LoadBmodel: funny lump size in {0}", _LoadModel.name); int count = l.filelen / texinfo_t.SizeInBytes; mtexinfo_t[] infos = new mtexinfo_t[count]; // out = Hunk_AllocName ( count*sizeof(*out), loadname); for (int i = 0; i < infos.Length; i++) infos[i] = new mtexinfo_t(); _LoadModel.texinfo = infos; _LoadModel.numtexinfo = count; for (int i = 0; i < count; i++)//, in++, out++) { texinfo_t src = Sys.BytesToStructure<texinfo_t>(_ModBase, l.fileofs + i * texinfo_t.SizeInBytes); for (int j = 0; j < 2; j++) infos[i].vecs[j] = Common.LittleVector4(src.vecs, j * 4); float len1 = infos[i].vecs[0].Length; float len2 = infos[i].vecs[1].Length; len1 = (len1 + len2) / 2; if (len1 < 0.32) infos[i].mipadjust = 4; else if (len1 < 0.49) infos[i].mipadjust = 3; else if (len1 < 0.99) infos[i].mipadjust = 2; else infos[i].mipadjust = 1; int miptex = Common.LittleLong(src.miptex); infos[i].flags = Common.LittleLong(src.flags); if (_LoadModel.textures == null) { infos[i].texture = Render.NoTextureMip; // checkerboard texture infos[i].flags = 0; } else { if (miptex >= _LoadModel.numtextures) Sys.Error("miptex >= loadmodel->numtextures"); infos[i].texture = _LoadModel.textures[miptex]; if (infos[i].texture == null) { infos[i].texture = Render.NoTextureMip; // texture not found infos[i].flags = 0; } } } }