Author Topic: 3D Seirpinski Triangle  (Read 5196 times)

0 Members and 1 Guest are viewing this topic.

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
3D Seirpinski Triangle
« on: February 21, 2019, 10:42:48 am »
Hi everyone! You can also call it Sierpinski Tetrahedron or Tetrix.

Controls -
  • Use Mouse movement for rotation.
  • Press 'Space' to switch between different modes of rendering.
Also, thanks to Fellippe's INPUTBOX()
Here is the code -

Code: QB64: [Select]
  1. '3D Sierpinski Triangle or Tetrix
  2. '21 Feb, 2019 Ashish
  3. 'The number of pyramid formed are at nth iterations = 4^(n-1). sss
  4. 'You must enter number of iterations value between 2-8 or you can enter higher value at your own risk.
  5.  
  6. _TITLE "3D Sierpinski Triangle"
  7. SCREEN _NEWIMAGE(700, 700, 32)
  8.  
  9. DECLARE LIBRARY 'camera related subroutine
  10.     SUB gluLookAt (BYVAL eyeX#, BYVAL eyeY#, BYVAL eyeZ#, BYVAL centerX#, BYVAL centerY#, BYVAL centerZ#, BYVAL upX#, BYVAL upY#, BYVAL upZ#)
  11.  
  12.  
  13. TYPE vec3
  14.     x AS SINGLE
  15.     y AS SINGLE
  16.     z AS SINGLE
  17.  
  18. TYPE face
  19.     v1 AS vec3
  20.     v2 AS vec3
  21.     v3 AS vec3
  22.     n AS vec3 'normal
  23.  
  24. TYPE pyramid
  25.     f1 AS face
  26.     f2 AS face
  27.     f3 AS face
  28.     f4 AS face
  29.  
  30. IF INPUTBOX("Enter the number of iterations", "Recommended range 2-8, or you can go higher at your own risk. ", "4", v$, -1) = 1 THEN
  31.     totalIterations = VAL(v$)
  32.     END
  33.  
  34. DIM SHARED glAllow AS _BYTE, totalFaces AS LONG, triangles(4 ^ (totalIterations)) AS face
  35. DIM SHARED mouseX, mouseY, modes
  36. generateFractalData totalIterations
  37. modes = 0
  38. glAllow = -1
  39.     k& = _KEYHIT
  40.     IF k& = ASC(" ") THEN modes = modes + 1
  41.     IF modes > 3 THEN modes = 0
  42.     mouseX = _MOUSEX: mouseY = _MOUSEY
  43.     _LIMIT 40
  44. LOOP UNTIL k& = 27
  45.  
  46. SUB _GL
  47.     STATIC glInit, aspect#, t#
  48.     IF NOT glAllow THEN EXIT SUB
  49.  
  50.     IF NOT glInit THEN
  51.         glInit = -1
  52.         aspect# = _WIDTH / _HEIGHT
  53.         _glViewport 0, 0, _WIDTH, _HEIGHT
  54.     END IF
  55.     _glClearColor 0.4, 0.4, 0.4, 1
  56.     _glClear _GL_DEPTH_BUFFER_BIT OR _GL_COLOR_BUFFER_BIT
  57.  
  58.     _glEnable _GL_DEPTH_TEST
  59.  
  60.  
  61.     IF modes = 0 THEN
  62.         _glEnable _GL_LIGHTING
  63.         _glEnable _GL_LIGHT0
  64.         _glLightfv _GL_LIGHT0, _GL_POSITION, glVec4(0, 0, 25, 0)
  65.         _glLightfv _GL_LIGHT0, _GL_AMBIENT, glVec3(0.4, 0.4, 0.4)
  66.         _glLightfv _GL_LIGHT0, _GL_DIFFUSE, glVec3(1, 1, 1)
  67.         _glLightfv _GL_LIGHT0, _GL_SPECULAR, glVec3(0.6, 0.6, 0.6)
  68.     END IF
  69.  
  70.     _glMatrixMode _GL_PROJECTION
  71.     _gluPerspective 45.0, aspect#, 1, 100
  72.  
  73.     _glMatrixMode _GL_MODELVIEW
  74.  
  75.     gluLookAt 0, 0, 4, 0, 0, 0, 0, 1, 0
  76.  
  77.  
  78.  
  79.     _glRotatef mouseX * 1.9, 0, 1, 0
  80.  
  81.     SELECT CASE modes
  82.         CASE 0
  83.             _glMaterialfv _GL_FRONT_AND_BACK, _GL_AMBIENT, glVec3(0.1745, 0.01175, 0.01175)
  84.             _glMaterialfv _GL_FRONT_AND_BACK, _GL_DIFFUSE, glVec3(0.61424, 0.04136, 0.04136)
  85.             _glMaterialfv _GL_FRONT_AND_BACK, _GL_SPECULAR, glVec3(0.727811, 0.626959, 0.626959)
  86.             _glMaterialfv _GL_FRONT_AND_BACK, _GL_SHININESS, glVec3(128 * 0.6, 0, 0)
  87.  
  88.             _glBegin _GL_TRIANGLES
  89.  
  90.             FOR i = 0 TO totalFaces - 1
  91.  
  92.                 _glNormal3f triangles(i).n.x, triangles(i).n.y, triangles(i).n.z
  93.                 _glVertex3f triangles(i).v1.x, triangles(i).v1.y, triangles(i).v1.z
  94.                 _glVertex3f triangles(i).v2.x, triangles(i).v2.y, triangles(i).v2.z
  95.                 _glVertex3f triangles(i).v3.x, triangles(i).v3.y, triangles(i).v3.z
  96.  
  97.             NEXT
  98.             _glEnd
  99.         CASE 1
  100.             _glBegin _GL_TRIANGLES
  101.             FOR i = 0 TO totalFaces - 1
  102.                 _glColor3f ABS(triangles(i).n.x), ABS(triangles(i).n.y), ABS(triangles(i).n.z)
  103.  
  104.                 _glVertex3f triangles(i).v1.x, triangles(i).v1.y, triangles(i).v1.z
  105.                 _glVertex3f triangles(i).v2.x, triangles(i).v2.y, triangles(i).v2.z
  106.                 _glVertex3f triangles(i).v3.x, triangles(i).v3.y, triangles(i).v3.z
  107.             NEXT
  108.             _glEnd
  109.         CASE 2
  110.             _glBegin _GL_LINES
  111.             FOR i = 0 TO totalFaces - 1
  112.                 _glVertex3f triangles(i).v1.x, triangles(i).v1.y, triangles(i).v1.z
  113.                 _glVertex3f triangles(i).v2.x, triangles(i).v2.y, triangles(i).v2.z
  114.  
  115.                 _glVertex3f triangles(i).v3.x, triangles(i).v3.y, triangles(i).v3.z
  116.                 _glVertex3f triangles(i).v2.x, triangles(i).v2.y, triangles(i).v2.z
  117.  
  118.                 _glVertex3f triangles(i).v3.x, triangles(i).v3.y, triangles(i).v3.z
  119.                 _glVertex3f triangles(i).v1.x, triangles(i).v1.y, triangles(i).v1.z
  120.             NEXT
  121.             _glEnd
  122.         CASE 3
  123.             _glBegin _GL_LINES
  124.             FOR i = 0 TO totalFaces - 1
  125.                 _glColor3f ABS(triangles(i).n.x), ABS(triangles(i).n.y), ABS(triangles(i).n.z)
  126.  
  127.                 _glVertex3f triangles(i).v1.x, triangles(i).v1.y, triangles(i).v1.z
  128.                 _glVertex3f triangles(i).v2.x, triangles(i).v2.y, triangles(i).v2.z
  129.  
  130.                 _glVertex3f triangles(i).v3.x, triangles(i).v3.y, triangles(i).v3.z
  131.                 _glVertex3f triangles(i).v2.x, triangles(i).v2.y, triangles(i).v2.z
  132.  
  133.                 _glVertex3f triangles(i).v3.x, triangles(i).v3.y, triangles(i).v3.z
  134.                 _glVertex3f triangles(i).v1.x, triangles(i).v1.y, triangles(i).v1.z
  135.             NEXT
  136.             _glEnd
  137.     END SELECT
  138.  
  139.  
  140.  
  141.     _glFlush
  142.  
  143.  
  144. SUB generateFractalData (num_of_iterations)
  145.     createFaces num_of_iterations, 0, 1, 1 / 3, -1, -1, 1, 1, -1, 1, 0, -1, -1, 1
  146.  
  147. SUB createFaces (i, x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, i_c)
  148.     STATIC Fc, normalVec AS vec3
  149.     IF i_c = 1 THEN Fc = 0
  150.     IF i = i_c THEN
  151.         triangles(Fc).v1.x = x1: triangles(Fc).v1.y = y1: triangles(Fc).v1.z = z1
  152.         triangles(Fc).v2.x = x2: triangles(Fc).v2.y = y2: triangles(Fc).v2.z = z2
  153.         triangles(Fc).v3.x = x3: triangles(Fc).v3.y = y3: triangles(Fc).v3.z = z3
  154.         OBJ_CalculateNormal triangles(Fc).v1, triangles(Fc).v2, triangles(Fc).v3, normalVec
  155.         triangles(Fc).n.x = normalVec.x: triangles(Fc).n.y = normalVec.y: triangles(Fc).n.z = normalVec.z
  156.         Fc = Fc + 1
  157.         triangles(Fc).v1.x = x2: triangles(Fc).v1.y = y2: triangles(Fc).v1.z = z2
  158.         triangles(Fc).v2.x = x3: triangles(Fc).v2.y = y3: triangles(Fc).v2.z = z3
  159.         triangles(Fc).v3.x = x4: triangles(Fc).v3.y = y4: triangles(Fc).v3.z = z4
  160.         OBJ_CalculateNormal triangles(Fc).v1, triangles(Fc).v2, triangles(Fc).v3, normalVec
  161.         triangles(Fc).n.x = normalVec.x: triangles(Fc).n.y = normalVec.y: triangles(Fc).n.z = normalVec.z
  162.         Fc = Fc + 1
  163.         triangles(Fc).v1.x = x3: triangles(Fc).v1.y = y3: triangles(Fc).v1.z = z3
  164.         triangles(Fc).v2.x = x4: triangles(Fc).v2.y = y4: triangles(Fc).v2.z = z4
  165.         triangles(Fc).v3.x = x1: triangles(Fc).v3.y = y1: triangles(Fc).v3.z = z1
  166.         OBJ_CalculateNormal triangles(Fc).v1, triangles(Fc).v2, triangles(Fc).v3, normalVec
  167.         triangles(Fc).n.x = normalVec.x: triangles(Fc).n.y = normalVec.y: triangles(Fc).n.z = normalVec.z
  168.         Fc = Fc + 1
  169.         triangles(Fc).v1.x = x4: triangles(Fc).v1.y = y4: triangles(Fc).v1.z = z4
  170.         triangles(Fc).v2.x = x1: triangles(Fc).v2.y = y1: triangles(Fc).v2.z = z1
  171.         triangles(Fc).v3.x = x2: triangles(Fc).v3.y = y2: triangles(Fc).v3.z = z2
  172.         OBJ_CalculateNormal triangles(Fc).v1, triangles(Fc).v2, triangles(Fc).v3, normalVec
  173.         triangles(Fc).n.x = normalVec.x: triangles(Fc).n.y = normalVec.y: triangles(Fc).n.z = normalVec.z
  174.         Fc = Fc + 1
  175.         totalFaces = totalFaces + 4
  176.  
  177.     ELSE
  178.         'creating 4 pyramid from single pyramid and then dividing them further
  179.         createFaces i, (x4 + x1) / 2, (y4 + y1) / 2, (z4 + z1) / 2, (x1 + x2) / 2, (y1 + y2) / 2, (z1 + z2) / 2, (x1 + x3) / 2, (y1 + y3) / 2, (z1 + z3) / 2, x1, y1, z1, i_c + 1
  180.         createFaces i, x4, y4, z4, (x2 + x4) / 2, (y2 + y4) / 2, (z2 + z4) / 2, (x3 + x4) / 2, (y3 + y4) / 2, (z3 + z4) / 2, (x1 + x4) / 2, (y1 + y4) / 2, (z1 + z4) / 2, i_c + 1
  181.         createFaces i, (x2 + x4) / 2, (y2 + y4) / 2, (z2 + z4) / 2, x2, y2, z2, (x2 + x3) / 2, (y2 + y3) / 2, (z2 + z3) / 2, (x1 + x2) / 2, (y1 + y2) / 2, (z1 + z2) / 2, i_c + 1
  182.         createFaces i, (x3 + x4) / 2, (y3 + y4) / 2, (z3 + z4) / 2, (x2 + x3) / 2, (y2 + y3) / 2, (z2 + z3) / 2, x3, y3, z3, (x1 + x3) / 2, (y1 + y3) / 2, (z1 + z3) / 2, i_c + 1
  183.     END IF
  184.  
  185. SUB OBJ_CalculateNormal (p1 AS vec3, p2 AS vec3, p3 AS vec3, N AS vec3)
  186.     DIM U AS vec3, V AS vec3
  187.  
  188.     U.x = p2.x - p1.x
  189.     U.y = p2.y - p1.y
  190.     U.z = p2.z - p1.z
  191.  
  192.     V.x = p3.x - p1.x
  193.     V.y = p3.y - p1.y
  194.     V.z = p3.z - p1.z
  195.  
  196.     N.x = (U.y * V.z) - (U.z * V.y)
  197.     N.y = (U.z * V.x) - (U.x * V.z)
  198.     N.z = (U.x * V.y) - (U.y * V.x)
  199.     OBJ_Normalize N
  200.  
  201. SUB OBJ_Normalize (V AS vec3)
  202.     mag! = SQR(V.x * V.x + V.y * V.y + V.z * V.z)
  203.     V.x = V.x / mag!
  204.     V.y = V.y / mag!
  205.     V.z = V.z / mag!
  206.  
  207. FUNCTION glVec4%& (x, y, z, w)
  208.     STATIC internal_vec4(3)
  209.     internal_vec4(0) = x
  210.     internal_vec4(1) = y
  211.     internal_vec4(2) = z
  212.     internal_vec4(3) = w
  213.     glVec4%& = _OFFSET(internal_vec4())
  214.  
  215. FUNCTION glVec3%& (x, y, z)
  216.     STATIC internal_vec3(2)
  217.     internal_vec3(0) = x
  218.     internal_vec3(1) = y
  219.     internal_vec3(2) = z
  220.     glVec3%& = _OFFSET(internal_vec3())
  221.  
  222. 'By Fellipe Heitor
  223. FUNCTION INPUTBOX (tTitle$, tMessage$, InitialValue AS STRING, NewValue AS STRING, Selected)
  224.     'INPUTBOX ---------------------------------------------------------------------
  225.     'Show a dialog and allow user input. Returns 1 = OK or 2 = Cancel.            '
  226.     '                                                                             '
  227.     '- tTitle$ is the desired dialog title. If not provided, it'll be "Input"     '
  228.     '                                                                             '
  229.     '- tMessage$ is the prompt that'll be shown to the user. You can show         '
  230.     '   a multiline message by adding line breaks with CHR$(10).                  '
  231.     '                                                                             '
  232.     ' - InitialValue can be passed both as a string literal or as a variable.     '
  233.     '                                                                             '
  234.     '- Actual user input is returned by altering NewValue, so it must be          '
  235.     '   passed as a variable.                                                     '
  236.     '                                                                             '
  237.     '- Selected indicates wheter the initial value will be preselected when the   '
  238.     '   dialog is first shown. -1 preselects the whole text; positive values      '
  239.     '   select only part of the initial value (from the character position passed '
  240.     '   to the end of the initial value).                                         '
  241.     '                                                                             '
  242.     'Intended for use with 32-bit screen modes.                                   '
  243.     '------------------------------------------------------------------------------
  244.  
  245.     'Variable declaration:
  246.     DIM Message$, Title$, CharW AS INTEGER, MaxLen AS INTEGER
  247.     DIM lineBreak AS INTEGER, totalLines AS INTEGER, prevlinebreak AS INTEGER
  248.     DIM Cursor AS INTEGER, Selection.Start AS INTEGER, InputViewStart AS INTEGER
  249.     DIM FieldArea AS INTEGER, DialogH AS INTEGER, DialogW AS INTEGER
  250.     DIM DialogX AS INTEGER, DialogY AS INTEGER, InputField.X AS INTEGER
  251.     DIM TotalButtons AS INTEGER, B AS INTEGER, ButtonLine$
  252.     DIM cb AS INTEGER, DIALOGRESULT AS INTEGER, i AS INTEGER
  253.     DIM message.X AS INTEGER, SetCursor#, cursorBlink%
  254.     DIM DefaultButton AS INTEGER, k AS LONG
  255.     DIM shiftDown AS _BYTE, ctrlDown AS _BYTE, Clip$
  256.     DIM FindLF%, s1 AS INTEGER, s2 AS INTEGER
  257.     DIM Selection.Value$
  258.     DIM prevCursor AS INTEGER, ss1 AS INTEGER, ss2 AS INTEGER, mb AS _BYTE
  259.     DIM mx AS INTEGER, my AS INTEGER, nmx AS INTEGER, nmy AS INTEGER
  260.     DIM FGColor AS LONG, BGColor AS LONG
  261.  
  262.     'Data type used for the dialog buttons:
  263.     TYPE BUTTONSTYPE
  264.         ID AS LONG
  265.         CAPTION AS STRING * 120
  266.         X AS INTEGER
  267.         Y AS INTEGER
  268.         W AS INTEGER
  269.     END TYPE
  270.  
  271.     'Color constants. You can customize colors by changing these:
  272.     CONST TitleBarColor = _RGB32(0, 178, 179)
  273.     CONST DialogBGColor = _RGB32(255, 255, 255)
  274.     CONST TitleBarTextColor = _RGB32(0, 0, 0)
  275.     CONST DialogTextColor = _RGB32(0, 0, 0)
  276.     CONST InputFieldColor = _RGB32(200, 200, 200)
  277.     CONST InputFieldTextColor = _RGB32(0, 0, 0)
  278.     CONST SelectionColor = _RGBA32(127, 127, 127, 100)
  279.  
  280.     'Initial variable setup:
  281.     Message$ = tMessage$
  282.     Title$ = RTRIM$(LTRIM$(tTitle$))
  283.     IF Title$ = "" THEN Title$ = "Input"
  284.     NewValue = RTRIM$(LTRIM$(InitialValue))
  285.     DefaultButton = 1
  286.  
  287.     'Save the current drawing page so it can be restored later:
  288.     FGColor = _DEFAULTCOLOR
  289.     BGColor = _BACKGROUNDCOLOR
  290.     PCOPY 0, 1
  291.  
  292.     'Figure out the print width of a single character (in case user has a custom font applied)
  293.     CharW = _PRINTWIDTH("_")
  294.  
  295.     'Place a color overlay over the old screen image so the focus is on the dialog:
  296.     LINE (0, 0)-STEP(_WIDTH - 1, _HEIGHT - 1), _RGBA32(170, 170, 170, 170), BF
  297.  
  298.     'Message breakdown, in case CHR$(10) was used as line break:
  299.     REDIM MessageLines(1) AS STRING
  300.     MaxLen = 1
  301.     DO
  302.         lineBreak = INSTR(lineBreak + 1, Message$, CHR$(10))
  303.         IF lineBreak = 0 AND totalLines = 0 THEN
  304.             totalLines = 1
  305.             MessageLines(1) = Message$
  306.             MaxLen = LEN(Message$)
  307.             EXIT DO
  308.         ELSEIF lineBreak = 0 AND totalLines > 0 THEN
  309.             totalLines = totalLines + 1
  310.             REDIM _PRESERVE MessageLines(1 TO totalLines) AS STRING
  311.             MessageLines(totalLines) = RIGHT$(Message$, LEN(Message$) - prevlinebreak + 1)
  312.             IF LEN(MessageLines(totalLines)) > MaxLen THEN MaxLen = LEN(MessageLines(totalLines))
  313.             EXIT DO
  314.         END IF
  315.         IF totalLines = 0 THEN prevlinebreak = 1
  316.         totalLines = totalLines + 1
  317.         REDIM _PRESERVE MessageLines(1 TO totalLines) AS STRING
  318.         MessageLines(totalLines) = MID$(Message$, prevlinebreak, lineBreak - prevlinebreak)
  319.         IF LEN(MessageLines(totalLines)) > MaxLen THEN MaxLen = LEN(MessageLines(totalLines))
  320.         prevlinebreak = lineBreak + 1
  321.     LOOP
  322.  
  323.     Cursor = LEN(NewValue)
  324.     Selection.Start = 0
  325.     InputViewStart = 1
  326.     FieldArea = _WIDTH \ CharW - 4
  327.     IF FieldArea > 62 THEN FieldArea = 62
  328.     IF Selected > 0 THEN Selection.Start = Selected: Selected = -1
  329.  
  330.     'Calculate dialog dimensions and print coordinates:
  331.     DialogH = _FONTHEIGHT * (6 + totalLines) + 10
  332.     DialogW = (CharW * FieldArea) + 10
  333.     IF DialogW < MaxLen * CharW + 10 THEN DialogW = MaxLen * CharW + 10
  334.  
  335.     DialogX = _WIDTH / 2 - DialogW / 2
  336.     DialogY = _HEIGHT / 2 - DialogH / 2
  337.     InputField.X = (DialogX + (DialogW / 2)) - (((FieldArea * CharW) - 10) / 2) - 4
  338.  
  339.     'Calculate button's print coordinates:
  340.     TotalButtons = 2
  341.     DIM Buttons(1 TO TotalButtons) AS BUTTONSTYPE
  342.     B = 1
  343.     Buttons(B).ID = 1: Buttons(B).CAPTION = "< OK >": B = B + 1
  344.     Buttons(B).ID = 2: Buttons(B).CAPTION = "< Cancel >": B = B + 1
  345.     ButtonLine$ = " "
  346.     FOR cb = 1 TO TotalButtons
  347.         ButtonLine$ = ButtonLine$ + RTRIM$(LTRIM$(Buttons(cb).CAPTION)) + " "
  348.         Buttons(cb).Y = DialogY + 5 + _FONTHEIGHT * (5 + totalLines)
  349.         Buttons(cb).W = _PRINTWIDTH(RTRIM$(LTRIM$(Buttons(cb).CAPTION)))
  350.     NEXT cb
  351.     Buttons(1).X = _WIDTH / 2 - _PRINTWIDTH(ButtonLine$) / 2
  352.     FOR cb = 2 TO TotalButtons
  353.         Buttons(cb).X = Buttons(1).X + _PRINTWIDTH(SPACE$(INSTR(ButtonLine$, RTRIM$(LTRIM$(Buttons(cb).CAPTION)))))
  354.     NEXT cb
  355.  
  356.     'Main loop:
  357.     DIALOGRESULT = 0
  358.     _KEYCLEAR
  359.     DO: _LIMIT 500
  360.         'Draw the dialog.
  361.         LINE (DialogX, DialogY)-STEP(DialogW - 1, DialogH - 1), DialogBGColor, BF
  362.         LINE (DialogX, DialogY)-STEP(DialogW - 1, _FONTHEIGHT + 1), TitleBarColor, BF
  363.         COLOR TitleBarTextColor
  364.         _PRINTSTRING (_WIDTH / 2 - _PRINTWIDTH(Title$) / 2, DialogY + 1), Title$
  365.  
  366.         COLOR DialogTextColor, _RGBA32(0, 0, 0, 0)
  367.         FOR i = 1 TO totalLines
  368.             message.X = _WIDTH / 2 - _PRINTWIDTH(MessageLines(i)) / 2
  369.             _PRINTSTRING (message.X, DialogY + 5 + _FONTHEIGHT * (i + 1)), MessageLines(i)
  370.         NEXT i
  371.  
  372.         'Draw the input field
  373.         LINE (InputField.X - 2, DialogY + 3 + _FONTHEIGHT * (3 + totalLines))-STEP(FieldArea * CharW, _FONTHEIGHT + 4), InputFieldColor, BF
  374.         COLOR InputFieldTextColor
  375.         _PRINTSTRING (InputField.X, DialogY + 5 + _FONTHEIGHT * (3 + totalLines)), MID$(NewValue, InputViewStart, FieldArea)
  376.  
  377.         'Selection highlight:
  378.         GOSUB SelectionHighlight
  379.  
  380.         'Cursor blink:
  381.         IF TIMER - SetCursor# > .4 THEN
  382.             SetCursor# = TIMER
  383.             IF cursorBlink% = 1 THEN cursorBlink% = 0 ELSE cursorBlink% = 1
  384.         END IF
  385.         IF cursorBlink% = 1 THEN
  386.             LINE (InputField.X + (Cursor - (InputViewStart - 1)) * CharW, DialogY + 5 + _FONTHEIGHT * (3 + totalLines))-STEP(0, _FONTHEIGHT), _RGB32(0, 0, 0)
  387.         END IF
  388.  
  389.         'Check if buttons have been clicked or are being hovered:
  390.         GOSUB CheckButtons
  391.  
  392.         'Draw buttons:
  393.         FOR cb = 1 TO TotalButtons
  394.             _PRINTSTRING (Buttons(cb).X, Buttons(cb).Y), RTRIM$(LTRIM$(Buttons(cb).CAPTION))
  395.             IF cb = DefaultButton THEN
  396.                 COLOR _RGB32(255, 255, 0)
  397.                 _PRINTSTRING (Buttons(cb).X, Buttons(cb).Y), "<" + SPACE$(LEN(RTRIM$(LTRIM$(Buttons(cb).CAPTION))) - 2) + ">"
  398.                 COLOR _RGB32(0, 178, 179)
  399.                 _PRINTSTRING (Buttons(cb).X - 1, Buttons(cb).Y - 1), "<" + SPACE$(LEN(RTRIM$(LTRIM$(Buttons(cb).CAPTION))) - 2) + ">"
  400.                 COLOR _RGB32(0, 0, 0)
  401.             END IF
  402.         NEXT cb
  403.  
  404.         _DISPLAY
  405.  
  406.         'Process input:
  407.         k = _KEYHIT
  408.         IF k = 100303 OR k = 100304 THEN shiftDown = -1
  409.         IF k = -100303 OR k = -100304 THEN shiftDown = 0
  410.         IF k = 100305 OR k = 100306 THEN ctrlDown = -1
  411.         IF k = -100305 OR k = -100306 THEN ctrlDown = 0
  412.  
  413.         SELECT CASE k
  414.             CASE 13: DIALOGRESULT = 1
  415.             CASE 27: DIALOGRESULT = 2
  416.             CASE 32 TO 126 'Printable ASCII characters
  417.                 IF k = ASC("v") OR k = ASC("V") THEN 'Paste from clipboard (Ctrl+V)
  418.                     IF ctrlDown THEN
  419.                         Clip$ = _CLIPBOARD$
  420.                         FindLF% = INSTR(Clip$, CHR$(13))
  421.                         IF FindLF% > 0 THEN Clip$ = LEFT$(Clip$, FindLF% - 1)
  422.                         FindLF% = INSTR(Clip$, CHR$(10))
  423.                         IF FindLF% > 0 THEN Clip$ = LEFT$(Clip$, FindLF% - 1)
  424.                         IF LEN(RTRIM$(LTRIM$(Clip$))) > 0 THEN
  425.                             IF NOT Selected THEN
  426.                                 IF Cursor = LEN(NewValue) THEN
  427.                                     NewValue = NewValue + Clip$
  428.                                     Cursor = LEN(NewValue)
  429.                                 ELSE
  430.                                     NewValue = LEFT$(NewValue, Cursor) + Clip$ + MID$(NewValue, Cursor + 1)
  431.                                     Cursor = Cursor + LEN(Clip$)
  432.                                 END IF
  433.                             ELSE
  434.                                 s1 = Selection.Start
  435.                                 s2 = Cursor
  436.                                 IF s1 > s2 THEN SWAP s1, s2
  437.                                 NewValue = LEFT$(NewValue, s1) + Clip$ + MID$(NewValue, s2 + 1)
  438.                                 Cursor = s1 + LEN(Clip$)
  439.                                 Selected = 0
  440.                             END IF
  441.                         END IF
  442.                         k = 0
  443.                     END IF
  444.                 ELSEIF k = ASC("c") OR k = ASC("C") THEN 'Copy selection to clipboard (Ctrl+C)
  445.                     IF ctrlDown THEN
  446.                         _CLIPBOARD$ = Selection.Value$
  447.                         k = 0
  448.                     END IF
  449.                 ELSEIF k = ASC("x") OR k = ASC("X") THEN 'Cut selection to clipboard (Ctrl+X)
  450.                     IF ctrlDown THEN
  451.                         _CLIPBOARD$ = Selection.Value$
  452.                         GOSUB DeleteSelection
  453.                         k = 0
  454.                     END IF
  455.                 ELSEIF k = ASC("a") OR k = ASC("A") THEN 'Select all text (Ctrl+A)
  456.                     IF ctrlDown THEN
  457.                         Cursor = LEN(NewValue)
  458.                         Selection.Start = 0
  459.                         Selected = -1
  460.                         k = 0
  461.                     END IF
  462.                 END IF
  463.  
  464.                 IF k > 0 THEN
  465.                     IF NOT Selected THEN
  466.                         IF Cursor = LEN(NewValue) THEN
  467.                             NewValue = NewValue + CHR$(k)
  468.                             Cursor = Cursor + 1
  469.                         ELSE
  470.                             NewValue = LEFT$(NewValue, Cursor) + CHR$(k) + MID$(NewValue, Cursor + 1)
  471.                             Cursor = Cursor + 1
  472.                         END IF
  473.                         IF Cursor > FieldArea THEN InputViewStart = (Cursor - FieldArea) + 2
  474.                     ELSE
  475.                         s1 = Selection.Start
  476.                         s2 = Cursor
  477.                         IF s1 > s2 THEN SWAP s1, s2
  478.                         NewValue = LEFT$(NewValue, s1) + CHR$(k) + MID$(NewValue, s2 + 1)
  479.                         Selected = 0
  480.                         Cursor = s1 + 1
  481.                     END IF
  482.                 END IF
  483.             CASE 8 'Backspace
  484.                 IF LEN(NewValue) > 0 THEN
  485.                     IF NOT Selected THEN
  486.                         IF Cursor = LEN(NewValue) THEN
  487.                             NewValue = LEFT$(NewValue, LEN(NewValue) - 1)
  488.                             Cursor = Cursor - 1
  489.                         ELSEIF Cursor > 1 THEN
  490.                             NewValue = LEFT$(NewValue, Cursor - 1) + MID$(NewValue, Cursor + 1)
  491.                             Cursor = Cursor - 1
  492.                         ELSEIF Cursor = 1 THEN
  493.                             NewValue = RIGHT$(NewValue, LEN(NewValue) - 1)
  494.                             Cursor = Cursor - 1
  495.                         END IF
  496.                     ELSE
  497.                         GOSUB DeleteSelection
  498.                     END IF
  499.                 END IF
  500.             CASE 21248 'Delete
  501.                 IF NOT Selected THEN
  502.                     IF LEN(NewValue) > 0 THEN
  503.                         IF Cursor = 0 THEN
  504.                             NewValue = RIGHT$(NewValue, LEN(NewValue) - 1)
  505.                         ELSEIF Cursor > 0 AND Cursor <= LEN(NewValue) - 1 THEN
  506.                             NewValue = LEFT$(NewValue, Cursor) + MID$(NewValue, Cursor + 2)
  507.                         END IF
  508.                     END IF
  509.                 ELSE
  510.                     GOSUB DeleteSelection
  511.                 END IF
  512.             CASE 19200 'Left arrow key
  513.                 GOSUB CheckSelection
  514.                 IF Cursor > 0 THEN Cursor = Cursor - 1
  515.             CASE 19712 'Right arrow key
  516.                 GOSUB CheckSelection
  517.                 IF Cursor < LEN(NewValue) THEN Cursor = Cursor + 1
  518.             CASE 18176 'Home
  519.                 GOSUB CheckSelection
  520.                 Cursor = 0
  521.             CASE 20224 'End
  522.                 GOSUB CheckSelection
  523.                 Cursor = LEN(NewValue)
  524.         END SELECT
  525.  
  526.         'Cursor adjustments:
  527.         GOSUB CursorAdjustments
  528.     LOOP UNTIL DIALOGRESULT > 0
  529.  
  530.     _KEYCLEAR
  531.     INPUTBOX = DIALOGRESULT
  532.  
  533.     'Restore previous display:
  534.     PCOPY 1, 0
  535.     COLOR FGColor, BGColor
  536.     EXIT SUB
  537.  
  538.     CursorAdjustments:
  539.     IF Cursor > prevCursor THEN
  540.         IF Cursor - InputViewStart + 2 > FieldArea THEN InputViewStart = (Cursor - FieldArea) + 2
  541.     ELSEIF Cursor < prevCursor THEN
  542.         IF Cursor < InputViewStart - 1 THEN InputViewStart = Cursor
  543.     END IF
  544.     prevCursor = Cursor
  545.     IF InputViewStart < 1 THEN InputViewStart = 1
  546.     RETURN
  547.  
  548.     CheckSelection:
  549.     IF shiftDown = -1 THEN
  550.         IF Selected = 0 THEN
  551.             Selected = -1
  552.             Selection.Start = Cursor
  553.         END IF
  554.     ELSEIF shiftDown = 0 THEN
  555.         Selected = 0
  556.     END IF
  557.     RETURN
  558.  
  559.     DeleteSelection:
  560.     NewValue = LEFT$(NewValue, s1) + MID$(NewValue, s2 + 1)
  561.     Selected = 0
  562.     Cursor = s1
  563.     RETURN
  564.  
  565.     SelectionHighlight:
  566.     IF Selected THEN
  567.         s1 = Selection.Start
  568.         s2 = Cursor
  569.         IF s1 > s2 THEN
  570.             SWAP s1, s2
  571.             IF InputViewStart > 1 THEN
  572.                 ss1 = s1 - InputViewStart + 1
  573.             ELSE
  574.                 ss1 = s1
  575.             END IF
  576.             ss2 = s2 - s1
  577.             IF ss1 + ss2 > FieldArea THEN ss2 = FieldArea - ss1
  578.         ELSE
  579.             ss1 = s1
  580.             ss2 = s2 - s1
  581.             IF ss1 < InputViewStart THEN ss1 = 0: ss2 = s2 - InputViewStart + 1
  582.             IF ss1 > InputViewStart THEN ss1 = ss1 - InputViewStart + 1: ss2 = s2 - s1
  583.         END IF
  584.         Selection.Value$ = MID$(NewValue, s1 + 1, s2 - s1)
  585.  
  586.         LINE (InputField.X + ss1 * CharW, DialogY + 5 + _FONTHEIGHT * (3 + totalLines))-STEP(ss2 * CharW, _FONTHEIGHT), _RGBA32(255, 255, 255, 150), BF
  587.     END IF
  588.     RETURN
  589.  
  590.     CheckButtons:
  591.     'Hover highlight:
  592.     mb = _MOUSEBUTTON(1): mx = _MOUSEX: my = _MOUSEY
  593.     FOR cb = 1 TO TotalButtons
  594.         IF (mx >= Buttons(cb).X) AND (mx <= Buttons(cb).X + Buttons(cb).W) THEN
  595.             IF (my >= Buttons(cb).Y) AND (my < Buttons(cb).Y + _FONTHEIGHT) THEN
  596.                 LINE (Buttons(cb).X, Buttons(cb).Y)-STEP(Buttons(cb).W, _FONTHEIGHT - 1), _RGBA32(230, 230, 230, 235), BF
  597.             END IF
  598.         END IF
  599.     NEXT cb
  600.  
  601.     IF mb THEN
  602.         IF mx >= InputField.X AND my >= DialogY + 3 + _FONTHEIGHT * (3 + totalLines) AND mx <= InputField.X + (FieldArea * CharW - 10) AND my <= DialogY + 3 + _FONTHEIGHT * (3 + totalLines) + _FONTHEIGHT + 4 THEN
  603.             'Clicking inside the text field positions the cursor
  604.             WHILE _MOUSEBUTTON(1)
  605.                 _LIMIT 500
  606.                 mb = _MOUSEINPUT
  607.             WEND
  608.             Cursor = ((mx - InputField.X) / CharW) + (InputViewStart - 1)
  609.             IF Cursor > LEN(NewValue) THEN Cursor = LEN(NewValue)
  610.             Selected = 0
  611.             RETURN
  612.         END IF
  613.  
  614.         FOR cb = 1 TO TotalButtons
  615.             IF (mx >= Buttons(cb).X) AND (mx <= Buttons(cb).X + Buttons(cb).W) THEN
  616.                 IF (my >= Buttons(cb).Y) AND (my < Buttons(cb).Y + _FONTHEIGHT) THEN
  617.                     DefaultButton = cb
  618.                     WHILE _MOUSEBUTTON(1): _LIMIT 500: mb = _MOUSEINPUT: WEND
  619.                     mb = 0: nmx = _MOUSEX: nmy = _MOUSEY
  620.                     IF nmx = mx AND nmy = my THEN DIALOGRESULT = cb
  621.                     RETURN
  622.                 END IF
  623.             END IF
  624.         NEXT cb
  625.     END IF
  626.     RETURN
  627.  
  628.  

Screenshot_1.png
« Last Edit: February 22, 2019, 10:35:37 am by Ashish »
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: 3D Seirpinski Triangle
« Reply #1 on: February 21, 2019, 01:26:03 pm »
Hi Ashish. Very nice use OpenGL!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: 3D Seirpinski Triangle
« Reply #2 on: February 21, 2019, 06:07:02 pm »
Cool 3D effect!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: 3D Seirpinski Triangle
« Reply #3 on: February 21, 2019, 09:56:19 pm »
I am wondering for the Input Box what the settings are for and if there are limits. I've tried several things but so far only the default 4 is working. Is this part still a work in progress?

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: 3D Seirpinski Triangle
« Reply #4 on: February 21, 2019, 10:50:16 pm »
Hi bplus! You can type any value to the inputbox() for the fractal which can be handle by your computer. For settings you can view that function. Is this what you intended to know?
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: 3D Seirpinski Triangle
« Reply #5 on: February 21, 2019, 11:58:58 pm »
OK it needs very low numbers, 12 gets the fan running on my computer and hangs.

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: 3D Seirpinski Triangle
« Reply #6 on: February 22, 2019, 04:42:56 am »
The number of pyramids formed at nth iteration is 4^(n-1). 12 iteration means 4^11 = 4,194,304 pyramids or 16,777,216 triangular faces. It needs a lot of gpu power to render. You can go for 7 or 8 iterations. Let me know how high other can go.
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: 3D Seirpinski Triangle
« Reply #7 on: February 22, 2019, 09:21:12 am »
The number of pyramids formed at nth iteration is 4^(n-1). 12 iteration means 4^11 = 4,194,304 pyramids or 16,777,216 triangular faces. It needs a lot of gpu power to render. You can go for 7 or 8 iterations. Let me know how high other can go.

:) yeah the term iteration threw me off, thinking of Chaos game when you need many, many...

It's true the default of 4 was a clue but I recommend offering limits in the InputBox message for people unfamiliar with your code.

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: 3D Seirpinski Triangle
« Reply #8 on: February 22, 2019, 10:38:39 am »
The number of pyramids formed at nth iteration is 4^(n-1). 12 iteration means 4^11 = 4,194,304 pyramids or 16,777,216 triangular faces. It needs a lot of gpu power to render. You can go for 7 or 8 iterations. Let me know how high other can go.

:) yeah the term iteration threw me off, thinking of Chaos game when you need many, many...

It's true the default of 4 was a clue but I recommend offering limits in the InputBox message for people unfamiliar with your code.
I'm a bit stupid that I have not think upon this. Thanks for the suggestion. I added a warning to the INPUTBOX() message.
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials