⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 r_rast.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
//100%
{$ALIGN 8}{$MINENUMSIZE 4}
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): r_rast.c                                                          }
{ Content:                                                                   }
{                                                                            }
{ Initial conversion by : Carl A Kenner (carl_kenner@hotmail.com)            }
{ Initial conversion on : 23-Feb-2002                                        }
{                                                                            }
{ This File contains part of convertion of Quake2 source to ObjectPascal.    }
{ More information about this project can be found at:                       }
{ http://www.sulaco.co.za/quake2/                                            }
{                                                                            }
{ Copyright (C) 1997-2001 Id Software, Inc.                                  }
{                                                                            }
{ 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.                       }
{                                                                            }
{----------------------------------------------------------------------------}
{ Updated on : 25-Feb-2002                                                   }
{ Updated by : Carl A Kenner (carl_kenner@hotmail.com)                       }
{ Updated on : 12-Aug-2002                                                   }
{ Updated by : CodeFusion (Michael@skovslund.dk)                             }
{                                                                            }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on:                               }
{ none                                                                       }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{----------------------------------------------------------------------------}
// r_rast.c
unit r_rast;

{$DEFINE _NODEPEND}

interface

uses
  q_shared,
  qfiles,
  r_model,
  r_misc,
  r_local;

procedure R_InitSkyBox;
procedure R_RenderFace(fa: msurface_p; clipflags: Integer);
procedure R_EmitEdge(pv0, pv1: mvertex_p);
procedure R_RenderBmodelFace(pedges: bedge_p; psurf: msurface_p);

var
  sintable: array[0..1279] of Integer;
  intsintable: array[0..1279] of Integer;
  blanktable: array[0..1279] of Integer; // PGM
  view_clipplanes: array[0..3] of clipplane_t;
  c_faceclip: Integer; // number of faces clipped
  r_skytexinfo: array[0..5] of mtexinfo_t;

implementation

uses
  r_poly,
  r_edgea,
  r_edge,
  r_bsp_c,
  r_main,
  SysUtils;

const
  MAXLEFTCLIPEDGES = 100;

// !!! if these are changed, they must be changed in asm_draw.h too !!!
  FULLY_CLIPPED_CACHED = $80000000;
  FRAMECOUNT_MASK = $7FFFFFFF;

var
  cacheoffset: Cardinal;
//  entity_clipplanes : clipplane_p;
//  world_clipplanes  : Array[0..15] of clipplane_t;
  r_pedge: medge_p;
  r_leftclipped: qboolean;
  r_rightclipped: qboolean;
  r_nearzionly: qboolean;
  r_leftenter: mvertex_t;
  r_leftexit: mvertex_t;
  r_rightenter: mvertex_t;
  r_rightexit: mvertex_t;

type
  evert_p = ^evert_t;
  pevert_t = evert_p;
  evert_t = record
    u, v: Single;
    ceilv: Integer;
  end;
  TEvert = evert_t;
  PEvert = evert_p;

var
  r_emitted: Integer;
  r_nearzi: Single;
  r_u1, r_v1, r_lzi1: Single;
  r_ceilv1: Integer;

  r_lastvertvalid: qboolean;
  r_skyframe: Integer;

  r_skyfaces: msurface_p;
  r_skyplanes: array[0..5] of mplane_t;
  r_skyverts: mvertex_p;
  r_skyedges: medge_p;
  r_skysurfedges: PInteger;

// I just copied this data from a box map...
var
  skybox_planes: array[0..11] of Integer = (2, -128, 0, -128, 2, 128, 1, 128, 0, 128, 1, -128);
  box_surfedges: array[0..23] of Integer = (1, 2, 3, 4, -1, 5, 6, 7, 8, 9, -6, 10, -2, -7, -9, 11,
    12, -3, -11, -8, -12, -10, -5, -4);
  box_edges: array[0..23] of Integer = (1, 2, 2, 3, 3, 4, 4, 1, 1, 5, 5, 6, 6, 2,
    7, 8, 8, 6, 5, 7, 8, 3, 7, 4);
  box_faces: array[0..5] of Integer = (0, 0, 2, 2, 2, 0);
  box_vecs: array[0..5, 0..1] of vec3_t = (
    ((0, -1, 0), (-1, 0, 0)),
    ((0, 1, 0), (0, 0, -1)),
    ((0, -1, 0), (1, 0, 0)),
    ((1, 0, 0), (0, 0, -1)),
    ((0, -1, 0), (0, 0, -1)),
    ((-1, 0, 0), (0, 0, -1))
    );
  box_verts: array[0..7, 0..2] of Single = (
    (-1, -1, -1),
    (-1, 1, -1),
    (1, 1, -1),
    (1, -1, -1),
    (-1, -1, 1),
    (-1, 1, 1),
    (1, -1, 1),
    (1, 1, 1)
    );

