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

📄 gl_mesh.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): gl_mesh.c                                                         }
{                                                                            }
{ Initial conversion by : softland                                           }
{ Initial conversion on : 14-Jan-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                                                                  }
{     16-Jun-2002 by Magog (magog@fistofbenztown.de)                         }
{     Added missing functions                                                }
{     30-Lug-2002 by Fabrizio Rossini (rossini.f@libero.it)                  }
{     added code convertion ( NOT 100% )                                     }
{----------------------------------------------------------------------------}
{ 28.06.2003 Juha: Proofreaded}
unit gl_mesh;

interface

uses
  DelphiTypes,
  q_shared,
  qfiles,
  gl_image,
  ref;

procedure R_DrawAliasModel(e: entity_p);


const
  NUMVERTEXNORMALS = 162;
  r_avertexnormals: array[0..NUMVERTEXNORMALS - 1, 0..2] of Single = (
{$I 'anorms.inc'}
    );

  // Precalculated dot products for quantized angles.
  SHADEDOT_QUANT = 16;
  r_avertexnormal_dots: array[0..SHADEDOT_QUANT - 1, 0..255] of Single = (
{$I 'anormtab.inc'}
    );

var
  shadedots: PSingleArray = @r_avertexnormal_dots;

type
  vec4_t = array[0..3] of Single;

var
  s_lerped: array[0..MAX_VERTS - 1] of vec4_t;
  shadevector: vec3_t;
  shadelight: array[0..2] of Single;

implementation

uses
  CPas,
  sysutils,
  OpenGL,
  gl_local,
  gl_light,
  gl_rmain,
  qgl_win,
  qgl_h;


procedure GL_LerpVerts(nverts: Integer; v, ov: dtrivertx_p; verts: dtrivertx_a;
  lerp: vec3_p; move, frontv, backv: vec3_t);
var
  i: Integer;
  normal: vec3_p;
begin
  //PMM -- added RF_SHELL_DOUBLE, RF_SHELL_HALF_DAM
  if (currententity^.flags and (RF_SHELL_RED or RF_SHELL_GREEN or RF_SHELL_BLUE or RF_SHELL_DOUBLE or RF_SHELL_HALF_DAM)) <> 0 then
  begin
    i := 0;
    while i < nverts do
    begin
      normal := @r_avertexnormals[verts[i].lightnormalindex];
      lerp[0] := move[0] + ov.v[0] * backv[0] + v.v[0] * frontv[0] + normal[0] * POWERSUIT_SCALE;
      lerp[1] := move[1] + ov.v[1] * backv[1] + v.v[1] * frontv[1] + normal[1] * POWERSUIT_SCALE;
      lerp[2] := move[2] + ov.v[2] * backv[2] + v.v[2] * frontv[2] + normal[2] * POWERSUIT_SCALE;
      Inc(i);
      Inc(v);
      Inc(ov);
      lerp := Pointer(Cardinal(lerp) + 4 * sizeof(Single));
    end;
  end
  else
  begin
    i := 0;
    while i < nverts do
    begin
      lerp[0] := move[0] + ov.v[0] * backv[0] + v.v[0] * frontv[0];
      lerp[1] := move[1] + ov.v[1] * backv[1] + v.v[1] * frontv[1];
      lerp[2] := move[2] + ov.v[2] * backv[2] + v.v[2] * frontv[2];
      Inc(i);
      Inc(v);
      Inc(ov);
      lerp := Pointer(Cardinal(lerp) + 4 * sizeof(Single));
    end;
  end;
end;

{
=============
GL_DrawAliasFrameLerp

interpolates between two frames and origins
FIXME: batch lerp all vertexes
=============
}

procedure GL_DrawAliasFrameLerp(
  paliashdr: dmdl_p;
  backlerp: Single);
var
  l: Single;
  frame, oldframe: daliasframe_p;
  v, ov, verts: dtrivertx_a;
  order: PInteger;
  count: Integer;
  frontlerp: Single;
  alpha: Single;
  move, delta: vec3_t;
  vectors: array[0..2] of vec3_t;
  frontv, backv: vec3_t;
  i: integer;
  index_xyz: integer;
  lerp: vec3_p;
  colorArray: array[0..MAX_VERTS * 4 - 1] of Single;
begin
  frame := @PByteArray(paliashdr)[paliashdr.ofs_frames + currententity.frame * paliashdr.framesize];
  verts := @frame.verts;
  v := @frame.verts;

  oldframe := @PByteArray(paliashdr)[paliashdr.ofs_frames + currententity.oldframe * paliashdr.framesize];
  ov := @oldframe.verts;

  order := @PByteArray(paliashdr)[paliashdr.ofs_glcmds];

