# User:Dora Gustafson/wind motor core

## Wind motor core

#### For use in virtual sailboats in SL

This wind motor uses four vectors to calculate boat velocity:

1. v: boat velocity
2. wind: wind velocity, direction at wind's eye
4. n: sail normal, normalized vector. It doesn't matter which one of two normals is used

The tricky thing in a wind motor is that v is a function of v and it can not be isolated
Therefor v is calculated by iteration, i.e. repeated calculations using the previous result
Notes

1. head and n are normalized vectors
2. It does not matter if the positive or negative sail normal n is used in the equation
3. wind is pointing the wind's eye so the wind blows opposite. Thus the minus sign in the equation
4. The magnitude of wind is the wind speed
5. The magnitude of v is the boat speed

#### A working LSL script based on this core

```// wind motor core, minimal sailboat script by Dora Gustafson, Studio Dora 2016
// use a two prim object: root prim for hull and child prim for sail
// enter this script, rez on water, sit and sail
// up, down arrows for setting sail
// left, right arrows for steering

vector windVector = <.0, 9.0, .0>; // wind from north, 9 m/S
float WindFactor = 12.0; // m/S
float heelFactor = .3;
float threeDEG = 0.052360; // 3°
float MAXSAIL = 1.48353; // 85°
float MINSAIL = 0.174533; // 10°
float sailAngle;
vector linear_motor;
vector angular_motor;
integer sailPrim = 2;
integer hullPrim = 1;
float time = 4.0;
vector blue = <0.0, 0.455, 0.851>;
vector green = <0.18, 0.8, 0.251>;
vector yellow = <1.0, 0.863, 0.0>;
vector red = <1.0, 0.255, 0.212>;

default
{
state_entry()
{
llSetVehicleType(VEHICLE_TYPE_BOAT);
llSetVehicleFloatParam( VEHICLE_HOVER_HEIGHT, 0.001 );
llSetVehicleFloatParam( VEHICLE_BANKING_EFFICIENCY, 0.0 );
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE, .75); // default 4
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 1); // default 0.5
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_TIMESCALE, .5); // default 3
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0); // default 0.5
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, .5); // default 5
llSitTarget( <-1.5, .0, 1.25>, ZERO_ROTATION);
sailAngle = MAXSAIL;
}
changed(integer change)
{
{
key sitter = llAvatarOnSitTarget() ;
if(sitter != NULL_KEY)
{
llSetStatus( STATUS_PHYSICS, TRUE);
llRequestPermissions( sitter, PERMISSION_TAKE_CONTROLS);
llSetTimerEvent( time);
}
else
{
llSetStatus( STATUS_PHYSICS, FALSE);
llReleaseControls();
llSetTimerEvent( .0);
}
}
}
run_time_permissions(integer perm)
{
if ( perm & PERMISSION_TAKE_CONTROLS ) llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);
}
control(key id, integer level, integer edge)
{
if ( edge & level & ( CONTROL_FWD | CONTROL_BACK) )
{
if ( edge & level & CONTROL_FWD )
{
if ( sailAngle + threeDEG < MAXSAIL ) sailAngle += threeDEG;
}
else if ( edge & level & CONTROL_BACK)
{
if ( sailAngle - threeDEG > MINSAIL ) sailAngle -= threeDEG;
}
llSetTimerEvent( 0.05);
}
else
{
if ( level & (CONTROL_ROT_RIGHT)) angular_motor.z = 0.8;
else if ( level & (CONTROL_ROT_LEFT)) angular_motor.z = -0.8;
else angular_motor.z = 0.0;
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor);
}
}
timer()
{
if ( llGetStatus( STATUS_PHYSICS) )
{
// vector capture
rotation sailRot = llGetRot();
vector left = llRot2Left( sailRot);
vector velocity = llGetVel();
float speed = llVecMag( velocity);
vector Aw = windVector + velocity;
Aw.z = 0.0;
vector nAw = llVecNorm( Aw);
vector axs = heading%nAw; // up or down axis to turn sail around
float AwAngle = llAcos( heading*nAw); // apparent wind, local angle [0;PI]
// setting sail
float setsail = AwAngle;
if ( setsail > sailAngle ) setsail = sailAngle;
sailRot = llAxisAngle2Rot( axs, setsail);
vector sailnormal = llRot2Left( sailRot)*llGetRot(); // Global
// Linear and Angular Motors
vector action = ZERO_VECTOR;
if ( llFabs( sailnormal*nAw) > MINSAIL ) action = -(sailnormal*Aw)*sailnormal;
llSetVehicleVectorParam( VEHICLE_LINEAR_MOTOR_DIRECTION, linear_motor);
// heel by wind
angular_motor.x = -heelFactor*action*left;
llSetVehicleVectorParam( VEHICLE_ANGULAR_MOTOR_DIRECTION, angular_motor);
llSetTimerEvent( time);
// optional signal color
vector color = red;
if ( sailAngle < 0.435*AwAngle ) color = blue;
else if ( sailAngle < 0.565*AwAngle ) color = green;
else if ( sailAngle < 0.825*AwAngle ) color = yellow;