// down, west, up, north, east, south
// {"rt", "bk", "lf", "ft", "up", "dn"};

var
  makeleftedge,
    makerightedge: qboolean; // CAK - global static means other units can't use it

(*
================
R_InitSkyBox

================
*)

procedure R_InitSkyBox;
var
  i: Integer;
begin
//  r_skyfaces := msurface_p(Integer(loadmodel^.surfaces)+(loadmodel^.numsurfaces*SizeOf(msurface_t)));
  r_skyfaces := @msurface_arrp(loadmodel^.surfaces)^[loadmodel^.numsurfaces];
  Inc(loadmodel^.numsurfaces, 6);

//  r_skyverts := mvertex_p(Integer(loadmodel^.vertexes)+(loadmodel^.numvertexes*SizeOf(mvertex_t)));
  r_skyverts := @mvertex_arrp(loadmodel^.vertexes)^[loadmodel^.numvertexes];
  Inc(loadmodel^.numvertexes, 8);

//  r_skyedges := medge_p(Integer(loadmodel^.edges)+(loadmodel^.numedges*SizeOf(medge_t)));
  r_skyedges := @medge_arrp(loadmodel^.edges)^[loadmodel^.numedges];
  Inc(loadmodel^.numedges, 12);

//  r_skysurfedges := PInteger(Integer(loadmodel^.surfedges)+(loadmodel^.numsurfedges*SizeOf(Integer)));
  r_skysurfedges := @PIntegerArray(loadmodel^.surfedges)^[loadmodel^.numsurfedges];
  Inc(loadmodel^.numsurfedges, 24);

  if (loadmodel^.numsurfaces > MAX_MAP_FACES) or (loadmodel^.numvertexes > MAX_MAP_VERTS) or (loadmodel^.numedges > MAX_MAP_EDGES) then
    ri.Sys_Error(ERR_DROP, 'InitSkyBox: map overflow');

  FillChar(r_skyfaces^, 6*sizeof(r_skyfaces^), 0);
  for i:= 0 to 5 do
  begin
    r_skyplanes[i].normal[skybox_planes[i * 2]] := 1;
    r_skyplanes[i].dist := skybox_planes[i * 2 + 1];

    VectorCopy(box_vecs[i][0], vec3_p(@r_skytexinfo[i].vecs[0][0])^);
    VectorCopy(box_vecs[i][1], vec3_p(@r_skytexinfo[i].vecs[1][0])^);

    msurface_arrp(r_skyfaces)^[i].plane := @r_skyplanes[i];
    msurface_arrp(r_skyfaces)^[i].numedges := 4;
    msurface_arrp(r_skyfaces)^[i].flags := box_faces[i] or SURF_DRAWSKYBOX;
    msurface_arrp(r_skyfaces)^[i].firstedge := loadmodel.numsurfedges - 24 + i * 4;
    msurface_arrp(r_skyfaces)^[i].texinfo := @r_skytexinfo[i];
    msurface_arrp(r_skyfaces)^[i].texturemins[0] := -128;
    msurface_arrp(r_skyfaces)^[i].texturemins[1] := -128;
    msurface_arrp(r_skyfaces)^[i].extents[0] := 256;
    msurface_arrp(r_skyfaces)^[i].extents[1] := 256;
  end;

  for i := 0 to 23 do
  begin
    if box_surfedges[i] > 0 then
      PIntegerArray(r_skysurfedges)^[i] := loadmodel^.numedges - 13 + box_surfedges[i]
