📄 gl_mesh.pas
字号:
// 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 + -