HeroEngine Forums
Welcome, Guest. Please login or Register for HeroCloud Account.

Author Topic: Example detection with raycast  (Read 3120 times)

AWW_boss

  • General Accounts
  • *
  • Posts: 846
  • gdfgd
    • View Profile
Example detection with raycast
« on: Nov 23, 15, 11:04:01 PM »

Due to request from some developers i'm gona copy/paste this code snippet. I use this snippet to detect ground proximity in my game with aircrafts. It basically takes a player characters, spawns raycasts in several directions around it and if the distance to heightmap is less than some arbitrary distance (i calculate this distance from aircrafts speed and acceleration) then i set ground proximity to be true.

Code: [Select]

method DetectGroundProximity ()
 
  char as NodeRef = me._accControllerOwnerRef
  pos as Vector3
  GetNodePosition(char,pos)
 
  leftVector as Vector3
  GetNodeForwardVector(char,leftVector)
  upVector as Vector3
  GetNodeUpVector(char,upVector)
 
  vectorList as List of Vector3
  forwardVector as Vector3 = RotateVector(leftVector, (0,-90,0))
  add back forwardVector to vectorList
  rightVector as Vector3 = RotateVector(leftVector, (0,-180,0))
  add back rightVector to vectorList
  backwardVector as Vector3 = RotateVector(leftVector, (0,90,0))
  add back backwardVector to vectorList
  downVector as Vector3 = RotateVector(upVector, (180,0,0))
  add back downVector to vectorList
  leftDownVector as Vector3 = leftVector + downVector
  add back leftDownVector to vectorList
  forwardDownVector as Vector3 = forwardVector + downVector
  add back forwardDownVector to vectorList
  rightDownVector as Vector3 = rightVector + downVector
  add back rightDownVector to vectorList
  backwardDownVector as Vector3 = backwardVector + downVector
  add back backwardDownVector to vectorList
 
 
  excludedNodes as List of NodeRef = MUD_ExternalFunctions:MUD_GetClientCharacters()
  add back char to excludedNodes
  //excludedNodes as List of NodeRef
  //add back myAccount to excludedNodes
 
  distance2Ground as Float = 30
  stoppingDistanceMultiplier as Float = 1
  groundProximityDetected as Boolean = false
  loop i from 1 to vectorList.length
    intercept as Vector3 = (0,0,0)
    meshName as String = ""
    hit as NodeRef = Raycast3D(pos, vectorList[i], excludedNodes, distance2Ground, intercept, meshName)
    if (hit <> None)
      where hit is kindof heightmapnode
        if(distance2Ground < (me.MUD_ACCCStoppingDistance * stoppingDistanceMultiplier))
          groundProximityDetected = true
        .
      .
    .
    //reset distance
    distance2Ground = 30
  .
 
  if (groundProximityDetected == true)   
    me.MUD_ACCCGroundProximityDetected = true
  else
    me.MUD_ACCCGroundProximityDetected = false
  .
 
.

Logged

Amanda_Brooks

  • General Accounts
  • *
  • Posts: 514
    • View Profile
    • Heroes and Villains
Re: Example detection with raycast
« Reply #1 on: Nov 24, 15, 01:53:58 AM »

Thanks for posting this - it could be helpful for several projects.
Logged
"Heroes and Villains" - www.heroes-and-villains.com
Facebook: https://www.facebook.com/HeroesAndVillainsMMORPG
Twitter: @Plan_Z_Studios

Thazager

  • General Accounts
  • *
  • Posts: 1160
  • Never stop learning
    • View Profile
Re: Example detection with raycast
« Reply #2 on: Nov 25, 15, 07:59:25 PM »

Had an error. not sure where to look for this. Looks like the C++ source code?

ERROR:system:PhysX Error: NxRay direction not valid: must be unit vector.
File: ..\..\Core\Common\src\SceneRaycast.cpp Line: 418

I was hoping for a simple out put of hit or not, but it repeats that error until I comment out the call.


Update:
Changed location for call, works a little better, but mostly gets ground node. Tried a check to exclude nodes below the character, but does find any nodes now (above character node).
« Last Edit: Nov 25, 15, 08:36:06 PM by Thazager »
Logged
Lead scripter for EO, Repop helper.
HSL Video tutorials:
https://community.heroengine.com/forums/index.php/topic,1719.msg36858.html#msg3685

