📄 colli3dx.pas
字号:
//collision is only possible when something moves
if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
then
begin
result := false;
exit;
end;
//factors
d0 := sqr(dstep.x) + sqr(dstep.y) + sqr(dstep.z) - sqr(radius);
d1 := 2 * (step.x * dstep.x + step.y * dstep.y + step.z * dstep.z);
d2 := sqr(step.x) + sqr(step.y) + sqr(step.z);
//solving an equation of the second degree
rod := sqr(d1) - 4 * d2 * d0;
//d2 is never zero
if rod > 0
then
begin
rod2 := sqrt(rod);
t1 := (-d1 - rod2)/2/d2;
t2 := (-d1 + rod2)/2/d2;
// if longshot then look into all future
if longshot
then
result := (t1 >= 0) or (t2 >= 0)
else
begin
//collision in between the starting and the ending point if
result := ((t1 >= 0) and (t1 <= 1))
or ((t2 >= 0) and (t2 <= 1));
end;
end;
end; //end of coll_test_sphere
function TcollisionTester3DX.coll_test_ellipsoid(coll_nr : byte;
old_attacker_position, attacker_position : TD3DVector;
bullet_radius : TD3DValue; longshot : boolean): boolean;
var
new_eye, old_eye : TD3DVector;
dstep, step, center : TD3DVector;
d0, d1, d2, rod, rod2, t1, t2, a, b, c : TD3DValue;
begin
result := false;
//Get the coordinates of the old eye_position in the actual coll frame
FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
(old_eye, old_attacker_position);
//Get the coordinates of the eye_position in the actual coll frame
FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
(new_eye, attacker_position);
center.x := (Fcoll_box_max[FSeriesNr, coll_nr].x
+ Fcoll_box_min[FSeriesNr, coll_nr].x)/2;
center.y := (Fcoll_box_max[FSeriesNr, coll_nr].y
+ Fcoll_box_min[FSeriesNr, coll_nr].y)/2;
center.z := (Fcoll_box_max[FSeriesNr, coll_nr].z
+ Fcoll_box_min[FSeriesNr, coll_nr].z)/2;
//x, y and z radius of ellipsoid enlarged with the radius of the bullet
//to cover the space where a collision may occure
a := (Fcoll_box_max[FSeriesNr, coll_nr].x
- Fcoll_box_min[FSeriesNr, coll_nr].x)/2 + bullet_radius;
b := (Fcoll_box_max[FSeriesNr, coll_nr].y
- Fcoll_box_min[FSeriesNr, coll_nr].y)/2 + bullet_radius;
c := (Fcoll_box_max[FSeriesNr, coll_nr].z
- Fcoll_box_min[FSeriesNr, coll_nr].z)/2 + bullet_radius;
//eye to center distance
dstep.x := old_eye.x - center.x;
dstep.y := old_eye.y - center.y;
dstep.z := old_eye.z - center.z;
//step in eye position
step.x := new_eye.x - old_eye.x;
step.y := new_eye.y - old_eye.y;
step.z := new_eye.z - old_eye.z;
//collision is only possible when something moves
if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
then
begin
result := false;
exit;
end;
//factors
d0 := sqr(b * c * dstep.x) + sqr(a * c * dstep.y) + sqr(a * b * dstep.z)
- sqr(a * b * c);
d1 := 2 * (sqr(b * c) * step.x * dstep.x + sqr(a * c) * step.y * dstep.y
+ sqr(a * b) * step.z * dstep.z);
d2 := sqr(b * c * step.x) + sqr(a * c * step.y) + sqr(a * b * step.z);
//solving an equation of the second degree
rod := sqr(d1) - 4 * d2 * d0;
//d2 is never zero
if rod > 0
then
begin
rod2 := sqrt(rod);
t1 := (-d1 - rod2)/2/d2;
t2 := (-d1 + rod2)/2/d2;
// if longshot then look into all future
if longshot
then
result := (t1 >= 0) or (t2 >= 0)
else
begin
//collision in between the starting and the ending point if
result := ((t1 >= 0) and (t1 <= 1))
or ((t2 >= 0) and (t2 <= 1));
end;
end;
end; //end of coll_test_ellipsoid
function TcollisionTester3DX.coll_test_cylinder(coll_nr : byte;
old_attacker_position, attacker_position : TD3DVector;
bullet_radius : TD3DValue; longshot : boolean): boolean;
var
distance : TD3DValue;
new_eye, old_eye : TD3DVector;
dstep, step, center : TD3DVector;
radius, d0, d1, d2, rod, rod2, t1, t2, xc1, yc1, zc1, xc2, yc2, zc2 : TD3DValue;
begin
result := false;
//Get the coordinates of the old eye_position in the actual coll frame
FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
(old_eye, old_attacker_position);
//Get the coordinates of the eye_position in the actual coll frame
FFrameSeries[FSeriesIndex, FNrinFrameSeries[FSeriesNr, coll_nr]].InverseTransform
(new_eye, attacker_position);
center.x := (Fcoll_box_max[FSeriesNr, coll_nr].x
+ Fcoll_box_min[FSeriesNr, coll_nr].x)/2;
center.y := (Fcoll_box_max[FSeriesNr, coll_nr].y
+ Fcoll_box_min[FSeriesNr, coll_nr].y)/2;
center.z := (Fcoll_box_max[FSeriesNr, coll_nr].z
+ Fcoll_box_min[FSeriesNr, coll_nr].z)/2;
//radius of sphere enlarged with the radius of the bullet
//to cover the space where a collision may occure
radius := Fcoll_radius[FSeriesNr, coll_nr] + bullet_radius;
//eye to center distance
dstep.x := old_eye.x - center.x;
dstep.y := old_eye.y - center.y;
dstep.z := old_eye.z - center.z;
//step in eye position
step.x := new_eye.x - old_eye.x;
step.y := new_eye.y - old_eye.y;
step.z := new_eye.z - old_eye.z;
//collision is only possible when something moves
if (abs(step.x) < 1e-3) and (abs(step.y) < 1e-3) and (abs(step.z) < 1e-3)
then
begin
result := false;
exit;
end;
d0 := 1; //just to avoid warnings
d1 := 1;
d2 := 1;
//The cylinder is alined parallel to the x, y or z axis
case FOrientation3D of
symmetric_x :
begin
//factors
d0 := sqr(dstep.y) + sqr(dstep.z) - sqr(radius);
d1 := 2 * (step.y * dstep.y + step.z * dstep.z);
d2 := sqr(step.y) + sqr(step.z);
end;
symmetric_y :
begin
//factors
d0 := sqr(dstep.x) + sqr(dstep.z) - sqr(radius);
d1 := 2 * (step.x * dstep.x + step.z * dstep.z);
d2 := sqr(step.x) + sqr(step.z);
end;
symmetric_z :
begin
//factors
d0 := sqr(dstep.x) + sqr(dstep.y) - sqr(radius);
d1 := 2 * (step.x * dstep.x + step.y * dstep.y);
d2 := sqr(step.x) + sqr(step.y);
end;
end; //end of case FOrientation3D of
//solving an equation of the second degree
rod := sqr(d1) - 4 * d2 * d0;
//d2 is never zero
if rod >= 0
then
begin
//only then is the collision possible
rod2 := sqrt(rod);
t1 := (-d1 - rod2)/2/d2;
t2 := (-d1 + rod2)/2/d2;
// if longshot then look into all future
if longshot
then
result := (t1 >= 0) or (t2 >= 0)
else
begin
//collision in between the starting and the ending point if
result := ((t1 >= 0) and (t1 <= 1))
or ((t2 >= 0) and (t2 <= 1));
end;
// however the collision also affords that we are within the length of the cylinder
if result then
begin
case FOrientation3D of
symmetric_x :
begin
xc1 := old_eye.x + t1 * step.x;
xc2 := old_eye.x + t2 * step.x;
if longshot
then
result :=
(result and (t1 >= 0) and
(xc1 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
(xc1 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
or
(result and (t2 >= 0) and
(xc2 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
(xc2 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
else
result :=
(result and (t1 >= 0) and (t1 <= 1) and
(xc1 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
(xc1 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) )
or
(result and (t2 >= 0) and (t2 <= 1) and
(xc2 >= (Fcoll_box_min[FseriesNr, coll_nr].x - bullet_radius)) and
(xc2 <= (Fcoll_box_max[FseriesNr, coll_nr].x + bullet_radius)) );
//if collision detected then exit now
if result then exit;
end;
symmetric_y :
begin
yc1 := old_eye.y + t1 * step.y;
yc2 := old_eye.y + t2 * step.y;
if longshot
then
result :=
(result and (t1 >= 0) and
(yc1 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
(yc1 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
or
(result and (t2 >= 0) and
(yc2 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
(yc2 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
else
result :=
(result and (t1 >= 0) and (t1 <= 1) and
(yc1 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
(yc1 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) )
or
(result and (t2 >= 0) and (t2 <= 1) and
(yc2 >= (Fcoll_box_min[FseriesNr, coll_nr].y - bullet_radius)) and
(yc2 <= (Fcoll_box_max[FseriesNr, coll_nr].y + bullet_radius)) );
//if collision detected then exit now
if result then exit;
end;
symmetric_z :
begin
zc1 := old_eye.z + t1 * step.z;
zc2 := old_eye.z + t2 * step.z;
if longshot
then
result :=
(result and (t1 >= 0) and
(zc1 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
(zc1 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
or
(result and (t2 >= 0) and
(zc2 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
(zc2 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
else
result :=
(result and (t1 >= 0) and (t1 <= 1) and
(zc1 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
(zc1 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) )
or
(result and (t2 >= 0) and (t2 <= 1) and
(zc2 >= (Fcoll_box_min[FseriesNr, coll_nr].z - bullet_radius)) and
(zc2 <= (Fcoll_box_max[FseriesNr, coll_nr].z + bullet_radius)) );
//if collision detected then exit now
if result then exit;
end;
end; //end of case
end;
//exit if a collision occured
if result then exit;
end;
//the collision may also occur with the end surfaces of the cylinder
case FOrientation3D of
symmetric_x :
begin
if step.x > 1e-6
then
begin
//1st end surface
t1 := (Fcoll_box_min[FseriesNr, coll_Nr].x - old_eye.x)/step.x;
yc1 := old_eye.y + t1 * step.y;
zc1 := old_eye.z + t1 * step.z;
distance := sqrt( sqr(yc1 - center.y) + sqr(zc1 - center.z) );
result := (distance < radius) and (t1 >= 0);
if not longshot then result := result and (t1 <= 1);
if result then exit;
//2nd end surface
t1 := (Fcoll_box_max[FseriesNr, coll_Nr].x - old_eye.x)/step.x;
yc1 := old_eye.y + t1 * step.y;
zc1 := old_eye.z + t1 * step.z;
distance := sqrt( sqr(yc1 - center.y) + sqr(zc1 - center.z) );
result := (distance < radius) and (t1 >= 0);
if not longshot then result := result and (t1 <= 1);
if result then exit;
end;
end;
symmetric_y :
begin
if step.y > 1e-6
then
begin
//1st end surface
t1 := (Fcoll_box_min[FseriesNr, coll_Nr].y - old_eye.y)/step.y;
xc1 := old_eye.x + t1 * step.x;
zc1 := old_eye.z + t1 * step.z;
distance := sqrt( sqr(xc1 - center.x) + sqr(zc1 - center.z) );
result := (distance < radius) and (t1 >= 0);
if not longshot then result := result and (t1 <= 1);
if result then exit;
//2nd end surface
t1 := (Fcoll_box_max[FseriesNr, coll_Nr].y - old_eye.y)/step.y;
xc1 := old_eye.x + t1 * step.x;
zc1 := old_eye.z + t1 * step.z;
distance := sqrt( sqr(xc1 - center.x) + sqr(zc1 - center.z) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -