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

📄 r_rast.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
R_ClipEdge
================
*)

procedure R_ClipEdge(pv0, pv1: mvertex_p; clip: clipplane_p);
var
  d0, d1, f: Single;
  clipvert: mvertex_t;
begin
  if clip <> nil then
  begin
    repeat
      d0 := DotProduct(pv0^.position, clip^.normal) - clip^.dist;
      d1 := DotProduct(pv1^.position, clip^.normal) - clip^.dist;

      if d0 >= 0 then
      begin
        // point 0 is unclipped
        if d1 >= 0 then
        begin
          // both points are unclipped
          clip := clip^.next;
          continue;
        end;

        // only point 1 is clipped

        // we don't cache clipped edges
        cacheoffset := $7FFFFFFF;

        f := d0 / (d0 - d1);
        clipvert.position[0] := pv0^.position[0] + f * (pv1^.position[0] - pv0^.position[0]);
        clipvert.position[1] := pv0^.position[1] + f * (pv1^.position[1] - pv0^.position[1]);
        clipvert.position[2] := pv0^.position[2] + f * (pv1^.position[2] - pv0^.position[2]);

        if clip^.leftedge <> 0 then
        begin
          r_leftclipped := true;
          r_leftexit := clipvert;
        end
        else
        begin
          if clip^.rightedge <> 0 then
          begin
            r_rightclipped := true;
            r_rightexit := clipvert;
          end;
        end;
        R_ClipEdge(pv0, @clipvert, clip^.next);
        Exit;
      end
      else
      begin
        // point 0 is clipped
        if d1 < 0 then
        begin
          // both points are clipped
          // we do cache fully clipped edges
          if not r_leftclipped then
          begin
            cacheoffset := FULLY_CLIPPED_CACHED or (Cardinal(r_framecount) and FRAMECOUNT_MASK);
          end;
          Exit;
        end;

        // only point 0 is clipped
        r_lastvertvalid := false;

        // we don't cache partially clipped edges
        cacheoffset := $7FFFFFFF;

        f := d0 / (d0 - d1);
        clipvert.position[0] := pv0^.position[0] + f * (pv1^.position[0] - pv0^.position[0]);
        clipvert.position[1] := pv0^.position[1] + f * (pv1^.position[1] - pv0^.position[1]);
        clipvert.position[2] := pv0^.position[2] + f * (pv1^.position[2] - pv0^.position[2]);

        if clip^.leftedge <> 0 then
        begin
          r_leftclipped := true;
          r_leftenter := clipvert;
        end
        else
        begin
          if clip^.rightedge <> 0 then
          begin
            r_rightclipped := true;
            r_rightenter := clipvert;
          end;
        end;
        R_ClipEdge(@clipvert, pv1, clip^.next);
        Exit;
      end;
      clip := clip^.next;
    until clip = nil;
  end;
  // add the edge
  R_EmitEdge(pv0, pv1);
end;
{$ENDIF}

(*
================
R_EmitCachedEdge
================
*)

procedure R_EmitCachedEdge;
var
  pedge_t: edge_p;
begin
  pedge_t := edge_p(Integer(r_edges) + r_pedge^.cachededgeoffset);
  if pedge_t^.surfs[0] = 0 then
    pedge_t^.surfs[0] := (Integer(surface_p) - Integer(surfaces)) div sizeof(surf_t)
  else
    pedge_t^.surfs[1] := (Integer(surface_p) - Integer(surfaces)) div sizeof(surf_t);

  if pedge_t^.nearzi > r_nearzi then // for mipmap finding
    r_nearzi := pedge_t^.nearzi;

  r_emitted := 1;
end;

(*
================
R_RenderFace
================
*)

procedure R_RenderFace(fa: msurface_p; clipflags: Integer);
var
  i, lindex: Integer;
  mask: Cardinal;
  pplane: mplane_p;
  distinv: Single;
  p_normal: vec3_t;
  pedges: medge_p;
  tedge: medge_t;
  pclip: clipplane_p;
begin
  // translucent surfaces are not drawn by the edge renderer
  if (fa^.texinfo^.flags and (SURF_TRANS33 or SURF_TRANS66)) <> 0 then
  begin
    fa^.nextalphasurface := r_alpha_surfaces;
    r_alpha_surfaces := fa;
    Exit;
  end;

  // sky surfaces encountered in the world will cause the
  // environment box surfaces to be emited
  if (fa^.texinfo^.flags and SURF_SKY) <> 0 then
  begin
    R_EmitSkyBox;
    Exit;
  end;

  // skip out if no more surfs
  if Integer(surface_p) >= Integer(surf_max) then
  begin
    Inc(r_outofsurfaces);
    Exit;
  end;
  // ditto if not enough edges left, or switch to auxedges if possible
  if Integer(@PEdge_tArray(edge_p_)^[(fa^.numedges + 4)]) >= Integer(edge_max) then
  begin
    Inc(r_outofedges, fa^.numedges);
    Exit;
  end;

  Inc(c_faceclip);

  // set up clip planes
  pclip := nil;

  mask := $08;
  for i := 3 downto 0 do
  begin
    if (clipflags and mask) <> 0 then
    begin
      view_clipplanes[i].next := pclip;
      pclip := @view_clipplanes[i];
    end;
    mask := mask shr 1;
  end;

  // push the edges through
  r_emitted := 0;
  r_nearzi := 0;
  r_nearzionly := false;
  makeleftedge := false;
  makerightedge := false;
  pedges := currentmodel^.edges;
  r_lastvertvalid := false;

  for i := 0 to fa^.numedges - 1 do
  begin
    lindex := PIntegerArray(currentmodel^.surfedges)^[fa^.firstedge + i];
    if lindex > 0 then
    begin
      r_pedge := @medge_arrp(pedges)^[lindex];

      // if the edge is cached, we can just reuse the edge
      if not insubmodel then
      begin
        if (r_pedge^.cachededgeoffset and FULLY_CLIPPED_CACHED) <> 0 then
        begin
          if Integer(r_pedge^.cachededgeoffset and FRAMECOUNT_MASK) = r_framecount then
          begin
            r_lastvertvalid := false;
            continue;
          end;
        end
        else
        begin
          if (Integer(edge_p_) - Integer(r_edges) > r_pedge^.cachededgeoffset) and
            (edge_p(Integer(r_edges) + r_pedge^.cachededgeoffset)^.owner = r_pedge) then
          begin
            R_EmitCachedEdge;
            r_lastvertvalid := false;
            continue;
          end;
        end;
      end;
      // assume it's cacheable
      cacheoffset := Cardinal(edge_p_) - Cardinal(r_edges);
      r_leftclipped := false;
      r_rightclipped := false;
      R_ClipEdge(@mvertex_arrp(r_pcurrentvertbase)^[r_pedge^.v[0]],
        @mvertex_arrp(r_pcurrentvertbase)^[r_pedge^.v[1]], pclip);
      r_pedge^.cachededgeoffset := cacheoffset;

      if r_leftclipped then
        makeleftedge := true;
      if r_rightclipped then
        makerightedge := true;
      r_lastvertvalid := true;
    end
    else
    begin
      lindex := -lindex;
      r_pedge := @medge_arrp(pedges)^[lindex];
      // if the edge is cached, we can just reuse the edge
      if not insubmodel then
      begin
        if (r_pedge^.cachededgeoffset and FULLY_CLIPPED_CACHED) > 0 then
        begin
          if Integer(r_pedge^.cachededgeoffset and FRAMECOUNT_MASK) = r_framecount then
          begin
            r_lastvertvalid := false;
            continue;
          end;
        end
        else
        begin
	  // it's cached if the cached edge is valid and is owned
	  // by this medge_t
          if (Cardinal(edge_p_) - Cardinal(r_edges) > Cardinal(r_pedge^.cachededgeoffset)) and
	           (edge_p(Integer(r_edges) + r_pedge^.cachededgeoffset)^.owner = r_pedge) then
          begin
            R_EmitCachedEdge;
            r_lastvertvalid := false;
            continue;
          end;
        end;
      end;
      // assume it's cacheable
      cacheoffset := Cardinal(edge_p_) - Cardinal(r_edges);
      r_leftclipped := false;
      r_rightclipped := false;
      R_ClipEdge(@mvertex_arrp(r_pcurrentvertbase)^[r_pedge^.v[1]],
        @mvertex_arrp(r_pcurrentvertbase)^[r_pedge^.v[0]], pclip);
      r_pedge^.cachededgeoffset := cacheoffset;

      if r_leftclipped then
        makeleftedge := true;
      if r_rightclipped then
        makerightedge := true;
      r_lastvertvalid := true;
    end;
  end;

  // if there was a clip off the left edge, add that edge too
  // FIXME: faster to do in screen space?
  // FIXME: share clipped edges?
  if makeleftedge then
  begin
    r_pedge := @tedge;
    r_lastvertvalid := false;
    R_ClipEdge(@r_leftexit, @r_leftenter, pclip^.next);
  end;
  // if there was a clip off the right edge, get the right r_nearzi
  if makerightedge then
  begin
    r_pedge := @tedge;
    r_lastvertvalid := false;
    r_nearzionly := true;
    R_ClipEdge(@r_rightexit, @r_rightenter, view_clipplanes[1].next);
  end;

  // if no edges made it out, return without posting the surface
  if r_emitted = 0 then
    exit;

  inc(r_polycount);

  surface_p^.msurf := fa;
  surface_p^.nearzi := r_nearzi;
  surface_p^.flags := fa^.flags;
  surface_p^.insubmodel := insubmodel;
  surface_p^.spanstate := 0;
  surface_p^.entity := currententity;
  surface_p^.key := r_currentkey;
  inc(r_currentkey);
  surface_p^.spans := nil;

  pplane := fa^.plane;

  // FIXME: cache this?
  TransformVector(pplane^.normal, p_normal);
  // FIXME: cache this?
  distinv := 1.0 / (pplane^.dist - DotProduct(modelorg, pplane^.normal));

  surface_p^.d_zistepu := p_normal[0] * xscaleinv * distinv;
  surface_p^.d_zistepv := -p_normal[1] * yscaleinv * distinv;
  surface_p^.d_ziorigin := p_normal[2] * distinv - xcenter * surface_p^.d_zistepu - ycenter * surface_p^.d_zistepv;
  inc(Integer(surface_p), SizeOf(surf_t));
end;

(*
================
R_RenderBmodelFace
================
*)

procedure R_RenderBmodelFace(pedges: bedge_p; psurf: msurface_p);
var
  i: Integer;
  mask: Cardinal;
  pplane: mplane_p;
  distinv: Single;
  p_normal: vec3_t;
  tedge: medge_t;
  pclip: clipplane_p;
begin
  if (psurf^.texinfo^.flags and (SURF_TRANS33 or SURF_TRANS66)) <> 0 then
  begin
    psurf^.nextalphasurface := r_alpha_surfaces;
    r_alpha_surfaces := psurf;
    Exit;
  end;

  // skip out if no more surfs
  if Cardinal(surface_p) >= Cardinal(surf_max) then
  begin
    inc(r_outofsurfaces);
    Exit;
  end;

  // ditto if not enough edges left, or switch to auxedges if possible
  if (Integer(edge_p_) + ((psurf^.numedges + 4) * sizeof(edge_t))) >= Integer(edge_max) then
  begin
    Inc(r_outofedges, psurf^.numedges);
    Exit;
  end;

  inc(c_faceclip);

  // this is a dummy to give the caching mechanism someplace to write to
  r_pedge := @tedge;

  // set up clip planes
  pclip := nil;

  mask := $08;
  for i := 3 downto 0 do
  begin
    if (r_clipflags and mask) <> 0 then
    begin
      view_clipplanes[i].next := pclip;
      pclip := @view_clipplanes[i];
    end;
    mask := mask shr 1;
  end;

  // push the edges through
  r_emitted := 0;
  r_nearzi := 0;
  r_nearzionly := false;
  makeleftedge := false;
  makerightedge := false;
  // FIXME: keep clipped bmodel edges in clockwise order so last vertex caching
  // can be used?
  r_lastvertvalid := false;

  while (pedges <> nil) do
  begin
    r_leftclipped := false;
    r_rightclipped := false;
    R_ClipEdge(pedges^.v[0], pedges^.v[1], pclip);

    if (r_leftclipped) then
      makeleftedge := true;
    if (r_rightclipped) then
      makerightedge := true;

    pedges := pedges^.pnext;
  end;

  // if there was a clip off the left edge, add that edge too
  // FIXME: faster to do in screen space?
  // FIXME: share clipped edges?
  if (makeleftedge) then
  begin
    r_pedge := @tedge;
    R_ClipEdge(@r_leftexit, @r_leftenter, pclip^.next);
  end;

  // if there was a clip off the right edge, get the right r_nearzi
  if makerightedge then
  begin
    r_pedge := @tedge;
    r_nearzionly := true;
    R_ClipEdge(@r_rightexit, @r_rightenter, view_clipplanes[1].next);
  end;

  // if no edges made it out, exit without posting the surface
  if r_emitted = 0 then
    exit;

  inc(r_polycount);

  surface_p^.msurf := psurf;
  surface_p^.nearzi := r_nearzi;
  surface_p^.flags := psurf^.flags;
  surface_p^.insubmodel := true;
  surface_p^.spanstate := 0;
  surface_p^.entity := currententity;
  surface_p^.key := r_currentbkey;
  surface_p^.spans := nil;

  pplane := psurf^.plane;
  // FIXME: cache this?
  TransformVector(pplane^.normal, p_normal);
  // FIXME: cache this?
  distinv := 1.0 / (pplane^.dist - DotProduct(modelorg, pplane^.normal));

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

  Inc(Integer(surface_p), SizeOf(surf_t));
end;

end.

⌨️ 快捷键说明

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