ToY-Krun

  • General Accounts
  • *
  • Posts: 677
  • Support Volunteer
    • View Profile
Re: Example detection with raycast
« Reply #3 on: Nov 25, 15, 08:29:37 PM »

yeah, check this out Thaz
https://community.heroengine.com/forums/index.php/topic,5907.msg33325.html#msg33325

I had a similar issue, and described how i fixed it.

I use raycast to determine what model if any im standing on, and act on it based on its "Spec",
Including speed reduction when in water.

ToY-Krun

  • General Accounts
  • *
  • Posts: 677
  • Support Volunteer
    • View Profile
Re: Example detection with raycast
« Reply #4 on: Nov 25, 15, 08:35:15 PM »

This is a function i use for determining what is beneath the players feet.

I assume Boss does this from mid air, however if you're on the ground, you'll probably have to make some adjustments as I did.  For example, what if the SRB winds up just beneath the heightmap etc.

Also, I still have an issue every now and then If I'm sharing the same world space with another character, however it varries as to when it does or doesn't happen even then.


Ignore the test code which is in comments.
I call this from several places when and as I need it.
One is a call from a timer, another place I use it on demand.
Together with what Boss has provided, maybe it will help someone.

Code: [Select]
method GetModelUnderFeet() as NodeRef of Class HBNode
  //return none
  //camera_object as NodeRef = GetActiveCamera()
  //opted to check beneath Player rather than Camera
  object as NodeRef = GetPlayerCharacterNode()
  //start_pos as Vector3 = GetCameraPosition( camera_object["CameraName"] )
  pos as Vector3
  if object = None
   
    return None
  .
  GetNodePosition(object, pos)
  //adjust this upward a tad or you may get the Unit Vector Error
  pos.y = pos.y + .5
  rotation as Vector3 = GetNodeRotation( object )
  adjusted_rotation as Vector3 = rotation
  adjusted_rotation.x *= -1
  adjusted_rotation.y = MungeHeadingDegrees( adjusted_rotation.y )
  adjusted_rotation.y *= -1
  direction as Vector3 = RotateVector( (0,-1,0), adjusted_rotation )
  rayStartPos as Vector3 = pos 
  intercept as Vector3 = (0,0,0)
  excludedNodes as List of NodeRef
  main as NodeRef of Class E_playerCharacter = SYSTEM.INFO.PLAYERCHARACTER.GetMyCharacter()
  if main = None
    return None
  .
  //I exclude any equipped items as they well may be propBucket items and "COULD" get in the way.
  inv as NodeRef of Class HJInventory = main.GetMyInventory()
  if inv != None
    if inv.equippedItems.length > 0
      foreach slotID in inv.equippedItems
        item as NodeRef of Class Item = inv.equippedItems[slotID]
        if item != None
          add back item to excludedNodes
        .
      .
    .
  .
  //Exclude the account and character just in case, havent tested with them NOT excluded.
  add back SYSTEM.INFO.PLAYERCHARACTER to excludedNodes
  add back SYSTEM.INFO.PLAYERCHARACTER.GetMyCharacter() to excludedNodes
  //add back charNode to excludedNodes
  distance as Float = 10
  meshName as String = ""
  //this is here to allow a println without locking up the client
  //as its only called on Shift Press
  //  if $GUI._ShiftIsPressed()
  //    println(direction)
  //  .
  test as NodeRef of Class HBNode = RayCast3D(rayStartPos, direction, excludedNodes, distance, intercept, meshName)
  return test
.


the node returned is an HBNode (if any) and you can access its properties via:
testNode["Spec"], testNode["PhysicsType"] etc etc.
« Last Edit: Nov 25, 15, 08:40:24 PM by ToY-Krun »
Logged

Thazager

  • General Accounts
  • *
  • Posts: 1160
  • Never stop learning
    • View Profile
Re: Example detection with raycast
« Reply #5 on: Nov 25, 15, 08:41:28 PM »

Thanks, do you know how to check for walls player might collide with? (Check forward instead of under character?)
Is there an easier way to see if they hit a wall, or would that need a raycast() ?

I was looking to check the forward only vector. Tried using:
        direction as Vector3 = me.HeroEngineACCC_DesiredRotation


add:
added floor as to exclude list, and will only find nodes on the ground that player walks over.

