Space Frame Loop Rezzer
Definition and Uses of Space Frame
A space frame is an architectural element consisting only of struts and hubs. A space frame can provide great strength in a light open structure and is used in many modern buildings. The key to its strength is that the struts are always in tension or compression and never see any torque.
This space frame is built by the loop rezzer SFRezzer and has all the struts of the same length with flat top and bottom grids made of squares. The grits are connected by struts at compound angles. The top grid has one more square each way than the bottom grid. The normal structural supports are the four corner hubs in the bottom grid but in Second Life it makes no difference how you use your space frame.
Loop Rezzer Use Summary
The process of building a custom Space Frame in Second Life is detailed below and includes the following these steps:
- Use click and point to move the Space Frame Rezzer Prim from you inventory to a Second Life area where you have permission to build.
- Edit the included script to show the size on the X and Y axis you need. (You may exceed the 10 meter limit.)
- Edit the nominal length of the strut.
- Save the script.
- Exit the editor
- Left click on the Space Frame Rezzer prim.
- The Space Frame will then be automatically generated. (The process takes about two minute.)
- Inspect the Space Frame visually and check the height and strut length in the communications window. (Erase and repeat steps 2 through 7 if needed.)
- Select all the struts for linking. (The limit is 256.)
- Select the base plate at the origin last.
- Be sure that the Space Frame Rezzer prim is not selected.
- Link all the selected prims in the Space Frame.
- Right click the linked Space Frame and Take it.
There are some limitations:
- The strut cannot exceed 10 meters.
- Space frames require a large number of prims.
A space frame can be used in Second Life for:
- Architectural element such as roof support
- Bridge or other landscape element
- Hat, shield, or other clothing
Peculiarities of this Space Frame Rezzer
To rez a space frame, decide how big a space you need to span. The space frame will be rezzed along the X and Y axis but can be repositioned after it has been rezzed and linked. All measurements are in meters and may be entered to three significant figures. Neither span is restricted by the 10 meter limit but be sure to stay in an open working space.
Decide the nominal length of the strut you wish to use. For best results, both the X and Y span distances should be integer multiples of the strut length. If you enter numbers that are not multiples, then the strut length will be adjusted to fit the X span and there may be an error on the Y span.
The number of primes needed for a space frame can run up very quickly. Using larger values of the strut length reduces the number of prims needed while increasing the height. The maximum number of primes that can be linked is 256.
The struts overlap slightly to form the hubs, so no extra prims are needed for them.
The height of the space frame is always 0.707 times the actual strut length.
The loop rezzer sends messages to the user through the local communication window giving such information as:
- number of X nodes
- number of Y nodes
- strut length
- height
- errors in Y
- number of prims used
All measurements are in meters. If more than 255 prims are used, you may wish to reconsider your inputs.
Credits
This Space Frame Rezzer was written by:
- // Space Frame Loop Rezzer V2.0
- // by Tom Riley a.k.a. Nikolai Vaniva, August 30, 2009
- Email: jriley@charm.net
- // Best known for "Woodware Designs"
- // http://www.charm.net/~jriley/woodware.html
Please email this author for additional information or a working copy of SFRezzer.
This script incorporates key software from two other rezzers:
- // "Building Prim Skirts using the Loop Rezzer"
- // LoopRez v0.6, by Ged Larsen, 20 December 2006
And
- // Shine Renoir's Geodesic Dome Builder
- // One time scale script
- // 2007 Copyright by Shine Renoir ( fb@frank-bus.de )
This rezzer was developed using the sandbox at:
- NASA eEducation (223,115,24)
Building the Loop Rezzer
The loop rezzer prim provided is a twisted sphere. You may use any prim you like as long as it is distinctive.
A very detailed step-by-step procedure for a loop rezzer can be found in:
- // "Building Prim Skirts using the Loop Rezzer"
- // LoopRez v0.6, by Ged Larsen, 20 December 2006
The following script listing must be included under Content in the loop rezzer:
<lsl> /////////////////////////////////////////////////////////////////////// // Space Frame Rezzer V2.0 with Scaling // Square grid, 2 user dimensions, strut scaled , span not limited in X and Y // by Tom Riley a.k.a. Nikolai Vaniva, August 29, 2009 // Best known for // "Woodware Designs" http://www.charm.net/~jriley/woodware.html // Modified from: // LoopRez v0.6, by Ged Larsen, 20 December 2006 // ///////////////////////////////////////////////////////////////////// //
// User entered information: (3 items)
float gSizeX = 3.000 ; // Distance between Space Frame supports in meters along X axis; best if an integer multiple of gStrutLength
float gSizeY = 2.000 ; // Distance between Space Frame supports in meters along Y axis; best if an integer multiple of gStrutLength
float gStrutLength = 1.000 ; // Nominal strut length float gStrutDia = 0.060 ; // strut diameter
//////////////////////////////////////////////////////////
// No user changes are needed below this line!
string objectName = "StrutScale" ; // object for Strut; // will need to be in the inventory of the prim containing this script integer gStrutPrim = 1 ; // Number of prims per strut string rootPrimName = "Space Frame Pad" ; // root prim that will appear at origin support
integer gNumStruts = 0 ; // count number of struts vector rotOffset = <0.0, 0.0, 0.0> ; // rotation offset in DEGREES vector posOffset = <0.0, 0.0, 1.5> ; // position offset from rezzing prim to root prime
move(vector destination) {
// llSetPos is limited to 10 m distances, // so it is called until the target is reached
vector p = ZERO_VECTOR; // need to check Y too ??? while (p.x != destination.x ) { llSetPos(destination); p = llGetPos(); }
}
sfRezLoop() // primary Space Frame generator {
vector orgPos = llGetPos() ; // save original position of rez generator
// Calculate number of X and Y nodes and strut length
float sfStrutLength = gStrutLength ; integer nXNode = (integer) ( gSizeX / sfStrutLength) + 1 ;
if ((gSizeX != (float) (nXNode-1) * gStrutLength) ) { ++nXNode ; } sfStrutLength = gSizeX / ((float)nXNode - 1.0) ; // adjust strut length float sfRealSizeX = ((float) nXNode -1.0) * sfStrutLength ; float sfErrorX = gSizeX - sfRealSizeX ; integer nYNode = (integer) (gSizeY / sfStrutLength) + 1; float sfRealSizeY = ((float) nYNode -1.0) * sfStrutLength ; float sfErrorY = gSizeY - sfRealSizeY ;
// calculate internal parameters vector sfStrutReSize = < (sfStrutLength + gStrutDia), gStrutDia , gStrutDia > ; // scaling
float sfStrut05 = sfStrutLength / 2.00 ; // 1/2 step float sfStrut025 = sfStrutLength / 4.00 ; // 1/4 step float sfDiaXY = llSqrt( 2* (sfStrut05 * sfStrut05 )) ; // diagonal in XY plane float sfHeight = llSqrt( ( sfStrutLength * sfStrutLength) - ( sfDiaXY * sfDiaXY ) ) ; // height of Space Frame float sfHeight05 = sfHeight / 2 ; // half step in height float sfAngle45 = PI / 4.0 ; // angle around Y and Z axis llOwnerSay( "X nodes: " + (string)nXNode + ", Y nodes: " + (string) nYNode + ", Strut: " + (string) sfStrutLength) ; // report XY node numbers to local talk window llOwnerSay( "X error: " + (string)sfErrorX + ", Y error: " + (string) sfErrorY + ", Height: " + (string) sfHeight) ; // report XY error values to local talk window
integer nX = 0; // Step counter in X axis integer nY = 0; // Step counter in Y axis integer n = 0 ; // general counter rotation rot; // rotation in quaternion format vector rezzerPos = llGetPos(); vector rootPrimPos = rezzerPos + posOffset ; vector pos = ZERO_VECTOR ; // Rez Space Frame pad for root prim
llRezObject(rootPrimName, rootPrimPos, ZERO_VECTOR, ZERO_ROTATION, 0); // This prim marks the center of the support at local <0.0,0.0,0.0> ++gNumStruts ;
// Rez lower struts || to X axis
rot = llEuler2Rot(rotOffset * DEG_TO_RAD) ; // set rotation for( nX = 0; nX < nXNode-1 ; ++nX) { for( nY=0 ; nY < nYNode ; ++nY) { pos = rootPrimPos + < (nX * sfStrutLength + sfStrut05), (nY * sfStrutLength), 0.0> ; // offset to node move(pos); llRezObject(objectName, pos, ZERO_VECTOR, rot, n) ; // rez the strut llSay(-2900, (string) sfStrutReSize ); // send resize message gNumStruts = gNumStruts + gStrutPrim ; // count struts rezzed } }
// Rez lower struts || to Y axis
rot = llEuler2Rot(rotOffset * DEG_TO_RAD) * llEuler2Rot(< 0.0, 0.0, 90.0> * DEG_TO_RAD) ; for( nX = 0; nX < nXNode ; ++nX) { for( nY=0 ; nY < nYNode-1 ; ++nY) { pos = rootPrimPos + < (nX * sfStrutLength), (nY * sfStrutLength + sfStrut05), 0.0> ; move(pos); llRezObject(objectName, pos, ZERO_VECTOR, rot, n); llSay(-2900, (string) sfStrutReSize ); // send resize message gNumStruts = gNumStruts + gStrutPrim ; // count struts rezzed } }
// Rez upper struts || to X axis
rot = llEuler2Rot(rotOffset * DEG_TO_RAD) ; for( nX = 0; nX < nXNode ; ++nX) { for( nY=0 ; nY < nYNode+1 ; ++nY) { pos = rootPrimPos + < (nX * sfStrutLength), (nY * sfStrutLength - sfStrut05 ), sfHeight > ; move(pos); llRezObject(objectName, pos, ZERO_VECTOR, rot, n); llSay(-2900, (string) sfStrutReSize ); // send resize message gNumStruts = gNumStruts + gStrutPrim ; // count struts rezzed } }
// Rez upper struts || to Y axis
rot = llEuler2Rot(rotOffset * DEG_TO_RAD) * llEuler2Rot(< 0.0, 0.0, 90.0> * DEG_TO_RAD); for( nX = 0; nX < nXNode+1 ; ++nX) { for( nY=0 ; nY < nYNode ; ++nY) { pos = rootPrimPos + < (nX * sfStrutLength - sfStrut05), (nY * sfStrutLength), sfHeight> ; move(pos); llRezObject(objectName, pos, ZERO_VECTOR, rot, n); llSay(-2900, (string) sfStrutReSize ); // send resize message gNumStruts = gNumStruts + gStrutPrim ; // count struts rezzed } } // Rez diagonal struts // Rez double diagonal struts group 1 (pos ++) of 4 groups
rot = llEuler2Rot(< 0.0, -sfAngle45, 0.0 > ) * llEuler2Rot(< 0.0, 0.0, sfAngle45 > ) ; // set compound angle for( nX = 0; nX < nXNode ; ++nX) { for( nY=0 ; nY < nYNode ; ++nY) { pos = rootPrimPos + < ((nX * sfStrutLength) + sfStrut025), ((nY * sfStrutLength) + sfStrut025), sfHeight05 > ; move(pos); llRezObject(objectName, pos, ZERO_VECTOR, rot, n); llSay(-2900, (string) sfStrutReSize ); // send resize message gNumStruts = gNumStruts + gStrutPrim ; // count struts rezzed } }
// Rez Diagonal struts group 2 (pos +-, clockwise)
rot = llEuler2Rot(< 0.0, -sfAngle45, 0.0 > ) * llEuler2Rot(< 0.0, 0.0, -sfAngle45 > ) ; for( nX = 0; nX < nXNode ; ++nX) { for( nY=0 ; nY < nYNode ; ++nY) { pos = rootPrimPos + < ((nX * sfStrutLength) + sfStrut025), ((nY * sfStrutLength) - sfStrut025), sfHeight05 > ; move(pos); llRezObject(objectName, pos, ZERO_VECTOR, rot, n); llSay(-2900, (string) sfStrutReSize ); // send resize message gNumStruts = gNumStruts + gStrutPrim ; // count struts rezzed } }
// Rez Diagonal struts group 3 (pos --)
rot = llEuler2Rot(< 0.0, sfAngle45, 0.0 > ) * llEuler2Rot(< 0.0, 0.0, sfAngle45 > ) ; for( nX = 0; nX < nXNode ; ++nX) { for( nY=0 ; nY < nYNode ; ++nY) { pos = rootPrimPos + < ((nX * sfStrutLength) - sfStrut025), ((nY * sfStrutLength) - sfStrut025), sfHeight05 > ; move(pos); llRezObject(objectName, pos, ZERO_VECTOR, rot, n); llSay(-2900, (string) sfStrutReSize ); // send resize message gNumStruts = gNumStruts + gStrutPrim ; // count struts rezzed } }
// Rez Diagonal struts group 4 (pos +-)
rot = llEuler2Rot(< 0.0, sfAngle45, 0.0 > ) * llEuler2Rot(< 0.0, 0.0, -sfAngle45 > ) ; for( nX = 0; nX < nXNode ; ++nX) { for( nY=0 ; nY < nYNode ; ++nY) { pos = rootPrimPos + < ((nX * sfStrutLength) - sfStrut025), ((nY * sfStrutLength) + sfStrut025), sfHeight05 > ; move(pos); llRezObject(objectName, pos, ZERO_VECTOR, rot, n); llSay(-2900, (string) sfStrutReSize ); // send resize message gNumStruts = gNumStruts + gStrutPrim ; // count struts rezzed } } llSetPos(orgPos) ; // restore original position of generator llOwnerSay( " Number pims: " + (string) gNumStruts); // report number of prims rezzed
}
default {
touch_start(integer total_number) // start action, click on generator prim { if (llDetectedOwner(0) == llGetOwner()) // only useful to owner { sfRezLoop(); // generate Space Frame } }
} </lsl>
You will also need to add the following two prims.
Adding the Space Frame Prim
You need a small simple prim to serve as the archer point for the final linked space frame. A small cylinder is provided but other prims may be used. This prim must be named "Space Frame Pad", but requires no software listing.
Adding the Strut
The Space Frame Strut is its construction element and must be named "StrutScale". Any single prime or linked prim group may be used but the number of prims used build up very quickly so a single prim is best.
The example uses a sphere prim that has been stretched along the X axis to provide the needed shape. A cylinder could also be used. A combination of the software in the Loop Rezzer and the strut itself will adjust the length of the strut as needed.
The color and texture of the strut are not changed by the Loop Rezzer so you should edit these to suit your needs before use.
The following software must be include in the Strut prim itself:
<lsl> ///////////////////////////////////////////////////////// // Space Frame Strut V1.0 // Strut resizing function // by Tom Riley a.k.a. Nikolai Vaniva, August 25, 2009 // Best known for "Woodware Designs" // http://www.charm.net/~jriley/woodware.html // Modified from: // One time scale script // 2007 Copyright by Shine Renoir ( fb@frank-bus.de ) // //////////////////////////////////////////////////////// //
integer handle;
default {
state_entry() { handle = llListen(-2900, "", NULL_KEY, "" ); }
listen(integer channel, string name, key id, string message) { llSetScale((vector) message); // Resize strut llListenRemove(handle); // no more messages }
on_rez(integer param) { llResetScript(); // start new with each rez }
} </lsl>