# Retail PView Indoor Render Pseudocode (2013 EoR) This note pins the indoor render port to the named retail decomp. The goal is behavioral fidelity: modern GL renderers may supply the draw calls, but the frame ownership, visibility graph, and draw order follow these functions. ## SmartBox::RenderNormalMode @ 0x00453aa0 ```text if render device has open scene: outside = SmartBox::is_player_outside(player position) seenOutside = outside || viewer_cell.seen_outside set FOV/view distance if !outside: if seenOutside: LScape::update_viewpoint(lscape, Position::get_outside_cell_id(viewer)) Render::update_viewpoint(viewer) RenderDeviceD3D::DrawInside(viewer_cell) else: LScape::update_viewpoint(lscape, viewer.objcell_id) Render::update_viewpoint(viewer) Render::set_default_view() Render::useSunlightSet(1) LScape::draw(lscape) FlushAlphaList() run targeting/render callbacks ``` Important split: the top-level branch follows `is_player_outside`, while indoor render calls `DrawInside(viewer_cell)`. ## RenderDeviceD3D::DrawInside @ 0x0059f0d0 ```text PView::DrawInside(RenderDeviceD3D::indoor_pview, viewer_cell) ``` This is a thin forwarder. The PView owns the indoor frame. ## PView::DrawInside @ 0x005a5860 ```text reset object scale CEnvCell::curr_view_push(root_cell) PView::add_views(root_cell.num_stabs, root_cell.stab_list) Frame::cache() Render::positionPush(root identity frame) Render::copy_view(root_cell.portal_view[last], null, 4) # full-screen root view forceClear = PView::ConstructView(root_cell, 0xffff) PView::DrawCells(forceClear) Render::framePop() PView::remove_views(root_cell.num_stabs, root_cell.stab_list) root_cell.num_view-- ``` ## PView::ConstructView(CEnvCell*) @ 0x005a57b0 ```text clear outside_view and cell draw/todo state insert root cell into distance-priority todo list while todo is not empty: cell = pop nearest append cell to cell_draw_list InitCell(cell, otherPortalId) project/clip each portal against the current cell view exit portals append clipped polygons to outside_view interior portals append clipped polygons to neighbor portal_view newly discovered neighbors enter the todo list once return forceClear flag ``` `cell_draw_list` is the only indoor membership source. Later growth can add view polygons to a discovered cell, but does not create a second draw-list entry. ## PView::DrawCells @ 0x005a4840 ```text if outside_view.view_count > 0: Render::useSunlightSet(1) Render::PortalList = this LScape::draw(lscape) # landscape clipped by outside_view D3DPolyRender::FlushAlphaList(0) render_device.frameStamp++ if forceClear || portalsDrawnCount != 0: render_device.Clear(DepthOnly) # Loop 1: exit portal masks, reverse cell_draw_list for cell in reverse(cell_draw_list): if cell.structure.drawing_bsp: push cell frame and surfaces for each current portal_view slice: CEnvCell::setup_view(cell, slice) for each exit portal: DrawPortalPolyInternal(portal polygon) pop frame Render::useSunlightSet(0) Render::restore_all_lighting() # Loop 2: closed cell shells, reverse cell_draw_list for cell in reverse(cell_draw_list): if cell.structure.drawing_bsp: push cell frame and surfaces for each current portal_view slice: CEnvCell::setup_view(cell, slice) DrawEnvCell(cell) pop frame # Loop 3: cell object lists, reverse cell_draw_list for cell in reverse(cell_draw_list): Render::PortalList = cell.portal_view[last] DrawObjCellForDummies(cell) restore object scale Render::useSunlightSet(1) ``` There is no global indoor object, terrain, sky, weather, or particle pass. Every visible indoor object comes from the cell draw list, and the landscape appears only through `outside_view`. ## RenderDeviceD3D::DrawObjCellForDummies @ 0x005a0760 ```text for object in cell.object_list: draw object under Render::PortalList attached effects/particles follow the owning object visibility ``` acdream maps this to per-cell `WorldEntity.ParentCellId` buckets. Parentless live objects must not bypass the indoor PView graph.