Code: [Select]
public function DetectWall()
  var player = MiscUtils:getCharPointer()

  if player.HaV_toggleSSWalls = true                    // toggle to check or not
    char as NodeRef = me._accControllerOwnerRef

    origin as Vector3
    GetNodePosition(char, origin)
    direction as Vector3 = me.HeroEngineACCC_DesiredRotation

    excludedNodes as List of NodeRef
    add back char to excludedNodes
    add back 9223372066449021589 to excludedNodes

    distance as Float = 0.1
    intercept as Vector3
    meshName as String

    hit as NodeRef = Raycast3D(origin, direction, excludedNodes, distance, intercept, meshName)
    if (hit <> None)
      println("found node "+ hit+"  mesh "+meshName)
    .
  .
.
« Last Edit: Nov 25, 15, 08:52:12 PM by Thazager »
Logged
Lead scripter for EO, Repop helper.
HSL Video tutorials:
https://community.heroengine.com/forums/index.php/topic,1719.msg36858.html#msg3685

ToY-Krun

  • General Accounts
  • *
  • Posts: 677
  • Support Volunteer
    • View Profile
Re: Example detection with raycast
« Reply #6 on: Nov 25, 15, 08:54:38 PM »

i use this as a very basic beginning of our archery system.  it works.

this is client only and in combination with a dynamic object (arrow) that is created, but
this should return you the nodeID of any node that is straight ahead of the camera, which ever
way the camera is facing at the time.

The debug Draw is helpful to ensure which way the Ray is being cast.

This is very basic, so ignore the comments etc.  I borrowed this from HJREF and began converting it
to my needs.  I needed to understand the way the RayCast function was working and this was a good
place to start.  It isnt accurate EVERY direction you face, something I've not yet gone back and fixed.
so adjust the vector where i comment below to get the angle etc you want.
Using Boss's example above should give a clue as to how to adjust the vector for more accuracy.

If you check hit_node for NONE that would tell you if you hit something.
i'll make a few comments to explain what i did.


Code: [Select]
camera_object as NodeRef = GetActiveCamera()
  start_pos as Vector3 = GetCameraPosition( camera_object["CameraName"] )
  rotation as Vector3 = GetNodeRotation( camera_object )
  rotation.y = MungeHeadingDegrees(rotation.y - 180)
  //weapon_spec as NodeRef of Class FPS_WeaponSpec = me._specRef
 
  //Adjusted the y to 180, as otherwise it shoots behind the camera.
  adjusted_rotation as Vector3 = rotation// - (0,180,0)
 
  adjusted_rotation.x *= -1
  //here, i was still working on the issue of it shooting behind the camera
  //  if rotation.y > 0.0 and rotation.y <= 180.0
  //    adjusted_rotation.y *= -1
  //  else if rotation.y > 180.0 and rotation.y <= 360.0
  //    adjusted_rotation.y = 360.0 - rotation.y
  //  .
 
  if adjusted_rotation.y < 0
    adjusted_rotation.y = adjusted_rotation.y * -1
  else
    adjusted_rotation.y = 0 - adjusted_rotation.y
  .
  //adjust (0,0,-1) to get your RayCast Angle.  this may take some experiementing.
  //but should get you started.
  direction as Vector3 = RotateVector( (0,0,-1), adjusted_rotation - (0,180,0) )
 
  excluded_nodes as List of NodeRef
  add back SYSTEM.INFO.PLAYERCHARACTER to excluded_nodes
 
  hit_node = Raycast3D( start_pos, direction, excluded_nodes, distance, intercept, mesh_name )
 
  #if DEBUG
  //message as String = SYSTEM.EXEC.THISFUNCTION+", mesh_name:"+mesh_name +", hit_node:"+hit_node +", intercept:"+intercept
  //println(message+(1.0,1.0,0.5))
  //
  DrawDebugRay(start_pos, start_pos + (direction * 10), 0.05, "FF0000", "FF0000", 1.0, false)
  if intercept != (0,0,0)
    DrawDebugPoint(intercept, 0.1, "00FF00", 1.0, true)
  .
  #endif

ToY-Krun

  • General Accounts
  • *
  • Posts: 677
  • Support Volunteer
    • View Profile
Re: Example detection with raycast
« Reply #7 on: Nov 25, 15, 08:59:28 PM »

Quote
added floor as to exclude list, and will only find nodes on the ground that player walks over.

Actually, good idea... I need to add something similar for when I DONT need to check for heightmap.

