Page 1 of 1

Perfomance of trace rays

Posted: Thu Feb 27, 2020 7:03 pm
by InvisibleSoldiers
Can I increase performance of trace rays in SP? I need to do many traces in loop for iterating over whole circle and check if any player there.

Sample code:

Syntax: Select all

trace_filter = TraceFilterSimple((player, ))
game_trace = GameTrace()

for i in range(1000):
engine_trace.trace_ray(
Ray(start_pos, start_pos + direction * 8192.0),
ContentMasks.SHOT,
trace_filter,
game_trace
)

Re: Perfomance of trace rays

Posted: Sat Feb 29, 2020 5:04 am
by VinciT
I'm assuming you're using trace rays to check for walls?
If that's the case, you can avoid using a lot of rays by getting the distance between the player and the starting position and seeing if it's within a certain radius before checking for walls.

Syntax: Select all

# ../get_players_in_sphere/get_players_in_sphere.py

# Source.Python
from engines.trace import (ContentMasks, engine_trace, GameTrace, Ray,
TraceFilterSimple)
from filters.players import PlayerIter
from mathlib import Vector


HEIGHT_OFFSET = Vector(0, 0, 32)


def get_players_in_sphere(position, radius, wall_check=True):
_players = []

# Go through all the Players.
for player in PlayerIter():
# Get the Player center.
player_center = player.origin + HEIGHT_OFFSET
# Calculate the distance between the center of the sphere and the
# center of the Player.
distance = position.get_distance(player_center)

# Is the Player within the radius?
if distance <= radius:
# Should we check for walls?
if wall_check:
# Create and fire a new trace ray from the center of the sphere
# to the center of the Player.
trace = GameTrace()
engine_trace.trace_ray(
Ray(position, player_center),
ContentMasks.ALL,
TraceFilterSimple(),
trace
)

# Did we hit a wall?
if trace.did_hit_world():
# Skip this Player.
continue

debug_line(position, trace.end_position)

_players.append(player)

return _players


# Debug
import effects
from commands import CommandReturn
from commands.client import ClientCommand
from engines.precache import Model
from filters.recipients import RecipientFilter
from players.dictionary import PlayerDictionary


beam_model = Model('sprites/laserbeam.vmt')
player_instances = PlayerDictionary()


def debug_line(start, end, color=(255, 255, 255)):
effects.beam(RecipientFilter(),
start=start,
end=end,
parent=False,
life_time=5,
red=color[0],
green=color[1],
blue=color[2],
alpha=175,
speed=1,
model_index=beam_model.index,
start_width=0.4,
end_width=0.4)


# Usage: get_players_in_sphere <radius>
@ClientCommand('get_players_in_sphere')
def radius_command(command, index):
player = player_instances[index]
try:
radius = float(command[1])
except IndexError:
return CommandReturn.BLOCK

players = get_players_in_sphere(player.view_coordinates, radius, True)

if players:
for player in players:
print(player.name)

return CommandReturn.BLOCK

Re: Perfomance of trace rays

Posted: Mon Mar 02, 2020 2:44 pm
by InvisibleSoldiers
No. Player shot, but missed, I want to trace ray the whole circle relative to the shot to find out the accuracy of the shot relative to near enemies.
Player shoot with some eye angle (QAngle), I have direction(get_angle_vectors), length(8192) of the shoot, I have start location of shot(eye_location), but to find out the accuracy I need to ray trace with new QAngle which will differ with every raytrace in loop. It is potential eye_angle with whom he could shoot and hit a enemy.

For example:

Syntax: Select all

shoot_eye_angle - QAngle(80.0, 65.0, 0.0)
shoot_pos - Vector(?, ?, ?)

Init loop:
for i in range(100) {
shoot_eye_angle.x += 0.04

forward = Vector()
direction = shoot_eye_angle.get_angle_vectors(forward, None, None)

engine_trace.trace_ray(
Ray(shoot_pos, shoot_pos + direction * 8192.0),
ContentMasks.SHOT,
trace_filter,
game_trace
)

if 0 < game_trace.entity_index < 65 {
accuracy_percent = 100 - i
break
}
}


It is only by vertically but I think the meaning is clear.
At each iteration in the loop, angle from player potentially eye_angle shoot sum with step angle(0.04), the further we go the worse the accuracy.

Horizontal and vertical can still be endured, but when there are full circle with some trigonometry server freezes.

Re: Perfomance of trace rays

Posted: Thu Mar 12, 2020 6:33 am
by Hymns For Disco
First you have said that you want to trace a circle to find any near player, then you said you are trying to find the "accuracy of the shot". What is the end goal here? If you want to find players that are nearby the shot angle, you can work that without traces (or maybe just a single trace per player to see if they are easily visible).

Also, if our server is freezing trying to do the full circle, it is possible you have a logic error, rather than a performance bottleneck. Presumably your 100 sample example here works? Whatever algorithm you have implemented for tracing the full circle, you should be able to adjust the number of samples there, and set it to 100 also. Running a few hundred trigonometry functions and/or traces shouldn't be enough to kill a server. I've run sourcemod plugins that trace ~100 times per tick without noticing any performance effects.