Jump to content

Jenna Huntsman

Resident
  • Posts

    674
  • Joined

  • Last visited

Everything posted by Jenna Huntsman

  1. That would make sense - my bad!
  2. While it doesn't seem to be documented behaviour, you can use llGetPrimitiveParams to return some info by calling the following: llGetPrimitiveParams([VEHICLE_ANGULAR_FRICTION_TIMESCALE,0]); Unfortunately I don't know exactly what the values returned mean (I'm not familiar with the function you're working with), but hopefully you'll be able to make some sense of it.
  3. Use a typecast as part of your listen: integer myInt; listen( integer channel, string name, key id, string message ) { if((integer)message) //check if message is an integer (and is not 0) { myInt = (integer)message } }
  4. I can't seem to comment on that Jira but I don't think this is a bug. In reality, it's because the PRIM_POINT_LIGHT colour value does not expect the given value to be gamma-encoded (sRGB) - instead, it wants a linear RGB value. (This makes sense for lights, as they are self-luminous). I've updated the wiki page for PRIM_POINT_LIGHT, added a caveat about this, and added a link to an example EOTF function. Links: https://wiki.secondlife.com/wiki/PRIM_POINT_LIGHT https://wiki.secondlife.com/wiki/LlsRGB2Linear
  5. Hey all, I have kept plugging away at this and have now created a V2, which in my opinion is a much improved version - It's a lot more accurate than the previous iteration. It also occurred to me that I should provide a demo, so anyone interested but unfamiliar with the topic can have a play - thus, I present, the (Free!) Studio Saberhagen Bodylight: https://marketplace.secondlife.com/p/Studio-Saberhagen-Lighting-System-Bodylight/23487490 Anyway, the V2 code: // ===--- BEGIN KELVIN TO RGB CODE ---=== /* * MIT License * * Copyright (c) 2022 Jenna Huntsman, based on original work(s) by Christopher J. Howard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ list xyz2709 = [<3.2409699419045235,-0.9692436362808801,0.05563007969699365>,<-1.5373831775700941,1.875967501507721,-0.20397695888897652>,<-0.4986107602930036,0.041555057407175605,1.0569715142428784>]; //XYZ to Rec. 709 primaries & whitepoint. vector TransformByMatrix(vector colourIn, list matrix) { //Transform vector by given 3x3 matrix. Credit: Jenna Huntsman vector Out; vector m1 = llList2Vector(matrix,0); vector m2 = llList2Vector(matrix,1); vector m3 = llList2Vector(matrix,2); Out.x = colourIn.x * m1.x + colourIn.y * m2.x + colourIn.z * m3.x; Out.y = colourIn.x * m1.y + colourIn.y * m2.y + colourIn.z * m3.y; Out.z = colourIn.x * m1.z + colourIn.y * m2.z + colourIn.z * m3.z; return Out; } /** * Calculates the color of an ideal black-body radiator, given its temperature in Kelvin. * * @param t Temperature, in Kelvin. * @return Correlated color, in linear RGB space. * * @see https://en.wikipedia.org/wiki/Planckian_locus * @see https://en.wikipedia.org/wiki/CIE_1960_color_space * @see https://google.github.io/filament/Filament.html */ float max(float x, float y) { //Return the higher of 2 given values. if( y > x ) return y; return x; } vector mix(vector x, vector y, vector t) { vector ret; ret.x = x.x*(1-t.x) + y.x*t.x; ret.y = x.y*(1-t.y) + y.y*t.y; ret.z = x.z*(1-t.z) + y.z*t.z; return ret; } vector step(vector edge, vector x) { vector ret = <1,1,1>; if(x.x < edge.x) ret.x = 0; if(x.y < edge.y) ret.x = 0; if(x.z < edge.z) ret.x = 0; return ret; } //Hint: Gamma value must be above 0. Recommeded values: 0.95, 1.0, 1.8, 2.2 and 2.4 //Hint: Duv value should be within range of -300 to 300. Set to 0 to disable. vector CCT2sRGB(float CCT, float Duv, float gamma) { //Convert CCT value and Duv value to RGB value. Credit: Jenna Huntsman, Christopher J. Howard // Approximate the Planckian locus in CIE 1960 UCS color space (Krystek's algorithm) if(gamma <= 0) return ZERO_VECTOR; //Return nothing if no gamma value was specified. Gamma MUST be above 0. float tt = CCT * CCT; float u = (0.860117757 + 1.54118254e-4 * CCT + 1.28641212e-7 * tt) / (1.0 + 8.42420235e-4 * CCT + 7.08145163e-7 * tt); float v = (0.317398726 + 4.22806245e-5 * CCT + 4.20481691e-8 * tt) / (1.0 - 2.89741816e-5 * CCT + 1.61456053e-7 * tt); if(Duv) { //Calculate offset from locus (not exactly accurate, but a good approximation of delta uv) float t1 = CCT + 5; //Calculate coords for next CCT value float tt1 = t1 * t1; float u1 = (0.860117757 + 1.54118254e-4 * t1 + 1.28641212e-7 * tt1) / (1.0 + 8.42420235e-4 * t1 + 7.08145163e-7 * tt1); float v1 = (0.317398726 + 4.22806245e-5 * t1 + 4.20481691e-8 * tt1) / (1.0 - 2.89741816e-5 * t1 + 1.61456053e-7 * tt1); vector Buv = <u,v,0>; vector Nuv = <u1,v1,0>-Buv; //Get 'direction' vector. (this isn't normalized, but it doesn't need to be in this case) Nuv = Nuv*llAxisAngle2Rot(<0,0,1>,(90*DEG_TO_RAD)); //Rotate 'direction' by 90deg. Nuv += Buv; Duv = -Duv; vector Fin = Buv*(1-Duv) + Nuv*Duv; //interpolate along line by x amount (Duv) u = Fin.x; v = Fin.y; } // CIE 1960 UCS -> CIE xyY, Y = 1 vector xyy = <3.0 * u, 2.0 * v,1> / (2.0 * u - 8.0 * v + 4.0); xyy.z = 1; //Set transmissive (luminence) value to 1 as this is a light source, thus always bright. // CIE xyY -> CIE XYZ vector xyz = <xyy.x / xyy.y, 1.0, (1.0 - xyy.x - xyy.y) / xyy.y>; // CIE XYZ -> linear sRGB vector srgb = TransformByMatrix(xyz,xyz2709); // Normalize RGB to preserve chromaticity return srgb_eotf_inverse(srgb / max(srgb.x, max(srgb.y, srgb.z)),gamma); } vector srgb_eotf_inverse(vector l, float gamma) { //Conversion into gamma-encoded sRGB space. Credit: Jenna Huntsman, Christopher J. Howard vector low = l * 12.92; vector high = <llPow(l.x,1.0 / gamma), llPow(l.y, 1.0 / gamma), llPow(l.z, 1.0 / gamma)>; high = high * (1.055 - 0.055); return mix(low, high, step(<0.0031308,0.0031308,0.0031308>, l)); } // https://www.shadertoy.com/view/tsKczy // ===--- END KELVIN TO RGB CODE ---===
  6. You can compress all of that into a single string through the use of llJsonGetValue and llJsonSetValue That will allow you to store an infinite* amount of variables and have the ability to do direct lookup on their value, for example: string MyVal = llJsonGetValue(JsonStore,[prefix+llDetectedLinkNumber(0)]); //Will return the value of prefix(+ the touched link number), e.g. hiccup32 , if present (will return JSON_INVALID if not present) *limited by script memory
  7. You might be able to use llSetLinkPrimitiveParamsFast with LINK_ROOT to set the root prim's rotation (and position for that matter). Also: You may want to consider using llVecDist for getting the distance the chair has moved, just so clean up the code a bit. Example: llSetLinkPrimitiveParamsFast(LINK_ROOT,[PRIM_POSITION,position,PRIM_ROTATION,rot]);
  8. Any idea is DOA because of this. You'd be better off contacting the creator of the chair, or replacing them with mod-enabled furniture.
  9. Hey all, Made a quick code port to LSL of an algorithm that converts colour temperature (in degrees Kelvin) to RGB or LSL colour. Hope someone finds this useful! Note: While the kelvin to RGB portion of this is pretty accurate, the addition (or subtraction) of the shift value (i.e. any values that aren't 0) will produce an inaccurate result - It's close enough to be usable, but something to keep in mind. vector Kelvin2RGB(integer Kelvin, integer Shift, integer ToLSL) { //Convert Kelvin value to regular RGB or LSL colour. Credit: Jenna Huntsman, Mollymews, Tanner Helland //This will take an input value between 1000 and 40000 kelvin - values outside of this may work; however will likely be inaccurate. //Shift corresponds to the Green / Magenta shift value to be applied. This should be 0 for a perfect conversion, however not all light sources produce a pure white light. For example, flourescent sources (~4100k) often produce light with a green tint. Try using a positive value to shift towards green, and a negative one to shift towards magenta. float Temp = Kelvin/100; float Red; float Green; float Blue; if(Temp <= 66) { Red = 255; Green = Temp; Green = 99.4708025861 * llLog(Green) - 161.1195681661; if(Temp <= 19) { Blue = 0; } else { Blue = Temp-10; Blue = 138.5177312231 * llLog(Blue) - 305.0447927307; } } else { Red = Temp-60; Red = 329.698727446 * llPow(Red,-0.1332047592); Green = Temp-60; Green = 288.1221695283 * llPow(Green,-0.0755148492); Blue = 255; } Green = Green + Shift; //G/M colour shift Blue = Blue + ((Shift/2)*(Temp/25)); //Offset shift to fake accuracy. //Note: the shift value is a hack and not at all accurate. //Clamp RGB values to RGB range - Credit: Mollymews vector RGB = < llList2Float([0, Red, 255], (Red >= 0) * (-(Red > 255) | 1)), llList2Float([0, Green, 255], (Green >= 0) * (-(Green > 255) | 1)), llList2Float([0, Blue, 255], (Blue >= 0) * (-(Blue > 255) | 1)) >; if(ToLSL) //Does the user want us to return the colour in LSL format or regular RGB? { RGB = RGB/255; } return RGB; } //https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
  10. To add on to this: AMD themselves dropped support for that APU back in 2016; so you've had half a decade of no driver or firmware updates to fix bugs and maintain compatibility with modern software (for example, the last driver released for that APU supports Windows 8.1 - We're now on Windows 11) - Even if you're on a 'supported' OS, that doesn't mean that it will still work properly - for example, if you're using Windows 7, that was only EOL'd in 2020 - meaning you've got 4 years worth of updates between the drivers running your hardware and the OS itself. With that said - bugs are to be expected with 'depreciated' products, so SL crashing due to unpatched driver or firmware bugs wouldn't be all that surprising. (+1 for running Linux in this case, it's probably the only hope for that hardware at this point, even with a RAM upgrade).
  11. You can't start an animation using it's UUID, but you can stop an animation with one. If you need to find the UUID of the animation, either use the 'Copy Asset UUID' function in the viewer, or see here: https://wiki.secondlife.com/wiki/LlGetInventoryKey#Notes
  12. Another thing to check - does it break if you call llStopAnimation with the animation's UUID instead of it's inventory name?
  13. Avatar UUIDs (mostly) follow RFC-4122 for Version 4 UUIDs - so you can test if a given key is an avatar if the first character in the 3rd block is the number 4. Example: There are some exceptions to this however (I believe older avatar UUIDs do not follow this pattern - pre 2006 (?)): Another way to test is to pass the key off to a function like llRequestUsername to see if a value is returned (key is an avatar); or if it times out (key is any other asset type).
  14. * There is an issue right now with iGPU VRAM detection which locks out the detected VRAM to the lowest 'reserved' amount (this can be as low as 64MB!) and most laptop manufacturers do not allow you to change this. Considering that modern iGPUs (Intel iris xe; upcoming AMD RDNA2 based iGPUs) are capable of running SL with ALM at 30+ FPS, it'd be good to get better VRAM limits for these more modern chips
  15. I posted this function on another thread somewhere, but this should do the trick: //Spherical raycasting position algorithm. Credit: Jenna Huntsman. vector SpherePos(float radial,vector rootPos,vector targetPos) //Radial offset in meters, rootPos is sphere center, targetPos is where to fire. { //vector v_rootPos = rootPos; //Info about the root prim rotation r_rootRot = llRotBetween(<1,0,0>,llVecNorm(<targetPos.x - rootPos.x,targetPos.y - rootPos.y,targetPos.z - rootPos.z>)); vector finPos = rootPos + (<radial,0,0>*r_rootRot); //radial*rootRot to get the correct offset relative to the root (accounting for rotation) then add the region coords. return finPos; } That will return the vector that's x distance from the root, in direction y (note that this is a non-normalized vector, so to get a direction you could use: llRot2Fwd(llGetRot())+llGetPos()
  16. Is anyone else encountering an absurd amount of TP failures over the past week? I swear to god that pretty much every other teleport has ended in a TP failure in the past week - usually, I almost never get TP failures.
  17. You can use: if(perm & PERMISSION_CONTROL_CAMERA) Which will pass when the permission PERMISSION_CONTROL_CAMERA is given (it will fail if not, and is not affected by the status of other perms) Oops, you're absolutely right - that flew straight over my head! In that case, llClearCameraParams() won't do anything, as they are part of scripted camera controls ( used as part of llSetCameraParams() ). You may actually be interested in the llSetLinkCamera command, as this combines the 2 camera commands you're currently using into a single command. You should shift the camera commands into your state_entry event, and if they are set at another offset, add them into your function to do so. As arton said, this isn't applied retroactively, so only avatars sitting down after will have their camera set accordingly.
  18. That script does need a lot of work as I can see that most of the camera interactions are taking place outside of the perms event - also no verification that PERMISSION_CONTROL_CAMERA happens which could also see the camera fail to set correctly. I can also see that you're trying to use llClearCameraParams when the avatar gets up - but this isn't needed as the permissions are revoked and camera position reset automatically, and likely will throw a perms error. It's also worth noting that in the event that an object can have multiple people sitting on it, when one person gets up the perms for the second (still sitting) person is also revoked and must be re-acquired and their camera set to it's desired position again.
  19. This, 100%. All actions that are being performed on the user's camera should take place in the perms event, otherwise you'll get an endless amount of perms errors when you try to interact with the user's camera. (ps. If the item you're creating for uses AVSitter, I actually already have a product which manages the user's camera in accordance to their pose on my MP store, inc. camera transitions)
  20. I'm with Quistess here - what exactly is the issue you're having - i.e. how is the script itself misbehaving? The core function seems simple enough (move the green prim about the red prim in a sphere), but without setting up a testing rig myself (I'm pretty busy RL right now, so I don't have the time to do so) I can't tell what the issue is immediately.
  21. I noticed this too - I think they've updated the backend wiki software, which in turn has brought some visual changes & modernization.
  22. You can actually shorten that up by quite a bit, like this: string HTMLreplaceCodedChars(string s_rawHTML) { //Replace coded HTML characters with Unicode equivalents. Credit: Jenna Huntsman, KT Kingsley, Quistess Alpha, Haravikk Mistral, AndreRush //Uses code from http://wiki.secondlife.com/wiki/Combined_Library#Replace while(llSubStringIndex(s_rawHTML,"&#") != -1) //Loop until no more encoded characters exist in the string. { integer i_hit = llSubStringIndex(s_rawHTML,"&#"); //Find coded character start. integer i_charID = (integer)llGetSubString(s_rawHTML,i_hit+2,i_hit+5); //Find the character number to convert to unicode character. s_rawHTML = llDumpList2String(llParseStringKeepNulls(s_rawHTML, [llGetSubString(s_rawHTML,i_hit,(i_hit + 2 + llStringLength((string)i_charID)))], []), llChar(i_charID)); //Replace coded character with unicode equiv. } //Replace XML characters with Unicode equivalents. list l_XMLchars = ["amp","&","lt","<","gt",">","quot","\"","apos","'"]; integer i; for(; i < llGetListLength(l_XMLchars); i = i+2) { //iterate through the list to find each of the characters present in the raw string. string s_CurChar = "&" + llList2String(l_XMLchars,i) + ";"; //create the full character to look for. while(llSubStringIndex(s_rawHTML,s_CurChar) != -1) { //Loop until all instances of the current character have been replaced. integer i_hit = llSubStringIndex(s_rawHTML,s_CurChar); s_rawHTML = llDumpList2String(llParseStringKeepNulls(s_rawHTML, [llGetSubString(s_rawHTML,i_hit,i_hit+(llStringLength(s_CurChar)-1))], []), llList2String(l_XMLchars, i+1)); } } return s_rawHTML; //pass the new string back }
  23. Oops! I originally put that in there so I could return an error code should something go wrong, but changed my approach while I was writing it which made an error code redundant, then forgot about that value.
  24. You are right! Here's a function which replaces the HTML coded characters with unicode characters: string HTMLreplaceCodedChars(string s_rawHTML) { //Replace coded HTML characters with Unicode equivalents. Credit: Jenna Huntsman, KT Kingsley, Quistess Alpha, Haravikk Mistral //Uses code from http://wiki.secondlife.com/wiki/Combined_Library#Replace while(llSubStringIndex(s_rawHTML,"&#") != -1) //Loop until no more encoded characters exist in the string. { integer i_hit = llSubStringIndex(s_rawHTML,"&#"); //Find coded character start. integer i_charID = (integer)llGetSubString(s_rawHTML,i_hit+2,i_hit+5); //Find the character number to convert to unicode character. if(llGetSubString(s_rawHTML,i_hit+5,i_hit+5) == ";") //If it's a 3 value coded character { s_rawHTML = llDumpList2String(llParseStringKeepNulls(s_rawHTML, [llGetSubString(s_rawHTML,i_hit,i_hit+5)], []), llChar(i_charID)); //Replace coded character with unicode equiv. } else //Nope, it's a 2 value character. { s_rawHTML = llDumpList2String(llParseStringKeepNulls(s_rawHTML, [llGetSubString(s_rawHTML,i_hit,i_hit+4)], []), llChar(i_charID)); //Replace coded character with unicode equiv. } } return s_rawHTML; //pass the new string back }
  25. That doesn't work because the response is using HTML coded characters, not URL escaped characters. Example: Unicode: I'm new, god help me HTML coded: I&#39;m new, god help me Escaped: I%26%2339%3Bm%20new%2C%20god%20help%20me Your best bet might be to find another API to request info from a user's profile, or you could either try to find a function which can replace coded characters with their unicode equivalents, or write one yourself.
×
×
  • Create New...