//  glTranslatef (frame->translate[0], frame->translate[1], frame->translate[2]);
//  glScalef (frame->scale[0], frame->scale[1], frame->scale[2]);

  if (currententity^.flags and RF_TRANSLUCENT <> 0) then
    alpha := currententity^.alpha
  else
    alpha := 1.0;

  // PMM - added double shell
  if (currententity^.flags and (RF_SHELL_RED or RF_SHELL_GREEN or RF_SHELL_BLUE or RF_SHELL_DOUBLE or RF_SHELL_HALF_DAM) <> 0) then
    qglDisable(GL_TEXTURE_2D);

  frontlerp := 1.0 - backlerp;

  // move should be the delta back to the previous frame * backlerp
  VectorSubtract(vec3_t(currententity^.oldorigin), vec3_t(currententity^.origin), delta);
  AngleVectors(vec3_t(currententity^.angles), @vectors[0], @vectors[1], @vectors[2]);

  move[0] := DotProduct(delta, vectors[0]); // forward
  move[1] := -DotProduct(delta, vectors[1]); // left
  move[2] := DotProduct(delta, vectors[2]); // up

  VectorAdd(move, oldframe^.translate, move);

  for i := 0 to 2 do
    move[i] := backlerp * move[i] + frontlerp * frame^.translate[i];

  for i := 0 to 2 do
  begin
    frontv[i] := frontlerp * frame^.scale[i];
    backv[i] := backlerp * oldframe^.scale[i];
  end;

  lerp := @s_lerped[0];

  GL_LerpVerts(paliashdr^.num_xyz, @v[0], @ov[0], verts, lerp, move, frontv, backv);

  if (gl_vertex_arrays^.value <> 0) then
  begin
    qglEnableClientState(GL_VERTEX_ARRAY);
    qglVertexPointer(3, GL_FLOAT, 16, @s_lerped); // padded for SIMD

//    if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
    // PMM - added double damage shell
    if (currententity.flags and (RF_SHELL_RED or RF_SHELL_GREEN or RF_SHELL_BLUE or RF_SHELL_DOUBLE or RF_SHELL_HALF_DAM) <> 0) then
      qglColor4f(shadelight[0], shadelight[1], shadelight[2], alpha)
    else
    begin
      qglEnableClientState(GL_COLOR_ARRAY);
      qglColorPointer(3, GL_FLOAT, 0, @colorArray);

      //
      // pre light everything
      //
      for i := 0 to paliashdr^.num_xyz - 1 do
      begin
        l := shadedots[verts[i].lightnormalindex];

        colorArray[i * 3 + 0] := l * shadelight[0];
        colorArray[i * 3 + 1] := l * shadelight[1];
        colorArray[i * 3 + 2] := l * shadelight[2];
      end;
    end;

    if Assigned(qglLockArraysEXT) then
      qglLockArraysEXT(0, paliashdr^.num_xyz);

    while true do
    begin
      // get the vertex count and primitive type
      count := order^;
      inc(order);
      if (count = 0) then
        break; // done

      if (count < 0) then
      begin
        count := -count;
        qglBegin(GL_TRIANGLE_FAN);
      end
      else
      begin
        qglBegin(GL_TRIANGLE_STRIP);
      end;

      // PMM - added double damage shell
      if (currententity^.flags and (RF_SHELL_RED or RF_SHELL_GREEN or RF_SHELL_BLUE or RF_SHELL_DOUBLE or RF_SHELL_HALF_DAM) <> 0) then
      begin
        repeat
          index_xyz := PIntegerArray(order)[2];
          inc(order, 3);
          qglVertex3fv(@s_lerped[index_xyz]);
          dec(count);
        until (count = 0);
      end
      else
      begin
        repeat
          // texture coordinates come from the draw list
          qglTexCoord2f(PSingleArray(order)[0], PSingleArray(order)[1]);
          index_xyz := PIntegerArray(order)[2];

          inc(order, 3);
          // normals and vertexes come from the frame list
          // l = shadedots[verts[index_xyz].lightnormalindex];
          // qglColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
          qglArrayElement(index_xyz);
          dec(count);
        until (count = 0);
      end;
      qglEnd;
    end;

    if Assigned(qglUnlockArraysEXT) then
      qglUnlockArraysEXT;
  end
  else
  begin
    while true do
    begin
      // get the vertex count and primitive type
      count := order^;
      inc(order);
      if (count = 0) then
        break; // done

      if (count < 0) then
      begin
        count := -count;
        qglBegin(GL_TRIANGLE_FAN);
      end
      else
      begin
        qglBegin(GL_TRIANGLE_STRIP);
      end;

      if (currententity^.flags and (RF_SHELL_RED or RF_SHELL_GREEN or RF_SHELL_BLUE) <> 0) then
      begin
        repeat
          index_xyz := PIntegerArray(order)[2];
          inc(order, 3);

          qglColor4f(shadelight[0], shadelight[1], shadelight[2], alpha);
          qglVertex3fv(@s_lerped[index_xyz]);
          dec(count);
        until (count = 0);
      end
      else
      begin
        repeat
          // texture coordinates come from the draw list
          qglTexCoord2f(PSingleArray(order)[0], PSingleArray(order)[1]);
          index_xyz := PIntegerArray(order)[2];
          inc(order, 3);

          // normals and vertexes come from the frame list
          l := shadedots[verts[index_xyz].lightnormalindex];

          qglColor4f(l * shadelight[0], l * shadelight[1], l * shadelight[2], alpha);
          qglVertex3fv(@s_lerped[index_xyz]);
          dec(count);
        until (count = 0);
      end;
      qglEnd;
    end;
  end;

