Talk:LlCastRay

From Second Life Wiki
Jump to navigation Jump to search

llSonar please?

I would appreciate if you took in consideration my suggestions at http://jira.secondlife.com/browse/SVC-2486 please; any feedback is more than welcome.

ps:llCastRay is already awesome, you rock! Please try the hardest you can to figure out how to get this to come to the maingrid with the least crippling as possible.

--TigroSpottystripes Katsu 03:01, 3 July 2010 (UTC)

Hi Tigro,

If I understand your feature request, it sounds much like the shape cast described in SVC-5381 (http://jira.secondlife.com/browse/SVC-5381) for a sphere or a cylinder cast along its primary axis. Is that correct?

Thanks, Falcon Linden

I have just skimmed thru the comments there, do shape casting allow for somthing liek for example have a nonphys object recognize the geometry so it could rest against a jumbled pile of prims as if it was laying against them physicly? (in the ASCII art in SVC-2486 it would be having the object represented by the O's resting in the diagonal line as if it was solid) --TigroSpottystripes Katsu 05:44, 3 July 2010 (UTC)
A practical example, imagine a giant mecha, with big flat feet, now imagine a landscape littered with prims of all sorts of shapes and sizes, to make it look realistic, on each step the foot should be rotated to rest against the highest points under it ; just raycasting you have the risk of shooting between prims, and with shapecast you don't get the rotation for the foot. --TigroSpottystripes Katsu 03:04, 4 July 2010 (UTC)

What am I looking at?

A function I just threw in to replace phantom bullets for quickly acquiring a point of interest -- whatever your camera's focused on (in this sim, within 20m) is returned, allowing quicker, more intuitive targeting of other objects. PERMISSION_TRACK_CAMERA must be previously set.

<lsl>key camPing() {

   // End points at the camera and 20m in front of it
   vector camPos = llGetCameraPos();
   vector endPos = camPos + ( <20.0, 0., 0.> * llGetCameraRot() );
   // Clamp the end position to within the sim
   // Except what I originally posted was wrong, and I'm too tired to do trig
   // Cast the ray; ignore hits on land, otherwise get the root key
   list contacts = llCastRay( camPos, endPos, 
       RC_REJECT_LAND,
       RC_GET_ROOT_KEY );
   // Return values
   if ( llList2Integer( contacts, -1 ) > 0 ) { // Got a return
       return llList2Key( contacts, 0 );
   }
   return NULL_KEY;

} </lsl>

Jack Abraham 04:42, 3 July 2010 (UTC)

RC_GET_LINK_NUM? Not RC_GET_LINK_KEY?

I can't think of a circumstance where knowing the link number of the return would be useful. UUID of the prim hit would be far more useful; is that within the realm of possibility? Jack Abraham 04:47, 3 July 2010 (UTC)

Hi Jack,

The default behavior is to return the UUID of the prim hit. If you want the root key instead, you have to use RC_GET_ROOT_KEY. The intended purpose of RC_GET_LINK_NUM was for scripts like your camera targeting system where it is expected that the camera will be pointed at a child of the linkset performing the cast. For example, suppose you make a minesweeper game where each tile is a prim in the linkset. And suppose you script it so that the use can select a tile by focusing on it and clicking. The script could cast a ray from the camera and determine the link number of the tile in the player's line of sight. Then it could use that link number in an llMessageLinked or some other LSL function to modify the appropriate child prim. Does that make sense? If it turns out no one has any use for RC_GET_LINK_NUM, I'll eliminate it for the sake of simplicity. But the behavior you're looking for is already there by default! Yay.

Cheers, Falcon Linden

Makes perfect sense; I need to read better. Thanks. Jack Abraham 05:44, 3 July 2010 (UTC)

Memory concerns

Dumping all possible avaible information into a list regardless of whether any of them will be used seems severely wasteful. If you really need to dump all the info as soon as the command is called straight into script memory, at least do somthing like adding a parameter to the command that is a list where each item identifies which pieces of information the scripter wants (like with llGetPrimtiveParams ) --TigroSpottystripes Katsu 05:51, 3 July 2010 (UTC)

I think we basically have that, Tigro; we only get UUID and hit position unless we set additional flags. Falcon indicated that we will not get all hits in the final version; that'll further reduce the size of the list. Jack Abraham 07:50, 3 July 2010 (UTC)

Clamping

It would be a waste of server resources if every script has to add clamping code to make sure their begin and end are inside the region! Instead, do not return an error code but just stop and return only the hits inside the region. That might mean you have to add the clamping code in the server, but that would be a hell of a lot more efficient than doing that in the LSL scripts.

Note that clamping is relatively easy, in C++ it shouldn't cost more than a few microseconds. The algorithm would be something like:

1) A bounding box can be given with two vectors: bbmin and bbmax, where bbmin is the bottom, south/west corner of the sim (0,0,0), and bbmax the upper, north/east corner of the sim (256,256,4096).

2) Let the ray begin at vector begin and end at vector end (using the same coordinate system as the bounding box).

