Difference between revisions of "Spiral Staircase Generator"
Jump to navigation
Jump to search
m (<lsl> tag to <source>) |
|||
(3 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{LSL Header}} | {{LSL Header}} | ||
[[Image:SpiralStaircase.jpg|thumb|A screenshot of a staircase generated by the Spiral Staircase Generator.]] | |||
Rezzes a spiral staircase according to configuration parameters. | Rezzes a spiral staircase according to configuration parameters. | ||
== Generator == | == Generator == | ||
Drop this in the generator prim, along with the step, banister, and baluster. | Drop this in the generator prim, along with the step, banister, and baluster. | ||
< | <source lang="lsl2"> | ||
//////////////////////////////// | //////////////////////////////// | ||
// Spiral Staircase Generator // | // Spiral Staircase Generator // | ||
Line 13: | Line 12: | ||
//////////////////////////////// | //////////////////////////////// | ||
// Staircase Configuration // | // Staircase Configuration // | ||
float wh = 2.5; | float wh = 2.5; //Height of one wave (in meters) | ||
float wc = 4.0; | float wc = 4.0; //Full waves in staircase | ||
float r_max = 10.0; //Radius maximum, (0.1 -> 10.0) | float r_max = 10.0; //Radius maximum, (0.1 -> 10.0) | ||
float r_min = 7.5; //Radius minimum, (0.1 -> 10.0) | float r_min = 7.5; //Radius minimum, (0.1 -> 10.0) | ||
integer landing = 5;//Number of non-rising stairs at top of staircase (not included in wc) | integer landing = 5; //Number of non-rising stairs at top of staircase (not included in wc) | ||
//Step Configuration | //Step Configuration | ||
Line 211: | Line 210: | ||
} | } | ||
} | } | ||
</ | </source> | ||
== Conf_Step == | == Conf_Step == | ||
Drop this in a prim named "Step". (Box with x-taper 1.0 is recommended). | Drop this in a prim named "Step". (Box with x-taper 1.0 is recommended). | ||
< | <source lang="lsl2"> | ||
default | default | ||
{ | { | ||
Line 232: | Line 231: | ||
} | } | ||
} | } | ||
</ | </source> | ||
== Conf_Banister == | == Conf_Banister == | ||
Drop this in a cylinder named "Banister". | Drop this in a cylinder named "Banister". | ||
< | <source lang="lsl2"> | ||
default | default | ||
{ | { | ||
Line 253: | Line 252: | ||
} | } | ||
} | } | ||
</ | </source> | ||
== Conf_Baluster == | == Conf_Baluster == | ||
Drop this in a cylinder named "Baluster". | Drop this in a cylinder named "Baluster". | ||
< | <source lang="lsl2"> | ||
default | default | ||
{ | { | ||
Line 274: | Line 273: | ||
} | } | ||
} | } | ||
</ | </source> | ||
{{LSLC|Library}} | {{LSLC|Library}} |
Latest revision as of 08:25, 25 January 2015
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Rezzes a spiral staircase according to configuration parameters.
Generator
Drop this in the generator prim, along with the step, banister, and baluster.
////////////////////////////////
// Spiral Staircase Generator //
// By Meyermagic Salome //
////////////////////////////////
// Staircase Configuration //
float wh = 2.5; //Height of one wave (in meters)
float wc = 4.0; //Full waves in staircase
float r_max = 10.0; //Radius maximum, (0.1 -> 10.0)
float r_min = 7.5; //Radius minimum, (0.1 -> 10.0)
integer landing = 5; //Number of non-rising stairs at top of staircase (not included in wc)
//Step Configuration
float s_h = 0.01; //Step height, (0.01 -> 0.99)
float s_s = 0.2; //Vertical stair spacing, (0.01 -> 10.00)
float l_max = 1.0; //Maximum stair length, (0.01 -> 10.00)
float l_min = 0.5; //Minimum stair length, (0.01 -> 10.00)
//Balustrade Configuration
float bal_d = 0.05; //Baluster diameter, (0.001 -> 1.000)
float bal_h = 0.5; //Height of baluster / height of banister, (0.01 -> 1.00)
float ban_d = 0.05; //Banister diameter, (0.001 -> 1.000)
float ban_h = 2.0; //Banister height, (0.01 -> 10.00)
// Functions //
string str_repeat(string src, integer count)
{
if(count > 0)
{
string output;
integer i;
for(i = 0; i < count; i++)
{
output += src;
}
return output;
}
else
{
return "";
}
}
string pad_left(string str, string pad, integer len)//Left-pads string str to length len with character pas
{
return str_repeat(pad, len - llStringLength(str)) + str;
}
list segment(vector a, vector b)//Returns the parameters for a cylinder connecting points a and b
{//Based on http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryBezierCurveDemo
vector mid = (a + b) / 2.0;
vector localZ = b - a;
float len = llVecMag(localZ);
localZ = localZ / len;
vector xAxis;
if(localZ.x < localZ.y)
{
xAxis = <1.0, 0.0, 0.0>;
}
else
{
xAxis= <0.0, 1.0, 0.0>;
}
vector localX = xAxis - (localZ * xAxis) * localZ;
localX = llVecNorm(localX);
rotation rot = llAxes2Rot(localX, localZ % localX, localZ);
return [len, mid, rot];
}
//Staircase-specific Functions
float wave(integer i)//Return i as portion of full wave (2PI)
{
return PI * (float)i * s_s / wh;
}
float radius(integer i)//Return the stair radius at step i
{
return llFabs(((llCos(wave(i)) + 1.0) * ((r_max - r_min) / 2)) + r_min);
}
float len(integer i)//Returns the length of stair at step i
{
return llFabs(((llCos(wave(i)) + 1.0) * ((l_max - l_min) / 2)) + l_min);
}
float rot(integer i)//Returns the rotation of stair at step i
{
return llAcos(1 - llPow(len(i), 2.0) / (2 * llPow(radius(i), 2)));
}
integer s_encode(integer i)
{
return (integer)("1" + pad_left((string)llRound(s_h * 100.0), "0", 2) + pad_left((string)llRound(radius(i) * 10.0), "0", 3) + pad_left((string)llRound(len(i) * 100.0), "0", 4));
}
integer p_encode(float h)
{
return (integer)("1" + pad_left((string)llRound(bal_d * 1000.0), "0", 4) + pad_left((string)llRound(h * 1000.0), "0", 5));
}
integer r_encode(float l)
{
return (integer)("1" + pad_left((string)llRound(ban_d * 1000.0), "0", 4) + pad_left((string)llRound(l * 1000.0), "0", 5));
}
default
{
touch_start(integer num_detected)
{
if(llDetectedKey(0) == llGetOwner())
{
integer i = 0;
float t = 0.0;
//Rez main rising steps
for(i = 0; i < (integer)(wc * wh / s_s); ++i)
{
llSetPos(llGetPos() + <0, 0, s_s>);//I'll have it do this every ~10m when I get around to it
float c_rot = rot(i);
float c_radius = radius(i);
float n_radius = radius(i + 1);
vector m_pos = llGetPos();
//Rez step
llRezObject("Step",
m_pos + <llCos(t + c_rot / 2.0) * c_radius / 2.0, llSin(t + c_rot / 2.0) * c_radius / 2.0, 0>,
ZERO_VECTOR,
llEuler2Rot(<PI_BY_TWO, t + c_rot / 2.0 + 4.7123889, 0>),
s_encode(i));
//Get balustrade data
list b_data = segment(m_pos + <llCos(t) * c_radius, llSin(t) * c_radius, ban_h + (s_h / 2.0)>,
m_pos + <llCos(t + c_rot) * n_radius, llSin(t + c_rot) * n_radius, ban_h + (s_h / 2.0) + s_s>);
if(i == (integer)(wc * wh / s_s) - 1)
{
b_data = segment(m_pos + <llCos(t) * c_radius, llSin(t) * c_radius, ban_h + (s_h / 2.0)>,
m_pos + <llCos(t + c_rot) * n_radius, llSin(t + c_rot) * n_radius, ban_h + (s_h / 2.0)>);
}
vector b_pos = llList2Vector(b_data, 1);
//Rez banister
llRezObject("Banister",
b_pos,
ZERO_VECTOR,
llList2Rot(b_data, 2),
r_encode(llList2Float(b_data, 0)));
//Rez baluster
llRezObject("Baluster",
<b_pos.x, b_pos.y, m_pos.z + ((b_pos.z - m_pos.z) / 2.0) + (s_h / 2.0)>,
ZERO_VECTOR,
ZERO_ROTATION,
p_encode((b_pos.z - m_pos.z) * bal_h));
//Increment rotation
t += rot(i);
}
//Rez non-rising steps
for(i = (integer)(wc * wh / s_s); i < (integer)(wc * wh / s_s) + landing; ++i)
{
float c_rot = rot(i);
float c_radius = radius(i);
float n_radius = radius(i + 1);
vector m_pos = llGetPos();
//Rez step
llRezObject("Step",
m_pos + <llCos(t + c_rot / 2.0) * c_radius / 2.0, llSin(t + c_rot / 2.0) * c_radius / 2.0, 0>,
ZERO_VECTOR,
llEuler2Rot(<PI_BY_TWO, t + c_rot / 2.0 + 4.7123889, 0>),
s_encode(i));
//Get balustrade data
list b_data = segment(m_pos + <llCos(t) * c_radius, llSin(t) * c_radius, ban_h + (s_h / 2.0)>,
m_pos + <llCos(t + c_rot) * n_radius, llSin(t + c_rot) * n_radius, ban_h + (s_h / 2.0)>);
vector b_pos = llList2Vector(b_data, 1);
//Rez banister
llRezObject("Banister",
b_pos,
ZERO_VECTOR,
llList2Rot(b_data, 2),
r_encode(llList2Float(b_data, 0)));
//Rez baluster
llRezObject("Baluster",
<b_pos.x, b_pos.y, m_pos.z + ((b_pos.z - m_pos.z) / 2.0) + (s_h / 2.0)>,
ZERO_VECTOR,
ZERO_ROTATION,
p_encode((b_pos.z - m_pos.z) * bal_h));
//Increment rotation
t += rot(i);
}
}
}
}
Conf_Step
Drop this in a prim named "Step". (Box with x-taper 1.0 is recommended).
default
{
on_rez(integer s)
{
if(s != 0)
{
string d = (string)s;
float y = ((float)llGetSubString(d, 1, 2)) / 100.0;//Height
float z = ((float)llGetSubString(d, 3, 5)) / 10.0;//Radius
float x = ((float)llGetSubString(d, 6, 9)) / 100.0;//Length
llSetScale(<x, y, z>);
llRemoveInventory(llGetScriptName());
}
}
}
Conf_Banister
Drop this in a cylinder named "Banister".
default
{
on_rez(integer s)
{
if(s != 0)
{
string d = (string)s;
float z = ((float)llGetSubString(d, 5, 9)) / 1000.0;//Length
float y = ((float)llGetSubString(d, 1, 4)) / 1000.0;//Diameter
float x = y;
llSetScale(<x, y, z>);
llRemoveInventory(llGetScriptName());
}
}
}
Conf_Baluster
Drop this in a cylinder named "Baluster".
default
{
on_rez(integer s)
{
if(s != 0)
{
string d = (string)s;
float z = ((float)llGetSubString(d, 5, 9)) / 1000.0;//Height
float y = ((float)llGetSubString(d, 1, 4)) / 1000.0;//Diameter
float x = y;
llSetScale(<x, y, z>);
llRemoveInventory(llGetScriptName());
}
}
}