📄 colli3dx.pas
字号:
result := (distance < radius) and (t1 >= 0);
if not longshot then result := result and (t1 <= 1);
if result then exit;
end;
end;
symmetric_z :
begin
if step.z > 1e-6
then
begin
//1st end surface
t1 := (Fcoll_box_min[FseriesNr, coll_Nr].z - old_eye.z)/step.z;
xc1 := old_eye.x + t1 * step.x;
yc1 := old_eye.y + t1 * step.y;
distance := sqrt( sqr(xc1 - center.x) + sqr(yc1 - center.y) );
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].z - old_eye.z)/step.z;
xc1 := old_eye.x + t1 * step.x;
yc1 := old_eye.y + t1 * step.y;
distance := sqrt( sqr(xc1 - center.x) + sqr(yc1 - center.y) );
result := (distance < radius) and (t1 >= 0);
if not longshot then result := result and (t1 <= 1);
if result then exit;
end;
end;
end; //end of case
end; //end of coll_test_cylinder
function TcollisionTester3DX.coll_test_conus(coll_nr : byte;
old_attacker_position, attacker_position : TD3DVector;
bullet_radius : TD3DValue; longshot : boolean): boolean;
var
height3D, width3D : TD3DValue;
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;
xc, yc, zc, conusfact : 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;
//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;
//if FPercentLeftatTop is positiv then the conus is largest at the bottom
xc := center.x;
yc := center.y;
zc := center.z;
width3D := 10; //just to avoid warnings
height3D := 10;
case FOrientation3D of
symmetric_x :
begin
height3D := Fcoll_box_max[FSeriesNr, coll_nr].x
- Fcoll_box_min[FSeriesNr, coll_nr].x;
width3D := (Fcoll_box_max[FSeriesNr, coll_Nr].y
- Fcoll_box_min[FSeriesNr, coll_nr].y
+ Fcoll_box_max[FSeriesNr, coll_nr].z
- Fcoll_box_min[FSeriesNr, coll_nr].z)/2;
//the top of the conus is maller than the bottom of it
if FPercentLeftatTop >= 0
then
xc := center.x - height3D/2 + 100 * height3D/(100 - FpercentLeftatTop)
else
xc := center.x + height3D/2 - 100 * height3D/(100 + FpercentLeftatTop);
end; //end of symmetric_x
symmetric_y :
begin
height3D := Fcoll_box_max[FSeriesNr, coll_nr].y
- Fcoll_box_min[FSeriesNr, coll_nr].y;
width3D := (Fcoll_box_max[FSeriesNr, coll_Nr].x
- Fcoll_box_min[FSeriesNr, coll_nr].x
+ Fcoll_box_max[FSeriesNr, coll_nr].z
- Fcoll_box_min[FSeriesNr, coll_nr].z)/2;
//the top of the conus is maller than the bottom of it
if FPercentLeftatTop >= 0
then
yc := center.y - height3D/2 + 100 * height3D/(100 - FpercentLeftatTop)
else
yc := center.y + height3D/2 - 100 * height3D/(100 + FpercentLeftatTop);
end; //end of symmetric_y
symmetric_z :
begin
height3D := Fcoll_box_max[FSeriesNr, coll_nr].z
- Fcoll_box_min[FSeriesNr, coll_nr].z;
width3D := (Fcoll_box_max[FSeriesNr, coll_Nr].x
- Fcoll_box_min[FSeriesNr, coll_nr].x
+ Fcoll_box_max[FSeriesNr, coll_nr].y
- Fcoll_box_min[FSeriesNr, coll_nr].y)/2;
//the top of the conus is maller than the bottom of it
if FPercentLeftatTop >= 0
then
zc := center.z - height3D/2 + 100 * height3D/(100 - FpercentLeftatTop)
else
zc := center.z + height3D/2 - 100 * height3D/(100 + FpercentLeftatTop);
end; //end of symmetric_z
end; //end of case
//mathematically we need the conusfact describing the ratio between the radius of
//the large end of the conus and the height of the conus
if width3D > 0
then
conusfact := height3D/2/width3D
else
conusfact := 1e9;
//eye to the fictive tip of the conus distance
dstep.x := old_eye.x - xc;
dstep.y := old_eye.y - yc;
dstep.z := old_eye.z - zc;
d0 := 1; //just to avoid warnings
d1 := 1;
d2 := 1;
//The conus is aligned parallel to the x, y or z axis
case FOrientation3D of
symmetric_x :
begin
//factors
d0 := sqr(dstep.y) + sqr(dstep.z) - sqr(dstep.x * conusfact);
d1 := 2 * (step.y * dstep.y + step.z * dstep.z
- sqr(conusfact) * step.x * dstep.x);
d2 := sqr(step.y) + sqr(step.z) - sqr(conusfact * step.x);
end;
symmetric_y :
begin
//factors
d0 := sqr(dstep.x) + sqr(dstep.z) - sqr(dstep.y * conusfact);
d1 := 2 * (step.x * dstep.x + step.z * dstep.z
- sqr(conusfact) * step.y * dstep.y);
d2 := sqr(step.x) + sqr(step.z) - sqr(conusfact * step.y);
end;
symmetric_z :
begin
//factors
d0 := sqr(dstep.x) + sqr(dstep.y) - sqr(dstep.z * conusfact);
d1 := 2 * (step.x * dstep.x + step.y * dstep.y
- sqr(conusfact) * step.z * dstep.z);
d2 := sqr(step.x) + sqr(step.y) - sqr(conusfact * step.z);
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 conus
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) );
if FPercentLeftatTop >= 0
then
radius := width3D/2 //the large end of the conus is down
else
radius := -width3D/2 * FPercentLeftatTop;
radius := radius + bullet_radius;
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) );
if FPercentLeftatTop >= 0
then
radius := width3D/2 * FPercentLeftatTop //the small end of the conus is upwards
else
radius := width3D/2;
radius := radius + bullet_radius;
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) );
if FPercentLeftatTop >= 0
then
radius := width3D/2 //the large end of the conus is down
else
radius := -width3D/2 * FPercentLeftatTop;
radius := radius + bullet_radius;
result := (distance < radius) and (t1 >= 0);
if not longshot then result := result and (t1 <= 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -