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

📄 r_poly.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 3 页
字号:
        Inc(Integer(pspan), SizeOf(espan_t));
      end;
    end;

    vtop := vbottom;

    Dec(i);
    if (i = 0) then
      i := r_polydesc.nump;

  until (i = lmaxindex);
end;

{
** R_PolygonScanRightEdge
**
** Goes through the polygon and scans the right edge, filling in
** count values.
}

procedure R_PolygonScanRightEdge;
var
  i, v, itop: Integer;
  ibottom: Integer;
  pvert, pnext: emitpoint_p;
  pspan: espan_p;
  du, dv, vtop: Single;
  vbottom: Single;
  slope, uvert: Single;
  unext, vvert: Single;
  vnext: Single;
  u, u_step: fixed16_t;
begin
  pspan := s_polygon_spans;
  i := s_minindex;

  vvert := emitpoint_arrp(r_polydesc.pverts)^[i].v;

  if (vvert < r_refdef.fvrecty_adj) then
    vvert := r_refdef.fvrecty_adj;

  if (vvert > r_refdef.fvrectbottom_adj) then
    vvert := r_refdef.fvrectbottom_adj;

  vtop := q_shared.ceil(vvert);

  repeat
    pvert := @emitpoint_arrp(r_polydesc.pverts)^[i];
    pnext := Pointer(Integer(pvert) + SizeOf(emitpoint_t));

    vnext := pnext^.v;
    if (vnext < r_refdef.fvrecty_adj) then
      vnext := r_refdef.fvrecty_adj;

    if (vnext > r_refdef.fvrectbottom_adj) then
      vnext := r_refdef.fvrectbottom_adj;

    vbottom := q_shared.ceil(vnext);

    if (vtop < vbottom) then
    begin
      uvert := pvert^.u;
      if (uvert < r_refdef.fvrectx_adj) then
        uvert := r_refdef.fvrectx_adj;
      if (uvert > r_refdef.fvrectright_adj) then
        uvert := r_refdef.fvrectright_adj;

      unext := pnext^.u;
      if (unext < r_refdef.fvrectx_adj) then
        unext := r_refdef.fvrectx_adj;
      if (unext > r_refdef.fvrectright_adj) then
        unext := r_refdef.fvrectright_adj;

      du := unext - uvert;
      dv := vnext - vvert;
      slope := du / dv;
      u_step := Trunc(slope * $10000);
      // adjust u to ceil the integer portion
      u := Trunc((uvert + (slope * (vtop - vvert))) * $10000) + ($10000 - 1);
      itop := Trunc(vtop);
      ibottom := Trunc(vbottom);

      for v := itop to ibottom - 1 do
      begin
        pspan^.count := _SAR(u, 16) - pspan^.u;
        Inc(u, u_step);
        Inc(Integer(pspan), SizeOf(espan_t));
      end;
    end;

    vtop := vbottom;
    vvert := vnext;

    Inc(i);
    if (i = r_polydesc.nump) then
      i := 0;

  until (i = s_maxindex);

  pspan^.count := DS_SPAN_LIST_END; // mark the end of the span list
end;

{
** R_ClipAndDrawPoly
}
// PGM - isturbulent was qboolean. changed to int to allow passing more flags

procedure R_ClipAndDrawPoly(alpha: single; isturbulent: integer; textured: qboolean);
var
  outverts: array[0..MAXWORKINGVERTS + 3 - 1] of emitpoint_t;
  pout: emitpoint_p;
  pv: PSingle;
  i, nump: integer;
  scale: single;
  transformed: vec3_t;
  local: vec3_t;
