📄 g_phys.pas
字号:
{----------------------------------------------------------------------------}
{ }
{ File(s): g_phys.c }
{ Content: physics logic }
{ }
{ Initial conversion by : MathD (matheus@tilt.net }
{ Initial conversion on : 05-Feb-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 on : }
{ Updated by : }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ none }
{----------------------------------------------------------------------------}
{ * TODO: }
{ 1.) A few functions need to be translated }
{ 2.) Give it a test }
{ }
{----------------------------------------------------------------------------}
{ * NOTES: }
{ }
{ translated the pointers to records as specified in message board }
{ edict_t = record; }
{ editc_p = ^edict_p }
{----------------------------------------------------------------------------}
unit g_phys;
{pushmove objects do not obey gravity, and do not interact with each other or
trigger fields, but block normal movement and push normal objects when they move.
onground is set for toss objects when they come to a complete rest. it is set
for steping or walking objects
doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
corpses are SOLID_NOT and MOVETYPE_TOSS
crates are SOLID_BBOX and MOVETYPE_TOSS
walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP
flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY
solid_edge items only clip against bsp models.}
interface
{delphi-note: completed functions}
function SV_TestEntityPosition(ent: edict_p): edict_p;
procedure SV_CheckVelocity (ent: edict_p);
function SV_RunThink (ent: edict_p): qboolean;
procedure SV_Impact(e1: edict_p; trace: trace_p);
function ClipVelocity(_in, normal, _out: vec3_t; overbounce: single): integer;
function SV_FlyMove(ent: edict_p; time: single; mask: integer): integer;
procedure SV_AddGravity(ent: edict_p);
function SV_PushEntity(ent: edict_p; push: vec3_t): trace_t;
procedure SV_Physics_None(ent: edict_p);
procedure SV_Physics_Noclip (ent: edict_p);
procedure SV_Physics_Toss(ent: edict_p);
procedure SV_AddRotationalFriction(ent: edict_p)
{delphi-note: not completed functions}
function SV_Push(pushed: edict_p, _move, amove: vec3_t): qboolean;
procedure SV_Physics_Pusher(ent: edict_p);
procedure SV_Physics_Step(ent: edict_p);
implementation
{/*
============
SV_TestEntityPosition
============
*/}
function SV_TestEntityPosition(ent: edict_p): edict_p;
var
trace: trace_t;
mask: integer;
begin
if ent^.clipMask then
mask:= ent^.clipMask
else
mask:= MASK_SOLID;
trace:= gi.trace(ent^.s.origin, ent^.mins, ent^.maxs, ent^.s.origin, ent, mask);
if (trace.startsolid) then begin
result:= g_edicts;
exit;
end;
result:= nil;
end;
{/*
================
SV_CheckVelocity
================
*/}
procedure SV_CheckVelocity (ent: edict_p);
var
i: integer;
begin
//
// bound velocity
//
i:= 0;
for i:= 0 to 2 do begin
if (ent^.velocity[i] > sv_maxvelocity^.value) then
ent^.maxvelocity[i]:= sv_maxvelocity^.value
else if (ent^.velocity[i] < -sv_maxvelocity^.value) then
ent^.velocity[i]:= -sv_maxvelocity^.value;
end;
end;
{/*
=============
SV_RunThink
Runs thinking code for this frame if necessary
=============
*/}
function SV_RunThink (ent: edict_p): qboolean;
var
thinktime: single;
begin
thinktime:= ent^.nextthink;
if (thinktime <= 0) then begin
result:= true;
exit;
end;
if (thinktime : level.time + 0.001) then begin
result:= true;
exit;
end;
ent^.nextthink:= 0;
if (ent^.think = false) then gi.error('NIL ent^.think');
ent^.think(ent);
result:= false;
end;
{/*
==================
SV_Impact
Two entities have touched, so run their touch functions
==================
*/}
procedure SV_Impact(e1: edict_p; trace: trace_p);
var
e2: edict_p;
backplane: cplane_p;
begin
e2:= trace^.ent;
{delphi-note: maybe this should be}
{if ((ei^.touch and e1^.solid) <> SOLID_NOT)}
if (ei^.touch and e1^.solid <> SOLID_NOT) then
e1^.touch(e1, e2, @trace^.plane, trace^.surface);
{delphi-note: same as above}
if (e2^.touch and e2^.solid <> SOLID_NOT then
e2^.touch(e2, e1, nil, nil);
end;
{/*
==================
ClipVelocity
Slide off of the impacting object
returns the blocked flags (1 = floor, 2 = step / wall)
==================
*/}
const STOP_EPSILON = 0.1;
function ClipVelocity(_in, normal, _out: vec3_t; overbounce: single): integer;
var
backoff, change: single;
i, blocked: integer;
begin
blocked:= 0;
if (normal[2] > 0) then blocked:= blocked or 1; //floor
{delphi-note: check this out. Not quite sure..}
if (normal[2] = 0) then blocked:= blocked or 2; //step
backoff:= DotProduct(_in, normal) * overbounce;
for i:= 0 to 2 do begin
change:= normal[i] * backoff;
_out[i]:= _in[i] - change;
if (_out[i] > -STOP_EPSILON) and (_out[i] < STOP_EPSILON) then _out[i]:= 0;
end;
result:= blocked;
end;
{/*
============
SV_FlyMove
The basic solid body movement clip that slides along multiple planes
Returns the clipflags if the velocity was modified (hit something solid)
1 = floor
2 = wall / step
4 = dead stop
============
*/}
const MAX_CLIP_PLANES = 5;
function SV_FlyMove(ent: edict_p; time: single; mask: integer): integer;
var
hit: edict_p;
bumpcount, numbumps: integer;
dir: vect3_t;
d: single;
numplanes: integer;
planes: array[0..MAX_CLIP_PLANES -1] of vec3_t;
primal_velocity, original_velocity, new_velocity: vec3_t;
i, j: integer;
trace: trace_t;
_end: vec3_t;
time_left: single;
blocked: integer;
begin
numbumps:= 4;
blocked:= 0;
VectorCopy(ent^.velocity, original_velocity);
VectorCopy(ent^.velocity, primal_velocity);
time_left:= time;
ent^.groundentity:= nil;
for bumpcount:= 0 to numbumps -1 do begin
for i:= 0 to 2 do _end[i]:= ent^.s.origin[i] + time_left * ent^.velocity[i];
trace:= gi.trace(ent^.origin, ent^.mins, ent^.maxs, _end, ent, mask);
if (trace.allsolid) then begin
//entity is trapped in another solid
VectorCopy(vec3_origin, ent^.velocity);
result:= 3;
exit;
end;
if (trace.fraction > 0) then begin
//actually covered some distance
VectorCopy(trace,endpos, ent^.s.origin);
VectorCopy(ent^.velocity, original_velocity);
numplanes:= 0;
end;
if (trace.fraction = 1) then break; //moved the entire distance
hit:= trace.ent;
if (trace.plane.normal[2] > 0.7) then begin
blocked:= blocked or 1; //floor;
if (hit^.solid == SOLID_BSP) then begin
ent^.groundentity:= hit;
ent^.groundentity_linkcount:= hit^.linkcount;
end;
if not trace.plane.normal[2] then blocked:= blocked or 2; //step
end;
//
// run the impact function
//
SV_Impact(ent, @trace);
if not ent^.inuse then break;
time_left:= timeleft - (time_left * trace.fraction);
//cliped to another plane
if (numplanes >= MAX_CLIP_PLANES then begin
//this shouldn't really happen
VectorCopy(vec3_origin, ent^.velocity);
result:= 3;
exit;
end;
VectorCopy(trace.plane.normal, planes[numplanes]);
inc(numplanes);
//
// modify original_velocity so it parallels all of the clip planes
//
for i:= 0 to numplanes -1 do begin
ClipVelocity(original_velocity, planes[i], new_velocity, 1);
for j:= 0 to numplanes -1 do begin
if (j <> i) then begin
if (DotProduct(new_velocity, planes[j]) < 0) then break; //not ok
end;
if j = numplanes then break;
end;
if (i <> numplanes) then VectorCopy(new_velocity, ent^.velocity) //go along this plane
else begin
if (numplanes <> 2) then begin //go along the crease
//gi.dprintf('clip velocity, numplanes = %i #13#10', numplanes);
VectorCopy(vec3_origin, ent^.velocity);
result:= 7;
exit;
end;
CrossProduct(planes[0], planes[1], dir);
d:= DotProduct(dir, ent^.velocity);
VectorScale(dir, d, ent^.velocity);
end;
//
// if original velocity is against the original velocity, stop dead
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -