SHARE
TWEET

Untitled

a guest Sep 11th, 2019 105 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. // OpenAlign 1.1
  3. // Second Life Texture Alignment Script
  4. // Copyright 2008 Edward L. Platt
  5. // SL: Phil Tracy
  6. // E-mail: <elplatt@alum.mit.edu>
  7. //
  8. // This program is free software: you can redistribute it and/or modify
  9. // it under the terms of the GNU General Public License as published by
  10. // the Free Software Foundation, either version 3 of the License, or
  11. // (at your option) any later version.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. // GNU General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU General Public License
  19. // along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20. //
  21. ////////////////////////////////////////////////////////////////////////
  22.  
  23.  
  24. //// GLOBAL VARIABLES ////
  25.  
  26. // Script name in inventory
  27. string SCRIPT_NAME = "OpenAlign";
  28.  
  29. // Channel to listen on
  30. integer LISTEN_CHANNEL = 1;
  31.  
  32. // 1 for debug mode, 0 otherwise
  33. integer DEBUG = 0;
  34.  
  35. // Properties of root
  36. vector rootSize;        // Size
  37. vector rootPos;         // Position
  38. integer rootFaceCount;  // Number of faces
  39. list rootTexScaleList;  // Texture scales (width0,height0,width1...)
  40. vector rootCut;         // Cut
  41.  
  42. //// GLOBAL FUNCTIONS ////
  43.  
  44. // Joins string elements from a list with spaces
  45. // Calculate the modulus of a / b
  46. float mod(float a, float b) {
  47.     return a/b - llFloor(a/b);
  48. }
  49.  
  50. // Broadcast a message on LISTEN_CHANNEL
  51. broadcast(string message) {
  52.     if (DEBUG) {
  53.         llSay(0, message);
  54.     }
  55.     llSay(LISTEN_CHANNEL, message);
  56. }
  57.  
  58. // Get the position, width, and height of the cut faces
  59. list getCutParams(float cutBegin, float cutEnd, rotation q) {
  60.  
  61.     integer beginQuad;  // Quadrant cut begins in
  62.     integer endQuad;    // Quadrant cut ends in
  63.     vector size;        // Size of this object
  64.     vector pos;         // Position of this object
  65.  
  66.     vector beginPos;   // Begin face position
  67.     vector endPos;     // End face position
  68.     vector beginSize;  // Size of begin face
  69.     vector endSize;    // Size of end face
  70.  
  71.     float angle;  // Angle of the face (radians)
  72.  
  73.     // Get size
  74.     size = llList2Vector(llGetPrimitiveParams([PRIM_SIZE]),0);
  75.  
  76.     // Calculate beginning face parameters
  77.     angle = cutBegin * TWO_PI - PI*3.0/4.0;
  78.     float x;
  79.     float y;
  80.  
  81.     // Calculate the dimensions of the beginning face without scaling
  82.     if (cutBegin < 0.25) {
  83.         y = -0.5;
  84.         x = y / llTan(angle);
  85.     } else if (cutBegin >= 0.5 && cutBegin < 0.75) {
  86.         y = 0.5;
  87.         x = y / llTan(angle);
  88.     } else if (cutBegin >= 0.25 && cutBegin < 0.5) {
  89.         x = 0.5;
  90.         y = x * llTan(angle);
  91.     } else {
  92.         x = -0.5;
  93.         y = x * llTan(angle);
  94.     }
  95.  
  96.     // Calculate the width of the beginning face with scaling
  97.     beginSize.x = llSqrt(size.x*size.x * x*x + size.y*size.y * y*y);
  98.  
  99.     // Set the height of the beginning face
  100.     beginSize.y = size.z;
  101.  
  102.     // Calculate beginning face position
  103.     beginPos = <x*size.x/2.0, y*size.y/2.0, 0>;
  104.     beginPos = beginPos * q;
  105.  
  106.     // Calculate end face parameters
  107.     angle = cutEnd * TWO_PI - PI*3.0/4.0;
  108.  
  109.     // Calculate the dimensions of the end face without scaling
  110.     if (cutEnd < 0.25) {
  111.         y = -0.5;
  112.         x = y / llTan(angle);
  113.     } else if (cutEnd >= 0.5 && cutEnd < 0.75) {
  114.         y = 0.5;
  115.         x = y / llTan(angle);
  116.     } else if (cutEnd >= 0.25 && cutEnd < 0.5) {
  117.         x = 0.5;
  118.         y = x * llTan(angle);
  119.     } else {
  120.         x = -0.5;
  121.         y = x * llTan(angle);
  122.     }
  123.  
  124.     // Calculate the width of the end face with scaling
  125.     endSize.x = llSqrt(size.x*size.x * x*x + size.y*size.y * y*y);
  126.  
  127.     // Set the height of the end face
  128.     endSize.y = size.z;
  129.  
  130.     // Calculate beginning face position
  131.     endPos = <x*size.x/2.0, y*size.y/2.0, 0>;
  132.     endPos = endPos * q;
  133.  
  134.     return [beginPos, beginSize, endPos, endSize];
  135. }
  136.  
  137. // Get face list from rotation
  138. list getFaceList(rotation q) {
  139.  
  140.     vector rot;     // Rotation in Euler coordinates
  141.     list faces;     // Indices of faces
  142.     list newFaces;  // Temporary indices of faces
  143.     integer zRot;       // Number of 90 degree Z rotations
  144.     integer yRot;       // Number of 90 degree Y rotations
  145.     integer xRot;       // Number of 90 degree X rotations
  146.  
  147.     // Get Euler coordinates
  148.     rot = llRot2Euler(q);
  149.  
  150.     // Initialize faces
  151.     faces = [0, 1, 2, 3, 4, 5];
  152.  
  153.     // Permute faces according to rotations in Z, Y, X order
  154.  
  155.     // Adjust ranges
  156.     zRot = (integer)llRound(rot.z / PI_BY_TWO);
  157.     yRot = (integer)llRound(rot.y / PI_BY_TWO);
  158.     xRot = (integer)llRound(rot.x / PI_BY_TWO);
  159.     while (zRot < 0) {
  160.         zRot += 4;
  161.     }
  162.     while (yRot < 0) {
  163.         yRot += 4;
  164.     }
  165.     while (xRot < 0) {
  166.         xRot += 4;
  167.     }
  168.  
  169.     // Permute faces for Z rotation
  170.     while (zRot > 0) {
  171.         newFaces = [];
  172.         newFaces += llList2Integer(faces, 0);
  173.         newFaces += llList2Integer(faces, 4);
  174.         newFaces += llList2Integer(faces, 1);
  175.         newFaces += llList2Integer(faces, 2);
  176.         newFaces += llList2Integer(faces, 3);
  177.         newFaces += llList2Integer(faces, 5);
  178.         faces = newFaces;
  179.         zRot--;
  180.     }
  181.  
  182.     // Permute faces for Y rotation
  183.     while (yRot > 0) {
  184.         newFaces = [];
  185.         newFaces += llList2Integer(faces, 4);
  186.         newFaces += llList2Integer(faces, 1);
  187.         newFaces += llList2Integer(faces, 0);
  188.         newFaces += llList2Integer(faces, 3);
  189.         newFaces += llList2Integer(faces, 5);
  190.         newFaces += llList2Integer(faces, 2);
  191.         faces = newFaces;
  192.         yRot--;
  193.     }
  194.  
  195.     // Permute faces for X rotation
  196.     while (xRot > 0) {
  197.         newFaces = [];
  198.         newFaces += llList2Integer(faces, 3);
  199.         newFaces += llList2Integer(faces, 0);
  200.         newFaces += llList2Integer(faces, 2);
  201.         newFaces += llList2Integer(faces, 5);
  202.         newFaces += llList2Integer(faces, 4);
  203.         newFaces += llList2Integer(faces, 1);
  204.         faces = newFaces;
  205.         xRot--;
  206.     }
  207.  
  208.     return faces;
  209. }
  210.  
  211. // Return the object face index of the specified global face
  212. // Faces are specified as "+x", "-y", "cutBegin", "cutEnd", etc.
  213. integer getFace(string face, vector cut, rotation q) {
  214.  
  215.     // Variables representing whether a face is present
  216.     // 1 is present, 0 is not, except for zp=0 which is always present
  217.     integer xp = 1; // +x
  218.     integer xm = 1; // -x
  219.     integer yp = 1; // +y
  220.     integer ym = 1; // -y
  221.     integer zp = 0; // +z
  222.     integer zm = 1; // -z
  223.     integer cb = 1; // cut begin
  224.     integer ce = 1; // cut end
  225.  
  226.     list faces;         // List mapping global faces to object faces
  227.     string mappedFace;  // Local face, after global face rotated
  228.     list faceOrder;     // The order of the faces
  229.  
  230.     // Set face order
  231.     faceOrder = ["+z", "-y", "+x", "+y", "-x", "-z", "cutBegin", "cutEnd"];
  232.  
  233.     // Get face mapping
  234.     faces = getFaceList(q);
  235.  
  236.     // Map face
  237.     if (face == "+z") {
  238.         mappedFace = llList2String(faceOrder, llList2Integer(faces, 0));
  239.     } else if (face == "-y") {
  240.         mappedFace = llList2String(faceOrder, llList2Integer(faces, 1));
  241.     } else if (face == "+x") {
  242.         mappedFace = llList2String(faceOrder, llList2Integer(faces, 2));
  243.     } else if (face == "+y") {
  244.         mappedFace = llList2String(faceOrder, llList2Integer(faces, 3));
  245.     } else if (face == "-x") {
  246.         mappedFace = llList2String(faceOrder, llList2Integer(faces, 4));
  247.     } else if (face == "-z") {
  248.         mappedFace = llList2String(faceOrder, llList2Integer(faces, 5));
  249.     } else {
  250.         mappedFace = face;
  251.     }
  252.  
  253.     // Determine which faces have been cut away
  254.     if (cut.x >= 0.25) {
  255.         ym = 0;
  256.     }
  257.     if (cut.x >= 0.5 || cut.y <= 0.25) {
  258.         xp = 0;
  259.     }
  260.     if (cut.x >= 0.75 || cut.y <= 0.5) {
  261.         yp = 0;
  262.     }
  263.     if (cut.y <= 0.75) {
  264.         xm = 0;
  265.     }
  266.     if (cut.x == 0 && cut.y == 1) {
  267.         cb = 0;
  268.         ce = 0;
  269.     }
  270.  
  271.     // Return face index, -1 if cut away
  272.     if (mappedFace == "+x") {
  273.         if (xp == 0) {
  274.             return -1;
  275.         }
  276.         return zp+ym+xp;
  277.     } else if (mappedFace == "-x") {
  278.         if (xm == 0) {
  279.             return -1;
  280.         }
  281.         return zp+ym+xp+yp+xm;
  282.     } else if (mappedFace == "+y") {
  283.         if (yp == 0) {
  284.             return -1;
  285.         }
  286.         return zp+ym+xp+yp;
  287.     } else if (mappedFace == "-y") {
  288.         if (yp == 0) {
  289.             return -1;
  290.         }
  291.         return zp+ym;
  292.     } else if (mappedFace == "+z") {
  293.         return zp;
  294.     } else if (mappedFace == "-z") {
  295.         return zp+ym+xp+yp+xm+zm;
  296.     } else if (mappedFace == "cutBegin") {
  297.         if (cb == 0) {
  298.             return -1;
  299.         }
  300.         return zp+ym+xp+yp+xm+zm+cb;
  301.     } else if (mappedFace == "cutEnd") {
  302.         if (ce == 0) {
  303.             return -1;
  304.         }
  305.         return zp+ym+xp+yp+xm+zm+cb+ce;
  306.     }
  307.  
  308.     // This should never happen
  309.     return -1;
  310. }
  311.  
  312. // Get local size from global size and rotation
  313. vector getSize(vector size, rotation q) {
  314.  
  315.     list faceList;   // Mapping from global to local faces
  316.     vector newSize;  // Size of <x, y, z> local dimensions
  317.     integer face;    // Temporary face index
  318.  
  319.     // Get face mapping
  320.     faceList = getFaceList(q);
  321.  
  322.     // Get local face for global x dimension
  323.     face = llList2Integer(faceList, 2);
  324.     if (face == 2 || face == 4) {
  325.         newSize.x = size.x;
  326.     }
  327.     if (face == 1 || face == 3) {
  328.         newSize.x = size.y;
  329.     }
  330.     if (face == 0 || face == 5) {
  331.         newSize.x = size.z;
  332.     }
  333.  
  334.     // Get local face for global y dimension
  335.     face = llList2Integer(faceList, 3);
  336.     if (face == 2 || face == 4) {
  337.         newSize.y = size.x;
  338.     }
  339.     if (face == 1 || face == 3) {
  340.         newSize.y = size.y;
  341.     }
  342.     if (face == 0 || face == 5) {
  343.         newSize.y = size.z;
  344.     }
  345.  
  346.     // Get local face for global y dimension
  347.     face = llList2Integer(faceList, 0);
  348.     if (face == 2 || face == 4) {
  349.         newSize.z = size.x;
  350.     }
  351.     if (face == 1 || face == 3) {
  352.         newSize.z = size.y;
  353.     }
  354.     if (face == 0 || face == 5) {
  355.         newSize.z = size.z;
  356.     }
  357.  
  358.     return newSize;
  359. }
  360.  
  361. // Initiates the entire alignment process
  362. align() {
  363.     if (llGetLinkNumber() == 1) {
  364.         // This is the root object, tell the other objects
  365.         // about our position and texture scaling
  366.  
  367.         integer faceCount;  // Number of faces
  368.         vector texScale;    // Texture scaling
  369.         list texScaleList;  // List of texture scales for each face
  370.         list params;        // Primitive params
  371.         vector cut;         // Cut
  372.  
  373.         // Get object parameters
  374.         cut = llList2Vector(llGetPrimitiveParams([PRIM_TYPE]),2);
  375.         faceCount = llGetNumberOfSides();
  376.  
  377.         // Broadcast root parameters
  378.         broadcast("faceCount " + (string)faceCount);
  379.         integer i;
  380.         for (i = 0; i < faceCount; i++) {
  381.             texScale = llGetTextureScale(i);
  382.             broadcast("texScale " + (string)texScale.x + " " + (string)texScale.y);
  383.         }
  384.         broadcast("size " + llList2String(llGetPrimitiveParams([PRIM_SIZE]),0));
  385.         broadcast("cut " + (string)cut);
  386.  
  387.         // Tell children to finish alignment
  388.         broadcast("finish");
  389.     } else {
  390.  
  391.         // Child object, reset root parameters
  392.         rootFaceCount = 0;
  393.         rootTexScaleList = [];
  394.     }
  395. }
  396.  
  397. // Finish alignment by changing this object's properties
  398. finish() {
  399.  
  400.     vector size;          // Size
  401.     vector globalSize;    // Size in global coordiantes
  402.     vector pos;           // Position
  403.     rotation rot;         // Rotation
  404.     vector posOffset;     // Offset between this object and root object
  405.     float rootTexScaleW;  // Texture scale of root object (width)
  406.     float rootTexScaleH;  // Texture scale of root object (height)
  407.     vector cut;           // Cut begin and end (in x and y)
  408.     list cutParams;       // Cut parameters
  409.     list rootCutParams;   // Root cut params
  410.     rotation rootRot;     // Root rotation
  411.     vector rootGlobalSize;  // Root size in global coordinates
  412.  
  413.     vector cutBeginPos;   // Cut begin face position
  414.     vector cutBeginSize;  // Cut begin face size (<width, height, 0>)
  415.     vector cutEndPos;     // Cut end face position
  416.     vector cutEndSize;    // Cut end face size (<width, height, 0>)
  417.  
  418.     vector rootCutBeginPos;   // Root cut begin face position
  419.     vector rootCutBeginSize;  // Root cut begin face size (<width, height, 0>)
  420.     vector rootCutEndPos;     // Root cut end face position
  421.     vector rootCutEndSize;    // Root cut end face size (<width, height, 0>)
  422.  
  423.     integer face;      // Current face index
  424.     integer rootFace;  // Current root face index
  425.     float widthOff;    // Texture W offset
  426.     float heightOff;   // Texture H offset
  427.  
  428.     float tileSize;
  429.     float texScaleW;
  430.     float texScaleH;
  431.  
  432.     vector beginNormal;      // Beginning cut face normal
  433.     vector endNormal;        // End cut face normal
  434.     vector rootBeginNormal;  // Beginning cut face normal for root object
  435.     vector rootEndNormal;    // End cut face normal for root object
  436.     vector cutOffset;        // Offset between two cut faces
  437.     vector cutPlaneOffset;   // Offset in plane of face
  438.  
  439.     // Exit if we are the root object
  440.     if (llGetLinkNumber() == 1) {
  441.         return;
  442.     }
  443.  
  444.     // Get this object's properties
  445.     posOffset = llGetLocalPos();
  446.     pos = llGetPos();
  447.     size = llList2Vector(llGetPrimitiveParams([PRIM_SIZE]),0);
  448.     cut = llList2Vector(llGetPrimitiveParams([PRIM_TYPE]),2);
  449.     rot = llGetRot();
  450.     globalSize = getSize(size, rot);
  451.     rootPos = llGetRootPosition();
  452.     rootRot = llGetRootRotation();
  453.     rootGlobalSize = getSize(rootSize, rootRot);
  454.  
  455.     // Calculate this object's cut parameters
  456.     cutParams = getCutParams(cut.x, cut.y, rot);
  457.     cutBeginPos = pos + llList2Vector(cutParams,0);
  458.     cutBeginSize = llList2Vector(cutParams,1);
  459.     cutEndPos = pos + llList2Vector(cutParams,2);
  460.     cutEndSize = llList2Vector(cutParams,3);
  461.  
  462.     // Calculate root cut parameters
  463.     rootCutParams = getCutParams(rootCut.x, rootCut.y, rootRot);
  464.     rootCutBeginPos = rootPos + llList2Vector(rootCutParams,0);
  465.     rootCutBeginSize = llList2Vector(rootCutParams,1);
  466.     rootCutEndPos = rootPos + llList2Vector(rootCutParams,2);
  467.     rootCutEndSize = llList2Vector(rootCutParams,3);
  468.  
  469.     // Calculate normals using cross product (%)
  470.     beginNormal = llVecNorm((cutBeginPos - pos) % <0,0,cutBeginSize.y>/2.0);
  471.     endNormal = llVecNorm((cutEndPos - pos) % <0,0,-cutEndSize.y/2.0>);
  472.     rootBeginNormal = llVecNorm((rootCutBeginPos - rootPos) % <0,0,rootCutBeginSize.y>/2.0);
  473.     rootEndNormal = llVecNorm((rootCutEndPos - rootPos) % <0,0,-rootCutEndSize.y>/2.0);
  474.  
  475.     // Align -X axis faces
  476.     face = getFace("-x", cut, rot);
  477.     rootFace = getFace("-x", rootCut, rootRot);
  478.     if (face != -1 && rootFace != -1) {
  479.         rootTexScaleW = llList2Float(rootTexScaleList, rootFace*2);
  480.         rootTexScaleH = llList2Float(rootTexScaleList, rootFace*2+1);
  481.  
  482.         tileSize = rootGlobalSize.y / rootTexScaleW;
  483.         texScaleW = rootTexScaleW * globalSize.y / rootGlobalSize.y;
  484.         widthOff = mod(-posOffset.y, tileSize);
  485.  
  486.         tileSize = rootGlobalSize.z / rootTexScaleH;
  487.         texScaleH = rootTexScaleH * globalSize.z / rootGlobalSize.z;
  488.         heightOff = mod(posOffset.z, tileSize);
  489.  
  490.         llOffsetTexture(widthOff, heightOff, face);
  491.         llScaleTexture(texScaleW, texScaleH, face);
  492.     }
  493.  
  494.     // Align +X axis faces
  495.     face = getFace("+x", cut, rot);
  496.     rootFace = getFace("+x", rootCut, rootRot);
  497.     if (face != -1 && rootFace != -1) {
  498.         rootTexScaleW = llList2Float(rootTexScaleList, rootFace*2);
  499.         rootTexScaleH = llList2Float(rootTexScaleList, rootFace*2+1);
  500.  
  501.         tileSize = rootGlobalSize.y / rootTexScaleW;
  502.         texScaleW = rootTexScaleW * globalSize.y / rootGlobalSize.y;
  503.         widthOff = mod(posOffset.y, tileSize);
  504.  
  505.         tileSize = rootGlobalSize.z / rootTexScaleH;
  506.         texScaleH = rootTexScaleH * globalSize.z / rootGlobalSize.z;
  507.         heightOff = mod(posOffset.z, tileSize);
  508.  
  509.         llOffsetTexture(widthOff, heightOff, face);
  510.         llScaleTexture(texScaleW, texScaleH, face);
  511.     }
  512.  
  513.     // Align -Y axis faces
  514.     face = getFace("-y", cut, rot);
  515.     rootFace = getFace("-y", rootCut, rootRot);
  516.     if (face != -1 && rootFace != -1) {
  517.         rootTexScaleW = llList2Float(rootTexScaleList, rootFace*2);
  518.         rootTexScaleH = llList2Float(rootTexScaleList, rootFace*2+1);
  519.  
  520.         tileSize = rootGlobalSize.x / rootTexScaleW;
  521.         texScaleW = rootTexScaleW * globalSize.x / rootGlobalSize.x;
  522.         widthOff = mod(posOffset.x, tileSize);
  523.  
  524.         tileSize = rootGlobalSize.z / rootTexScaleH;
  525.         texScaleH = rootTexScaleH * globalSize.z / rootGlobalSize.z;
  526.         heightOff = mod(posOffset.z, tileSize);
  527.  
  528.         llOffsetTexture(widthOff, heightOff, face);
  529.         llScaleTexture(texScaleW, texScaleH, face);
  530.     }
  531.  
  532.     // Align +Y axis faces
  533.     face = getFace("+y", cut, rot);
  534.     rootFace = getFace("+y", rootCut, rootRot);
  535.     if (face != -1 && rootFace != -1) {
  536.         rootTexScaleW = llList2Float(rootTexScaleList, rootFace*2);
  537.         rootTexScaleH = llList2Float(rootTexScaleList, rootFace*2+1);
  538.  
  539.         tileSize = rootGlobalSize.x / rootTexScaleW;
  540.         texScaleW = rootTexScaleW * globalSize.x / rootGlobalSize.x;
  541.         widthOff = mod(-posOffset.x, tileSize);
  542.  
  543.         tileSize = rootGlobalSize.z / rootTexScaleH;
  544.         texScaleH = rootTexScaleH * globalSize.z / rootGlobalSize.z;
  545.         heightOff = mod(posOffset.z, tileSize);
  546.  
  547.         llOffsetTexture(widthOff, heightOff, face);
  548.         llScaleTexture(texScaleW, texScaleH, face);
  549.     }
  550.  
  551.     // Align -Z axis faces
  552.     face = getFace("-z", cut, rot);
  553.     rootFace = getFace("-z", rootCut, rootRot);
  554.     if (face != -1 && rootFace != -1) {
  555.         rootTexScaleW = llList2Float(rootTexScaleList, rootFace*2);
  556.         rootTexScaleH = llList2Float(rootTexScaleList, rootFace*2+1);
  557.  
  558.         tileSize = rootGlobalSize.x / rootTexScaleW;
  559.         texScaleW = rootTexScaleW * globalSize.x / rootGlobalSize.x;
  560.         widthOff = mod(posOffset.x, tileSize);
  561.  
  562.         tileSize = rootGlobalSize.y / rootTexScaleH;
  563.         texScaleH = rootTexScaleH * globalSize.y / rootGlobalSize.y;
  564.         heightOff = mod(-posOffset.y, tileSize);
  565.  
  566.         llOffsetTexture(widthOff, heightOff, face);
  567.         llScaleTexture(texScaleW, texScaleH, face);
  568.     }
  569.  
  570.     // Align +Z axis faces
  571.     face = getFace("+z", cut, rot);
  572.     rootFace = getFace("+z", rootCut, rootRot);
  573.     if (face != -1 && rootFace != -1) {
  574.         rootTexScaleW = llList2Float(rootTexScaleList, rootFace*2);
  575.         rootTexScaleH = llList2Float(rootTexScaleList, rootFace*2+1);
  576.  
  577.         tileSize = rootGlobalSize.x / rootTexScaleW;
  578.         texScaleW = rootTexScaleW * globalSize.x / rootGlobalSize.x;
  579.         widthOff = mod(posOffset.x, tileSize);
  580.  
  581.         tileSize = rootGlobalSize.y / rootTexScaleH;
  582.         texScaleH = rootTexScaleH * globalSize.y / rootGlobalSize.y;
  583.         heightOff = mod(posOffset.y, tileSize);
  584.  
  585.         llOffsetTexture(widthOff, heightOff, face);
  586.         llScaleTexture(texScaleW, texScaleH, face);
  587.     }
  588.  
  589.     // Align cut beginning
  590.     face = getFace("cutBegin", cut, rot);
  591.     if (face != -1 && rootFace != -1) {
  592.  
  593.         // Compare to root cut begin face
  594.         rootFace = getFace("cutBegin", rootCut, rootRot);
  595.         cutOffset = cutBeginPos - rootCutBeginPos;
  596.         if (rootFace != -1
  597.                 && llFabs(beginNormal * rootBeginNormal) > 0.9999) {
  598.  
  599.             // Calculate W and H offset for face
  600.             cutPlaneOffset.y = cutOffset.z;
  601.             cutPlaneOffset.x = llVecMag(cutOffset - <0,0,cutOffset.z>);
  602.             if (((cutOffset - <0,0,cutOffset.z>) % rootBeginNormal) * <0,0,1> > 0) {
  603.                 cutPlaneOffset.x = cutPlaneOffset.x * -1;
  604.             }
  605.  
  606.             rootTexScaleW = llList2Float(rootTexScaleList, rootFace*2);
  607.             rootTexScaleH = llList2Float(rootTexScaleList, rootFace*2+1);
  608.  
  609.             tileSize = rootCutBeginSize.x / rootTexScaleW;
  610.             texScaleW = rootTexScaleW * cutBeginSize.x / rootCutBeginSize.x;
  611.             widthOff = mod(cutPlaneOffset.x, tileSize);
  612.  
  613.             tileSize = rootCutBeginSize.y / rootTexScaleH;
  614.             texScaleH = rootTexScaleH * cutBeginSize.y / rootCutBeginSize.y;
  615.             heightOff = mod(cutPlaneOffset.y, tileSize);
  616.  
  617.             llOffsetTexture(widthOff, heightOff, face);
  618.             llScaleTexture(texScaleW, texScaleH, face);
  619.         }
  620.  
  621.         // Compare to root cut end face
  622.         rootFace = getFace("cutEnd", rootCut, rootRot);
  623.         cutOffset = cutBeginPos - rootCutEndPos;
  624.         if (rootFace != -1
  625.                 && llFabs(beginNormal * rootEndNormal) > 0.9999) {
  626.  
  627.             // Calculate W and H offset for face
  628.             cutPlaneOffset.y = cutOffset.z;
  629.             cutPlaneOffset.x = llVecMag(cutOffset - <0,0,cutOffset.z>);
  630.             if (((cutOffset - <0,0,cutOffset.z>) % rootEndNormal) * <0,0,1> > 0) {
  631.                 cutPlaneOffset.x = cutPlaneOffset.x * -1;
  632.             }
  633.  
  634.             rootTexScaleW = llList2Float(rootTexScaleList, rootFace*2);
  635.             rootTexScaleH = llList2Float(rootTexScaleList, rootFace*2+1);
  636.  
  637.             tileSize = rootCutEndSize.x / rootTexScaleW;
  638.             texScaleW = rootTexScaleW * cutBeginSize.x / rootCutEndSize.x;
  639.             widthOff = mod(cutPlaneOffset.x, tileSize);
  640.  
  641.             tileSize = rootCutEndSize.y / rootTexScaleH;
  642.             texScaleH = rootTexScaleH * cutBeginSize.y / rootCutEndSize.y;
  643.             heightOff = mod(cutPlaneOffset.y, tileSize);
  644.  
  645.             llOffsetTexture(widthOff, heightOff, face);
  646.             llScaleTexture(texScaleW, texScaleH, face);
  647.  
  648.         }
  649.     }
  650.  
  651.     // Align cut end
  652.     face = getFace("cutEnd", cut, rot);
  653.     if (face != -1) {
  654.         // Compare to root cut begin face
  655.         rootFace = getFace("cutBegin", rootCut, rootRot);
  656.         cutOffset = cutEndPos - rootCutBeginPos;
  657.         if (rootFace != -1
  658.                 && llFabs(endNormal * rootBeginNormal) > 0.9999) {
  659.  
  660.             // Calculate W and H offset for face
  661.             cutPlaneOffset.y = cutOffset.z;
  662.             cutPlaneOffset.x = llVecMag(cutOffset - <0,0,cutOffset.z>);
  663.             if (((cutOffset - <0,0,cutOffset.z>) % rootBeginNormal) * <0,0,1> > 0) {
  664.                 cutPlaneOffset.x = cutPlaneOffset.x * -1;
  665.             }
  666.  
  667.             rootTexScaleW = llList2Float(rootTexScaleList, rootFace*2);
  668.             rootTexScaleH = llList2Float(rootTexScaleList, rootFace*2+1);
  669.  
  670.             tileSize = rootCutBeginSize.x / rootTexScaleW;
  671.             texScaleW = rootTexScaleW * cutEndSize.x / rootCutBeginSize.x;
  672.             widthOff = mod(cutPlaneOffset.x, tileSize);
  673.  
  674.             tileSize = rootCutBeginSize.y / rootTexScaleH;
  675.             texScaleH = rootTexScaleH * cutEndSize.y / rootCutBeginSize.y;
  676.             heightOff = mod(cutPlaneOffset.y, tileSize);
  677.  
  678.             llOffsetTexture(widthOff, heightOff, face);
  679.             llScaleTexture(texScaleW, texScaleH, face);
  680.         }
  681.  
  682.         // Compare to root cut end face
  683.         rootFace = getFace("cutEnd", rootCut, rootRot);
  684.         cutOffset = cutEndPos - rootCutEndPos;
  685.         if (rootFace != -1
  686.                 && llFabs(endNormal * rootEndNormal) > 0.9999) {
  687.  
  688.             // Calculate W and H offset for face
  689.             cutPlaneOffset.y = cutOffset.z;
  690.             cutPlaneOffset.x = llVecMag(cutOffset - <0,0,cutOffset.z>);
  691.             if (((cutOffset - <0,0,cutOffset.z>) % rootEndNormal) * <0,0,1> > 0) {
  692.                 cutPlaneOffset.x = cutPlaneOffset.x * -1;
  693.             }
  694.  
  695.             rootTexScaleW = llList2Float(rootTexScaleList, rootFace*2);
  696.             rootTexScaleH = llList2Float(rootTexScaleList, rootFace*2+1);
  697.  
  698.             tileSize = rootCutEndSize.x / rootTexScaleW;
  699.             texScaleW = rootTexScaleW * cutEndSize.x / rootCutEndSize.x;
  700.             widthOff = mod(cutPlaneOffset.x, tileSize);
  701.  
  702.             tileSize = rootCutEndSize.y / rootTexScaleH;
  703.             texScaleH = rootTexScaleH * cutEndSize.y / rootCutEndSize.y;
  704.             heightOff = mod(cutPlaneOffset.y, tileSize);
  705.  
  706.             llOffsetTexture(widthOff, heightOff, face);
  707.             llScaleTexture(texScaleW, texScaleH, face);
  708.        }
  709.     }
  710. }
  711.  
  712. // Remove the script from this object
  713. remove() {
  714.     llSay(0, "Removing OpenAlign script by Phil Tracy");
  715.     llRemoveInventory(SCRIPT_NAME);
  716. }
  717.  
  718.  
  719. //// DEFAULT STATE SCRIPT ////
  720. default
  721. {
  722.  
  723.     // Initialize state
  724.     state_entry()
  725.     {
  726.         // Set up a listener on LISTEN_CHANNEL
  727.         llListen(LISTEN_CHANNEL,"",NULL_KEY,"");
  728.     }
  729.  
  730.     // Called when there is a message on LISTEN_CHANNEL
  731.     listen(integer channel, string name, key id, string message) {
  732.  
  733.         // Make sure we're on the right channel
  734.         if (channel != LISTEN_CHANNEL) {
  735.             return;
  736.         }
  737.  
  738.         // Split message into the first word and the rest
  739.         integer space = llSubStringIndex(message, " ");
  740.         string cmd;
  741.         string rest;
  742.         if (space != -1) {
  743.             cmd = llGetSubString(message, 0, space - 1);
  744.             rest = llGetSubString(message, space + 1, -1);
  745.         } else {
  746.             cmd = message;
  747.         }
  748.  
  749.         // Read and execute commands for children
  750.         if (llGetLinkNumber() != 1) {
  751.             if (cmd == "texScale") {
  752.                 space = llSubStringIndex(rest, " ");
  753.                 rootTexScaleList += (float)llGetSubString(rest, 0, space - 1);
  754.                 rootTexScaleList += (float)llGetSubString(rest, space + 1, -1);
  755.             } else if (cmd == "align") {
  756.                 align();
  757.             } else if (cmd == "faceCount") {
  758.                 rootFaceCount = (integer)rest;
  759.             } else if (cmd == "size") {
  760.                 rootSize = (vector)rest;
  761.             } else if (cmd == "finish") {
  762.                 finish();
  763.             } else if (cmd == "cut") {
  764.                 rootCut = (vector)rest;
  765.             }
  766.         }
  767.  
  768.         // All objects handle these commands
  769.         if (cmd == "align") {
  770.             align();
  771.         } else if (cmd == "remove") {
  772.             remove();
  773.         }
  774.     }
  775. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top