//      PInteger(Integer(r_skysurfedges)+(i*SizeOf(Integer)))^ := loadmodel.numedges-13 + box_surfedges[i]
    else
      PIntegerArray(r_skysurfedges)^[i] := -(loadmodel^.numedges-13 + (-box_surfedges[i]));
//      PInteger(Integer(r_skysurfedges)+(i*SizeOf(Integer)))^ := - (loadmodel.numedges-13 + -box_surfedges[i]);
  end;

  for i := 0 to 11 do
  begin
    medge_arrp(r_skyedges)^[i].v[0] := loadmodel.numvertexes - 9 + box_edges[i * 2 + 0];
    medge_arrp(r_skyedges)^[i].v[1] := loadmodel.numvertexes - 9 + box_edges[i * 2 + 1];
    medge_arrp(r_skyedges)^[i].cachededgeoffset := 0;
  end;
end;

(*
================
R_EmitSkyBox
================
*)

procedure R_EmitSkyBox;
var
  i, j: Integer;
  oldkey: Integer;
begin
  if insubmodel then
    exit; // submodels should never have skies
  if r_skyframe = r_framecount then
    exit; // already set this frame

  r_skyframe := r_framecount;

  // set the eight fake vertexes
  for i := 0 to 7 do
    for j := 0 to 2 do
      mvertex_arrp(r_skyverts)^[i].position[j] := r_origin[j] + box_verts[i][j] * 128;

  // set the six fake planes
  for i := 0 to 5 do
    if skybox_planes[(i * 2) + 1] > 0 then
      r_skyplanes[i].dist := r_origin[skybox_planes[i * 2]] + 128
    else
      r_skyplanes[i].dist := r_origin[skybox_planes[i * 2]] - 128;

  // fix texture offseets
  for i := 0 to 5 do
  begin
    r_skytexinfo[i].vecs[0][3] := -DotProduct(r_origin, vec3_p(@r_skytexinfo[i].vecs[0][0])^);
    r_skytexinfo[i].vecs[1][3] := -DotProduct(r_origin, vec3_p(@r_skytexinfo[i].vecs[1][0])^);
  end;

  // emit the six faces
  oldkey := r_currentkey;
  r_currentkey := $7FFFFFF0;
  for i := 0 to 5 do
  begin
    R_RenderFace(@msurface_arrp(r_skyfaces)^[i], 15);
  end;
  r_currentkey := oldkey; // bsp sorting order
end;

(*
================
R_EmitEdge
================
*)
{$IFNDEF id386}

procedure R_EmitEdge(pv0, pv1: mvertex_p);
var
  edge, pcheck: edge_p;
  u_check: Integer;
  u, u_step: Single;
  local: vec3_t;
  transformed: vec3_t;
  world: PSingle;
  v, v2, ceilv0: Integer;
  scale, lzi0: Single;
  u0, v0: Single;
  side: Integer;