begin
  FillChar(outverts, SizeOf(outverts), 0);
  if not textured then
  begin
    r_polydesc.drawspanlet := R_DrawSpanletConstant33;
  end
  else
  begin
    {
      ** choose the correct spanlet routine based on alpha
    }
    if (alpha = 1) then
    begin
      // isturbulent is ignored because we know that turbulent surfaces
      // can't be opaque
      r_polydesc.drawspanlet := R_DrawSpanletOpaque;
    end
    else
    begin
      if sw_stipplealpha^.value <> 0.0 then
      begin
        if (isturbulent <> 0) then
        begin
          if (alpha > 0.33) then
            r_polydesc.drawspanlet := R_DrawSpanletTurbulentStipple66
          else
            r_polydesc.drawspanlet := R_DrawSpanletTurbulentStipple33;
        end
        else
        begin
          if (alpha > 0.33) then
            r_polydesc.drawspanlet := R_DrawSpanlet66Stipple
          else
            r_polydesc.drawspanlet := R_DrawSpanlet33Stipple;
        end;
      end
      else
      begin
        if (isturbulent <> 0) then
        begin
          if (alpha > 0.33) then
            r_polydesc.drawspanlet := R_DrawSpanletTurbulentBlended66
          else
            r_polydesc.drawspanlet := R_DrawSpanletTurbulentBlended33;
        end
        else
        begin
          if (alpha > 0.33) then
            r_polydesc.drawspanlet := R_DrawSpanlet66
          else
            r_polydesc.drawspanlet := R_DrawSpanlet33;
        end;
      end;
    end;
  end;

  // clip to the frustum in worldspace
  nump := r_polydesc.nump;
  clip_current := 0;

  for i := 0 to 3 do
  begin
    nump := R_ClipPolyFace(nump, @view_clipplanes[i]);
    if (nump < 3) then
      exit;
    if (nump > MAXWORKINGVERTS) then
      ri.Sys_Error(ERR_DROP, PChar('R_ClipAndDrawPoly: too many points: ' + IntToStr(nump)));
  end;

  // transform vertices into viewspace and project
  pv := @r_clip_verts[clip_current][0];

  for i := 0 to nump - 1 do
  begin
    VectorSubtract(vec3_p(pv)^, r_origin, local);
    TransformVector(local, transformed);

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

    pout := @outverts[i];
    pout^.zi := 1.0 / transformed[2];

    pout^.s := vec5_p(pv)^[3];
    pout^.t := vec5_p(pv)^[4];

    scale := xscale * pout^.zi;
    pout^.u := (xcenter + scale * transformed[0]);

    scale := yscale * pout^.zi;
    pout^.v := (ycenter - scale * transformed[1]);
    Inc(Integer(pv), SizeOf(vec5_t));
  end;

// draw it
  r_polydesc.nump := nump;
  r_polydesc.pverts := @outverts[0]; // C pointer can be converted as Pascal's 1st address element
  R_DrawPoly(isturbulent);
end;

{
** R_BuildPolygonFromSurface
}

procedure R_BuildPolygonFromSurface(fa: msurface_p);
var
  i, lindex: Integer;
  lnumverts: Integer;
  pedges: medge_p;
  r_pedge: medge_p;
//  vertpage  : Integer; // never used
  vec: PSingle;
  pverts: vec5_p;
  tmins: array[0..2 - 1] of Single;
  scache: surfcache_p;
begin
  tmins[0] := 0;
  tmins[1] := 0;

  r_polydesc.nump := 0;

  // reconstruct the polygon
  pedges := currentmodel^.edges;
  lnumverts := fa^.numedges;
//  vertpage  := 0; // never used

  pverts := @r_clip_verts[0][0];

  for i := 0 to lnumverts - 1 do
  begin
    lindex := PIntegerArray(currentmodel^.surfedges)^[fa^.firstedge + i];

    if (lindex > 0) then
    begin
      r_pedge := @medge_arrp(pedges)^[lindex];
      vec := @mvertex_arrp(currentmodel^.vertexes)^[r_pedge^.v[0]].position;
    end
    else
    begin
      r_pedge := @medge_arrp(pedges)^[-lindex];
      vec := @mvertex_arrp(currentmodel^.vertexes)^[r_pedge^.v[1]].position;
    end;
    VectorCopy(vec3_p(vec)^, vec3_p(@vec5_arrp(pverts)^[i])^);
  end;

  VectorCopy(vec3_p(@fa^.texinfo^.vecs[0])^, r_polydesc.vright);
  VectorCopy(vec3_p(@fa^.texinfo^.vecs[1])^, r_polydesc.vup);
  VectorCopy(fa^.plane^.normal, r_polydesc.vpn);
  VectorCopy(r_origin, vec3_p(@r_polydesc.viewer_position)^);

  if (fa^.flags and SURF_PLANEBACK) <> 0 then
  begin
    VectorSubtract(vec3_origin, r_polydesc.vpn, r_polydesc.vpn);
  end;

