So, given something like this:
I'll get rid of that very regular pattern by going through every face and changing the relevant values until it all looks a bit mixed up. The thing is though, in a very large linkset, that can get really boring. Sure, there's a certain meditative quality to doing a repetitive task like that again and again and again but... sometimes, just sometimes, you want to get on with actually building the damn thing.
Last night, as I headed for bed, I had one of those "why the hell didn't I think of that before?!?" moments. The idea that popped into my head was that I should write a really simple script that'll do the job for me (and likely do a better job of it than I do). So, this morning, I fired up the code editor and knocked it out.
Now I can drop a script in an object like that above, touch a face that matches the faces I want shuffled, and the result is this:
Or, if I don't like it, I can touch it again and get a different random arrangement. Or another. Or... you get the idea. And, of course, if I decide that one or two faces could do with a better tweak I can remove the script and finish it off by hand.
Here's the script in question:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////////////////////////////////////////////////////////// | |
// Z&A Shuffle Texture offsets | |
// By Antony Fairport | |
// | |
// Z&A Shuffle Texture Offsets - Randomly shuffle offsets in textutes. | |
// | |
// Revision history: | |
// ------------------------------------------------------------ | |
// | |
// 2014-12-27 | |
// Initial revision. | |
////////////////////////////////////////////////////////////////////// | |
// Set this to FALSE if you don't want the repeats randomly flipped | |
// between positive and negative values. Normally this gives an extra | |
// bit of variation in how things look, but it might not make sense | |
// for some textures. | |
integer FLIP_REPEATS = TRUE; | |
////////////////////////////////////////////////////////////////////// | |
// Get the important texture information for a face on a prim. | |
list GetTextureInfo( integer iPrim, integer iFace ) | |
{ | |
list lInfo = llGetLinkPrimitiveParams( iPrim, [ | |
PRIM_TEXTURE, iFace, | |
PRIM_COLOR, iFace | |
] ); | |
return [ | |
llList2String( lInfo, 0 ), // Texture UUID | |
llList2Vector( lInfo, 4 ), // Colour vector | |
llList2Float( lInfo, 5 ) // Alpha | |
]; | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Do the two textures appear to match? | |
integer TextureMatches( list lTest, list lAgainst ) | |
{ | |
return ( (string) lTest ) == ( (string) lAgainst ); | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Create a random offset between -1.0 and 1.0, in steps of 0.01. | |
float RandomOffset() | |
{ | |
return -1.0 + ( ( (integer) llFrand( 200.0 ) ) / 100.0 ); | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Returns either 1.0 or -1.0, randomly. | |
float RandomSign() | |
{ | |
if ( llFrand( 1.0 ) < 0.5 ) | |
{ | |
return 1.0; | |
} | |
return -1.0; | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Randomly flip both axis of a texture repeat. | |
vector MakeRandomRepeatFlip( vector vRepeats ) | |
{ | |
if ( FLIP_REPEATS ) | |
{ | |
return < | |
llFabs( vRepeats.x ) * RandomSign(), | |
llFabs( vRepeats.y ) * RandomSign(), | |
vRepeats.z | |
>; | |
} | |
return vRepeats; | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Create a random texture offset vector. | |
vector MakeRandomOffsets() | |
{ | |
return < RandomOffset(), RandomOffset(), 0 >; | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Shuffle the offsets of a texture on a given face. | |
Shuffle( integer iPrim, integer iFace ) | |
{ | |
// Get the existing texture details. | |
list lTexture = llGetLinkPrimitiveParams( iPrim, [ PRIM_TEXTURE, iFace ] ); | |
// Replace them with the tweaked value. | |
llSetLinkPrimitiveParamsFast( iPrim, [ | |
PRIM_TEXTURE, iFace | |
] + llListReplaceList( lTexture, [ | |
MakeRandomRepeatFlip( llList2Vector( lTexture, 1 ) ), | |
MakeRandomOffsets() | |
], 1, 2 ) ); | |
} | |
////////////////////////////////////////////////////////////////////// | |
// Default state. | |
default | |
{ | |
////////////////////////////////////////////////////////////////// | |
// Announce we're ready. | |
state_entry() | |
{ | |
llOwnerSay( llGetScriptName() + " is ready. Touch a face to shuffle " + | |
"it and all similar faces. Don't forget to delete me once you're " + | |
"all done." ); | |
} | |
////////////////////////////////////////////////////////////////// | |
// Respond to a touch event. | |
touch_start( integer _ ) | |
{ | |
// Don't let random people mess with the textures. | |
if ( llDetectedKey( 0 ) == llGetOwner() ) | |
{ | |
// Let them know we've started. | |
llOwnerSay( "Shuffling, please wait..." ); | |
// Get the texture details of the touched face. We'll then look for | |
// all faces that match this one. | |
list lTouchedFace = GetTextureInfo( llDetectedLinkNumber( 0 ), llDetectedTouchFace( 0 ) ); | |
// We'll track how many faces we shuffle. | |
integer iShuffled; | |
// Now, for every prim in the linkset... | |
integer iMaxPrim = llGetNumberOfPrims(); | |
integer iPrim; | |
for ( iPrim = 1; iPrim <= iMaxPrim; iPrim++ ) | |
{ | |
// For every face on the target prim... | |
integer iMaxFace = llGetLinkNumberOfSides( iPrim ); | |
integer iFace; | |
for ( iFace = 0; iFace < iMaxFace; iFace++ ) | |
{ | |
// If that face looks like the face that was touched... | |
if ( TextureMatches( GetTextureInfo( iPrim, iFace ), lTouchedFace ) ) | |
{ | |
// ...shuffle it. | |
Shuffle( iPrim, iFace ); | |
iShuffled++; | |
} | |
} | |
} | |
// Let them know we're done. | |
llOwnerSay( ( (string) iShuffled ) + " face(s) shuffled across " + | |
( (string) iMaxPrim ) + " prim(s)." ); | |
} | |
} | |
} |
This is brilliant. <3
ReplyDelete