begin
  if r_lastvertvalid then
  begin
    u0 := r_u1;
    v0 := r_v1;
    lzi0 := r_lzi1;
    ceilv0 := r_ceilv1;
  end
  else
  begin
    world := @pv0^.position[0];

    // transform and project
    VectorSubtract(vec3_p(world)^, modelorg, local);
    TransformVector(local, transformed);

    if transformed[2] < NEAR_CLIP then
      transformed[2] := NEAR_CLIP;

    lzi0 := 1.0 / transformed[2];

    // FIXME: build x/yscale into transform?
    scale := xscale * lzi0;
    u0 := xcenter + scale * transformed[0];
    if u0 < r_refdef.fvrectx_adj then
      u0 := r_refdef.fvrectx_adj;
    if u0 > r_refdef.fvrectright_adj then
      u0 := r_refdef.fvrectright_adj;

    scale := yscale * lzi0;
    v0 := ycenter - scale * transformed[1];
    if v0 < r_refdef.fvrecty_adj then
      v0 := r_refdef.fvrecty_adj;
    if v0 > r_refdef.fvrectbottom_adj then
      v0 := r_refdef.fvrectbottom_adj;

    ceilv0 := ceil(v0);
  end;

  world := @pv1^.position[0];

  // transform and project
  VectorSubtract(vec3_p(world)^, modelorg, local);
  TransformVector(local, transformed);

  if transformed[2] < NEAR_CLIP then
    transformed[2] := NEAR_CLIP;

  r_lzi1 := 1.0 / transformed[2];

  scale := xscale * r_lzi1;
  r_u1 := (xcenter + scale * transformed[0]);
  if r_u1 < r_refdef.fvrectx_adj then
    r_u1 := r_refdef.fvrectx_adj;
  if r_u1 > r_refdef.fvrectright_adj then
    r_u1 := r_refdef.fvrectright_adj;

  scale := yscale * r_lzi1;
  r_v1 := ycenter - scale * transformed[1];
  if r_v1 < r_refdef.fvrecty_adj then
    r_v1 := r_refdef.fvrecty_adj;
  if r_v1 > r_refdef.fvrectbottom_adj then
    r_v1 := r_refdef.fvrectbottom_adj;

  if r_lzi1 > lzi0 then
    lzi0 := r_lzi1;

  if lzi0 > r_nearzi then // for mipmap finding
    r_nearzi := lzi0;

  // for right edges, all we want is the effect on 1/z
  if r_nearzionly then
    exit;

  r_emitted := 1;

  r_ceilv1 := ceil(r_v1);

  // create the edge
  if ceilv0 = r_ceilv1 then
  begin
    // we cache unclipped horizontal edges as fully clipped
    if cacheoffset <> $7FFFFFFF then
    begin
      cacheoffset := FULLY_CLIPPED_CACHED or (Cardinal(r_framecount) and FRAMECOUNT_MASK);
    end;
    exit; // horizontal edge
  end;

  side := Integer(ceilv0 > r_ceilv1);

  edge := edge_p_;
  Inc(Integer(edge_p_), SizeOf(edge_p_^));

  edge^.owner := r_pedge;

  edge^.nearzi := lzi0;

  if side = 0 then
  begin
    // trailing edge (go from p1 to p2)
    v := ceilv0;
    v2 := r_ceilv1 - 1;

    edge^.surfs[0] := (Integer(surface_p) - Integer(surfaces)) div sizeof(surf_t);
    edge^.surfs[1] := 0;

    u_step := ((r_u1 - u0) / (r_v1 - v0));
    u := v;
    u := u0 + (u - v0) * u_step;
  end
  else
  begin
    // leading edge (go from p2 to p1)
    v2 := ceilv0 - 1;
    v := r_ceilv1;

    edge^.surfs[0] := 0;
    edge^.surfs[1] := (Integer(surface_p) - Integer(surfaces)) div sizeof(surf_t);

    u_step := ((u0 - r_u1) / (v0 - r_v1));
    u := v;
    u := r_u1 + (u - r_v1) * u_step;
  end;

  edge^.u_step := Trunc(u_step * $100000); // CAK truncate or round ???? CODEFUSION -> Trunc!!!!
  edge^.u := Trunc(u * $100000 + $FFFFF);

// we need to do this to avoid stepping off the edges if a very nearly
// horizontal edge is less than epsilon above a scan, and numeric error causes
// it to incorrectly extend to the scan, and the extension of the line goes off
// the edge of the screen
// FIXME: is this actually needed?
  if edge^.u < r_refdef.vrect_x_adj_shift20 then
    edge^.u := r_refdef.vrect_x_adj_shift20;
  if edge^.u > r_refdef.vrectright_adj_shift20 then
    edge^.u := r_refdef.vrectright_adj_shift20;

//
// sort the edge in normally
//
  u_check := edge^.u;
  if edge^.surfs[0] <> 0 then
    inc(u_check); // sort trailers after leaders

  if (newedges[v] = nil) or (newedges[v]^.u >= u_check) then
  begin
    edge^.next := newedges[v];
    newedges[v] := edge;
  end
  else
  begin
    pcheck := newedges[v];
    while (pcheck^.next <> nil) and (pcheck^.next^.u < u_check) do
      pcheck := pcheck^.next;
    edge^.next := pcheck^.next;
    pcheck^.next := edge;
  end;

  edge^.nextremove := removeedges[v2];
  removeedges[v2] := edge;
end;

(*
================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -