note description: "[ r_plane.c Here is a core component: drawing the floors and ceilings while maintaining a per column clipping list only. Moreover, the sky areas have to be determined. ]" license: "[ Copyright (C) 1993-1996 by id Software, Inc. Copyright (C) 2005-2014 Simon Howard Copyright (C) 2021 Ilgiz Mustafin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ]" class R_PLANE create make feature i_main: I_MAIN make (a_i_main: like i_main) local i: INTEGER_32 do i_main := a_i_main create cachedheight.make_filled (create {FIXED_T}.from_integer (0), 0, {DOOMDEF_H}.screenheight - 1) create openings.make_filled (0, 0, Maxopenings - 1) create lastopening.make (0, openings) create ceilingclip.make_filled (0, 0, {DOOMDEF_H}.screenwidth - 1) create floorclip.make_filled (0, 0, {DOOMDEF_H}.screenwidth - 1) create visplanes.make_filled (create {VISPLANE_T}.make, 0, Maxvisplanes - 1) from i := visplanes.lower until i > visplanes.upper loop visplanes [i] := create {VISPLANE_T}.make i := i + 1 end create cachedystep.make_filled (create {FIXED_T}.from_integer (0), 0, {DOOMDEF_H}.screenheight - 1) create cachedxstep.make_filled (create {FIXED_T}.from_integer (0), 0, {DOOMDEF_H}.screenheight - 1) create cacheddistance.make_filled (create {FIXED_T}.from_integer (0), 0, {DOOMDEF_H}.screenheight - 1) create spanstart.make_filled (0, 0, {DOOMDEF_H}.screenheight - 1) end feature spanstart: ARRAY [INTEGER_32] -- spanstart holds the start of a plane span -- initialized to 0 at start cacheddistance: ARRAY [FIXED_T] cachedxstep: ARRAY [FIXED_T] cachedystep: ARRAY [FIXED_T] feature -- Clip values are the solid pixel bounding the range. -- floorclip starts out SCREENHEIGHT -- ceilingclip starts out -1 floorclip: ARRAY [INTEGER_16] ceilingclip: ARRAY [INTEGER_16] lastvisplane: INTEGER_32 -- originally pointer inside visplanes Maxopenings: INTEGER_32 once Result := {DOOMDEF_H}.screenwidth * 64 ensure instance_free: class end openings: ARRAY [INTEGER_16] lastopening: INDEX_IN_ARRAY [INTEGER_16] assign set_lastopening -- originally pointer inside openings set_lastopening (a_lastopening: like lastopening) do lastopening := a_lastopening end cachedheight: ARRAY [FIXED_T] -- SCREENHEIGHT feature -- Here comes the obnoxious "visplane". Maxvisplanes: INTEGER_32 = 128 visplanes: ARRAY [VISPLANE_T] floorplane: detachable VISPLANE_T assign set_floorplane set_floorplane (a_floorplane: like floorplane) do floorplane := a_floorplane end ceilingplane: detachable VISPLANE_T assign set_ceilingplane set_ceilingplane (a_ceilingplane: like ceilingplane) do ceilingplane := a_ceilingplane end feature -- Texture mapping basexscale: FIXED_T baseyscale: FIXED_T planeheight: FIXED_T planezlight: detachable ARRAY [detachable INDEX_IN_ARRAY [LIGHTTABLE_T]] -- lighttable_t** feature r_initplanes do end r_clearplanes -- At begining of frame. local i: INTEGER_32 angle: ANGLE_T do from i := 0 until i >= i_main.R_draw.viewwidth loop floorclip [i] := i_main.R_draw.viewheight.to_integer_16 ceilingclip [i] := -1 i := i + 1 end lastvisplane := 0 create lastopening.make (0, openings) cachedheight.fill_with (create {FIXED_T}.from_integer (0)) angle := ((i_main.R_main.viewangle - {R_MAIN}.ang90) |>> {R_MAIN}.angletofineshift) basexscale := {M_FIXED}.fixeddiv ({R_MAIN}.finecosine [angle.as_integer_32], i_main.R_main.centerxfrac) baseyscale := - {M_FIXED}.fixeddiv (create {FIXED_T}.from_integer ({R_MAIN}.finesine [angle.as_integer_32]), i_main.R_main.centerxfrac) end r_drawplanes -- At the end of each frame. require rangecheck_drawsegs_overflow: i_main.R_bsp.ds_p <= {R_DEFS}.maxdrawsegs rangecheck_visplane_overflow: lastvisplane <= Maxvisplanes rangecheck_opening_overflow: lastopening.index <= Maxopenings local pl: INTEGER_32 light: INTEGER_32 x: INTEGER_32 stop: INTEGER_32 angle: INTEGER_32 do from pl := 0 until pl >= lastvisplane loop if visplanes [pl].minx > visplanes [pl].maxx then else if visplanes [pl].picnum = i_main.R_sky.skyflatnum then i_main.R_draw.dc_iscale := i_main.R_things.pspriteiscale |>> i_main.R_main.detailshift i_main.R_draw.dc_colormap := create {INDEX_IN_ARRAY [LIGHTTABLE_T]}.make (0, i_main.R_data.colormaps) i_main.R_draw.dc_texturemid := create {FIXED_T}.from_integer (i_main.R_sky.skytexturemid) from x := visplanes [pl].minx until x > visplanes [pl].maxx loop i_main.R_draw.dc_yl := visplanes [pl].top [x].to_integer_32 i_main.R_draw.dc_yh := visplanes [pl].bottom [x].to_integer_32 if i_main.R_draw.dc_yl < i_main.R_draw.dc_yh then angle := (i_main.R_main.viewangle + i_main.R_main.Xtoviewangle [x]) |>> {R_SKY}.angletoskyshift.as_integer_32 i_main.R_draw.dc_x := x i_main.R_draw.dc_source := i_main.R_data.r_getcolumn (i_main.R_sky.skytexture, angle) check attached i_main.R_main.colfunc as colfunc then colfunc.call end end x := x + 1 end else i_main.R_draw.ds_source := create {MANAGED_POINTER_WITH_OFFSET}.make (i_main.W_wad.w_cachelumpnum (i_main.R_data.firstflat + i_main.R_data.flattranslation [visplanes [pl].picnum]), 0) planeheight := create {FIXED_T}.from_integer ((visplanes [pl].height - i_main.R_main.viewz).abs) light := (visplanes [pl].lightlevel |>> {R_MAIN}.lightsegshift) + i_main.R_main.extralight if light >= {R_MAIN}.lightlevels then light := {R_MAIN}.lightlevels - 1 end if light < 0 then light := 0 end planezlight := i_main.R_main.zlight [light] visplanes [pl].top [visplanes [pl].maxx + 1] := 255 visplanes [pl].top [visplanes [pl].minx - 1] := 255 stop := visplanes [pl].maxx + 1 from x := visplanes [pl].minx until x > stop loop r_makespans (x, visplanes [pl].top [x - 1].to_integer_32, visplanes [pl].bottom [x - 1].to_integer_32, visplanes [pl].top [x].to_integer_32, visplanes [pl].bottom [x].to_integer_32) x := x + 1 end end end pl := pl + 1 end end r_makespans (x, a_t1, a_b1, a_t2, a_b2: INTEGER_32) local t1: INTEGER_32 b1: INTEGER_32 t2: INTEGER_32 b2: INTEGER_32 do t1 := a_t1 b1 := a_b1 t2 := a_t2 b2 := a_b2 from until not (t1 < t2 and t1 <= b1) loop r_mapplane (t1, spanstart [t1], x - 1) t1 := t1 + 1 end from until not (b1 > b2 and b1 >= t1) loop r_mapplane (b1, spanstart [b1], x - 1) b1 := b1 - 1 end from until not (t2 < t1 and t2 <= b2) loop spanstart [t2] := x t2 := t2 + 1 end from until not (b2 > b1 and b2 >= t2) loop spanstart [b2] := x b2 := b2 - 1 end end r_mapplane (y, x1, x2: INTEGER_32) require rangecheck: x2 >= x1 and x1 >= 0 and x2 < i_main.R_draw.viewwidth and y <= i_main.R_draw.viewheight local angle: ANGLE_T distance: FIXED_T length: FIXED_T index: NATURAL_32 do if planeheight /= cachedheight [y] then cachedheight [y] := planeheight distance := {M_FIXED}.fixedmul (planeheight, Yslope [y]) cacheddistance [y] := distance i_main.R_draw.ds_xstep := {M_FIXED}.fixedmul (distance, basexscale) cachedxstep [y] := i_main.R_draw.ds_xstep i_main.R_draw.ds_ystep := {M_FIXED}.fixedmul (distance, baseyscale) cachedystep [y] := i_main.R_draw.ds_ystep else distance := cacheddistance [y] i_main.R_draw.ds_xstep := cachedxstep [y] i_main.R_draw.ds_ystep := cachedystep [y] end length := {M_FIXED}.fixedmul (distance, Distscale [x1]) angle := (i_main.R_main.viewangle + i_main.R_main.Xtoviewangle [x1]) |>> {R_MAIN}.angletofineshift i_main.R_draw.ds_xfrac := i_main.R_main.viewx + {M_FIXED}.fixedmul (i_main.R_main.Finecosine [angle.as_integer_32], length) i_main.R_draw.ds_yfrac := - i_main.R_main.viewy - {M_FIXED}.fixedmul (create {FIXED_T}.from_integer (i_main.R_main.Finesine [angle.as_integer_32]), length) if attached i_main.R_main.fixedcolormap as fixedcolormap then i_main.R_draw.ds_colormap := fixedcolormap else index := distance |>> {R_MAIN}.lightzshift.as_natural_32 if index >= {R_MAIN}.maxlightz.to_natural_32 then index := {R_MAIN}.maxlightz.to_natural_32 - 1 end check attached planezlight as pzl then check attached pzl [index.to_integer_32] as pzli then i_main.R_draw.ds_colormap := pzli end end end i_main.R_draw.ds_y := y i_main.R_draw.ds_x1 := x1 i_main.R_draw.ds_x2 := x2 check attached i_main.R_main.spanfunc as spanfunc then spanfunc.call end end r_findplane (a_height: FIXED_T; picnum: INTEGER_32; a_lightlevel: INTEGER_32): VISPLANE_T local c: INTEGER_32 height: FIXED_T lightlevel: INTEGER_32 found: BOOLEAN ch: VISPLANE_T do height := a_height lightlevel := a_lightlevel if picnum = i_main.R_sky.skyflatnum then height := create {FIXED_T}.from_integer (0) lightlevel := 0 end from c := 0 found := False until found or c >= lastvisplane loop ch := visplanes [c] if height = ch.height and picnum = ch.picnum and lightlevel = ch.lightlevel then found := True else c := c + 1 end end if found then Result := visplanes [c] else if lastvisplane = Maxvisplanes then {I_MAIN}.i_error ("R_FindPlane: no more visplanes") end ch := visplanes [lastvisplane] lastvisplane := lastvisplane + 1 ch.height := height ch.picnum := picnum ch.lightlevel := lightlevel ch.minx := {DOOMDEF_H}.screenwidth ch.maxx := -1 ch.top.fill_with (255) Result := ch end end r_checkplane (pl: VISPLANE_T; start, stop: INTEGER_32): VISPLANE_T local intrl: INTEGER_32 intrh: INTEGER_32 unionl: INTEGER_32 unionh: INTEGER_32 x: INTEGER_32 do if start < pl.minx then intrl := pl.minx unionl := start else unionl := pl.minx intrl := start end if stop > pl.maxx then intrh := pl.maxx unionh := stop else unionh := pl.maxx intrh := stop end from x := intrl until x > intrh or else pl.top [x] /= 255 loop x := x + 1 end if x > intrh then pl.minx := unionl pl.maxx := unionh Result := pl else Result := visplanes [lastvisplane] lastvisplane := lastvisplane + 1 Result.height := pl.height Result.picnum := pl.picnum Result.lightlevel := pl.lightlevel Result.minx := start Result.maxx := stop Result.top.fill_with (255) end end feature Yslope: ARRAY [FIXED_T] once create Result.make_filled (create {FIXED_T}.from_integer (0), 0, {DOOMDEF_H}.screenheight - 1) end Distscale: ARRAY [FIXED_T] once create Result.make_filled (create {FIXED_T}.from_integer (0), 0, {DOOMDEF_H}.screenwidth - 1) end invariant floorclip.count = {DOOMDEF_H}.screenwidth ceilingclip.count = {DOOMDEF_H}.screenwidth visplanes.count = Maxvisplanes visplanes.lower = 0 openings.lower = 0 and openings.count = Maxopenings cachedystep.lower = 0 and cachedystep.count = {DOOMDEF_H}.screenheight cachedxstep.lower = 0 and cachedxstep.count = {DOOMDEF_H}.screenheight cacheddistance.lower = 0 and cacheddistance.count = {DOOMDEF_H}.screenheight cachedheight.lower = 0 and cachedheight.count = {DOOMDEF_H}.screenheight spanstart.lower = 0 and spanstart.count = {DOOMDEF_H}.screenheight end -- class R_PLANE
Generated by ISE EiffelStudio