3) Calculate bbmine = bbmin - end, and bbmaxe = bbmax - end. Check if end is outside the sim, so clamping is needed at all, by checking that at least one coordinate in bbmine is positive or one coordinate in bbmaxe is negative (set 'clamping_needed').

4) Shift coordinates so that begin becomes the origin and end becomes the direction (bbmin -= begin; bbmax -= begin; dir = end - begin). Lets call end dir from now on.

5) Check that bbmin has three negative coordinates and bbmax has three positive coordinates. If not then begin is outside the bounding box (if the signs are correct, except there are one or more zeroes, it's on the border and you can just return begin). Not sure if you should return an error code or return just no results. Finally, if begin is outside the bounding box, but end was inside, you might want to clamp begin instead of end. Lets assume that begin is inside the bounding box for now. If end was also inside it, then no clamping is needed and we stop here.

6) Clamping is needed. Calculate dir.x / bbmin.x, dir.x / bbmax.x, dir.y / bbmin.y, dir.y / bbmax.y, dir.z / bbmin.z and dir.z / bbmax.z.

7) Find the largest value 'max' of those six and return begin + dir / max as the collision point of the ray in the direction dir.

As you can see, this is a very fast routine. Still, I think it should be added to the server side. I didn't add code in order to avoid any license problems ;)

Aleric Inglewood 12:00, 3 July 2010 (UTC)

Actually, using SSE2, clamping would take just a few cpu instructions. It's not a question of efficiency for me, it's a question of future compatibility. Since we don't have script versioning for LSL, if we later add the ability to cast rays between sims or change the size of a region, existing scripts will break. I've been thinking of adding a version parameter to this function in order to deal with that possibility, in which case I could clamp in native code.

Cheers Falcon Linden 17:20, 3 July 2010 (UTC)

return also types casted

since filters RC_REJECT_AGENTS, RC_REJECT_PHYSICAL, RC_REJECT_NONPHYSICAL, and RC_REJECT_LAND are used, and therefore detected, it would be handy if in the results returned, the status AGENT, NON_PHYSICAL, PHYSICAL and LAND would also be returned. Is it douable ? --


I've been thinking about that. Either I'll somehow include the type in the list of returned data (perhaps only if you add the flag RC_GET_TYPE or something) or else modify llGetObjectDetails to return the data. You'll definitely have access one way or the other. Regarding land, though, you can definitively identify that because it will return null UUID.

Falcon Linden 17:20, 3 July 2010 (UTC)

Meep

Heya Falcon, really would absolutely love to have an llCastRay function in production.

I saw you had a concern of versioning issues. To overcome that, I heavily recommend using a list as an input, as that would be far more flexible on the kind of parameters and options you can push through rather than fooling yourself into using a hardcoded structure of llCastRay(vector start, vector end, other stuff) etc. A bit like how llSetPrimitiveParams works basically. For example in the past, LL upgraded the prim type interface from legacy to a more advanced and flexible set of input (torii, tubes and rings, yey), they could do this easily because a list was used as a parameter in the function, instead of having to expend resources on adding more functions, bloating LSL and causing legacy issues.

I also have a question, when you cast a ray and it hits an avatar, that hits the avatars' actual sphere-ish phys mesh, correct?

I have actually experimented personally with LSL and my custom client with a prototype LSL Script API, I could offload raycast processing into nearby clients easily and even built a half-working hexapod spider that can walk on a prim landscape, as well as all the fun raycasting combat gun stuff :). So, I have some serious experience to share in this field and having the raycasts locally processed would be really useful in a more timely manner (rather than suffering the delays of network lag).

What are your thoughts on the kind of filtering? Whitelist versus Blacklist? Whitelists are apparently more effective based on desire. (Would be good for consistency (which is hard enough to come by..): llSensors, llListen, ...)

On a last note, you might be wondering about my achievement with my custom client, I couldn't get raycasting weapons taking off because there is a missing critical element to gameplay: Tracers. The user of a gun MUST be able to see WHERE their bullets went (guns use fire cone spread algorithms for added realism). This is one of the significant problems that keep raycasting usage in weaponry really taking off. Otherwise I could have seriously introduced raycasting and changed the face of SL combat with my custom client. If only particle systems could be spontaneously created midair (without requiring the particle system to be 'attached' to the prim (it's possible code-wise in the client btw)) via scripts to simulate tracer effects, then raycasting would seriously be able to take off socially.

--Nexii Malthus 02:10, 4 July 2010 (UTC)

Hi Nexii,

Let me take these one at a time. First, in regard to versioning, LSL lists are very inefficient on the C++ side. They're implemented as linked lists (yuck). I do see the advantage to using a list for parameters, but it would make parsing it slower and I'd rather pull a Windows API (heh, also yuck) style move and (a) add a reserved version number parameter and (b) if necessary later, create an llCastRayEx function. Not the world's most extensible implementation, but c'est la vie.

