Author Topic: 3d_model_viewer by Galleon  (Read 4544 times)

0 Members and 1 Guest are viewing this topic.

Offline Qwerkey

  • Forum Resident
  • Posts: 755
3d_model_viewer by Galleon
« on: March 23, 2020, 06:48:08 am »
3d_model_viewer

Author: @Galleon
Source: QB64 Folder (/programs/samples/open_gl/3d_model_viewer.bas)
URL: N/A
Version: 1
Tags: [3D], [Graphics], [Open_GL], [Demonstration]

Description:
Librarian's note: This demonstration by Galleon comes with the QB64 install, but is given here as an excellent demonstration of what Open_GL can do.

Note: If you have the Run Option “Output Exe to Source Folder” checked, you will need to comment out the first line.  The code given here is for reference only.  Load the .bas file from the given folder.

Controls:
Mouse and wheel
1 / 2 / 3 to change rendering order
A / B / C to change displayed image

Source Code:
Code: QB64: [Select]
  1. CHDIR "programs\samples\open_gl"
  2.  
  3. ' This example shows how models with textures or materials can be displayed with OpenGL using QB64
  4. '
  5. 'IMPORTANT:
  6. ' Whilst the .X file loader is optimized for speed, it is very incomplete:
  7. '  -only .X files in text file format
  8. '  -only one object, not a cluster of objects
  9. '  -if using a texture, use a single texture which will be applied to all materials
  10. '  -all the 3D models in this example were exported from Blender, a free 3D creation tool
  11. '   Blender tips: CTRL+J to amalgamate objects, select object to export first, in the UV/image-editor
  12. '                 window you can export the textures built into your .blend file, apply the decimate
  13. '                 modifier to reduce your polygon count to below 10000, preferably ~3000 or less
  14. ' This program is not a definitive guide to OpenGL in any way
  15. ' The GLH functions are something I threw together to stop people crashing their code by making
  16. '  calls to OpenGL with incorrectly sized memory regions. The GLH... prefixed commands are not mandatory or
  17. '  part of QB64, nor do they represent a complete library of helper commands.
  18. ' Lighting is not this example's strongest point, there's probably some work to do on light positioning
  19. '  and vertex normals
  20. '
  21. 'Finally, I hope you enjoy this program as much as I enjoyed piecing it together,
  22. ' Galleon
  23.  
  24. '###################################### GLH SETUP #############################################
  25.  
  26. 'Used to manage textures
  27. TYPE DONT_USE_GLH_Handle_TYPE
  28.     in_use AS _BYTE
  29.     handle AS LONG
  30.  
  31. 'Used by GLH RGB/etc helper functions
  32. DIM SHARED DONT_USE_GLH_COL_RGBA(1 TO 4) AS SINGLE
  33.  
  34. REDIM SHARED DONT_USE_GLH_Handle(1000) AS DONT_USE_GLH_Handle_TYPE
  35.  
  36. '.X Format Model Loading Data
  37. TYPE VERTEX_TYPE
  38.     X AS DOUBLE
  39.     Y AS DOUBLE
  40.     Z AS DOUBLE
  41.     NX AS DOUBLE
  42.     NY AS DOUBLE
  43.     NZ AS DOUBLE
  44. REDIM SHARED VERTEX(1) AS VERTEX_TYPE
  45. DIM SHARED VERTICES AS LONG
  46. TYPE FACE_CORNER_TYPE
  47.     V AS LONG 'the vertex index
  48.     TX AS SINGLE 'texture X coordinate
  49.     TY AS SINGLE 'texture Y coordinate
  50. TYPE FACE_TYPE
  51.     V1 AS FACE_CORNER_TYPE
  52.     V2 AS FACE_CORNER_TYPE
  53.     V3 AS FACE_CORNER_TYPE
  54.     Material AS LONG
  55.     Index AS LONG
  56. REDIM SHARED FACE(1) AS FACE_TYPE
  57. TYPE MATERIAL_RGBAI_TYPE
  58.     R AS SINGLE
  59.     G AS SINGLE
  60.     B AS SINGLE
  61.     A AS SINGLE
  62.     Intensity AS SINGLE
  63. TYPE MATERIAL_TYPE
  64.     Diffuse AS MATERIAL_RGBAI_TYPE 'regular col
  65.     Specular AS MATERIAL_RGBAI_TYPE 'hightlight/shine col
  66.     Texture_Image AS LONG 'both an image and a texture handle are held
  67.     Texture AS LONG 'if 0, there is no texture
  68. REDIM SHARED MATERIAL(1) AS MATERIAL_TYPE
  69. DIM SHARED MATERIALS AS LONG
  70.  
  71. '##############################################################################################
  72.  
  73. DIM SHARED AllowSubGL
  74.  
  75. SCREEN _NEWIMAGE(1024, 768, 32)
  76.  
  77. backdrop = _LOADIMAGE("backdrop_tron.png")
  78.  
  79. DIM SHARED rot1
  80. DIM SHARED rot2, rot3
  81. DIM SHARED scale: scale = 1
  82.  
  83. 'Load (default) model
  84. GLH_Load_Model_Format_X "marty.x", "marty_tmap.png"
  85. 'draw backdrop
  86. _PUTIMAGE , backdrop: _DONTBLEND: LINE (200, 200)-(500, 500), _RGBA(0, 255, 255, 0), BF: _BLEND
  87.  
  88. AllowSubGL = 1
  89.  
  90.     'This is our program's main loop
  91.     _LIMIT 100
  92.     LOCATE 1, 1
  93.     PRINT "Mouse Input:"
  94.     PRINT "{Horizonal Movement}Spin"
  95.     PRINT "{Vertical Movement}Flip"
  96.     PRINT "{Wheel}Scale"
  97.     PRINT
  98.     PRINT "Keyboard comands:"
  99.     PRINT "Switch rendering order: {1}GL behind, {2}GL on top, {3}GL only, good for speed"
  100.     PRINT "Switch/Load model: {A}Zebra, {B}Pig, {C}Car"
  101.  
  102.     k$ = INKEY$
  103.     IF k$ = "1" THEN _GLRENDER _BEHIND
  104.     IF k$ = "2" THEN _GLRENDER _ONTOP
  105.     IF k$ = "3" THEN _GLRENDER _ONLY
  106.  
  107.  
  108.     PRINT "Angles:"; rot1, rot2, rot3
  109.  
  110.  
  111.     IF UCASE$(k$) = "A" THEN
  112.         AllowSubGL = 0
  113.         GLH_Load_Model_Format_X "marty.x", "marty_tmap.png"
  114.         _PUTIMAGE , backdrop: _DONTBLEND: LINE (200, 200)-(500, 500), _RGBA(0, 255, 255, 0), BF: _BLEND
  115.         AllowSubGL = 1
  116.     END IF
  117.  
  118.     IF UCASE$(k$) = "B" THEN
  119.         AllowSubGL = 0
  120.         GLH_Load_Model_Format_X "piggy_mini3.x", ""
  121.         _PUTIMAGE , backdrop: _DONTBLEND: LINE (200, 200)-(500, 500), _RGBA(0, 255, 255, 0), BF: _BLEND
  122.         AllowSubGL = 1
  123.     END IF
  124.  
  125.     IF UCASE$(k$) = "C" THEN
  126.         AllowSubGL = 0
  127.         GLH_Load_Model_Format_X "gasprin.x", "gasprin_tmap.png"
  128.         _PUTIMAGE , backdrop: _DONTBLEND: LINE (200, 200)-(500, 500), _RGBA(0, 255, 255, 0), BF: _BLEND
  129.         AllowSubGL = 1
  130.     END IF
  131.  
  132.         scale = scale * (1 - (_MOUSEWHEEL * .1))
  133.         rot1 = _MOUSEX
  134.         rot2 = _MOUSEY
  135.     LOOP
  136.  
  137.     IF k$ = "." THEN rot3 = rot3 + 1
  138.     IF k$ = "," THEN rot3 = rot3 - 1
  139.  
  140.  
  141.  
  142.  
  143. LOOP UNTIL k$ = CHR$(27)
  144.  
  145. 'this specially named sub "_GL" is detected by QB64 and adds support for OpenGL commands
  146. 'it is called automatically whenever the underlying software deems an update is possible
  147. 'usually/ideally, this is in sync with your monitor's refresh rate
  148.     'STATIC was used above to make all variables in this sub maintain their values between calls to this sub
  149.  
  150.     IF AllowSubGL = 0 THEN EXIT SUB 'we aren't ready yet!
  151.  
  152.     'timing is everything, we don't know how fast the 3D renderer will call this sub to we use timers to smooth things out
  153.     T# = TIMER(0.001)
  154.     IF ETT# = 0 THEN ETT# = T#
  155.     ET# = T# - ETT#
  156.     ETT# = T#
  157.  
  158.     IF sub_gl_called = 0 THEN
  159.         sub_gl_called = 1 'we only need to perform the following code once
  160.         '...
  161.     END IF
  162.  
  163.     'These settings affect how OpenGL will render our content
  164.     '!!! THESE SETTINGS ARE TO SHOW HOW ALPHA CAN WORK, BUT IT IS 10x FASTER WHEN ALPHA OPTIONS ARE DISABLED !!!
  165.     '*** every setting must be reset because SUB _GL cannot guarantee settings have not changed since last time ***
  166.     _glMatrixMode _GL_PROJECTION 'Select The Projection Matrix
  167.     _glLoadIdentity 'Reset The Projection Matrix
  168.     _gluPerspective 45, _WIDTH(0) / _HEIGHT(0), 1, 100 'QB64 internally supports this GLU command for convenience sake, but does not support GLU
  169.     _glEnable _GL_TEXTURE_2D
  170.     _glEnable _GL_BLEND
  171.     _glBlendFunc _GL_SRC_ALPHA, _GL_ONE_MINUS_SRC_ALPHA 'how alpha values are interpretted
  172.     _glEnable _GL_DEPTH_TEST 'use the zbuffer
  173.     _glDepthMask _GL_TRUE
  174.     _glAlphaFunc _GL_GREATER, 0.5 'dont do anything if alpha isn't greater than 0.5 (or 128)
  175.     _glEnable _GL_ALPHA_TEST
  176.     _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MAG_FILTER, _GL_LINEAR
  177.     _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MIN_FILTER, _GL_LINEAR
  178.     '**************************************************************************************************************
  179.  
  180.     _glMatrixMode _GL_MODELVIEW 'Select The Modelview Matrix
  181.     _glLoadIdentity 'Reset The Modelview Matrix
  182.  
  183.  
  184.  
  185.     'setup our light
  186.     _glEnable _GL_LIGHTING
  187.     _glEnable _GL_LIGHT0
  188.     _glLightfv _GL_LIGHT0, _GL_DIFFUSE, GLH_RGB(.8, .8, .8)
  189.     _glLightfv _GL_LIGHT0, _GL_AMBIENT, GLH_RGB(0.1, 0.1, 0.1)
  190.     _glLightfv _GL_LIGHT0, _GL_SPECULAR, GLH_RGB(0.3, 0.3, 0.3)
  191.  
  192.     light_rot = light_rot + ET#
  193.     _glLightfv _GL_LIGHT0, _GL_POSITION, GLH_RGBA(SIN(light_rot) * 20, COS(light_rot) * 20, 20, 1)
  194.  
  195.  
  196.     _glTranslatef 0, 0, -20 'Translate Into The Screen
  197.     _glRotatef rot1, 0, 1, 0
  198.     _glRotatef rot2, 1, 0, 0
  199.     _glRotatef rot3, 0, 0, 1
  200.  
  201.  
  202.  
  203.     current_m = -1
  204.     FOR F = 1 TO FACES
  205.  
  206.         m = FACE(F).Material
  207.         IF m <> current_m THEN 'we don't switch materials unless we have to
  208.             IF current_m <> -1 THEN _glEnd 'stop rendering triangles so we can change some settings
  209.             current_m = m
  210.             IF MATERIAL(m).Texture_Image THEN
  211.  
  212.                 _glEnable _GL_TEXTURE_2D
  213.                 _glDisable _GL_COLOR_MATERIAL
  214.                 _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MAG_FILTER, _GL_LINEAR 'seems these need to be respecified
  215.                 _glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MIN_FILTER, _GL_LINEAR
  216.  
  217.  
  218.                 IF MATERIAL(m).Texture = 0 THEN
  219.                     MATERIAL(m).Texture = GLH_Image_to_Texture(MATERIAL(m).Texture_Image)
  220.                 END IF
  221.                 GLH_Select_Texture MATERIAL(m).Texture
  222.  
  223.                 _glMaterialfv _GL_FRONT, _GL_DIFFUSE, GLH_RGBA(1, 1, 1, 1)
  224.  
  225.             ELSE
  226.                 'use materials, disable textures
  227.                 _glDisable _GL_TEXTURE_2D
  228.                 _glDisable _GL_COLOR_MATERIAL
  229.  
  230.                 mult = MATERIAL(m).Diffuse.Intensity 'otherwise known as "power"
  231.                 r = MATERIAL(m).Diffuse.R * mult
  232.                 g = MATERIAL(m).Diffuse.G * mult
  233.                 b = MATERIAL(m).Diffuse.B * mult
  234.                 '            _glColor3f r, g, b
  235.                 _glMaterialfv _GL_FRONT, _GL_DIFFUSE, GLH_RGBA(r, g, b, 1)
  236.  
  237.                 mult = MATERIAL(m).Specular.Intensity
  238.                 r = MATERIAL(m).Specular.R * mult
  239.                 g = MATERIAL(m).Specular.G * mult
  240.                 b = MATERIAL(m).Specular.B * mult
  241.                 _glMaterialfv _GL_FRONT, _GL_SPECULAR, GLH_RGBA(r, g, b, 1)
  242.  
  243.             END IF
  244.  
  245.             _glBegin _GL_TRIANGLES
  246.  
  247.         END IF
  248.  
  249.         FOR s = 1 TO 3
  250.  
  251.             IF s = 1 THEN v = FACE(F).V1.V
  252.             IF s = 2 THEN v = FACE(F).V2.V
  253.             IF s = 3 THEN v = FACE(F).V3.V
  254.             v = v + 1
  255.  
  256.             'vertex
  257.             x = (VERTEX(v).X + 0) * scale
  258.             y = (VERTEX(v).Y + 0) * scale
  259.             z = (VERTEX(v).Z + 0) * scale
  260.             'normal direction from vertex
  261.             nx = VERTEX(v).NX: ny = VERTEX(v).NY: nz = VERTEX(v).NZ
  262.  
  263.  
  264.             'corner's texture coordinates
  265.             IF MATERIAL(m).Texture THEN
  266.                 IF s = 1 THEN tx = FACE(F).V1.TX: ty = FACE(F).V1.TY
  267.                 IF s = 2 THEN tx = FACE(F).V2.TX: ty = FACE(F).V2.TY
  268.                 IF s = 3 THEN tx = FACE(F).V3.TX: ty = FACE(F).V3.TY
  269.                 _glTexCoord2f tx, ty
  270.             END IF
  271.  
  272.             _glNormal3d nx, my, nz
  273.             _glVertex3f x, y, z
  274.  
  275.         NEXT
  276.  
  277.     NEXT
  278.     _glEnd
  279.  
  280.  
  281.  
  282.  
  283. 'QB64 OPEN-GL HELPER MACROS (aka. GLH macros) #######################################################################
  284.  
  285. SUB GLH_Select_Texture (texture_handle AS LONG) 'turn an image handle into a texture handle
  286.     IF texture_handle < 1 OR texture_handle > UBOUND(DONT_USE_GLH_HANDLE) THEN ERROR 258: EXIT FUNCTION
  287.     IF DONT_USE_GLH_Handle(texture_handle).in_use = 0 THEN ERROR 258: EXIT FUNCTION
  288.     _glBindTexture _GL_TEXTURE_2D, DONT_USE_GLH_Handle(texture_handle).handle
  289.  
  290. FUNCTION GLH_Image_to_Texture (image_handle AS LONG) 'turn an image handle into a texture handle
  291.     IF image_handle >= 0 THEN ERROR 258: EXIT FUNCTION 'don't allow screen pages
  292.     DIM m AS _MEM
  293.     m = _MEMIMAGE(image_handle)
  294.     DIM h AS LONG
  295.     h = DONT_USE_GLH_New_Texture_Handle
  296.     GLH_Image_to_Texture = h
  297.     _glBindTexture _GL_TEXTURE_2D, DONT_USE_GLH_Handle(h).handle
  298.     _glTexImage2D _GL_TEXTURE_2D, 0, _GL_RGBA, _WIDTH(image_handle), _HEIGHT(image_handle), 0, &H80E1&&, _GL_UNSIGNED_BYTE, m.OFFSET
  299.     _MEMFREE m
  300.  
  301. FUNCTION DONT_USE_GLH_New_Texture_Handle
  302.     handle&& = 0
  303.     _glGenTextures 1, _OFFSET(handle&&)
  304.     DONT_USE_GLH_New_Texture_Handle = handle&&
  305.     FOR h = 1 TO UBOUND(DONT_USE_GLH_Handle)
  306.         IF DONT_USE_GLH_Handle(h).in_use = 0 THEN
  307.             DONT_USE_GLH_Handle(h).in_use = 1
  308.             DONT_USE_GLH_Handle(h).handle = handle&&
  309.             DONT_USE_GLH_New_Texture_Handle = h
  310.             EXIT FUNCTION
  311.         END IF
  312.     NEXT
  313.     REDIM _PRESERVE DONT_USE_GLH_Handle(UBOUND(DONT_USE_GLH_HANDLE) * 2) AS DONT_USE_GLH_Handle_TYPE
  314.     DONT_USE_GLH_Handle(h).in_use = 1
  315.     DONT_USE_GLH_Handle(h).handle = handle&&
  316.     DONT_USE_GLH_New_Texture_Handle = h
  317.  
  318.  
  319.  
  320.  
  321. SUB GLH_Load_Model_Format_X (Filename$, Optional_Texture_Filename$)
  322.  
  323.     _AUTODISPLAY 'so loading messages can be seen
  324.  
  325.     DEFLNG A-Z
  326.  
  327.     IF LEN(Optional_Texture_Filename$) THEN
  328.         texture_image = _LOADIMAGE(Optional_Texture_Filename$, 32)
  329.         IF texure_image = -1 THEN texure_image = 0
  330.     END IF
  331.  
  332.     'temporary arrays
  333.     DIM SIDE_LIST(10000) AS LONG 'used for wrangling triangle-fans/triangle-strips
  334.     REDIM TEXCO_TX(1) AS SINGLE
  335.     REDIM TEXCO_TY(1) AS SINGLE
  336.     REDIM POLY_FACE_INDEX_FIRST(1) AS LONG
  337.     REDIM POLY_FACE_INDEX_LAST(1) AS LONG
  338.  
  339.     'buffer file
  340.     fh = FREEFILE: OPEN Filename$ FOR BINARY AS #fh: file_data$ = SPACE$(LOF(fh)): GET #fh, , file_data$: CLOSE #fh
  341.  
  342.     file_x = 1
  343.     file_data$ = UCASE$(file_data$)
  344.  
  345.     ASC_COMMA = 44
  346.     ASC_SEMICOLON = 59
  347.     ASC_LBRAC = 123
  348.     ASC_RBRAC = 125
  349.     ASC_SPACE = 32
  350.     ASC_TAB = 9
  351.     ASC_CR = 13
  352.     ASC_LF = 10
  353.     ASC_FSLASH = 47
  354.     ASC_DOT = 46
  355.     ASC_MINUS = 45
  356.  
  357.     DIM WhiteSpace(255) AS LONG
  358.     WhiteSpace(ASC_LF) = -1
  359.     WhiteSpace(ASC_CR) = -1
  360.     WhiteSpace(ASC_SPACE) = -1
  361.     WhiteSpace(ASC_TAB) = -1
  362.  
  363.     DIM FormattingCharacter(255) AS LONG
  364.     FormattingCharacter(ASC_COMMA) = -1
  365.     FormattingCharacter(ASC_SEMICOLON) = -1
  366.     FormattingCharacter(ASC_LBRAC) = -1
  367.     FormattingCharacter(ASC_RBRAC) = -1
  368.  
  369.     DIM Numeric(255) AS LONG
  370.     FOR a = 48 TO 57
  371.         Numeric(a) = -1
  372.     NEXT
  373.     Numeric(ASC_DOT) = -1
  374.     Numeric(ASC_MINUS) = -1
  375.  
  376.     PRINT "Loading model:"
  377.  
  378.     DO
  379.  
  380.         skip_comment:
  381.  
  382.         'find start of element
  383.         x1 = -1
  384.         FOR x = file_x TO LEN(file_data$)
  385.             IF WhiteSpace(ASC(file_data$, x)) = 0 THEN x1 = x: EXIT FOR
  386.         NEXT
  387.         IF x1 = -1 THEN EXIT DO 'no more data
  388.  
  389.         a = ASC(file_data$, x1)
  390.         IF a = ASC_FSLASH THEN 'commend
  391.             IF ASC(file_data$, x1 + 1) = ASC_FSLASH THEN
  392.                 FOR x = x1 TO LEN(file_data$)
  393.                     a = ASC(file_data$, x)
  394.                     IF a = ASC_CR OR a = ASC_LF THEN file_x = x + 1: GOTO skip_comment '//.....
  395.                 NEXT
  396.             END IF
  397.         END IF
  398.  
  399.         'find end of element
  400.         x2 = x1
  401.         FOR x = x1 TO LEN(file_data$)
  402.             a = ASC(file_data$, x)
  403.             IF WhiteSpace(a) THEN
  404.                 IF a = ASC_CR OR a = ASC_LF THEN EXIT FOR 'it is the end
  405.             ELSE
  406.                 'not whitespace
  407.                 IF FormattingCharacter(a) THEN EXIT FOR
  408.                 x2 = x
  409.             END IF
  410.         NEXT
  411.         file_x = x2 + 1
  412.  
  413.         a2$ = MID$(file_data$, x1, x2 - x1 + 1)
  414.  
  415.         IF LEN(skip_until$) THEN
  416.             IF a2$ <> skip_until$ THEN GOTO skip_comment
  417.             skip_until$ = ""
  418.         END IF
  419.  
  420.  
  421.  
  422.         a = ASC(a2$)
  423.  
  424.         IF Numeric(a) AND a <> ASC_DOT THEN 'faster than VAL, value conversion
  425.             v = 0
  426.             dp = 0
  427.             div = 1
  428.             IF a = ASC_MINUS THEN neg = 1: x1 = 2 ELSE neg = 0: x1 = 1
  429.             FOR x = x1 TO LEN(a2$)
  430.                 a2 = ASC(a2$, x)
  431.                 IF a2 = ASC_DOT THEN
  432.                     dp = 1
  433.                 ELSE
  434.                     v = v * 10 + (a2 - 48)
  435.                     IF dp THEN div = div * 10
  436.                 END IF
  437.             NEXT
  438.  
  439.             IF dp = 1 THEN
  440.                 v# = v
  441.                 div# = div
  442.                 IF neg THEN value# = (-v#) / div# ELSE value# = v# / div#
  443.             ELSE
  444.                 IF neg THEN value# = -v ELSE value# = v
  445.             END IF
  446.  
  447.         END IF
  448.  
  449.         IF face_input THEN
  450.             IF face_input = 3 THEN
  451.                 IF a2$ = ";" THEN
  452.                     IF last_a2$ = ";" THEN face_input = 0
  453.                     SLI = SLI + 1
  454.                 ELSEIF a2$ = "," THEN
  455.                     face_input = 2
  456.                     polygon = polygon + 1
  457.                 ELSE
  458.                     SIDE_LIST(SLI) = value#
  459.                     IF SLI >= 3 THEN
  460.                         FACES = FACES + 1
  461.                         IF FACES > UBOUND(FACE) THEN REDIM _PRESERVE FACE(UBOUND(FACE) * 2) AS FACE_TYPE
  462.                         FACE(FACES).V1.V = SIDE_LIST(1)
  463.                         FACE(FACES).V2.V = SIDE_LIST(SLI - 1)
  464.                         FACE(FACES).V3.V = SIDE_LIST(SLI)
  465.                         IF POLY_FACE_INDEX_FIRST(polygon) = 0 THEN POLY_FACE_INDEX_FIRST(polygon) = FACES
  466.                         POLY_FACE_INDEX_LAST(polygon) = FACES
  467.                         FACE(FACES).Index = polygon
  468.                     END IF
  469.  
  470.                     file_x = file_x + 1: a2$ = ";": a = ASC_SEMICOLON: SLI = SLI + 1
  471.  
  472.  
  473.                 END IF
  474.                 GOTO done
  475.             END IF
  476.             IF face_input = 2 THEN
  477.                 SIDES = value#
  478.                 SLI = 0
  479.                 face_input = 3
  480.                 GOTO done
  481.             END IF
  482.             IF face_input = 1 THEN
  483.                 POLYGONS = value#
  484.                 REDIM _PRESERVE FACE(POLYGONS * 4) AS FACE_TYPE 'estimate triangles in polygons
  485.                 REDIM POLY_FACE_INDEX_FIRST(POLYGONS) AS LONG
  486.                 REDIM POLY_FACE_INDEX_LAST(POLYGONS) AS LONG
  487.                 polygon = 1
  488.                 face_input = 2
  489.                 FACES = 0
  490.                 GOTO done
  491.             END IF
  492.         END IF
  493.  
  494.         IF mesh_input THEN
  495.             IF mesh_input = 5 THEN
  496.                 IF a = ASC_SEMICOLON THEN
  497.                     mesh_input = 0: face_input = 1
  498.                     IF normals_input = 1 THEN
  499.                         face_input = 0 'face input is unrequired on 2nd pass
  500.                         skip_until$ = "MESHMATERIALLIST"
  501.                     END IF
  502.                 END IF
  503.                 GOTO done
  504.             END IF
  505.             IF mesh_input = 4 THEN
  506.                 IF a = ASC_SEMICOLON THEN
  507.                     'ignore
  508.                 ELSEIF a = ASC_COMMA THEN
  509.                     vertex = vertex + 1
  510.                 ELSE
  511.                     IF normals_input = 1 THEN
  512.                         IF plane = 1 THEN VERTEX(vertex).NX = value#
  513.                         IF plane = 2 THEN VERTEX(vertex).NY = value#
  514.                         IF plane = 3 THEN VERTEX(vertex).NZ = value#
  515.                     ELSE
  516.                         IF plane = 1 THEN VERTEX(vertex).X = value#
  517.                         IF plane = 2 THEN VERTEX(vertex).Y = value#
  518.                         IF plane = 3 THEN VERTEX(vertex).Z = value#
  519.                     END IF
  520.  
  521.                     plane = plane + 1
  522.                     IF plane = 4 THEN
  523.                         plane = 1
  524.                         IF vertex = VERTICES THEN mesh_input = 5
  525.                     END IF
  526.  
  527.                     file_x = file_x + 1 'skip next character (semicolon)
  528.  
  529.                 END IF
  530.                 GOTO done
  531.             END IF
  532.             IF mesh_input = 3 THEN
  533.                 IF a2$ = ";" THEN mesh_input = 4
  534.                 GOTO done
  535.             END IF
  536.             IF mesh_input = 2 THEN
  537.                 VERTICES = value#
  538.                 IF normals_input = 0 THEN
  539.                     REDIM VERTEX(VERTICES) AS VERTEX_TYPE
  540.                     REDIM TEXCO_TX(VERTICES) AS SINGLE
  541.                     REDIM TEXCO_TY(VERTICES) AS SINGLE
  542.                 END IF
  543.                 mesh_input = 3
  544.                 GOTO done
  545.             END IF
  546.             IF mesh_input = 1 THEN
  547.                 IF a2$ = "{" THEN mesh_input = 2: plane = 1: vertex = 1
  548.                 GOTO done
  549.             END IF
  550.             GOTO done
  551.         END IF
  552.  
  553.         IF matlist_input THEN
  554.             IF matlist_input = 6 THEN
  555.                 IF a2$ = "," THEN
  556.                     'do nothing
  557.                 ELSEIF a2$ = ";" THEN
  558.                     matlist_input = 0
  559.                 ELSE
  560.                     polygon = polygon + 1: m = value#
  561.                     FOR f = POLY_FACE_INDEX_FIRST(polygon) TO POLY_FACE_INDEX_LAST(polygon)
  562.                         FACE(f).Material = m + 1
  563.                     NEXT
  564.                 END IF
  565.                 GOTO done
  566.             END IF
  567.             IF matlist_input = 5 AND a2$ = ";" THEN matlist_input = 6: polygon = 0: face_search_start = 1: GOTO done
  568.             IF matlist_input = 4 THEN matlist_input = 5: GOTO done
  569.             IF matlist_input = 3 AND a2$ = ";" THEN matlist_input = 4: GOTO done
  570.             IF matlist_input = 2 THEN MATERIALS = value#: REDIM MATERIAL(MATERIALS) AS MATERIAL_TYPE: matlist_input = 3: GOTO done
  571.             IF matlist_input = 1 AND a2$ = "{" THEN matlist_input = 2: GOTO done
  572.             GOTO done
  573.         END IF
  574.  
  575.         IF material_input THEN
  576.             IF material_input = 2 THEN
  577.                 IF a2$ = ";" THEN
  578.                     'do nothing
  579.                 ELSEIF a2$ = "}" THEN
  580.                     material_input = 0
  581.                 ELSE
  582.                     N = material_n
  583.                     IF N = 1 THEN MATERIAL(MATERIAL).Diffuse.R = value#
  584.                     IF N = 2 THEN MATERIAL(MATERIAL).Diffuse.G = value#
  585.                     IF N = 3 THEN MATERIAL(MATERIAL).Diffuse.B = value#
  586.                     IF N = 4 THEN MATERIAL(MATERIAL).Diffuse.A = value#
  587.                     IF N = 5 THEN MATERIAL(MATERIAL).Diffuse.Intensity = value# / 100
  588.                     IF N = 6 THEN MATERIAL(MATERIAL).Specular.R = value#
  589.                     IF N = 7 THEN MATERIAL(MATERIAL).Specular.G = value#
  590.                     IF N = 8 THEN MATERIAL(MATERIAL).Specular.B = value#
  591.                     IF N = 9 THEN MATERIAL(MATERIAL).Specular.A = value#
  592.                     IF N = 10 THEN MATERIAL(MATERIAL).Specular.Intensity = MATERIAL(MATERIAL).Diffuse.Intensity
  593.  
  594.                     'if texture_image
  595.                     material_n = N + 1
  596.  
  597.                 END IF
  598.                 GOTO done
  599.             END IF
  600.             IF material_input = 1 AND a2$ = "{" THEN material_input = 2: material_n = 1: GOTO done
  601.             GOTO done
  602.         END IF
  603.  
  604.         IF texco_input THEN
  605.             IF texco_input = 4 THEN
  606.                 IF a2$ = ";" THEN
  607.                     IF last_a2$ = ";" THEN
  608.                         texco_input = 0
  609.                         GOTO finished
  610.                     END IF
  611.                     plane = plane + 1: IF plane = 3 THEN plane = 1
  612.                 ELSEIF a2$ = "," THEN
  613.                     vertex = vertex + 1
  614.                 ELSE
  615.                     IF plane = 1 THEN
  616.                         TEXCO_TX(vertex) = value#
  617.                     ELSE
  618.                         TEXCO_TY(vertex) = value#
  619.                     END IF
  620.                 END IF
  621.                 GOTO done
  622.             END IF
  623.             IF texco_input = 3 THEN
  624.                 IF a2$ = ";" THEN texco_input = 4: plane = 1: vertex = 1
  625.                 GOTO done
  626.             END IF
  627.             IF texco_input = 2 THEN
  628.                 'vertices already known
  629.                 texco_input = 3
  630.                 GOTO done
  631.             END IF
  632.             IF texco_input = 1 THEN
  633.                 IF a2$ = "{" THEN texco_input = 2
  634.                 GOTO done
  635.             END IF
  636.  
  637.             GOTO done
  638.         END IF
  639.  
  640.         'mode switch?
  641.         IF a2$ = "MESHTEXTURECOORDS" THEN texco_input = 1: PRINT "[Texture Coordinates]";: GOTO done
  642.         IF a2$ = "MESHNORMALS" THEN normals_input = 1: mesh_input = 1: face_input = 0: PRINT "[Normals]";: GOTO done
  643.         IF a2$ = "MESH" THEN mesh_input = 1: PRINT "[Mesh Vertices & Faces]";: GOTO done
  644.         IF a2$ = "MESHMATERIALLIST" THEN matlist_input = 1: PRINT "[Face Material Indexes]";: GOTO done
  645.         IF LEFT$(a2$, 9) = "MATERIAL " THEN
  646.             material_input = 1: MATERIAL = MATERIAL + 1
  647.             MATERIAL(MATERIAL).Texture = 0: MATERIAL(MATERIAL).Texture_Image = texture_image
  648.             PRINT "[Material]";: GOTO done
  649.         END IF
  650.         done:
  651.  
  652.         progress = progress + 1: IF progress > 5000 THEN PRINT ".";: progress = 0
  653.  
  654.         IF a = ASC_SEMICOLON THEN
  655.             last_a2$ = a2$
  656.         ELSE
  657.             IF LEN(last_a2$) THEN last_a2$ = ""
  658.         END IF
  659.  
  660.     LOOP
  661.     finished:
  662.     'change texture coords (with are organised per vertex to be organised by face side
  663.     'that way one vertex can share multiple materials without duplicating the vertex
  664.     PRINT "[Attaching Texture Coordinates to Face Cornders]";
  665.     f = 1
  666.     DO UNTIL f > FACES
  667.         v = FACE(f).V1.V + 1: FACE(f).V1.TX = TEXCO_TX(v): FACE(f).V1.TY = TEXCO_TY(v)
  668.         v = FACE(f).V2.V + 1: FACE(f).V2.TX = TEXCO_TX(v): FACE(f).V2.TY = TEXCO_TY(v)
  669.         v = FACE(f).V3.V + 1: FACE(f).V3.TX = TEXCO_TX(v): FACE(f).V3.TY = TEXCO_TY(v)
  670.         f = f + 1
  671.     LOOP
  672.     PRINT
  673.     PRINT "Model loaded!"
  674.  
  675.     DEFSNG A-Z
  676.  
  677.  
  678. FUNCTION GLH_RGB%& (r AS SINGLE, g AS SINGLE, b AS SINGLE)
  679.     DONT_USE_GLH_COL_RGBA(1) = r
  680.     DONT_USE_GLH_COL_RGBA(2) = g
  681.     DONT_USE_GLH_COL_RGBA(3) = b
  682.     DONT_USE_GLH_COL_RGBA(4) = 1
  683.     GLH_RGB = _OFFSET(DONT_USE_GLH_COL_RGBA())
  684.  
  685. FUNCTION GLH_RGBA%& (r AS SINGLE, g AS SINGLE, b AS SINGLE, a AS SINGLE)
  686.     DONT_USE_GLH_COL_RGBA(1) = r
  687.     DONT_USE_GLH_COL_RGBA(2) = g
  688.     DONT_USE_GLH_COL_RGBA(3) = b
  689.     DONT_USE_GLH_COL_RGBA(4) = a
  690.     GLH_RGBA = _OFFSET(DONT_USE_GLH_COL_RGBA())
  691.  

 
3d_model_viewer screenshot.jpg
« Last Edit: March 30, 2020, 05:51:50 am by Qwerkey »