Search Unity

RaycastCommand offset positions

Discussion in 'Entity Component System' started by DeanGiddy, Aug 2, 2019.

  1. DeanGiddy

    DeanGiddy

    Joined:
    Oct 30, 2018
    Posts:
    10
    We are constructing a flattened 2D native array of raycast commands. We start from the top left corner, define the first start position of every row, then assign the remaining positions of the rays in a parallel job where on each loop of the job, an inner loop is run to assign one whole row. Our results are like so:

    upload_2019-8-2_17-22-35.png

    The orange points are where our start positions for each row are assigned and the left side of the image is supposed to be where all the rays are. Instead, we get a pattern where one row would overflow to be more than double the width it should be, causing the following row to be empty. So we have the correct total number of rays and they all fire in the same direction but they sometimes start in odd places.

    Our code is as follows:

    Code (CSharp):
    1. /// <summary>
    2.     /// Schedules a Raycast Job in a grid defined by a rect of a landmark, then generates a silhouette based on
    3.     /// all the returned hit points
    4.     /// </summary>
    5.     private void RaycastSilhouetteGrid()
    6.     {
    7.         float3 topRightCorner = GetFloat3FromPoint(rectPoints[0]);
    8.         float3 topLeftCorner = GetFloat3FromPoint(rectPoints[1]);
    9.         float3 bottomLeftCorner = GetFloat3FromPoint(rectPoints[2]);
    10.  
    11.         float width = math.distance(topRightCorner, topLeftCorner);
    12.         float height = math.distance(bottomLeftCorner, topLeftCorner);
    13.  
    14.         int raycastsPerRow = (int)(width / distanceBetweenRaycasts);
    15.         int raycastsPerColumn = (int)(height / distanceBetweenRaycasts);
    16.  
    17.         int raycastAmount = raycastsPerRow * raycastsPerColumn;
    18.  
    19.         Debug.Log(raycastAmount);
    20.  
    21.         NativeArray<RaycastCommand> commands = new NativeArray<RaycastCommand>(raycastAmount, Allocator.TempJob);
    22.         NativeArray<RaycastHit> hits = new NativeArray<RaycastHit>(raycastAmount, Allocator.TempJob);
    23.         NativeArray<float3> startPositons = new NativeArray<float3>(raycastsPerRow, Allocator.TempJob);
    24.  
    25.         float3 referencePointUp = referencePoint.up;
    26.  
    27.         startPositons[0] = topLeftCorner;
    28.  
    29.         for (int i = 1; i < raycastsPerRow; i++)
    30.         {
    31.             startPositons[i] = startPositons[i - 1] + (-referencePointUp * distanceBetweenRaycasts);
    32.             Instantiate(hitPointPrefab, startPositons[i], Quaternion.identity);
    33.         }
    34.  
    35.         float3 relativeForward = math.normalize(landmark.position - referencePoint.position);
    36.         float3 relativeRight = math.cross(new float3(0, 1, 0), relativeForward);
    37.  
    38.         SilhouetteRaycastJob raycastJob = new SilhouetteRaycastJob(commands, startPositons, relativeForward, relativeRight, raycastsPerColumn, raycastsPerRow, distanceBetweenRaycasts);
    39.  
    40.         JobHandle commandHandle = raycastJob.Schedule(raycastsPerRow, 1);
    41.         JobHandle handle = RaycastCommand.ScheduleBatch(commands, hits, 1, commandHandle);
    42.         handle.Complete();
    43.  
    44.         GenerateSilhouette(hits);
    45.         //ShowHitDebugs(hits);
    46.         onSilhouetteFinishedGenerating.RaiseEvent();
    47.  
    48.         for (int i = 0; i < commands.Length; i++)
    49.         {
    50.             Debug.DrawRay(commands[i].from, commands[i].direction, Color.red, 1000);
    51.         }
    52.  
    53.         startPositons.Dispose();
    54.         commands.Dispose();
    55.         hits.Dispose();
    56.     }
    And here is our job code which calculates each position within a row:

    Code (CSharp):
    1. [BurstCompile]
    2. public struct SilhouetteRaycastJob : IJobParallelFor
    3. {
    4.     [WriteOnly] [NativeDisableParallelForRestriction] public NativeArray<RaycastCommand> commands;
    5.     [ReadOnly] public NativeArray<float3> startPositons;
    6.     [ReadOnly] public float3 direction;
    7.     [ReadOnly] public float3 right;
    8.     [ReadOnly] public int columnAmount;
    9.     [ReadOnly] public int rowAmount;
    10.     [ReadOnly] public float distanceBetween;
    11.  
    12.     public SilhouetteRaycastJob(NativeArray<RaycastCommand> commands, NativeArray<float3> startPositons, float3 direction, float3 right, int columnAmount, int rowAmount, float distanceBetween)
    13.     {
    14.         this.commands = commands;
    15.         this.startPositons = startPositons;
    16.         this.direction = direction;
    17.         this.right = right;
    18.         this.columnAmount = columnAmount;
    19.         this.rowAmount = rowAmount;
    20.         this.distanceBetween = distanceBetween;
    21.     }
    22.  
    23.     public void Execute(int index)
    24.     {
    25.         float3 position = startPositons[index];
    26.  
    27.         for (int j = 0; j < columnAmount - 1; j++)
    28.         {
    29.             commands[(rowAmount * index) + j] = new RaycastCommand(position, direction);
    30.             position += (right * distanceBetween);
    31.         }
    32.  
    33.         commands[(rowAmount * index) + columnAmount - 1] = new RaycastCommand(position, direction);
    34.     }
    35. }
    Has anyone come across a similar issue?
     
  2. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    Code (CSharp):
    1. for (int j = 0; j < columnAmount - 1; j++)
    2.         {
    3.             commands[(rowAmount * index) + j] =
    if columnAmount > rowAmount, you are writing to the same indices from multiple jobs => race condition

    what you want to di is scheduling the IJobParallelFor (or IJobParallelForBatch) so that it only writes to a single index / it's allowed indices, and calculate the positions inside the job with
    Code (CSharp):
    1. x = (i % rowAmount) * width;
    2. y = (i / rowAmount) * height;