Second, an avatar's shape isn't sphere shaped at all...and it's not a mesh, it's a convex hull. Its basic shape is kind of like a capsule. I'll leave the process of determining its exact shape via llCastRay calls with RC_GET_NORMAL as an exercise to the reader. :) (And if you do it, be sure to post pictures! That would rock.)

Third, I'm pushing hard for LL to provide client side prediction/client side physics. Although that wouldn't immediately lead to client side scripting, it eventually might. And in the meantime, although open source viewers would need to replace the physics module with an open source version (of which there are plenty), you would have a framework for doing physics-based raycasts locally.

Fourth, regarding filtering, it just made the most sense to use blacklists as it's most common to want to know "What's the first thing I'm hitting?" It's less common to want to know "what's the first avatar/prim/land triangle that I'm hitting?"

Finally, after seeing your comment about tracers I looked up the details of llParticleSystem and was astonished to see that, as far as I could tell, you're totally right. Here's one idea as a temporary workaround: rez a transparent, phantom, nonphysical sphere (perfect, solid spheres are the simplest physics shape available) at the location you need your particle effect, create it there, and then call llDie(). It sucks, I know, but I'm not a graphics programmer and can't add an appropriate particle system function. Another idea, though much much less efficient, would be to rez a set of long, colored, phantom cylinders the length of the raycast. It's still much more efficient than prim bullets since it would be nonphysical and phantom, though.

Hope that helps, Falcon Linden 05:44, 4 July 2010 (UTC)

Function to not fail, what do you think?

I made this:

<lsl>list JustRayIt(vector start, vector end, integer filter, integer flags) {

   list temp;
  
  
   while((llList2Integer(temp, -1) < 0) || (llGetListLength(temp) == 0))
   {
       temp = llCastRay(start, end, filter, flags);
       
   }
   
   return temp;

} </lsl>

The idea being to halt the rest of the script until it can get a valid trace; does it work the way i intended it to? Is there any downside to using this? Is there a better way to get the same result? --TigroSpottystripes Katsu 04:14, 4 July 2010 (UTC)

Hi Tigro,

The script you're suggesting would, sadly, be hugely inefficient. It would hog system resources until the script's time slice ran out. And, to make matters worse, once you fail you're guaranteed not succeed until at least the next frame anyway. I'm not a huge lsl scripter, so I'm not 100% sure, but I believe if you added an llSleep(0) call in the while loop, your script would be put to sleep until the next frame. Failing that, try llSleep(0.1) or some other small number.

Good luck, Falcon Linden 05:29, 4 July 2010 (UTC)

The way it is on the Oatmeals, do tracing ever fail in the frame? --TigroSpottystripes Katsu 05:40, 4 July 2010 (UTC)
Also, doesn't llSleep hog systems resources just the same? --TigroSpottystripes Katsu 05:44, 4 July 2010 (UTC)

On Oatmeal, casts will fail if the overall physics FPS drops too low. It will never fail due to too many raycasts in the same frame, however. In production it will, but I wanted to see how people used it before determining appropriate limits.

llSleep stops execution of your script and allows the simulator to move on to processing another script. It is not implemented as a busy-wait. (At least, I sure hope not. I haven't actually checked the code.)

Falcon Linden 05:50, 4 July 2010 (UTC)

Partially offtopic: about SVC-4606 "Surface conveyour belt"

Falcon, if it's not you, could you please bring SVC-4606 to the attention of whatever Linden that would be able to evaluate it and get it in the plans if it's possible please? (If it's you, then please take a look and see what you can do) --TigroSpottystripes Katsu 04:43, 4 July 2010 (UTC)

I have thought about adding a much, much simpler version of this (where you simply get to specify a velocity vector and a face of the prim), but it would be at least a little tricky to implement and there are a number of things of more general use that I'd like to get to first. Some day, though, it would be a great feature. Falcon Linden 05:51, 4 July 2010 (UTC)

If the server already knows about which face collided and things like the normal of the collision point (and of course the texture parameters of the prim), wouldn't iit be just a matter of basic vector math to get the resulting force and stuff? I imagine this could be a game changer to the scale of flexies, people moving around a mall on flat conveyors like those on some airports, working escalators, more realistic wheeled and tracked vehicle behavior, people will find all sorts of uses for it. Is there somewhere i can see the stuff you got planned? --TigroSpottystripes Katsu 06:01, 4 July 2010 (UTC)

selfignoring?

Is there a way to have the raytrace ignore prims in the same linkset? --TigroSpottystripes Katsu 05:42, 4 July 2010 (UTC)

No, unfortunately this is not possible and would be hacky to implement (though it could be done if there were enough demand for it). It will, however, always ignore a shape that the ray begins inside of. So if you use llGetPos() from a convex prim, that prim will not be returned by the cast. You can always use the UUID of the prim to ignore the result as well.

Falcon Linden 05:46, 4 July 2010 (UTC)