| 1 |
I think a better solution must be possible without much computational effort. If the tested collision volume has a circular base area, the current calculation is fine because errors are very unlikely. The current code can already be made a bit more efficient by checking muzzle position collision before the calculation of hitVec and hitPos and if true, skipping the rest of the calculation until the debug rendering. The calculation of "ret" can be made a bit more efficient, namely:{{{ret = (cv->GetPointSurfaceDistance(static_cast<const CUnit*>(obj), nullptr, tstPos) <= coneSize);
|
1 |
I think a better solution must be possible without much computational effort. If the tested collision volume has a circular base area, the current calculation is fine because errors are very unlikely. The current code can already be made a bit more efficient by checking muzzle position collision before the calculation of hitVec and hitPos and if true, skipping the rest of the calculation until the debug rendering. The calculation of "ret" can be made a bit more efficient, namely:{{{ret = (cv->GetPointSurfaceDistance(static_cast<const CUnit*>(obj), nullptr, tstPos) <= coneSize);
|
| 2 |
or
|
2 |
or
|
| 3 |
ret = (cv->GetPointSurfaceDistance(static_cast<const CUnit*>(obj), nullptr, hitPos) <= coneSize);
|
3 |
ret = (cv->GetPointSurfaceDistance(static_cast<const CUnit*>(obj), nullptr, hitPos) <= coneSize);
|
| 4 |
}}}For tested collision volumes with rectangular base area, a better calculation can be done. I propose the following algorithm:
|
4 |
}}}For tested collision volumes with rectangular base area, a better calculation can be done. I propose the following algorithm:
|
| 5 |
\n
|
5 |
\n
|
| 6 |
Define "ret" as whether the muzzle position is within the collision volume. If true, skip the rest of the calculation until the debug rendering. Otherwise do the current calculation until hitVec. Then check if the collision volume has a rectangular base area. If no, apply the current calculation but without checking the muzzle position.
|
6 |
Define "ret" as whether the muzzle position is within the collision volume. If true, skip the rest of the calculation until the debug rendering. Otherwise do the current calculation until hitVec. Then check if the collision volume has a rectangular base area. If no, apply the current calculation but without checking the muzzle position.
|
| 7 |
\n
|
7 |
\n
|
| 8 |
Otherwise (rectangular base area), set{{{distToCenter = dist((tstPos + hitVec), collision volume center) - coneSize;
|
8 |
Otherwise (rectangular base area), set{{{distToCenter = dist((tstPos + hitVec), collision volume center) - coneSize;
|
| 9 |
ret = (4*distToCenter * distToCenter <= (collison volume length * collison volume length + collision volume width * collision volume width));.
|
9 |
ret = (4*distToCenter * distToCenter <= (collison volume length * collison volume length + collision volume width * collision volume width));.
|
| 10 |
}}}If ret is false, skip the rest of the calculation until the debug rendering. This excludes cases where we are for sure not hitting the target to safe computation time.
|
10 |
}}}If ret is false, skip the rest of the calculation until the debug rendering. This excludes cases where we are for sure not hitting the target to safe computation time.
|
| 11 |
\n
|
11 |
\n
|
| 12 |
Otherwise, get the 4 border lines of the collision volume base area. Calculate the crossing points with the 2D projectile trajectory. Exclude the crossing points outside the border limits. Exclude the crossing points outside the trajectory limits. If the number of remaining crossing points is <= 0, the object is out of trajectory, so ret is false. Then, skip the rest of the calculation until the debug rendering.
|
12 |
Otherwise, get the 4 border lines of the collision volume base area. Calculate the crossing points with the 2D projectile trajectory. Exclude the crossing points outside the border limits. Exclude the crossing points outside the trajectory limits. If the number of remaining crossing points is <= 0, the object is out of trajectory, so ret is false. Then, skip the rest of the calculation until the debug rendering.
|
| 13 |
\n
|
13 |
\n
|
| 14 |
Otherwise,
calculate
the
3D
hit
position
for
the
first
remaining
crossing
point
and
check
if
it's
within
the
object.
If
yes,
ret
is
true
and
go
to
debug
rendering.
Otherwise
check
through
the
remaining
crossing
points
until
one
is
found
that
is
unequal
the
first
crossing
point.
If
no
such
point
is
found
(
the
target
is
either
within
the
base
area
or
the
trajectory
goes
exactly
through
a
corner
but
not
any
other
point
of
the
base
area)
,
set
ret
as
whether
the
target
itself
is
within
the
collision
volume.
If
one
is
found,
calculate
its
3D
hit
position
and
set
ret
as
whether
it's
within
the
object.
Don't
check
further
crossing
points
because
they
can
only
be
equal
to
the
previous
ones.
Do
debug
rendering.
Return
ret.
|
14 |
Otherwise,
calculate
the
3D
hit
position
for
the
first
remaining
crossing
point
and
check
if
it's
within
the
object.
If
yes,
ret
is
true
and
go
to
debug
rendering.
Otherwise
check
through
the
remaining
crossing
points
until
one
is
found
that
is
unequal
the
first
crossing
point.
If
no
such
point
is
found
(
the
target
is
either
within
the
base
area
or
the
trajectory
goes
exactly
through
a
corner
but
not
any
other
point
of
the
base
area)
,
set
ret
as
whether
the
target
itself
is
within
the
collision
volume
and
go
to
debug
rendering.
If
one
is
found,
calculate
its
3D
hit
position
and
check
whether
it's
within
the
object.
If
yes,
ret
is
true
and
go
to
debug
rendering.
Otherwise
check
if
the
first
crossing
point
3D
hitposition
is
above
or
below
the
object.
Then
check
if
the
found
next
unequal
crossing
point
3D
position
is
above
or
below
the
object.
Set
ret
as
the
inequality
of
the
two
above/below
states
because
then,
the
trajectory
must
go
through
the
object
even
though
the
2D
entry
and
leave
points
don't.
Don't
check
further
crossing
points
because
they
can
only
be
equal
to
the
previous
ones.
Do
debug
rendering.
Return
ret.
|
| 15 |
\n
|
15 |
\n
|
| 16 |
[spoiler]If you want to shoot even though you might hit some allied units due to spread, reducing coneSize is the proper way to do it. Otherwise you will hit yourself even without spread.[/spoiler]
|
16 |
[spoiler]If you want to shoot even though you might hit some allied units due to spread, reducing coneSize is the proper way to do it. Otherwise you will hit yourself even without spread.[/spoiler]
|
| 17 |
\n
|
17 |
\n
|
| 18 |
[spoiler]Parallel computation can be used to loop through collision checks with multiple units. If the loop to find the crossing points is not parallelized, it can be stopped after a second point within the limits has been found that is unequal the first. If this equality check was not done, projectiles shooting exactly through a corner of the base area might be miscalculated which might be tolerated due to very low probability.[/spoiler]
|
18 |
[spoiler]Parallel computation can be used to loop through collision checks with multiple units. If the loop to find the crossing points is not parallelized, it can be stopped after a second point within the limits has been found that is unequal the first. If this equality check was not done, projectiles shooting exactly through a corner of the base area might be miscalculated which might be tolerated due to very low probability.[/spoiler]
|