Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. --3D-Palette viewer V0.72 (HSL-models added, 3D-World added, Pen-color only cycles thru unique colors, InputBox)
  2. --by Richard 'Dawnbringer' Fhager
  3.  
  4. -- Mouse:       Rotate Cube (Stops animation)
  5. -- Arrow-keys:  Move Cube (in 3D world)
  6. -- F1:          Start/Stop animation
  7. -- F2:          Reset
  8. -- F3:          Increase Color-Size
  9. -- F4:          Decrease Color-Size
  10. -- F5:          (Wip) Cycle thru selected PenColor (Note that only unique colors are displayed)
  11. -- F9:          RGB-space model
  12. --F10:          HSL-space model
  13. --F11:          HSLcubic-space model
  14. -- "+" (Num):   Zoom In
  15. -- "-" (Num):   Zoom Out
  16. -- Esc:         Exit script
  17.  
  18. -- Drawing updated, rectangle missing, Sep11
  19.  
  20. run("../libs/dawnbringer_lib.lua")
  21.  
  22.  
  23. BRIDIAG_SHOW = 1     -- Show brightness/Grayscale diagonal (1 = on, 0 = off)
  24. ANIM         = 1     -- Animation (1 = on, 0 = off)
  25. BOX_DRK      = 8     -- Darkest   color used for box (0-255)
  26. BOX_BRI      = 112   -- Brightest color used for box (0-255)
  27. COLSIZE_BASE = 26    -- Colors base size (value to adjusted by palette-size, with 2 cols maxsize is v / 1.23)
  28.  
  29. --
  30. OK,RGB,HSL,HSLC,BOX_BRI,COLSIZE_BASE,SET800x600 = inputbox("3D-Palette Viewer Settings",
  31.                        
  32.                            "1. RGB space [F9]",       1,  0,1,-1,
  33.                            "2. HSL space [F10]",      0,  0,1,-1,
  34.                            "3. HSL-cubic space [F11]",0,  0,1,-1,
  35.                            "Box Brightness (16-255)", BOX_BRI,   16,255,0,  
  36.                            "Col Size (1-100) [F3/F4]", COLSIZE_BASE,   1,100,0,                    
  37.                            "Set Screen to 800x600",      1,0,1,0
  38.                                                                        
  39. );
  40. --
  41.  
  42. if OK then
  43.  
  44.  if SET800x600 == 1 then setpicturesize(800,600); end
  45.  
  46.  SPACE = "rgb"
  47.  FORM  = "cube"
  48.  if HSL == 1 then
  49.   SPACE = "hsl"
  50.   FORM  = "cylinder"
  51.  end
  52.  if HSLC == 1 then
  53.   SPACE = "hsl_cubic"
  54.   FORM  = "cube"
  55.  end
  56.  
  57.  
  58. pal = db.fixPalette(db.makePalList(256))
  59.  
  60. FG = getforecolor()
  61. BG = getbackcolor()
  62.  
  63. palcol = FG
  64.  
  65. --
  66. function initColors(space)
  67.   for n = 1, #pal, 1 do
  68.    c = pal[n];
  69.    if space == "rgb" then
  70.    cols[n] = {c[1]/128-1,c[2]/128-1,c[3]/128-1,c[4]};
  71.   end
  72.   if space == "hsl_cubic" then
  73.    cols[n] = {}
  74.    cols[n][1] = (db.getHUE(c[1],c[2],c[3],0) / 6.0 * 255) / 128 - 1
  75.    cols[n][2] = (db.getSaturation(c[1],c[2],c[3])) / 128 - 1
  76.    cols[n][3] = (db.getLightness(c[1],c[2],c[3])) / 128 - 1
  77.    cols[n][4] = c[4]
  78.   end
  79.   if space == "hsl" then
  80.    cols[n] = {}
  81.    hue = db.getHUE(c[1],c[2],c[3],0) / 6.0 * math.pi*2
  82.    rad = db.getSaturation(c[1],c[2],c[3]) / 256
  83.    cols[n][1] = math.cos(hue) * rad
  84.    cols[n][2] = math.sin(hue) * rad
  85.    cols[n][3] = (db.getLightness(c[1],c[2],c[3])) / 128 - 1
  86.    cols[n][4] = c[4]
  87.   end
  88.  end
  89. end
  90. --
  91.  
  92. cols = {} -- Make points of palette colors
  93. colz = {} -- To hold calculated points
  94. initColors(SPACE)
  95.  
  96.  
  97. function initPointsAndLines(form,bridiag)
  98.  if form == "cube" then
  99.   pts = {{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1}, -- The box
  100.         {-1,1, 1},{1,1, 1},{1,-1, 1},{-1,-1, 1}}
  101.   lin = {{1,2},{2,3},{3,4},{4,1},{5,6},{6,7},{7,8},{8,5},{1,5},{2,6},{3,7},{4,8}} -- Box Lines
  102.   if bridiag == 1 then lin[13] = {4,6}; end
  103.  end
  104.  if form == "cylinder" then
  105.   p = 28
  106.   pts = {}
  107.   lin = {}
  108.   for n = 1, p, 1 do
  109.    x = math.cos(math.pi*2 / p * (n-1))
  110.    y = math.sin(math.pi*2 / p * (n-1))
  111.    pts[n] = {x,y,-1}
  112.    lin[n] = {n,1 + (n%p)}
  113.    pts[n + p] = {x,y,1}
  114.    lin[n + p] = {n+p,p + 1 + (n%p)}
  115.   end
  116.   lin[p*2+1] = {1,p+1} -- Red (0 degrees)
  117.   lin[p*2+2] = {p+1,p+1+math.ceil(p/2)} -- Lightness end (needs an even # of points to work)
  118.  end
  119. end
  120.  
  121. boxp = {} -- To hold the calculated points
  122. initPointsAndLines(FORM,BRIDIAG_SHOW)
  123.  
  124. w,h = getpicturesize()
  125. CX,CY = w/2, h/2
  126.  
  127.  
  128.  
  129. function initAndReset()
  130.  XANG, YANG, ZANG, ZOOM, COLSIZE_ADJ, XD, YD, WORLD_X, WORLD_Y, ZSELECT = 0,0,0,0,0,0,0,0,0,0
  131. end
  132.  
  133. initAndReset()
  134.  
  135. SIZE = math.min(w,h)/4
  136. DIST = 5 -- Distance perspective modifier, ~5 is nominal, more means "less 3D"
  137.  
  138. CMAXSIZE = math.floor(COLSIZE_BASE / ((#pal)^0.3))
  139. --CMAXSIZE = 8
  140. CMINSIZE = 1 -- Negative values are ok. Color are never smaller than 1 pix
  141.  
  142. BOX_LINE_DIV = 20 -- Number of colors/segments that a box-line can be divided into (depth)
  143. BOX_DIV_MULT = BOX_LINE_DIV / (math.sqrt(3)*2)
  144.  
  145. -- Box depth colors
  146. box_div = {}
  147. for n = 0, BOX_LINE_DIV-1, 1 do
  148.  c = BOX_DRK + (BOX_BRI / (BOX_LINE_DIV - 1)) * n
  149.  --box_div[BOX_LINE_DIV - n] = matchcolor(c,c,c)
  150.  box_div[BOX_LINE_DIV - n] = db.getBestPalMatchHYBRID({c,c,c},pal,0.5,true)
  151. end
  152.  
  153. --BOX_COL = matchcolor(80,80,80)
  154. BKG_COL = matchcolor(0,0,0)
  155. --CUR_COL = matchcolor(112,112,112)
  156.  
  157.  
  158.  function rotate3D(x,y,z,Xsin,Ysin,Zsin,Xcos,Ycos,Zcos) -- PrecCalced cos&sin for speed
  159.  
  160.    local x1,x2,x3,y1,y2,y3,f,xp,yp
  161.  
  162.     x1 = x
  163.     y1 = y * Xcos + z * Xsin
  164.     z1 = z * Xcos - y * Xsin
  165.  
  166.     x2 = x1 * Ycos - z1 * Ysin
  167.     y2 = y1
  168.     z2 = x1 * Ysin + z1 * Ycos
  169.  
  170.     x3 = x2 * Zcos - y2 * Zsin
  171.     y3 = x2 * Zsin + y2 * Zcos
  172.     z3 = z2
  173.  
  174.     return x3,y3,z3
  175.   end
  176.  
  177.  function do3D(x,y,z,zoom,dist,Xsin,Ysin,Zsin,Xcos,Ycos,Zcos) -- PrecCalced cos&sin for speed
  178.  
  179.    local x1,x2,x3,y1,y2,y3,f,xp,yp
  180.  
  181.     x1 = x
  182.     y1 = y * Xcos + z * Xsin
  183.     z1 = z * Xcos - y * Xsin
  184.  
  185.     x2 = x1 * Ycos - z1 * Ysin
  186.     y2 = y1
  187.     z2 = x1 * Ysin + z1 * Ycos
  188.  
  189.     x3 = x2 * Zcos - y2 * Zsin
  190.     y3 = x2 * Zsin + y2 * Zcos
  191.     z3 = z2
  192.  
  193.     f = dist/(z3 + dist + zoom)
  194.     xp = x3 * f
  195.     yp = y3 * f
  196.  
  197.     return xp,yp,z3
  198.   end
  199.  
  200.  
  201. function draw3Dline(x1,y1,z1,x2,y2,z2,div,mult,depthlist)
  202.    local s,xt,yt,xd,yd,zd,xf,yf
  203.    xd = (x2 - x1) / div
  204.    yd = (y2 - y1) / div
  205.    zd = (z2 - z1) / div
  206.    xf,yf = x1,y1
  207.  
  208.   for s = 1, div, 1 do
  209.     -- Depth assumes a 1-Box (z ranges from -sq(3) to sq(3))
  210.     depth = math.floor(1 + (z1+zd*s + 1.732) * mult)
  211.     xt = x1 + xd*s -- + math.random()*8
  212.     yt = y1 + yd*s -- + math.random()*8
  213.     c = depthlist[depth]
  214.     if c == null then c = 1; end -- Something isn't perfect, error is super rare but this controls it
  215.     --db.line(xf,yf,xt,yt,c)
  216.     drawline(xf,yf,xt,yt,c)
  217.     xf = xt
  218.     yf = yt
  219.   end
  220. end
  221.  
  222. function killinertia()
  223.  XD = 0
  224.  YD = 0
  225. end
  226.  
  227.  -- If using 1-box, z is -sq(3) to sq(3)
  228.  minz = math.sqrt(3)
  229.  totz = minz * 2
  230.  maxrad = CMAXSIZE - CMINSIZE
  231.  
  232. --q = 0
  233. --delay = 4
  234. --move = 0.03
  235.  
  236. while 1 < 2 do
  237.  
  238.  -- Time-for-space-wiggle...or somekindof attempt
  239.  --WORLD_X = -move
  240.  --q = (q + 1) % delay
  241.  --if q < delay/2 then WORLD_X = move; end
  242.  
  243.  clearpicture(BKG_COL)
  244.  
  245.  Xsin = math.sin(XANG); Xcos = math.cos(XANG)
  246.  Ysin = math.sin(YANG); Ycos = math.cos(YANG)
  247.  Zsin = math.sin(ZANG); Zcos = math.cos(ZANG)
  248.  
  249.  -- Rotate Box points
  250.  for n = 1, #pts, 1 do
  251.   p = pts[n]
  252.   x,y,z = p[1],p[2],p[3]
  253.   XP,YP,zp = rotate3D(x,y,z,Xsin,Ysin,Zsin,Xcos,Ycos,Zcos)
  254.   boxp[n] = {XP,YP,zp}
  255.  end
  256.  
  257.  -- Rotate Colors in palette
  258.  for n = 1, #cols, 1 do
  259.   p = cols[n]
  260.   x,y,z,c = p[1],p[2],p[3],p[4]
  261.   XP,YP,zp = rotate3D(x,y,z,Xsin,Ysin,Zsin,Xcos,Ycos,Zcos)
  262.   colz[n] = {XP,YP,zp,c}
  263.  end
  264.  
  265.  ------------------------------------
  266.  -- Control world
  267.  ------------------------------------
  268.  
  269.   -- Calculate points anew
  270.  
  271.  -- Worldize Box points
  272.  for n = 1, #boxp, 1 do
  273.   s = SIZE
  274.   v = boxp[n]
  275.   x = v[1] + WORLD_X
  276.   y = v[2] + WORLD_Y
  277.   z = v[3]
  278.   f = DIST/(z + DIST + ZOOM)
  279.   XP = CX + x * f * s
  280.   YP = CY + y * f * s
  281.   boxp[n] = {XP,YP,z}
  282.  end
  283.  
  284.  -- Worldize Colors in palette
  285.  for n = 1, #colz, 1 do
  286.   s = SIZE
  287.   v = colz[n]
  288.   x = v[1] + WORLD_X
  289.   y = v[2] + WORLD_Y
  290.   z = v[3]
  291.   c = v[4]
  292.   f = DIST/(z + DIST + ZOOM)
  293.   XP = CX + x * f * s
  294.   YP = CY + y * f * s
  295.   colz[n] = {XP,YP,z,c}
  296.  end
  297.  
  298.  
  299. -------------------------------------
  300. -------------------------------------
  301.  
  302.  -- Brightness Diagonal
  303.  --if BRIDIAG_SHOW == 1 then
  304.  -- p1 = boxp[4]
  305.  -- p2 = boxp[6]
  306.  -- x1,y1,z1 = p1[1],p1[2],p1[3]
  307.  -- x2,y2,z2 = p2[1],p2[2],p2[3]
  308.  -- draw3Dline(x1,y1,z1,x2,y2,z2,BOX_LINE_DIV,BOX_DIV_MULT,box_div)
  309.  --end
  310.  
  311.   --c1 = math.min(FG,BG)
  312.   --c2 = math.max(FG,BG)
  313.   --p = colz[26]
  314.   --XP1,YP1,zp1,c1 = p[1],p[2],p[3],p[4]
  315.   --for n = #colz, 1, -1 do
  316.   -- p = colz[27]
  317.   -- XP2,YP2,zp2,c2 = p[1],p[2],p[3],p[4]
  318.   -- drawline(XP1,YP1,XP2,YP2,c1)
  319.   --end
  320.  
  321.  -- sort on z
  322.  db.sorti(colz,3)
  323.  
  324.  -- Draw colors
  325.  for n = #colz, 1, -1 do
  326.   p = colz[n]
  327.   XP,YP,zp,c = p[1],p[2],p[3],p[4]
  328.  
  329.   radius = CMINSIZE + maxrad - (zp+minz) / totz * maxrad
  330.   dorad = math.floor(radius - ZOOM*2 +  COLSIZE_ADJ)
  331.  
  332.   if dorad >= 1 then
  333.    --db.drawCircle(XP,YP,dorad,c)
  334.    drawdisk(XP,YP,dorad,c)
  335.    --db.drawRectangle(XP,YP,dorad,dorad,c)
  336.    else putpicturepixel(XP,YP,c)
  337.   end
  338.  
  339.   if c == FG or c == BG then
  340.    sz = math.max(3,dorad + 3)
  341.    if c == BKG_COL then v = (c+128) % 255; c = matchcolor(v,v,v); end
  342.    db.drawRectangleLine(XP-sz,YP-sz,sz*2,sz*2,c)
  343.   end
  344.  
  345.  end -- colz
  346.  
  347.  
  348.  
  349.  -- Draw box
  350.  for n = 1, #lin, 1 do
  351.  
  352.   l = lin[n]
  353.   p1 = boxp[l[1]]
  354.   p2 = boxp[l[2]]
  355.   x1,y1,z1 = p1[1],p1[2],p1[3]
  356.   x2,y2,z2 = p2[1],p2[2],p2[3]
  357.   draw3Dline(x1,y1,z1,x2,y2,z2,BOX_LINE_DIV,BOX_DIV_MULT,box_div)
  358.  
  359.  end -- eof box
  360.  
  361.  --updatescreen(); if (waitbreak(0.00)==1) then return; end
  362.  
  363.  repeat
  364.  
  365.     old_key = key;
  366.     old_mouse_x = mouse_x;
  367.     old_mouse_y = mouse_y;
  368.     old_mouse_b = mouse_b;
  369.    
  370.     updatescreen()
  371.  
  372.     moved, key, mouse_x, mouse_y, mouse_b = waitinput(0)
  373.    
  374.     if mouse_b == 1 then ANIM = 0; end
  375.  
  376.     if (key==27) then
  377.        return;
  378.     end
  379.  
  380.     if (key==282) then  ANIM = (ANIM+1) % 2;  end -- F1: Stop/Start Animation
  381.     if (key==283) then  initAndReset();       end -- F2: Reset all values
  382.     if (key==284) then  COLSIZE_ADJ = COLSIZE_ADJ + 0.5;       end -- F3
  383.     if (key==285) then  COLSIZE_ADJ = COLSIZE_ADJ - 0.5;       end -- F4
  384.  
  385.    --messagebox(key)
  386.  
  387.     if (key==286) then  
  388.       --FG = (FG + 1) % 255;
  389.       palcol = (palcol + 1) % #pal
  390.       FG = pal[palcol+1][4]
  391.       setforecolor(FG);
  392.       setcolor(0,getcolor(0))  -- Force update of palette until setforecolor() is fixed
  393.      end -- F5
  394.  
  395.     if (key==290) then -- F9
  396.      initColors("rgb")
  397.      initPointsAndLines("cube",BRIDIAG_SHOW)
  398.     end
  399.     if (key==291) then -- F10
  400.      initColors("hsl")
  401.      initPointsAndLines("cylinder", 0) -- Bridiag won't show even if turned on, it's only for cube
  402.     end
  403.     if (key==292) then -- F11
  404.      initColors("hsl_cubic")
  405.      initPointsAndLines("cube",BRIDIAG_SHOW)
  406.     end
  407.  
  408.     if (key==269) then  ZOOM = ZOOM + 0.1;  end
  409.     if (key==270) then  ZOOM = ZOOM - 0.1;  end
  410.  
  411.     if (key==32) then  
  412.        ZSELECT = (ZSELECT + math.pi/2) % (2*math.pi);  
  413.        --YANG = ((YANG - math.pi/2) % (math.pi*2));
  414.        --XANG = ((XANG + math.pi/2) % (math.pi*2));
  415.    
  416.  
  417.       YANG = ((YANG + math.pi/2) % (math.pi*2));
  418.       XANG = ((XANG + math.pi/2) % (math.pi*2));
  419.       YANG = ((YANG - math.pi/2) % (math.pi*2));
  420.     end -- Rotate Z 90 Degrees
  421.  
  422.     SPEED = math.pi / 100
  423.  
  424.  
  425.     if (key==273) then WORLD_Y = WORLD_Y - 0.05; killinertia();  end
  426.     if (key==274) then WORLD_Y = WORLD_Y + 0.05; killinertia();  end
  427.  
  428.     if (key==276) then WORLD_X = WORLD_X - 0.05; killinertia();  end
  429.     if (key==275) then WORLD_X = WORLD_X + 0.05; killinertia();  end
  430.    
  431.   until ((mouse_b == 1 and (old_mouse_x~=mouse_x or old_mouse_y~=mouse_y)) or key~=0 or ANIM==1 or math.abs(XD)>0.01 or math.abs(YD)>0.01);
  432.  
  433.  if ANIM == 0 then
  434.   if (mouse_b==1 and (old_mouse_x~=mouse_x or old_mouse_y~=mouse_y)) then -- Inertia
  435.    XD = (mouse_y - old_mouse_y)*0.005
  436.    YD = (mouse_x - old_mouse_x)*0.005
  437.     else
  438.      XD = XD*0.92
  439.      YD = YD*0.92
  440.   end
  441.   XANG = ((XANG - XD) % (math.pi*2));
  442.   YANG = ((YANG + YD) % (math.pi*2));
  443.   ZANG = ZSELECT
  444.  end
  445.  
  446.  if ANIM == 1 then
  447.     XANG = (XANG + math.pi/300) % (math.pi*2)
  448.     YANG = (YANG + math.pi/500) % (math.pi*2)
  449.     ZANG = (ZANG + math.pi/1000) % (math.pi*2)
  450.  end
  451.  
  452.  --XANG = ((CY-mouse_y) / 200  % (math.pi*2));
  453.   --YANG = ((mouse_x - CX) / 200  % (math.pi*2));
  454.   --ZANG = 0
  455.  
  456.  statusmessage("x"..math.floor(XANG*57.3).."° y"..math.floor(YANG*57.3).."° z"..math.floor(ZANG*57.3).."° Zm: "..math.floor(-ZOOM*10).."   ")
  457.  
  458. end
  459.  
  460. end -- OK
  461.