// #!/usr/local/bin/lsl // Talk to display here integer dchan = 997788; // Have each renderer draw this many pixels per call. integer chunksize = 8; // Keep a list of all chunks we've ordered drawn and haven't been drawn yet, so that we can know when a chunk was lost. list chunks; // Size of display integer xsize = 70; integer ysize = 70; // FOV of camera float fov=60; // Max number of reflections integer reflectmax = 8; // FSAA amount (this value is squared) integer fsaa = 6; float bright = 3; // Lamp will listen for "reset" here and say it's coordinates when it moves or hears reset on this chan: integer lampchan = 12367; float timeout = 10; // Timeout before we start rerequesting dropped chunks. // Nothing to update below here! integer x; integer y; integer numrender; integer currender; vector light; // Position of the light source vector mypos; rotation myrot; // shapes! integer OBJ_CUBE = 0; integer OBJ_SPHERE = 1; // Sensor'd data list obj_pos; list obj_rot; list obj_key; list obj_name; list obj_min; //bbox list obj_max; //bbox list obj_color; list obj_reflect; list obj_diffuse; list obj_shape; integer obj_count; integer drawing; list msgs; DEBUG(string msg) { msgs += msg; while (llStringLength(llDumpList2String(msgs,"\n")) > 254) { msgs = llListReplaceList(msgs,[],0,0); } llSetText(llDumpList2String(msgs, "\n"), <1,1,1>,1); } czResetAll() { DEBUG("Resetting all child scripts."); integer m = llGetInventoryNumber(INVENTORY_SCRIPT); integer i; string me = llGetScriptName(); for (i = 0; i < m; i++) { string name = llGetInventoryName(INVENTORY_SCRIPT,i); if (name != me) llResetOtherScript(name); } } integer chunk_pos; string nextchunk() { if (drawing<0 || llGetListLength(chunks) > numrender*2) { integer ch = llList2Integer(chunks,0); chunks = llDeleteSubList(chunks,0,0) + llList2Integer(chunks,0); integer x = ch%xsize; integer y = (ch-x)/xsize; return llList2CSV([x,y,chunksize]); } // else! string chunk = llList2CSV([x,y,chunksize]); chunks += (x + (y*xsize)); x += chunksize; while (x >= xsize) { x -= xsize; y++; if (y >= ysize) { DEBUG("No more chunks to give out..."); llMessageLinked(LINK_SET, 0, "done", NULL_KEY); drawing=-1; llSetTimerEvent(timeout); } } return chunk; } default { state_entry() { //llMessageLinked(LINK_SET, 0, "done", NULL_KEY); llListen(lampchan,"", NULL_KEY,""); // Light source llSetText("", ZERO_VECTOR, 0); llSitTarget(<-1,0,0>, ZERO_ROTATION); llSetCameraEyeOffset(<0,0,0>); llSetCameraAtOffset(<1,0,0>); llShout(lampchan,"reset"); // Get position if (fsaa < 1) fsaa = 1; // Can't be <1 czResetAll(); DEBUG("Ready."); } listen(integer c, string who, key id, string msg) { light = (vector)msg; } touch_start(integer tn) { if (llDetectedKey(0) == llGetOwner()) { if (drawing) { llSay(0,"Drawing already in progress."); return; } llResetTime(); msgs = []; llSensor("", NULL_KEY, PASSIVE, 20, TWO_PI); llSay(0,"Sensing..."); // llTriggerSound("3d09f582-3851-c0e0-f5ba-277ac5c73fb4", 1); llTriggerSound("Reticulating Splines", 1); drawing = 1; } } no_sensor() { llOwnerSay("Nothing sensed, won't draw."); drawing = 0; } sensor(integer tn) { obj_pos = []; obj_rot = []; obj_key = []; obj_name = []; obj_color = []; obj_min = []; obj_max = []; obj_reflect = []; obj_shape = []; obj_count = tn; integer i; for (i = 0; i < tn; i++) { obj_pos += llDetectedPos(i); obj_rot += llDetectedRot(i); obj_key += llDetectedKey(i); obj_name += llDetectedName(i); list bb = llGetBoundingBox(llDetectedKey(i)); obj_min += llList2Vector(bb,0); obj_max += llList2Vector(bb,1); //defaults vector color = llVecNorm(); float reflect = .20; float diffuse = .5; integer shape = OBJ_CUBE; list dat = llParseString2List(llDetectedName(i), ["^"], []); integer datpos; for (datpos = 0; datpos < llGetListLength(dat); datpos++) { string msg = llList2String(dat,datpos); if (msg == "mirror") { color = <.7,.7,.7>; reflect = .5; diffuse = 0; } else if (msg == "checkerboard") { color = <-1,-1,-1>; } else if (llGetSubString(msg,0,5) == "color:") { color = (vector)llGetSubString(msg,6,-1); } else if (llGetSubString(msg,0,7) == "reflect:") { reflect = (float)llGetSubString(msg,8,-1); } else if (llGetSubString(msg,0,7) == "diffuse:") { diffuse = (float)llGetSubString(msg,8,-1); } else if (llGetSubString(msg,0,5) == "shape:") { string shp = llGetSubString(msg,6,-1); if (shp == "cube") { shape = OBJ_CUBE; } else if (shp == "sphere") { shape = OBJ_SPHERE; } } } obj_color += color; obj_reflect += reflect; obj_diffuse += diffuse; obj_shape += shape; } llSay(dchan, "dimensions " + (string)xsize + "," + (string)ysize); myrot = llGetRot(); mypos = llGetPos(); numrender = 0; czResetAll(); llSleep(2.0); DEBUG("Searching for children..."); llMessageLinked(LINK_SET, 0, "getrenderers", NULL_KEY); // Get a count of how many renderers we have. llSetTimerEvent(1.5); } link_message(integer snum, integer num, string msg, key id) { if (num == 0) { if (msg == "amrenderer") { numrender++; llSetTimerEvent(1.5); } } if (msg == "next") { if (!drawing) { // Not drawing, disregard. return; } if (drawing) { // Send out another chunk. string next = nextchunk(); llMessageLinked(LINK_SET, num, "render " + next, NULL_KEY); } if (id != NULL_KEY) { // In case they have no new data. list dat = llParseString2List(id, ["|^|"], []); integer drawnx = (integer)llList2String(dat,0); integer drawny = (integer)llList2String(dat,1); integer cn = drawnx+(drawny*xsize); integer l = llListFindList(chunks, [cn]); if (l != -1) { chunks = llListReplaceList(chunks, [], l, l); llShout(dchan, "draw " + (string)xsize + "|^|" + (string)id); DEBUG("Got update for chunk #" + (string)drawnx + ","+ (string)drawny); } else { DEBUG("Recv dup " + (string)drawnx + ","+ (string)drawny); } if (drawing == -1) { if (!llGetListLength(chunks)) { llSetTimerEvent(0); llTriggerSound("loom intro", 1); DEBUG("Render finished!"); llSay(0,"Render finished in " + (string)llGetTime() + "sec! All chunks accounted for!"); //llMessageLinked(LINK_SET, 0, "done", NULL_KEY); czResetAll(); drawing=0; } else { llSetTimerEvent(5); // Restart the timer. } } } } else if (msg == "DEBUG") { DEBUG((string)(num) + "| " + (string)id); } } timer() { if (drawing == -1) { llSay(0,(string)timeout + " second timeout at end-of-render elapsed. Still missing " +(string)llGetListLength(chunks) + " chunks. Rerequesting..."); currender = 1; integer p; for (p = 0; p < llGetListLength(chunks) && currender <= numrender; p++) { llMessageLinked(LINK_SET, currender, "render " + nextchunk(), NULL_KEY); currender++; } llSetTimerEvent(timeout); return; } llSetTimerEvent(0); DEBUG("Timer expired. Found " + (string)numrender + " children."); DEBUG("Describing scene..."); llMessageLinked(LINK_SET, 0, "info", (key)llDumpList2String([xsize,ysize,myrot,mypos,fov,light,obj_count,dchan,bright,reflectmax,fsaa], "|^|")); llSleep(.1); integer i; for (i = 0; i < obj_count; i++) { llMessageLinked(LINK_SET, 0, "objinfo", (key)llDumpList2String([ llList2Vector(obj_pos,i), llList2Rot(obj_rot,i), llList2Key(obj_key,i), llList2String(obj_name,i), llList2Vector(obj_color,i), llList2Float(obj_reflect,i), llList2Float(obj_diffuse,i), llList2Integer(obj_shape,i), llList2Vector(obj_min,i), llList2Vector(obj_max,i) ], "|^|")); llSleep(0.05); } DEBUG("Children updated. Beginning render."); x=0; y=0; chunks = []; for (currender = 1; currender <= numrender; currender++) { llMessageLinked(LINK_SET, currender, "render " + llList2CSV([x,y,chunksize]), NULL_KEY); chunks += (x + (y*xsize)); x += chunksize; while (x >= xsize) { x -= xsize; y++; } } } }