// PGM 09/16/98
  if (fa^.texinfo^.flags and (SURF_WARP or SURF_FLOWING)) <> 0 then
  begin
    r_polydesc.pixels := fa^.texinfo^.image^.pixels[0];
    r_polydesc.pixel_width := fa^.texinfo^.image^.width;
    r_polydesc.pixel_height := fa^.texinfo^.image^.height;
  end
// PGM 09/16/98
  else
  begin
    scache := D_CacheSurface(fa, 0);

    r_polydesc.pixels := @scache^.data[0];
    r_polydesc.pixel_width := scache^.width;
    r_polydesc.pixel_height := scache^.height;

    tmins[0] := fa^.texturemins[0];
    tmins[1] := fa^.texturemins[1];
  end;

  r_polydesc.dist := DotProduct(r_polydesc.vpn, vec3_p(pverts)^);
  r_polydesc.s_offset := fa^.texinfo^.vecs[0, 3] - tmins[0];
  r_polydesc.t_offset := fa^.texinfo^.vecs[1, 3] - tmins[1];

  // scrolling texture addition
  if (fa^.texinfo^.flags and SURF_FLOWING) <> 0 then
  begin
    r_polydesc.s_offset := r_polydesc.s_offset + (-128 * ((r_newrefdef.time * 0.25) - Trunc(r_newrefdef.time * 0.25)));
  end;

  r_polydesc.nump := lnumverts;
end;

{
** R_PolygonCalculateGradients
}

procedure R_PolygonCalculateGradients;
var
  p_normal: vec3_t;
  p_saxis: vec3_t;
  p_taxis: vec3_t;
  distinv: single;
begin
  TransformVector(r_polydesc.vpn, p_normal);
  TransformVector(r_polydesc.vright, p_saxis);
  TransformVector(r_polydesc.vup, p_taxis);

  distinv := 1.0 / (-(DotProduct(vec3_t(r_polydesc.viewer_position), r_polydesc.vpn)) + r_polydesc.dist);

  d_sdivzstepu := p_saxis[0] * xscaleinv;
  d_sdivzstepv := -p_saxis[1] * yscaleinv;
  d_sdivzorigin := p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv;

  d_tdivzstepu := p_taxis[0] * xscaleinv;
  d_tdivzstepv := -p_taxis[1] * yscaleinv;
  d_tdivzorigin := p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv;

  d_zistepu := p_normal[0] * xscaleinv * distinv;
  d_zistepv := -p_normal[1] * yscaleinv * distinv;
  d_ziorigin := p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv;

  sadjust := fixed16_t(Trunc((DotProduct(vec3_p(@r_polydesc.viewer_position)^, r_polydesc.vright) + r_polydesc.s_offset) * $10000));
  tadjust := fixed16_t(Trunc((DotProduct(vec3_p(@r_polydesc.viewer_position)^, r_polydesc.vup) + r_polydesc.t_offset) * $10000));

// -1 (-epsilon) so we never wander off the edge of the texture
  bbextents := (r_polydesc.pixel_width shl 16) - 1;
  bbextentt := (r_polydesc.pixel_height shl 16) - 1;
end;

{
** R_DrawPoly
**
** Polygon drawing function.  Uses the polygon described in r_polydesc
** to calculate edges and gradients, then renders the resultant spans.
**
** This should NOT be called externally since it doesn't do clipping!
}
// PGM - iswater was qboolean. changed to support passing more flags

procedure R_DrawPoly(iswater: Integer);
var
  i, nump: integer;
  ymin, ymax: single;
  pverts: emitpoint_p;
  spans: array[0..MAXHEIGHT + 1 - 1] of espan_t;
begin
  FillChar(spans, SizeOf(spans), 0);
  s_polygon_spans := @spans[0];