Direction is tricky.  Its a Unit Vector, it represents pitch/angle/... and im a blank here.. help me boss heh,
so a a position or heading vector isnt the same.


I still have trouble with that as i've researched them and still don't completely understand it.

« Last Edit: Nov 25, 15, 09:02:56 PM by ToY-Krun »
Logged

Thazager

  • General Accounts
  • *
  • Posts: 1160
  • Never stop learning
    • View Profile
Re: Example detection with raycast
« Reply #8 on: Nov 25, 15, 09:29:26 PM »

added part of it, tried to adjust for differences, debug line not quite showing right.

Kind of based this on the character position/direction rather than camera position/direction, which seems to make a bit of difference. the debug line is off to an angle then moves opposite the character direction change.

Add:
found it - the "if"-"else" was making it go reverse
and the x value to forward rather than the z value, sends it to the front of character
« Last Edit: Nov 25, 15, 09:41:41 PM by Thazager »
Logged
Lead scripter for EO, Repop helper.
HSL Video tutorials:
https://community.heroengine.com/forums/index.php/topic,1719.msg36858.html#msg3685

ToY-Krun

  • General Accounts
  • *
  • Posts: 677
  • Support Volunteer
    • View Profile
Re: Example detection with raycast
« Reply #9 on: Nov 25, 15, 09:36:32 PM »

yeah if based on char direction you'll need to adjust to .... i think -90 rather than 180.
Cameras heading is handled a bit different.


this is the function i use for NPC's archery which determines if their projectile hits something,
its basically what HJREF uses.  it might work better for you since you're calculating from the character.
remember there is a 90 degree rotation correction we have to make for chars.

I'm allowing for npcs on walls to target things above / below them so you'll still have to made some
adjustments for straight ahead i think.  The previous one I showed you (based on camera) works perfect
at all times, THIS is the one I was thinking of when I said it wasnt 100% accurate.

Between the two maybe you can find what you need.  I use the one above for players since archery is done
from Camera View rather than player (we have an AiM mode with crosshairs, much like that used by FPS games)
for archery.

Code: [Select]
target as NodeRef = me.TargetNodeID
  if target = None
    return
  .
  //return
  where target is kindof E_CommonCharacter
    target = target.GetCharacterNode()
  .
  attacker as NodeRef = me.DRO_Owner
 
  if attacker = None// or (not (attacker = 9223372119738021825))
    return
  .
 
  where target is kindof E_CommonCharacter
    target = target.GetCharacterNode()
  .
  where attacker is kindof E_CommonCharacter
    attacker = attacker.GetCharacterNode()
  .
 
 
  #if alter   


  attackerController as NodeRef of Class E_ACCController = attacker._getACCController()
  if attackerController == None
    return //skip this event until the character is completely initialized
  .
  intendedVictim as NodeRef = target
  intendedVictimLocation as Vector3 = me.DRO_TargetPos
 
 
 
  if intendedVictim == None or attacker == None
    return
  .
 
  curHeading as Vector3 = GetNodeRotation(attacker)
  curHeading.x = 0
  curHeading.z = 0
  attackerPos as Vector3 = me.positionStored
 
  victimPos as Vector3 = me.DRO_TargetPos
 
  deltaHeading as Vector3
 
  desired_heading as Vector3 = me.rotationStored//deltaHeading
 
  aim_heading as Vector3// = desired_heading
 
  aim_heading.y = desired_heading.y
 
  excludedNodes as List of NodeRef
  add back attacker to excludedNodes
  victim as NodeRef
 
  aim_heading = RotateVector( (0,0,-1), desired_heading )
 
  hit_node = Raycast3D( attackerPos, aim_heading, excludedNodes, distance, intercept, mesh_name )
  #if debug
  DrawDebugRay(attackerPos, attackerPos+ (aim_heading * distance), 0.05, "FF0000", "FF0000", 1.0, false)
  #endif
 
  return
  #endif
 

ToY-Krun

  • General Accounts
  • *
  • Posts: 677
  • Support Volunteer
    • View Profile
Re: Example detection with raycast
« Reply #10 on: Nov 25, 15, 09:39:15 PM »

bah i keep referencing HJREF......  this code is based on the FPS example NOT HJREF...

Sorry about that.

Thats pretty much all i have example wise to post, if you have any specific questions you
can contact me on skype (gitchimo)  if you like.
« Last Edit: Nov 25, 15, 09:41:20 PM by ToY-Krun »
Logged