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

📄 gl_mesh.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
// 90 %
{----------------------------------------------------------------------------}
{                                                                            }
{ 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% )                                     }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on:                               }
{   - needs "currententity" to be exported by "gl_rmain.pas"                 }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{ some code convertion + test for compile                                    }
{----------------------------------------------------------------------------}
unit gl_mesh;

interface
uses
  q_shared, qfiles, ref, cvar;

type
  TFloatArray = array[0..1] of float;
  PFloatArray = ^TFloatArray;

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'}
  );

  shadedots: PFloatArray = @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;

// TODO: remove this if gl_rmain.pas is finished !!!
  currententity: entity_p;
  gl_vertex_arrays: cvar_p;
// END OF TODO  

implementation
uses
  sysutils,
  gl,
  qgl_h;

type
  Single3 = array[0..2] of Single;

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];
      lerp[1] := move[1] + ov.v[1]*backv[1] + v.v[1]*frontv[1] + normal[1];
      lerp[2] := move[2] + ov.v[2]*backv[2] + v.v[2]*frontv[2] + normal[2];
      Inc(i);
      Inc(v);
      Inc(ov);
      Inc(lerp, 4);
    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);
      Inc(lerp, 4);
    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(currententity.oldorigin, currententity.origin, delta);
  AngleVectors(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(PFloatArray(order)[0], PFloatArray(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(PFloatArray(order)[0], PFloatArray(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;

{-------------------------------{FAB} //start convertion here-------------------------------}
// #if 1
{$IFDEF 1}
(*/*
=============
GL_DrawAliasShadow
=============
*/*)

// extern	vec3_t			lightspot;

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 := @PByteArray(paliashdr)[paliashdr.ofs_frames + currententity.frame * paliashdr.framesize];
  	verts := @frame.verts;

	height := 0;

	order := @PByteArray(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 
	  begin
        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[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); //order += 3;

			//	commented by ID soft		verts++;

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

{$endif}

(*/*
** R_CullAliasModel
*/*)
function R_CullAliasModel( bbox :array [0..7] 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 , aggregatemask :integer = 0 ; // int p, f, aggregatemask = ~0; // {FAB} check this translation
mask : integer = 0 ;
dp : Single ;
begin
	//paliashdr = (dmdl_t *)currentmodel->extradata;
	paliashdr := @currentmodel.extradata;  // {FAB} check this translation

	if ( ( e.frame >= paliashdr.num_frames ) or ( e.frame < 0 ) )then
	begin
		ri.Con_Printf (PRINT_ALL, 'R_CullAliasModel %s: no such frame %d\n', 
			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\n', 
			currentmodel.name, e.oldframe);
		e.oldframe := 0;
	end;

	pframe := @PByteArray (paliashdr)[ paliashdr.ofs_frames + e.frame * paliashdr.framesize]; //// {FAB} check this translation

	poldframe := @PByteArray (paliashdr)[ paliashdr.ofs_frames + e.oldframe * paliashdr.framesize]; // {FAB} check this translation

	(*/*
	** compute axially aligned mins and maxs
	*/*)
	if ( pframe = poldframe )then
	begin
		for  i := 0  to 3 do
		begin
			mins[i] := pframe.translate[i];
			maxs[i] := mins[i] + pframe.scale[i]*255;
		end;
	end
	else
	
		for  i := 0 to 3 do
		begin
			thismins[i] := pframe.translate[i];
			thismaxs[i] := thismins[i] + pframe.scale[i]*255;

			oldmins[i]  := poldframe.translate[i];

⌨️ 快捷键说明

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