Difference between revisions of "LlCastRay"

From Second Life Wiki
Jump to navigation Jump to search
(Clarified behavior of RC_DETECT_PHANTOM flag; this setting overrides the RC_REJECT_FLAGS setting for phantom objects)
Line 1: Line 1:
==llCastRay==
{{LSL_Function
===Introduction===
|func=llCastRay
The API for llCastRay has changed. Below is info on the new API as it exists on mesh-enabled sims on Aditi.
|func_id=?
|func_desc=Description TBD


===API===
|func_sleep=
|func_energy=


list llCastRay( vector <b>start</b>, vector <b>end</b>, list <b>options</b> )
|func_footnote=
Return value: [UUID_1, {link_number_1}, hit_position_1, {hit_normal_1}, UUID_2, {link_number_2}, hit_position_2, {hit_normal_2}, ... , <b>status_code</b>] where {} indicates optional data.
|return_type=list
|return_text=consisting of a three values for each hit:
* UUID
* Link number
* Hit position


''Start'' and ''end'' are vectors specifying the start and end point of the ray. The ray must both start and end within the region where the script is located or a script runtime error will be generated. (So be sure to clamp your values!)
|p1_type=Vector|p1_name=start|p1_desc=starting location


"Options" is a list comprising one or more of:
|p2_type=Vector|p2_name=end|p2_desc=ending location
*RC_REJECT_TYPES followed by an integer "filter" described below (default 0)
*RC_DATA_FLAGS followed by an integer "flags" described below (default 0)
*RC_MAX_HITS followed by an integer specifying the max number of hits to return (default 1, max 256...I strongly recommend you don't choose a large number here, and I may restrict this prior to main grid release)
*RC_DETECT_PHANTOM followed by a boolean integer (default 0, FALSE). Set to TRUE (or nonzero) if you want phantom AND volume detect objects to be detected. It is not possible to detect /only/ phantom objects or /only/ volume detect objects.  If set to TRUE, phantom and volume detect objects will always be detected, even if RC_REJECT_NONPHYSICAL and RC_REJECT_PHYSICAL are set in RC_REJECT_TYPES.


''Filter'' is a bitwise-or combination of the following constants: ''RC_REJECT_AGENTS'', ''RC_REJECT_PHYSICAL'', ''RC_REJECT_NONPHYSICAL'', and ''RC_REJECT_LAND'' except that if you select all 4 of them, a script runtime error will be generated (it makes no sense to cast a ray and reject everything!). Note that phantom and volume detect objects are never returned and that seated agents are treated like unseated agents. I.e., you either get seated and unseated agents in your results, or you use ''RC_REJECT_AGENTS'' and get neither. Using 0 as the filter value will return all hits.
|p3_type=list|p3_name=options|p3_desc= Consists of one or more of:
*RC_REJECT_TYPES followed by an integer "filter" described below.
*RC_DATA_FLAGS followed by an integer "flags" described below.
*RC_MAX_HITS followed by an integer specifying the max number of hits to return. 
*RC_DETECT_PHANTOM followed by a boolean integer (default 0, FALSE).  


''Flags'' is a bitwise-or combination of: ''RC_GET_NORMAL'', ''RC_GET_ROOT_KEY'', and ''RC_GET_LINK_NUM''. These select whether you want link numbers and hit normals in your results list. By default, you will get the UUID (i.e., 'key') of the exact child prim hit. If instead you want the key of the root prim, set ''RC_GET_ROOT_KEY''. Oh, and also, a terrain hit will register as NULL_KEY.
|constants=
<table class=lltable border=1>
<tr>
<th>Constant</th>
<th>Default Value</th>
<th>Description</th>
</tr>
<tr><td>RC_REJECT_TYPES </td>
<td>0</td>
<td></td>
</tr>
<tr><td>RC_DATA_FLAGS </td>
<td>0</td>
<td></td>
</tr>
<tr><td>RC_MAX_HITS</td>
<td>1</td>
<td>Maximum number of hits to return.  Maximum value is 256--To avoid performance issues, keep it small.</td>
</tr>
<tr><td>RC_DETECT_PHANTOM</td>
<td>0, FALSE</td>
<td>Set to TRUE (or nonzero) to detect phantom AND volume detect objects. It is not possible to detect only phantom objects or only volume detect objects. If set to TRUE, phantom and volume detect objects will always be detected, even if RC_REJECT_NONPHYSICAL and RC_REJECT_PHYSICAL are set in RC_REJECT_TYPES.</td>
</tr>
</table>


''Status_code'' is a number tacked onto the end of the strided list to give you extra information about the ray cast. If the cast succeeded, it will be >=0 and will indicate the number of hits. If the ray cast failed (which should only happen right now if the simulator performance is running low), you'll get a negative status code. ''RCERR_SIM_PERF_LOW'' will be used as the status code if the overall physics time in the simulator is too high to perform raycasts. The idea is that you will know to try your cast again in a few frames.
|caveats=
Ray casts are throttled by the amount of time actually taken to perform the cast. Each region is allotted a 2ms pool, divided proportionally over parcels the same way prim limits are. Each agent is allotted 100us. All scripts in attachments and, objects on which an avatar is seated, use the agent pool whereas all scripts use the parcel pool. A ray cast can be performed if at least 30us of raycast time remain in the appropriate pool. If there is insufficient time remaining, RCERR_CAST_TIME_EXCEEDED is returned as the status code. The exact time used by the ray cast is measured when it is performed and that number (in microseconds) is subtracted from the pool. (The time remaining can be a negative number.) Over time, the pool is automatically replenished (at a rate of 25% of the max time per frame).


===Limits===
For example, if you start out with 100us and perform a 50us raycast, 50us will be remain. If you then a 70us raycast during the same frame, you will have -20us remaining. Subsequent calls to llCastRay that frame will fail with status code RCERR_CAST_TIME_EXCEEDED. At the start of the next frame, you will have 5us available (25us are restored each frame) and any attempt to call llCastRay will again fail as you need 30us to execute a raycast. One frame after that, 30us will be available and a raycast can once again be performed.
Ray casts are throttled by the amount of time actually taken to perform the cast. Each region is allotted a 2ms pool, divided proportionally over parcels the same way prim limits are. Each agent is allotted 100us. All scripts in attachments and, if I'm not mistaken, objects on which an avatar is seated, use the agent pool whereas all scripts use the parcel pool. A ray cast can be performed if at least 30us of raycast time remain in the appropriate pool. If there is insufficient time remaining, RCERR_CAST_TIME_EXCEEDED is returned as the status code. The exact time used by the ray cast is measured when it is performed and that number (in microseconds) is subtracted from the pool. (The time remaining can be a negative number.) Over time, the pool is automatically replenished (at a rate of 25% of the max time per frame). So, for example, if you start out with 100us and perform a 50us raycast, 50us will be remain. If you then a 70us raycast during the same frame, you will have -20us remaining. Subsequent calls to llCastRay that frame will fail with status code RCERR_CAST_TIME_EXCEEDED. At the start of the next frame, you will have 5us available (25us are restored each frame) and any attempt to call llCastRay will again fail as you need 30us to execute a raycast. One frame after that, 30us will be available and a raycast can once again be performed.


I decided to use this method of throttling as it puts the scripter "closer to the machine". That is, you're only being charged for what you use, and more efficient raycast techniques will automatically be charged less than less efficient ones. The exact throttle values are subject to change at any time before we release to the main grid.
This method of throttling puts the scripter "closer to the machine". That is, you're only being charged for what you use, and more efficient raycast techniques will automatically be charged less than less efficient ones. The exact throttle values are subject to change at any time before release to the main grid.


Tips for Efficient Raycasts:
Tips for Efficient Raycasts:
#Keep the max number of hits returned as small as possible
*Keep the max number of hits returned as small as possible
#Set as many RC_REJECT_TYPES as possible (of factors you can control, this will likely have the largest impact). For example, if you only want to know where the nearest agent is along a ray, use RC_REJECT_LAND | RC_REJECT_PHYSICAL | RC_REJECT_NONPHYSICAL
*Set as many RC_REJECT_TYPES as possible (of factors you can control, this will likely have the largest impact). For example, if you only want to know where the nearest agent is along a ray, use RC_REJECT_LAND | RC_REJECT_PHYSICAL | RC_REJECT_NONPHYSICAL
#When possible, avoid raycasting through piles of prims and avoid raycasting against concave physics objects (anything with cut, hollow, twist, etc., and any mesh object that has no decomposition and has physics type "prim"). Obviously this can't always be avoided, so some casts may take significantly longer than others. Plan for that with robust scripts that handle RCERR_CAST_TIME_EXCEEDED responsibly, namely by sleeping briefly after the call and waiting for a few frames to go by before trying again.
*When possible, avoid raycasting through piles of prims and avoid raycasting against concave physics objects (anything with cut, hollow, twist, and so on, and any mesh object that has no decomposition and has physics type "prim"). Obviously this can't always be avoided, so some casts may take significantly longer than others. Plan for that with robust scripts that handle RCERR_CAST_TIME_EXCEEDED responsibly, namely by sleeping briefly after the call and waiting for a few frames to go by before trying again.




===Example Code===
''Filter'' is a bitwise-or combination of the following constants: ''RC_REJECT_AGENTS'', ''RC_REJECT_PHYSICAL'', ''RC_REJECT_NONPHYSICAL'', and ''RC_REJECT_LAND'' except that if you select all four of them, a script runtime error will be generated (it makes no sense to cast a ray and reject everything!). Note that phantom and volume detect objects are never returned and that seated agents are treated like unseated agents. I.e., you either get seated and unseated agents in your results, or you use ''RC_REJECT_AGENTS'' and get neither. Using 0 as the filter value will return all hits.
This is a very poor script that I wrote to test the ray casts. Use it as a starting point if you like.


''Flags'' is a bitwise-or combination of: ''RC_GET_NORMAL'', ''RC_GET_ROOT_KEY'', and ''RC_GET_LINK_NUM''. These select whether you want link numbers and hit normals in your results list. By default, you will get the UUID ('key') of the exact child prim hit. If instead you want the key of the root prim, set ''RC_GET_ROOT_KEY''. A terrain hit will register as NULL_KEY.
''Status_code'' is a number tacked onto the end of the strided list to give you extra information about the ray cast. If the cast succeeded, it will be &gt;=0 and will indicate the number of hits. If the ray cast failed (which should only happen right now if the simulator performance is running low), you'll get a negative status code. ''RCERR_SIM_PERF_LOW'' will be used as the status code if the overall physics time in the simulator is too high to perform raycasts. The idea is that you will know to try your cast again in a few frames.
|examples=
<lsl>
<lsl>
integer filter = 0;
integer filter = 0;
Line 83: Line 117:
</lsl>
</lsl>


===Notes===
|notes=
* Quick Tip: use [[llDumpList2String]] to see what the output looks like when you try a new set of flags
Use [[llDumpList2String]] to see what the output looks like when you try a new set of flags.
 
'''Ideas for uses''':


===Ideas===
* Weapons. I'm personally praying that llCastRay will make simulated projectile weapons essentially obsolete in SL. They're horrible for performance. Ray casts FTW!
* Not that you folks need any ideas to get started, but here are a few:
* AI objects
# Weapons. I'm personally praying that llCastRay will make simulated projectile weapons essentially obsolete in SL. They're horrible for performance. Ray casts FTW!
* Vehicles. Try simulating the wheels using raycasts. Not sure if LSL will be fast enough, but I'd love for someone to try and report back.
# AI objects
* A very slow, but kind of cool, ray tracer that could build an image of a sim by casting rays around and determining the color of the thing they hit and modifying a child prim in a display object to have that color...or something. I'd really love to see someone build something like this, actually.
# Vehicles. Try simulating the wheels using raycasts. Not sure if LSL will be fast enough, but I'd love for someone to try and report back.
# A very slow, but kind of cool, ray tracer that could build an image of a sim by casting rays around and determining the color of the thing they hit and modifying a child prim in a display object to have that color...or something. I'd really love to see someone build something like this, actually.
# Lots of other stuff.


===Questions===
|cat1=LSL Physics
# Is llCastRay supposed to support crossing sim-borders ? Currently it does not seem to work. This would be important for next-gen combat-systems. Contrary to what is stated above, no script runtime error gets reported thou.
|cat2=LSL Light
}}

Revision as of 15:26, 21 June 2011

Summary

Function: list llCastRay( Vector start, Vector end, list options );

Description TBD
Returns a list consisting of a three values for each hit:

  • UUID
  • Link number
  • Hit position
• Vector start starting location
• Vector end ending location
• list options Consists of one or more of:
  • RC_REJECT_TYPES followed by an integer "filter" described below.
  • RC_DATA_FLAGS followed by an integer "flags" described below.
  • RC_MAX_HITS followed by an integer specifying the max number of hits to return.
  • RC_DETECT_PHANTOM followed by a boolean integer (default 0, FALSE).

Constant Default Value Description
RC_REJECT_TYPES 0
RC_DATA_FLAGS 0
RC_MAX_HITS 1 Maximum number of hits to return. Maximum value is 256--To avoid performance issues, keep it small.
RC_DETECT_PHANTOM 0, FALSE Set to TRUE (or nonzero) to detect phantom AND volume detect objects. It is not possible to detect only phantom objects or only volume detect objects. If set to TRUE, phantom and volume detect objects will always be detected, even if RC_REJECT_NONPHYSICAL and RC_REJECT_PHYSICAL are set in RC_REJECT_TYPES.

Caveats

Expression error: Unexpected > operator.Ray casts are throttled by the amount of time actually taken to perform the cast. Each region is allotted a 2ms pool, divided proportionally over parcels the same way prim limits are. Each agent is allotted 100us. All scripts in attachments and, objects on which an avatar is seated, use the agent pool whereas all scripts use the parcel pool. A ray cast can be performed if at least 30us of raycast time remain in the appropriate pool. If there is insufficient time remaining, RCERR_CAST_TIME_EXCEEDED is returned as the status code. The exact time used by the ray cast is measured when it is performed and that number (in microseconds) is subtracted from the pool. (The time remaining can be a negative number.) Over time, the pool is automatically replenished (at a rate of 25% of the max time per frame).

For example, if you start out with 100us and perform a 50us raycast, 50us will be remain. If you then a 70us raycast during the same frame, you will have -20us remaining. Subsequent calls to llCastRay that frame will fail with status code RCERR_CAST_TIME_EXCEEDED. At the start of the next frame, you will have 5us available (25us are restored each frame) and any attempt to call llCastRay will again fail as you need 30us to execute a raycast. One frame after that, 30us will be available and a raycast can once again be performed.

This method of throttling puts the scripter "closer to the machine". That is, you're only being charged for what you use, and more efficient raycast techniques will automatically be charged less than less efficient ones. The exact throttle values are subject to change at any time before release to the main grid.

Tips for Efficient Raycasts:

  • Keep the max number of hits returned as small as possible
  • Set as many RC_REJECT_TYPES as possible (of factors you can control, this will likely have the largest impact). For example, if you only want to know where the nearest agent is along a ray, use RC_REJECT_LAND

Examples

<lsl> integer filter = 0;

default {

   state_entry()
   {
       llSay(0, "Hello, Avatar!");
   }
   touch_start(integer total_number)
   {
       vector start = llGetPos();
       vector end = start - <0,-25,0>;
       
       if ( filter > 8 )
       {
           filter = 0;
       }
       
       llOwnerSay("Filter " + (string)filter);
       list results = llCastRay(start, end, [RC_REJECT_TYPES, filter, RC_MAX_HITS, 4] );
       
       integer hitNum = 0;
       // Handle error conditions here by checking llList2Integer(results, -1) >= 0
       for ( hitNum = 0; hitNum < llList2Integer(results, -1); hitNum++ )
       {
           // Stride is 2 because we didn't request normals or link numbers
           key uuid = llList2Key(results, 2*hitNum);
           string name;
           if ( uuid == NULL_KEY )
           {
               name = "Land";
           }                
           else
           {
               name = llKey2Name(uuid);
           }
           llOwnerSay("Hit " + name);
       }
       
       filter += 1;
   }

}

</lsl>

Notes

Use llDumpList2String to see what the output looks like when you try a new set of flags.

Ideas for uses:

  • Weapons. I'm personally praying that llCastRay will make simulated projectile weapons essentially obsolete in SL. They're horrible for performance. Ray casts FTW!
  • AI objects
  • Vehicles. Try simulating the wheels using raycasts. Not sure if LSL will be fast enough, but I'd love for someone to try and report back.
  • A very slow, but kind of cool, ray tracer that could build an image of a sim by casting rays around and determining the color of the thing they hit and modifying a child prim in a display object to have that color...or something. I'd really love to see someone build something like this, actually.

Deep Notes

Signature

function list llCastRay( Vector start, Vector end, list options );