// if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
  // PMM - added double damage shell
  if (currententity^.flags and (RF_SHELL_RED or RF_SHELL_GREEN or RF_SHELL_BLUE or RF_SHELL_DOUBLE or RF_SHELL_HALF_DAM) <> 0) then
    qglEnable(GL_TEXTURE_2D);
end;


(*
=============
GL_DrawAliasShadow
=============
*)
procedure GL_DrawAliasShadow(paliashdr: dmdl_p; posenum: integer);
var
  verts: dtrivertx_p;
  order: pInteger;
  point: vec3_t;
  height, lheight: Single;
  count: integer;
  frame: daliasframe_p;
begin
  lheight := currententity^.origin[2] - lightspot[2];
  frame := Pointer(Cardinal(paliashdr) + paliashdr^.ofs_frames + currententity^.frame * paliashdr^.framesize);
  verts := @frame.verts;

  height := 0;

  order := Pointer(Cardinal(paliashdr) + paliashdr.ofs_glcmds);

  height := -lheight + 1.0;

  while true do
  begin
      // get the vertex count and primitive type
    count := order^;
    inc(order);
    if (count = 0) then
      break; // done

    if (count < 0) then
    begin
      count := -count;
      qglBegin(GL_TRIANGLE_FAN);
    end
    else
      qglBegin(GL_TRIANGLE_STRIP);

    //do
    repeat
      // normals and vertexes come from the frame list
(*
      point[0] = verts[order[2]].v[0] * frame->scale[0] + frame->translate[0];
      point[1] = verts[order[2]].v[1] * frame->scale[1] + frame->translate[1];
      point[2] = verts[order[2]].v[2] * frame->scale[2] + frame->translate[2];
*)

      memcpy(@point, @s_lerped[PIntegerArray(order)^[2]], sizeof(point));

      point[0] := point[0] - shadevector[0] * (point[2] + lheight);
      point[1] := point[1] - shadevector[1] * (point[2] + lheight);
      point[2] := height;
      // commented by ID soft			height -= 0.001;
      qglVertex3fv(@point);

      inc(order, 3);

      //	commented by ID soft		verts++;

      dec(count);
    until (count = 0);
    qglEnd;
  end;
end;


(*
** R_CullAliasModel
*)
function R_CullAliasModel(var bbox: array of vec3_t; e: entity_p): qboolean;
var
  i: integer;
  mins, maxs, tmp: vec3_t;
  paliashdr: dmdl_p;
  vectors: array[0..2] of vec3_t;
  thismins, oldmins, thismaxs, oldmaxs, angles: vec3_t;
  pframe, poldframe: daliasframe_p;
  p, f: Integer;
  aggregatemask: Integer;
  mask: integer;
  dp: Single;
begin
  paliashdr := currentmodel^.extradata;

  if ((e^.frame >= paliashdr^.num_frames) or (e^.frame < 0)) then
  begin
    ri.Con_Printf(PRINT_ALL, 'R_CullAliasModel %s: no such frame %d'#10,
      currentmodel^.name, e^.frame);
    e^.frame := 0;
  end;
  if ((e^.oldframe >= paliashdr^.num_frames) or (e^.oldframe < 0)) then
  begin
    ri.Con_Printf(PRINT_ALL, 'R_CullAliasModel %s: no such oldframe %d'#10,
      currentmodel^.name, e^.oldframe);
    e^.oldframe := 0;
  end;

  pframe := Pointer(Cardinal(paliashdr) + paliashdr^.ofs_frames + e^.frame * paliashdr^.framesize);

  poldframe := Pointer(Cardinal(paliashdr) + paliashdr^.ofs_frames + e^.oldframe * paliashdr^.framesize);

 (*
 ** compute axially aligned mins and maxs
 *)
  if (pframe = poldframe) then
  begin
    for i := 0 to 3 - 1 do
    begin
      mins[i] := pframe^.translate[i];

⌨️ 快捷键说明

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