// find the top and bottom vertices, and make sure there's at least one scan to
// draw
  ymin := 999999.9;
  ymax := -999999.9;
  pverts := r_polydesc.pverts;

  for i := 0 to r_polydesc.nump - 1 do
  begin
    if (pverts^.v < ymin) then
    begin
      ymin := pverts^.v;
      s_minindex := i;
    end;

    if (pverts^.v > ymax) then
    begin
      ymax := pverts^.v;
      s_maxindex := i;
    end;
    Inc(Integer(pverts), SizeOf(emitpoint_p));
  end;

  ymin := q_shared.ceil(ymin);
  ymax := q_shared.ceil(ymax);

  if (ymin >= ymax) then
    Exit; // doesn't cross any scans at all

  cachewidth := r_polydesc.pixel_width;
  cacheblock := r_polydesc.pixels;

// copy the first vertex to the last vertex, so we don't have to deal with
// wrapping
  nump := r_polydesc.nump;
  pverts := r_polydesc.pverts;

  emitpoint_arrp(pverts)^[nump] := pverts^;

  R_PolygonCalculateGradients;
  R_PolygonScanLeftEdge;
  R_PolygonScanRightEdge;

  R_PolygonDrawSpans(s_polygon_spans, iswater);
end;

{
** R_DrawAlphaSurfaces
}

procedure R_DrawAlphaSurfaces;
var
  s: msurface_p;
begin
  s := r_alpha_surfaces;

  currentmodel := r_worldmodel;

  modelorg[0] := -r_origin[0];
  modelorg[1] := -r_origin[1];
  modelorg[2] := -r_origin[2];

  while s <> nil do
  begin
    R_BuildPolygonFromSurface(s);

//=======
//PGM
//		if (s->texinfo->flags & SURF_TRANS66)
//			R_ClipAndDrawPoly( 0.60f, ( s->texinfo->flags & SURF_WARP) != 0, true );
//		else
//			R_ClipAndDrawPoly( 0.30f, ( s->texinfo->flags & SURF_WARP) != 0, true );

  // PGM - pass down all the texinfo flags, not just SURF_WARP.
    if (s^.texinfo^.flags and SURF_TRANS66) <> 0 then
      R_ClipAndDrawPoly(0.60, (s^.texinfo^.flags and (SURF_WARP or SURF_FLOWING)), true)
    else
      R_ClipAndDrawPoly(0.30, (s^.texinfo^.flags and (SURF_WARP or SURF_FLOWING)), true);
//PGM
//=======
    s := s^.nextalphasurface;
  end;
  r_alpha_surfaces := nil;
end;

{
** R_IMFlatShadedQuad
}

procedure R_IMFlatShadedQuad(a, b, c, d: vec3_t; color: integer; alpha: single);
var
  s0, s1: vec3_t;
begin
  r_polydesc.nump := 4;

  VectorCopy(r_origin, vec3_p(@r_polydesc.viewer_position)^);

  VectorCopy(a, vec3_p(@r_clip_verts[0][0])^);
  VectorCopy(b, vec3_p(@r_clip_verts[0][1])^);
  VectorCopy(c, vec3_p(@r_clip_verts[0][2])^);
  VectorCopy(d, vec3_p(@r_clip_verts[0][3])^);

  r_clip_verts[0][0][3] := 0;
  r_clip_verts[0][1][3] := 0;
  r_clip_verts[0][2][3] := 0;
  r_clip_verts[0][3][3] := 0;

  r_clip_verts[0][0][4] := 0;
  r_clip_verts[0][1][4] := 0;
  r_clip_verts[0][2][4] := 0;
  r_clip_verts[0][3][4] := 0;

  VectorSubtract(d, c, s0);
  VectorSubtract(c, b, s1);
  CrossProduct(s0, s1, r_polydesc.vpn);
  VectorNormalize(r_polydesc.vpn);

  //???? DotProduct expects vec3_t instead vec5_t
  r_polydesc.dist := DotProduct(r_polydesc.vpn, vec3_p(@r_clip_verts[0][0])^);
  r_polyblendcolor := color;
  R_ClipAndDrawPoly(alpha, 0, false);
end;

end.

⌨️ 快捷键说明

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