Jump to content

Judy Hynes

Resident
  • Posts

    31
  • Joined

  • Last visited

Everything posted by Judy Hynes

  1. Sure, I agree with you that there may be some names that will never be available again, but that's not my question. I found at least one name that has been regularly available as outlined in my original post, so I'm wondering if anyone has any insight into how often the last names get rotated or how long it takes the same ones come back around again, and if there are any better ways to know when it happens than just checking the website myself.
  2. I recently looked into how name changes work in SL. I see that there is a small selection of last names available to change to, but I also read that it changes periodically. I found a name I might be interested in that's not available now. However, when I looked up that last name, I saw that many accounts that use it ranging in age from 2 to 20ish years old. This implies that the name is regularly cycled into the available choices. My question is, does anyone know how often the last name choices are rotated or how long it takes names to cycle back around again? I guess it can't be too long if the only name I dug into appears on accounts both very old and relatively new. And if this is the case, is there any better way to know when the available last names change other than to check the SL site's name change feature regularly?
  3. Posting to add I still see this happening with llPreloadSound(). I drove myself crazy debugging the issue until I narrowed it down to use of this function, then belatedly found this thread afterwards. Thanks to @Rolig Loon for the suggestion to "preload" via llPlaySound() at zero volume. This is a very good workaround for my use case and shows no signs of the issue.
  4. @Quistess Alpha I did some playing around with llGetAccel and it is a handy way to see the forces on an object. However, using it as a detection method doesn't seem like it would pan out. The acceleration change imparted by pushes or even collisions doesn't seem to last long enough to show up when just polling it in a periodic timer, no matter how fast the timer is firing. So trying to catch something accelerating an object in the act this way isn't really feasible. Detecting the velocity change does work reliably of course, since that is a persistent change we can detect even after the acceleration has come and gone.
  5. @Rolig Loon Excellent point that freely-moving objects will see most of the change in the Z dimension even if there's wind at play. You're right that wanting to know what all possible external forces are would be tough. Fortunately, just knowing that any external force of any type was applied (even if I don't know precisely where it came from) is good enough for my purposes. Some initial experimentation shows that wind indeed is NOT a factor, at least for the objects I tried. I launched a 0.25m radius sphere at various angles measuring the velocity periodically as before but examining all the x,y,z components. It is indeed true that x and y components do not change at all despite the wind, which itself changed quite a bit more or less randomly during my testing. I also tried with a much larger object (2m sphere) to see if there's some kind of surface area threshold for wind to affect things, but that object also experienced no change at all in the x or y directions. Despite the one-sentence claim on the wiki (with no further information) that wind affects physical objects, I can see no evidence of it here. (Maybe it's only true for object with different buoyancy or something.) I think knowing if it changed in the horizontal plane will turn out to be good enough. I'll have to think about whether I care if it's being pushed straight up or down, which still has the original problem of how to detect an "additional" force beyond gravity. None of the above makes that problem any easier. If anyone has more ideas on the "z-force" problem I'd love to hear it. @Quistess Alpha You make a good point that explaining the "solution" that I want could preclude someone helping me go an entirely different direction if only they knew the "problem" I wanted to solve. In this case, llPushObject is just the most obvious way I could think of to change a moving object's direction. Another obvious way is by colliding with something during its flight, but fortunately there's an event for that. But LSL allows for forces to be applied at a distance to any object owned by anyone and with no (direct) reporting of accountability for where the extra force came from (that I know of). The situation I'm working on happens on sims with push enabled and on which I don't control every script that runs there. Hence the possibility exists that something, somewhere can push stuff around, and it would be handy if I could know it's happening even if I don't know the source.
  6. I am trying to figure out a reliable method to detect that a physical object has been pushed. That is, something else called llPushObject (or I guess one of the other functions that can change an object's motion). The object I want to detect on may be moving, so just detecting that it moved at all is not enough. I looked over the available events, but nothing seems like it would get me what I want directly. Having a force applied doesn't count as a "collision", all the "target" events are based on motion from llMoveToTarget, and moving start/end are related to keyframe motion. I considered doing some kind of polling, like checking the object's velocity periodically and seeing if it experienced a "big change" from one sample to the next. This seemed promising to me as the objects are "unpowered" so they just get an initial velocity and physics and gravity do the rest. However, just checking for a large magnitude difference in these samples isn't all that reliable in practice I've found. timer() { vector current_vel = llGetVel(); float diff = llVecMag(current_vel-previous_vel); if(diff >= PUSH_DETECT_THRESHOLD) { llOwnerSay("Something pushed me"); } } An object being accelerated by gravity will experience a whole range of velocity values over its travel. If the timer samples perfectly on time every time, I might be able to make an upper bound of the difference that would be "natural" and declare anything else the result of an outside force acting on it. But timer events in LSL are really bad at firing on time, at least for the sample rate's I'd need to pull this off, so any fixed threshold I choose will be "wrong" for a timer event that goes off "late" relative to the assumptions that set that threshold. I tried collecting some data to see if I could establish a correlation between llGetRegionTimeDilation and the amount of velocity change observed, but this data was not correlated well at all when I tested it on a sim experiencing fluctuations in time dilation. I suppose I could record the time of previous velocity sample with llGetTime and only evaluate the velocity difference if the elapsed time is close enough to the timer rate I was expecting for whatever threshold I set. This has a chance of preventing false detects I guess, but means giving up trying to detect anything if the sim slows down, so it's not ideal. Does anyone have ideas on how to approach the problem of detecting that an outside force has been applied to an object? Or suggestions on refining this method of sampling the velocity for abrupt changes that would better handle the variability inherent in timer events?
  7. I was able to test the endpoint limiting suggestion from @Quistess Alpha. The math all seems to work just as expected, so thank you for that. I have been able to try my same experiment with the limiting in place and have not reproduced the llCastRay error. Since I was able to get the error regularly before, I think this does in fact address the issue. I did a little rewriting on the conditions of the limit function, but otherwise it's what you originally wrote. Here is the code I used when testing in case others want to try this solution for the issue. // returns the end point adjusted to the specified limit vector uWallLimitRay(vector start, vector end, vector dimension, float limit) { vector diff = (end-start); float f = (limit-(start*dimension))/(diff*dimension); return start+(f*diff); } // returns end point adjusted to remain inside the region if necessary vector uSimLimitRay(vector start, vector end) { if(end.z < 0.0) { end = uWallLimitRay(start, end, <0.0, 0.0, 1.0>, 0.0); } /* don't need an upper bound on vertical dimension else if(end.z > 4096.0) { end = uWallLimitRay(start, end, <0.0, 0.0, 1.0>, 4096); } */ if(end.x < 0.0) { end = uWallLimitRay(start, end, <1.0, 0.0, 0.0>, 0.0); } else if(end.x > 256.0) { end = uWallLimitRay(start, end, <1.0, 0.0, 0.0>, 256.0); } if(end.y < 0.0) { end = uWallLimitRay(start, end, <0.0, 1.0, 0.0>, 0.0); } else if(end.y > 256.0) { end = uWallLimitRay(start, end, <0.0, 1.0, 0.0>, 256.0); } return end; } cast_ray_experiment() { vector start = llGetPos(); vector end = start + <300.0,0.0,0.0>*llGetRot(); // bound the endpoint within the current region end = uSimLimitRay(start, end); // now do the ray and see if anything was hit list ray = llCastRay(start, end, [RC_MAX_HITS, 3, RC_DETECT_PHANTOM, FALSE]); integer status_code = llList2Integer(ray, -1); llOwnerSay("status_code="+(string)status_code+" start="+(string)start+" end="+(string)end); }
  8. Thanks for the ideas @Quistess Alpha. I will give this concept a try and see how it goes. @Qie NiangaoI too am surprised this has not be discussed or brought up before. I remember back when I first starting learning how llCastRay works that I questioned whether I needed to take care to bound the start and end points to stay inside the same region. But my initial experiments not doing so using some out of bounds points didn't seem to have any issues. It's only now that I see it mostly works even with negative vector components, but I think this must be some kind of accident of the math somehow. I say this because I attached the test prim, went into mouselook and triggered the script changing my look angle slightly each time. I could get the failure to happen this way sometimes (I would estimate 1 in about 10 to 15 tries). Then I added this code just to test the "is it the math" theory. rotation rot = llGetRot(); vector start = llGetPos() + <1.0, 0.0, 0.0>*rot; vector end = start + <300.0,0.0,0.0>*rot; list ray; integer status_code=0; integer retry_count=3; while( (status_code == 0) && (retry_count > 0) ) { ray = llCastRay(start, end, [RC_MAX_HITS, 3, RC_DETECT_PHANTOM, FALSE]); status_code = llList2Integer(ray, -1); if(status_code == 0) { llOwnerSay(" status 0, trying again"); //end += <0.0001, 0.0001, 0.0001>; --retry_count; } } llOwnerSay(" status="+(string)status_code+" start="+(string)start+" end="+(string)end); With the line end += <0.0001, 0.0001, 0.0001>; commented out, any time status_code was 0 it repeated this result for all the the loop's retries. That is, the same inputs into llCastRay always produced the same output, so it's not some kind of timing or transient issue that clears up if there happens to be some time that passes between calls. However, with that line active (NOT commented out), a failure is almost always followed by success upon the first retry. (I only had one test I can remember where 2 retries were needed to get a non-zero result.) So changing the end point, and thus the math, even by a tiny amount causes a different result. And of course as before, there should have been hits detected in all tests, so the zero result is definitely wrong. I'd love to know what's going on here. It seems like insisting that the start and end points to llCastRay must be bounded in some way would be a reasonable API restriction, so I'm actually a little surprised it isn't. But clearly there's something wrong happening under the hood with out-of-bounds points, so it would be good to understand what's really going on here.
  9. After much additional experimentation, I've found what I think the issue is. I am calculating the end point by projecting from the start point along the rotation of the script's prim. However, this sometimes makes one or more of the coordinates of the endpoint negative. When this happens, the failure can occur seemingly at random, although llCastRay does return valid and reasonable results most of the time even so. When I move my test or reduce the distance out that end point is placed such that none of the end point vector's components are negative, I am unable to reproduce the issue. I feel pretty good that this is indeed the problem. Here is my new question. What is a good way to "cut off" the calculated endpoint so that it never crosses the boundary of the region it's in? Or put another way, I still want to project up to a fixed distance away from the start point based on the prim rotation, but I want to "truncate" the result if it hits the edge of the sim. What's a good way to do this? The end point calculation is simple: vector end = start + <100.0,0.0,0.0>*llGetRot(); How can I bound the result so that neither of the x,y values falls outside the range [0, 256], nor z allowed to be negative?
  10. In the course of developing a script that uses llCastRay, I saw a behavior that makes no sense to me based on the documentation for this function. The short story is that in the course of debugging some other issues, I found that multiple calls to llCastRay with the same inputs would sometimes produce zero hits (that is, a status_code of 0) even though it just produced several hits casting the same ray a few seconds earlier. I cannot detect a pattern of any kind; it seems to detect the correct number of hits many times in a row, but occasionally returns status_code 0 for no apparent reason. My function call looks like this: list ray = llCastRay(start, end, [RC_MAX_HITS, 3, RC_DETECT_PHANTOM, FALSE]); integer status_code = llList2Integer(ray, -1); I have verified start and end are always valid and reasonable (based on debugging print statements) status_code is never negative, i.e. no error codes are ever being returned nothing is changing about the test environment, i.e. the prims it should be detecting are present, not moving, and not changing any of their attributes it's not being called repeatedly super fast; there's always at least 2 seconds between calls and often more nothing else weird is going on on the sim at the time; I'm the only one on it and nothing is going on around me There is nothing in the llCastRay wiki page about this kind of behavior; as I read it, all errors return a negative status_code, and there are no caveats about "it will actually give status 0 under condition x" or similar. In short, I can think of no reason that I shouldn't always get the same positive number in the status_code if I give the function the same inputs, nothing changes in the environment, and there are no errors (i.e. negative status codes) related to sim performance. Does anyone know why llCastRay could return status_code 0 at seemingly random times? Or does anyone have any suggestions on debugging further or reducing/eliminating the chance of this random 0 result?
  11. Figures I give up trying to find it and post my question, then I discover exactly what I need right after. For the curious, here's the answer. The file controlling menu shortcuts is this one: C:\Program Files\Firestorm-Releasex64\skins\default\xui\en\menu_viewer.xml Although if you use a different language you'll want to go to that language's directory and not "en". Before changing anything, exit Firestorm and make a backup copy of this file. Now you can edit the shortcuts (and lots of other stuff) presented in the menus. Here's an example entry I changed: the Move Tool menu item. Original entry: <menu_item_call label="Move Tool" name="Move" shortcut="control|2"> <menu_item_call.on_click function="Tools.SelectTool" parameter="move" /> Modified entry: <menu_item_call label="Move Tool" name="Move"> <menu_item_call.on_click function="Tools.SelectTool" parameter="move" /> So you can see I removed line 4, "shortcut", and placed the closing angle bracket on line 3 above after the "name" entry. This removes the shortcut entirely; I could instead have changed the shortcut to a different key combination by editing "control|2" to something else. (I have no idea what happens if you accidentally change it to a shortcut that's already in use, so be careful.) Happy editing!
  12. I am trying to change a couple of default key bindings for menus in Firestorm. In particular, I don't need Ctrl+2 (Move Tool) and Ctrl+3 (Edit Tool) and would rather free these key combinations up for use by gestures. I have done this before but I can't for the life of me find the file I edited to accomplish this. I think I vaguely remember the file I needed to change has "xui" in the name, but I'm unable to find any file with this in its name. To be clear, I DON'T need to change the default keybindings as found in C:\Program Files\Firestorm-Releasex64\app_settings\key_bindings.xml. I'm looking to change (in fact remove) the two menu shortcuts I listed above. I did it before somehow on my old computer but can't figure out what file I changed.
  13. Thanks for all the insight into RLV and experiences. I didn't know much about either so it was good background to have. One thing that is answered for me though is that there is no explicit "precedence" or "masking" of events, as I thought was likely the case in my original post. I was hoping there was some way to "consume" an event in one script so it doesn't propagate to others (a concept lots of other environments provide), but this seems not to be the case for LSL. Thanks for helping me confirm there is no practical way to manage the problem with scripting alone.
  14. I was wondering if it's possible for one object to take a control in a way that it overrides another script that takes the same controls. I think the answer is no, but I thought I'd ask here. To be clear, the situation is like this. Avatar is wearing an attachment that does this: llTakeControls(CONTROL_ML_LBUTTON, TRUE, TRUE); Then avatar sits on an object that also takes the same control: llTakeControls(CONTROL_ML_LBUTTON, TRUE, FALSE); Is there any way for the object being sat on to receive the mouselook button press but the attachment not to receive it while sitting on the object? Setting the last parameter to FALSE was an attempt to do what I want, but on second reading it seems this only suppresses the "normal behavior" of the control but does not affect whether the event propagates to other scripts registered for that control. Obviously the avatar could simply detatch the worn object, but I'm trying to see if there's a way to automatically disable/suppress the attachment's response to button press while sitting on the object, then go back to working as it did before when avatar stands up. I also realize I could add code to both objects to have them coordinate taking and releasing of controls on sit and stand of avatar, but it's not feasible to modify the code of all the possible attachments that could be used. I'm looking for a technique to set a precedence order or otherwise suppress control events that's built into the LSL scripting system (if such a thing exists).
  15. Yes, this is what I was after. I tried using your implementation of Rot2YPR, and it does what I need. A couple of things I noticed: The line that says "I think this is a typo" seems to be correct that it is a mistake. I had to comment out that line and use the one below it instead to get the right results for pitch when facing north/south. The pitch value returned is negative for up tilt and positive for down tilt. I guess this is a right-hand rule thing with orientation of the axes. I thought people usually use positive pitch to mean up not down for things like airplanes. In any event, it's easy enough to negate the value if you want to use the "positive means up" frame of reference. The function rotate_prim_intrinsic that you posted seems to do upward rotation for positive angles, at least the way I'm using it. I guess this should be obvious, but for anyone else new to using this notation, the "roll" for the camera is always zero since there's no way to rotate the camera around the forward direction axis, i.e. you can't "tilt" the camera left or right when looking at something.
  16. Great, this is very helpful. After playing with this function a little I was able to apply some simple rotations about the offset axis that I wanted. I decided to add one more step to my sample by making it apply a rotation to match the angle the user is looking in mouselook. However, I can't seem to figure out how to determine the angle between camera rotation and horizontal plane, i.e. the angle of elevation that the camera is looking up or down from horizontal. I feel like this should be simple but I just haven't been able to figure it out.
  17. I have a problem with trying to rotate a child prim in a link set. Id like to use llSetLocalRot in a script, which rotates the child relative to the root prim and is exactly what I'd like to do. However, the prim rotates about its center and I'd rather it rotated about a different point. I attached a picture to help make it clearer. As you can see, the center of the selected gun prim is not at the hinge (marked with the yellow box), which is the point I would ideally like to have it rotate around. My first thought was to link the gun prim to another prim that is centered at the hinge and then rotate the two as a pair. This works fine if only these 2 prims are linked, but I still have to link them back to the base prim, which breaks the relationship between the "hinge" prim and the gun prim. Once all 3 are linked, I can rotate the hinge prim all I want but it doesn't move the gun prim along with it anymore. And if I rotate the gun prim it still rotates about its own center point. so I'm back where I started. Is there anything I can do to make it seem like the gun prim is rotating at that hinge point (not its own prim center)? Can I link it in some more clever way than I tried before? Is there some script magic that will let me pull this off?
  18. After playing around for a while, I was able to get something that mostly works. It doesn't meet my original goal of stopping an object in one push, but this technique will whittle most moving objects down to near zero velocity over several sensor detection cycles. sensor(integer num_detected) { key target = llDetectedKey(0); string target_name = llDetectedName(0); vector target_vel = llDetectedVel(0); vector target_pos = llDetectedPos(0); float dist = llVecDist(llGetPos(), target_pos); float target_mass = llGetObjectMass(target) * 5.0; // for some reason this works vector push_impulse = -target_vel * target_mass * llPow(dist, 3); llSay(0, "Apply impulse to "+target_name+": "+(string)push_impulse); llPushObject(target, push_impulse, ZERO_VECTOR, FALSE); } Some points I discovered: Negating the velocity does create the right vector to push against the object's current motion. The scaling of the impulse for distance, llPow(dist, 3), is the most important factor. Not using this (or making it significantly smaller) results in the object's velocity reducing by very little each time. There is some scaling needed for mass, and I found that llGetObjectMass() * 5 seems to work to reliably slow down the object each time through the sensor. Using a factor larger than 5 tends to knock the object back the other direction rather than slow it down, and lower factors tend to take too long to dampen near zero. I don't really get why mass times 5 works well. The wiki says llGetObjectMass returns "lindograms", which are kg*100. So the first thing I tried was mass * 100 to convert back to kg, but that applied way too much force. I wish I understood why the magic constant 5 ends up working well. All I know is this slowed down objects that were small and about 7 or 8 times larger mass than the small object, so it gets me something workable.
  19. Thanks for all the suggestions everyone. Both these suggestions would be great, but I'm trying to affect an object from a script in a different object. I can't use llSetVelocity or llSetStatus(STATUS_PHYSICS) in this case. Can't believe I overlooked this. I'll give it a shot and see if I can affect things better when I have the correct mass in the mix.
  20. I'm experimenting with physical objects, and in particular with stopping their motion via an external script. It looks to me like I can use llPushObject (on push-enabled land of course) to cancel out a moving object's momentum. In this case, I'm only concerned with physical objects that apply no force or impulse of their own; that is, they are rezzed with some initial velocity and direction and then continue on that path subject to the usual operation of physics on them. Ideally, the sensor would detect the object, calculate the perfect impulse to apply, and stop the object dead with one call to llPushObject. It looks to me like I could use a sensor, detect the object's current velocity, then apply an impulse that's opposite to that using llPushObject. However, I'm not entirely sure how to get the math for the impulse vector right. I think I would need to know the object's mass in order to calculate the impulse to apply. In addition, the wiki entry for llPushObject says: The push impact is diminished with distance by a factor of distance cubed. So I guess I would need to take distance to into account. This is my best guess: sensor(integer num_detected) { key target = llDetectedKey(0); vector target_vel = llDetectedVel(0); vector target_pos = llDetectedPos(0); float dist = llVecDist(llGetPos(), target_pos); float target_mass = ????? vector push_impulse = -target_vel * target_mass * llPow(dist, 3); llSay(0, "Apply impulse to "+llDetectedName(0)+": "+(string)push_impulse); llPushObject(target, push_impulse, ZERO_VECTOR, FALSE); } So I don't know how to get the right mass to use (or if I'm even understanding that part correctly). I'm also not sure if "cube of distance" thing is actually relevant and if this is the correct way to account for it. The basic technique (without the mass term since I don't know how to get that) seems to work for relatively small, slow-moving objects. Larger, faster-moving ones, especially those traveling fast in a straight line, don't seem to get slowed down anywhere near enough. I guess that's due to not accounting for mass. Any suggestions?
  21. Ah great that's what I needed. I'll have to play with the llAtan2 to understand how it works. I decided to start with just the "whole angle" not broken into horizontal and vertical components. As an example to anyone who wants to play around with it, here is my test script. Put it in a prim, enter mouselook, press left mouse button with some other av nearby to try it out. float SENSOR_ARC_DEGREES = 180.0; float SENSOR_RANGE = 90.0; default { attach(key id) { if(id != NULL_KEY) { llRequestPermissions(llGetOwner(), PERMISSION_TRACK_CAMERA|PERMISSION_TAKE_CONTROLS); } } run_time_permissions(integer perm) { if(!(perm & PERMISSION_TRACK_CAMERA)) { llOwnerSay("Failed to get camera permissions"); } else if(perm & PERMISSION_TAKE_CONTROLS) { llTakeControls(CONTROL_ML_LBUTTON, TRUE, TRUE); } else { llOwnerSay("Failed to get control permissions"); } } control(key agt, integer hld, integer chg) { if(hld&chg) { llSensor("", NULL_KEY, AGENT, SENSOR_RANGE, SENSOR_ARC_DEGREES*DEG_TO_RAD); } } sensor(integer num_detected) { rotation my_rot = llGetRot(); vector my_pos = llGetPos(); vector sensor_center_line = <SENSOR_RANGE, 0.0, 0.0>*my_rot; integer i=0; for(; i<num_detected; ++i) { vector target_pos = llDetectedPos(i); vector target_line = target_pos - my_pos; float angle = llRot2Angle(llRotBetween(sensor_center_line, target_line)); llSay(0, "Angle to target "+llDetectedName(i)+" is "+(string)angle+" ("+(string)(angle*RAD_TO_DEG)+" degrees)"); } } }
  22. I'm stuck on a problem trying to do some trig and I just can't get it. Hopefully someone here can help me work through it. The problem: I want to figure out the angle of displacement to a target discovered in a sensor call. I run the sensor, find the target's position, and now I want to know its angle from the center line (the local x-axis) used by sensor. Actually, I want to know two angles: the angle from center in both the horizontal and vertical planes. I figured out the vertical angle correctly I think. I can find how much the target is vertically angled up (or down) from the center line based making a vertical right triangle. I can do this easily because I can find the opposite side of the triangle by just examining the height (z-axis coordinate) of the target relative to the sensor's position. But I'm stuck trying to do the same in the horizontal plane, since the local x-axis is based on the orientation of the prim containing the script and not necessarily aligned with any of the region axes. It's probably clearer to take a look at my sample code at this point. float SENSOR_ARC_DEGREES = 20.0; float SENSOR_RANGE = 30.0; float find_vertical_angle_from_center(vector my_pos, vector target_pos) { // right triangle has hypotenuse that is distance between the two points float hyp = llVecDist(my_pos, target_pos); // right triangle has opposite side that is vertical (z-axis) distance between the two points float opp = llFabs(my_pos.z-target_pos.z); // Angle x: sin(x) = opp/hyp; x = arcsin(opp/hyp); return llAsin(opp/hyp); } float find_horizontal_angle_from_center(vector my_pos, vector target_pos, rotation my_rot) { // translate the target position into the xy-plane vector target_xy_plane_pos = <target_pos.x, target_pos.y, my_pos.z>; // right triangle has hypotenuse that is distance between the two points in xy-plane float hyp = llVecDist(my_pos, target_xy_plane_pos); // STUCK HERE // How do I get the opposite side, which forms a perpendicular to local x-axis used in sensor call? // I guess I will need the rotation, but I don't know how to calculate where the perpendicular is. } default { on_rez(integer p) { llSensor("", NULL_KEY, AGENT, SENSOR_RANGE, SENSOR_ARC_DEGREES*DEG_TO_RAD); } sensor(integer num_detected) { rotation my_rot = llGetRot(); vector my_pos = llGetPos(); vector target_pos = llDetectedPos(0); float angle_vert = find_vertical_angle_from_center(my_pos, target_pos)*RAD_TO_DEG; float angle_horiz = find_horizontal_angle_from_center(my_pos, target_pos, my_rot)*RAD_TO_DEG; llSay(0, "Vertical angle (degrees): "+(string)angle_vert); llSay(0, "Horizontal angle (degrees): "+(string)angle_horiz); } } So you can see I'd like to do the same right triangle math for horizontal plane that I did for vertical, but I don't know how to find the opposite side as I did in the vertical calculation. Can anyone give me any pointers? NOTE: I'm only interested in the magnitude of the angle (I don't care if it's up/down or left/right) so that's why I used absolute value in the vertical calculation.
  23. Yeah, as I understand it, llAxisAngle2Rot lets you define an arbitrary axis to rotate around and not be constrained to the fixed Euler axes. For my purposes, it comes out the same though right? I just wanted to rotate about one axis and it happened to be one of the Euler ones. rotation delta_yaw_per_shot = llEuler2Rot(<0.0, 0.0, TWO_PI/shot_count>); rotation same_as_above = llAxisAngle2Rot(<0.0, 0.0, 1.0>, TWO_PI/shot_count); I think in the above both come out to the same rotation. I get why defining my own axis would be very handy, like if I wanted to rotate 90 degrees about an axis that's a diagonal in the x-z plane I could do llAxisAngle2Rot(<1.0, 0.0, 1.0>, PI_BY_TWO); What I struggle to figure out is how I could define a similarly-useful custom axis for my specific case that would be any better than the Euler function it uses now. Is there some axis I could have defined that would have gotten me both the pitch and yaw I needed in one step instead of two? I don't know how I'd go about figuring that out. (I suspect it's not possible since I wanted to rotate about two axes that are orthogonal, but I don't have a strong enough background in this kind of thing to be sure.)
  24. Ah ok I get it now. The "shooting down" thing explains why I saw the objects scatter a lot more than I expected; they were being slammed into the ground. I see that you took the tact of remembering the orientation each time and applying the delta_yaw_per_shot each time, incrementing around the circle. That makes sense to me. I think what I was doing was also correct though, creating the "bearing_rot" each time with increasingly larger numbers each time.....0x then 1x then 2x and so on. Is there something fundamentally flawed about that technique or just another way to think about the same thing?
  25. I'm making a script that fires objects off around a circular pattern. It's basically a firework launcher that shoots the fireworks out as if the launcher is rotating a fixed amount between each shot until it rotates all the way back to where it started. I have it nearly doing what I want, but not quite. integer NUM_OF_SHOTS = 10; integer SPEED = 30; float SHOT_ANGLE_UP = 80.0; string OBJECT_TO_REZ = "firework"; default { touch_start(integer num_detected) { rotation up_tilt_rot = llEuler2Rot(<0, SHOT_ANGLE_UP, 0>*DEG_TO_RAD); float bearing_turn_per_shot = 2*PI/NUM_OF_SHOTS; integer i=0; for(; i<NUM_OF_SHOTS; ++i) { rotation bearing_rot = llEuler2Rot(<0, 0, bearing_turn_per_shot*i>); rotation final_rot = up_tilt_rot * bearing_rot; llRezObject(OBJECT_TO_REZ, llGetPos()+<0, 0, 2>, llRot2Fwd(final_rot)*SPEED, final_rot, 0); llSleep(0.5); } } } The idea is that it will rotate 2PI / NUM_OF_SHOTS each time, which means it should make its way around the circle by the time it's done. From what I've read on rotations, I can compose them together to make a final rotation, so that's what I did. I first did the up_tilt_rot to set the angle upwards that it will launch (this is the same for every shot). Then each shot I calculate how far around the circle it should rotate, which is the bearing_rot you see in the code. Then I compose them together, up tilt first, to get the final rotation for the shot. I use that rotation on the firework and apply velocity rotated to its forward direction so the firework flies in its local x direction at the defined speed. All this seems to work great, except I don't get the full 360 degree circle. Instead, I get a semi-circle in the positive x direction for the first half of the shots, then the second half retrace that same semi-circle again. I don't get any along the negative x half of the circle. I thought that my bearing_rot would just keep incrementing all the way around the circle, but I guess that's not true. It confuses me that it seem to "reset" on shot 6 to return to where shot 1 was launched. Can anyone help me understand what I'm doing wrong?
×
×
  • Create New...