mirror of
https://github.com/QB64-Phoenix-Edition/QB64pe.git
synced 2024-09-09 12:50:17 +00:00
These tests use a variety of sample code (with some of the larger files removed, so they are not complete!) and verifies that they all compile successfully.
711 lines
22 KiB
QBasic
711 lines
22 KiB
QBasic
CHDIR "programs\samples\open_gl"
|
|
|
|
' This example shows how models with textures or materials can be displayed with OpenGL using QB64
|
|
'
|
|
'IMPORTANT:
|
|
' Whilst the .X file loader is optimized for speed, it is very incomplete:
|
|
' -only .X files in text file format
|
|
' -only one object, not a cluster of objects
|
|
' -if using a texture, use a single texture which will be applied to all materials
|
|
' -all the 3D models in this example were exported from Blender, a free 3D creation tool
|
|
' Blender tips: CTRL+J to amalgamate objects, select object to export first, in the UV/image-editor
|
|
' window you can export the textures built into your .blend file, apply the decimate
|
|
' modifier to reduce your polygon count to below 10000, preferably ~3000 or less
|
|
' This program is not a definitive guide to OpenGL in any way
|
|
' The GLH functions are something I threw together to stop people crashing their code by making
|
|
' calls to OpenGL with incorrectly sized memory regions. The GLH... prefixed commands are not mandatory or
|
|
' part of QB64, nor do they represent a complete library of helper commands.
|
|
' Lighting is not this example's strongest point, there's probably some work to do on light positioning
|
|
' and vertex normals
|
|
'
|
|
'Finally, I hope you enjoy this program as much as I enjoyed piecing it together,
|
|
' Galleon
|
|
|
|
'###################################### GLH SETUP #############################################
|
|
|
|
'Used to manage textures
|
|
TYPE DONT_USE_GLH_Handle_TYPE
|
|
in_use AS _BYTE
|
|
handle AS LONG
|
|
END TYPE
|
|
|
|
'Used by GLH RGB/etc helper functions
|
|
DIM SHARED DONT_USE_GLH_COL_RGBA(1 TO 4) AS SINGLE
|
|
|
|
REDIM SHARED DONT_USE_GLH_Handle(1000) AS DONT_USE_GLH_Handle_TYPE
|
|
|
|
'.X Format Model Loading Data
|
|
TYPE VERTEX_TYPE
|
|
X AS DOUBLE
|
|
Y AS DOUBLE
|
|
Z AS DOUBLE
|
|
NX AS DOUBLE
|
|
NY AS DOUBLE
|
|
NZ AS DOUBLE
|
|
END TYPE
|
|
REDIM SHARED VERTEX(1) AS VERTEX_TYPE
|
|
DIM SHARED VERTICES AS LONG
|
|
TYPE FACE_CORNER_TYPE
|
|
V AS LONG 'the vertex index
|
|
TX AS SINGLE 'texture X coordinate
|
|
TY AS SINGLE 'texture Y coordinate
|
|
END TYPE
|
|
TYPE FACE_TYPE
|
|
V1 AS FACE_CORNER_TYPE
|
|
V2 AS FACE_CORNER_TYPE
|
|
V3 AS FACE_CORNER_TYPE
|
|
Material AS LONG
|
|
Index AS LONG
|
|
END TYPE
|
|
REDIM SHARED FACE(1) AS FACE_TYPE
|
|
DIM SHARED FACES AS LONG
|
|
TYPE MATERIAL_RGBAI_TYPE
|
|
R AS SINGLE
|
|
G AS SINGLE
|
|
B AS SINGLE
|
|
A AS SINGLE
|
|
Intensity AS SINGLE
|
|
END TYPE
|
|
TYPE MATERIAL_TYPE
|
|
Diffuse AS MATERIAL_RGBAI_TYPE 'regular col
|
|
Specular AS MATERIAL_RGBAI_TYPE 'hightlight/shine col
|
|
Texture_Image AS LONG 'both an image and a texture handle are held
|
|
Texture AS LONG 'if 0, there is no texture
|
|
END TYPE
|
|
REDIM SHARED MATERIAL(1) AS MATERIAL_TYPE
|
|
DIM SHARED MATERIALS AS LONG
|
|
|
|
'##############################################################################################
|
|
|
|
DIM SHARED AllowSubGL
|
|
|
|
SCREEN _NEWIMAGE(1024, 768, 32)
|
|
|
|
backdrop = _LOADIMAGE("backdrop_tron.png")
|
|
|
|
DIM SHARED rot1
|
|
DIM SHARED rot2, rot3
|
|
DIM SHARED scale: scale = 1
|
|
|
|
'Load (default) model
|
|
GLH_Load_Model_Format_X "marty.x", "marty_tmap.png"
|
|
'draw backdrop
|
|
_PUTIMAGE , backdrop: _DONTBLEND: LINE (200, 200)-(500, 500), _RGBA(0, 255, 255, 0), BF: _BLEND
|
|
|
|
AllowSubGL = 1
|
|
|
|
DO
|
|
'This is our program's main loop
|
|
_LIMIT 100
|
|
LOCATE 1, 1
|
|
PRINT "Mouse Input:"
|
|
PRINT "{Horizonal Movement}Spin"
|
|
PRINT "{Vertical Movement}Flip"
|
|
PRINT "{Wheel}Scale"
|
|
PRINT
|
|
PRINT "Keyboard comands:"
|
|
PRINT "Switch rendering order: {1}GL behind, {2}GL on top, {3}GL only, good for speed"
|
|
PRINT "Switch/Load model: {A}Zebra, {B}Pig, {C}Car"
|
|
|
|
k$ = INKEY$
|
|
IF k$ = "1" THEN _GLRENDER _BEHIND
|
|
IF k$ = "2" THEN _GLRENDER _ONTOP
|
|
IF k$ = "3" THEN _GLRENDER _ONLY
|
|
|
|
|
|
PRINT "Angles:"; rot1, rot2, rot3
|
|
|
|
|
|
IF UCASE$(k$) = "A" THEN
|
|
AllowSubGL = 0
|
|
GLH_Load_Model_Format_X "marty.x", "marty_tmap.png"
|
|
_PUTIMAGE , backdrop: _DONTBLEND: LINE (200, 200)-(500, 500), _RGBA(0, 255, 255, 0), BF: _BLEND
|
|
AllowSubGL = 1
|
|
END IF
|
|
|
|
IF UCASE$(k$) = "B" THEN
|
|
AllowSubGL = 0
|
|
GLH_Load_Model_Format_X "piggy_mini3.x", ""
|
|
_PUTIMAGE , backdrop: _DONTBLEND: LINE (200, 200)-(500, 500), _RGBA(0, 255, 255, 0), BF: _BLEND
|
|
AllowSubGL = 1
|
|
END IF
|
|
|
|
IF UCASE$(k$) = "C" THEN
|
|
AllowSubGL = 0
|
|
GLH_Load_Model_Format_X "gasprin.x", "gasprin_tmap.png"
|
|
_PUTIMAGE , backdrop: _DONTBLEND: LINE (200, 200)-(500, 500), _RGBA(0, 255, 255, 0), BF: _BLEND
|
|
AllowSubGL = 1
|
|
END IF
|
|
|
|
DO WHILE _MOUSEINPUT
|
|
scale = scale * (1 - (_MOUSEWHEEL * .1))
|
|
rot1 = _MOUSEX
|
|
rot2 = _MOUSEY
|
|
LOOP
|
|
|
|
IF k$ = "." THEN rot3 = rot3 + 1
|
|
IF k$ = "," THEN rot3 = rot3 - 1
|
|
|
|
|
|
|
|
|
|
LOOP UNTIL k$ = CHR$(27)
|
|
END
|
|
|
|
'this specially named sub "_GL" is detected by QB64 and adds support for OpenGL commands
|
|
'it is called automatically whenever the underlying software deems an update is possible
|
|
'usually/ideally, this is in sync with your monitor's refresh rate
|
|
SUB _GL STATIC
|
|
'STATIC was used above to make all variables in this sub maintain their values between calls to this sub
|
|
|
|
IF AllowSubGL = 0 THEN EXIT SUB 'we aren't ready yet!
|
|
|
|
'timing is everything, we don't know how fast the 3D renderer will call this sub to we use timers to smooth things out
|
|
T# = TIMER(0.001)
|
|
IF ETT# = 0 THEN ETT# = T#
|
|
ET# = T# - ETT#
|
|
ETT# = T#
|
|
|
|
IF sub_gl_called = 0 THEN
|
|
sub_gl_called = 1 'we only need to perform the following code once
|
|
'...
|
|
END IF
|
|
|
|
'These settings affect how OpenGL will render our content
|
|
'!!! THESE SETTINGS ARE TO SHOW HOW ALPHA CAN WORK, BUT IT IS 10x FASTER WHEN ALPHA OPTIONS ARE DISABLED !!!
|
|
'*** every setting must be reset because SUB _GL cannot guarantee settings have not changed since last time ***
|
|
_glMatrixMode _GL_PROJECTION 'Select The Projection Matrix
|
|
_glLoadIdentity 'Reset The Projection Matrix
|
|
_gluPerspective 45, _WIDTH(0) / _HEIGHT(0), 1, 100 'QB64 internally supports this GLU command for convenience sake, but does not support GLU
|
|
_glEnable _GL_TEXTURE_2D
|
|
_glEnable _GL_BLEND
|
|
_glBlendFunc _GL_SRC_ALPHA, _GL_ONE_MINUS_SRC_ALPHA 'how alpha values are interpretted
|
|
_glEnable _GL_DEPTH_TEST 'use the zbuffer
|
|
_glDepthMask _GL_TRUE
|
|
_glAlphaFunc _GL_GREATER, 0.5 'dont do anything if alpha isn't greater than 0.5 (or 128)
|
|
_glEnable _GL_ALPHA_TEST
|
|
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MAG_FILTER, _GL_LINEAR
|
|
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MIN_FILTER, _GL_LINEAR
|
|
'**************************************************************************************************************
|
|
|
|
_glMatrixMode _GL_MODELVIEW 'Select The Modelview Matrix
|
|
_glLoadIdentity 'Reset The Modelview Matrix
|
|
|
|
|
|
|
|
'setup our light
|
|
_glEnable _GL_LIGHTING
|
|
_glEnable _GL_LIGHT0
|
|
_glLightfv _GL_LIGHT0, _GL_DIFFUSE, GLH_RGB(.8, .8, .8)
|
|
_glLightfv _GL_LIGHT0, _GL_AMBIENT, GLH_RGB(0.1, 0.1, 0.1)
|
|
_glLightfv _GL_LIGHT0, _GL_SPECULAR, GLH_RGB(0.3, 0.3, 0.3)
|
|
|
|
light_rot = light_rot + ET#
|
|
_glLightfv _GL_LIGHT0, _GL_POSITION, GLH_RGBA(SIN(light_rot) * 20, COS(light_rot) * 20, 20, 1)
|
|
|
|
|
|
_glTranslatef 0, 0, -20 'Translate Into The Screen
|
|
_glRotatef rot1, 0, 1, 0
|
|
_glRotatef rot2, 1, 0, 0
|
|
_glRotatef rot3, 0, 0, 1
|
|
|
|
|
|
|
|
current_m = -1
|
|
FOR F = 1 TO FACES
|
|
|
|
m = FACE(F).Material
|
|
IF m <> current_m THEN 'we don't switch materials unless we have to
|
|
IF current_m <> -1 THEN _glEnd 'stop rendering triangles so we can change some settings
|
|
current_m = m
|
|
IF MATERIAL(m).Texture_Image THEN
|
|
|
|
_glEnable _GL_TEXTURE_2D
|
|
_glDisable _GL_COLOR_MATERIAL
|
|
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MAG_FILTER, _GL_LINEAR 'seems these need to be respecified
|
|
_glTexParameteri _GL_TEXTURE_2D, _GL_TEXTURE_MIN_FILTER, _GL_LINEAR
|
|
|
|
|
|
IF MATERIAL(m).Texture = 0 THEN
|
|
MATERIAL(m).Texture = GLH_Image_to_Texture(MATERIAL(m).Texture_Image)
|
|
END IF
|
|
GLH_Select_Texture MATERIAL(m).Texture
|
|
|
|
_glMaterialfv _GL_FRONT, _GL_DIFFUSE, GLH_RGBA(1, 1, 1, 1)
|
|
|
|
ELSE
|
|
'use materials, disable textures
|
|
_glDisable _GL_TEXTURE_2D
|
|
_glDisable _GL_COLOR_MATERIAL
|
|
|
|
mult = MATERIAL(m).Diffuse.Intensity 'otherwise known as "power"
|
|
r = MATERIAL(m).Diffuse.R * mult
|
|
g = MATERIAL(m).Diffuse.G * mult
|
|
b = MATERIAL(m).Diffuse.B * mult
|
|
' _glColor3f r, g, b
|
|
_glMaterialfv _GL_FRONT, _GL_DIFFUSE, GLH_RGBA(r, g, b, 1)
|
|
|
|
mult = MATERIAL(m).Specular.Intensity
|
|
r = MATERIAL(m).Specular.R * mult
|
|
g = MATERIAL(m).Specular.G * mult
|
|
b = MATERIAL(m).Specular.B * mult
|
|
_glMaterialfv _GL_FRONT, _GL_SPECULAR, GLH_RGBA(r, g, b, 1)
|
|
|
|
END IF
|
|
|
|
_glBegin _GL_TRIANGLES
|
|
|
|
END IF
|
|
|
|
FOR s = 1 TO 3
|
|
|
|
IF s = 1 THEN v = FACE(F).V1.V
|
|
IF s = 2 THEN v = FACE(F).V2.V
|
|
IF s = 3 THEN v = FACE(F).V3.V
|
|
v = v + 1
|
|
|
|
'vertex
|
|
x = (VERTEX(v).X + 0) * scale
|
|
y = (VERTEX(v).Y + 0) * scale
|
|
z = (VERTEX(v).Z + 0) * scale
|
|
'normal direction from vertex
|
|
nx = VERTEX(v).NX: ny = VERTEX(v).NY: nz = VERTEX(v).NZ
|
|
|
|
|
|
'corner's texture coordinates
|
|
IF MATERIAL(m).Texture THEN
|
|
IF s = 1 THEN tx = FACE(F).V1.TX: ty = FACE(F).V1.TY
|
|
IF s = 2 THEN tx = FACE(F).V2.TX: ty = FACE(F).V2.TY
|
|
IF s = 3 THEN tx = FACE(F).V3.TX: ty = FACE(F).V3.TY
|
|
_glTexCoord2f tx, ty
|
|
END IF
|
|
|
|
_glNormal3d nx, my, nz
|
|
_glVertex3f x, y, z
|
|
|
|
NEXT
|
|
|
|
NEXT
|
|
_glEnd
|
|
|
|
END SUB
|
|
|
|
|
|
|
|
'QB64 OPEN-GL HELPER MACROS (aka. GLH macros) #######################################################################
|
|
|
|
SUB GLH_Select_Texture (texture_handle AS LONG) 'turn an image handle into a texture handle
|
|
IF texture_handle < 1 OR texture_handle > UBOUND(DONT_USE_GLH_HANDLE) THEN ERROR 258: EXIT FUNCTION
|
|
IF DONT_USE_GLH_Handle(texture_handle).in_use = 0 THEN ERROR 258: EXIT FUNCTION
|
|
_glBindTexture _GL_TEXTURE_2D, DONT_USE_GLH_Handle(texture_handle).handle
|
|
END SUB
|
|
|
|
FUNCTION GLH_Image_to_Texture (image_handle AS LONG) 'turn an image handle into a texture handle
|
|
IF image_handle >= 0 THEN ERROR 258: EXIT FUNCTION 'don't allow screen pages
|
|
DIM m AS _MEM
|
|
m = _MEMIMAGE(image_handle)
|
|
DIM h AS LONG
|
|
h = DONT_USE_GLH_New_Texture_Handle
|
|
GLH_Image_to_Texture = h
|
|
_glBindTexture _GL_TEXTURE_2D, DONT_USE_GLH_Handle(h).handle
|
|
_glTexImage2D _GL_TEXTURE_2D, 0, _GL_RGBA, _WIDTH(image_handle), _HEIGHT(image_handle), 0, &H80E1&&, _GL_UNSIGNED_BYTE, m.OFFSET
|
|
_MEMFREE m
|
|
END FUNCTION
|
|
|
|
FUNCTION DONT_USE_GLH_New_Texture_Handle
|
|
handle&& = 0
|
|
_glGenTextures 1, _OFFSET(handle&&)
|
|
DONT_USE_GLH_New_Texture_Handle = handle&&
|
|
FOR h = 1 TO UBOUND(DONT_USE_GLH_Handle)
|
|
IF DONT_USE_GLH_Handle(h).in_use = 0 THEN
|
|
DONT_USE_GLH_Handle(h).in_use = 1
|
|
DONT_USE_GLH_Handle(h).handle = handle&&
|
|
DONT_USE_GLH_New_Texture_Handle = h
|
|
EXIT FUNCTION
|
|
END IF
|
|
NEXT
|
|
REDIM _PRESERVE DONT_USE_GLH_Handle(UBOUND(DONT_USE_GLH_HANDLE) * 2) AS DONT_USE_GLH_Handle_TYPE
|
|
DONT_USE_GLH_Handle(h).in_use = 1
|
|
DONT_USE_GLH_Handle(h).handle = handle&&
|
|
DONT_USE_GLH_New_Texture_Handle = h
|
|
END FUNCTION
|
|
|
|
|
|
|
|
|
|
SUB GLH_Load_Model_Format_X (Filename$, Optional_Texture_Filename$)
|
|
|
|
_AUTODISPLAY 'so loading messages can be seen
|
|
|
|
DEFLNG A-Z
|
|
|
|
IF LEN(Optional_Texture_Filename$) THEN
|
|
texture_image = _LOADIMAGE(Optional_Texture_Filename$, 32)
|
|
IF texure_image = -1 THEN texure_image = 0
|
|
END IF
|
|
|
|
'temporary arrays
|
|
DIM SIDE_LIST(10000) AS LONG 'used for wrangling triangle-fans/triangle-strips
|
|
REDIM TEXCO_TX(1) AS SINGLE
|
|
REDIM TEXCO_TY(1) AS SINGLE
|
|
REDIM POLY_FACE_INDEX_FIRST(1) AS LONG
|
|
REDIM POLY_FACE_INDEX_LAST(1) AS LONG
|
|
|
|
'buffer file
|
|
fh = FREEFILE: OPEN Filename$ FOR BINARY AS #fh: file_data$ = SPACE$(LOF(fh)): GET #fh, , file_data$: CLOSE #fh
|
|
|
|
file_x = 1
|
|
file_data$ = UCASE$(file_data$)
|
|
|
|
ASC_COMMA = 44
|
|
ASC_SEMICOLON = 59
|
|
ASC_LBRAC = 123
|
|
ASC_RBRAC = 125
|
|
ASC_SPACE = 32
|
|
ASC_TAB = 9
|
|
ASC_CR = 13
|
|
ASC_LF = 10
|
|
ASC_FSLASH = 47
|
|
ASC_DOT = 46
|
|
ASC_MINUS = 45
|
|
|
|
DIM WhiteSpace(255) AS LONG
|
|
WhiteSpace(ASC_LF) = -1
|
|
WhiteSpace(ASC_CR) = -1
|
|
WhiteSpace(ASC_SPACE) = -1
|
|
WhiteSpace(ASC_TAB) = -1
|
|
|
|
DIM FormattingCharacter(255) AS LONG
|
|
FormattingCharacter(ASC_COMMA) = -1
|
|
FormattingCharacter(ASC_SEMICOLON) = -1
|
|
FormattingCharacter(ASC_LBRAC) = -1
|
|
FormattingCharacter(ASC_RBRAC) = -1
|
|
|
|
DIM Numeric(255) AS LONG
|
|
FOR a = 48 TO 57
|
|
Numeric(a) = -1
|
|
NEXT
|
|
Numeric(ASC_DOT) = -1
|
|
Numeric(ASC_MINUS) = -1
|
|
|
|
PRINT "Loading model:"
|
|
|
|
DO
|
|
|
|
skip_comment:
|
|
|
|
'find start of element
|
|
x1 = -1
|
|
FOR x = file_x TO LEN(file_data$)
|
|
IF WhiteSpace(ASC(file_data$, x)) = 0 THEN x1 = x: EXIT FOR
|
|
NEXT
|
|
IF x1 = -1 THEN EXIT DO 'no more data
|
|
|
|
a = ASC(file_data$, x1)
|
|
IF a = ASC_FSLASH THEN 'commend
|
|
IF ASC(file_data$, x1 + 1) = ASC_FSLASH THEN
|
|
FOR x = x1 TO LEN(file_data$)
|
|
a = ASC(file_data$, x)
|
|
IF a = ASC_CR OR a = ASC_LF THEN file_x = x + 1: GOTO skip_comment '//.....
|
|
NEXT
|
|
END IF
|
|
END IF
|
|
|
|
'find end of element
|
|
x2 = x1
|
|
FOR x = x1 TO LEN(file_data$)
|
|
a = ASC(file_data$, x)
|
|
IF WhiteSpace(a) THEN
|
|
IF a = ASC_CR OR a = ASC_LF THEN EXIT FOR 'it is the end
|
|
ELSE
|
|
'not whitespace
|
|
IF FormattingCharacter(a) THEN EXIT FOR
|
|
x2 = x
|
|
END IF
|
|
NEXT
|
|
file_x = x2 + 1
|
|
|
|
a2$ = MID$(file_data$, x1, x2 - x1 + 1)
|
|
|
|
IF LEN(skip_until$) THEN
|
|
IF a2$ <> skip_until$ THEN GOTO skip_comment
|
|
skip_until$ = ""
|
|
END IF
|
|
|
|
|
|
|
|
a = ASC(a2$)
|
|
|
|
IF Numeric(a) AND a <> ASC_DOT THEN 'faster than VAL, value conversion
|
|
v = 0
|
|
dp = 0
|
|
div = 1
|
|
IF a = ASC_MINUS THEN neg = 1: x1 = 2 ELSE neg = 0: x1 = 1
|
|
FOR x = x1 TO LEN(a2$)
|
|
a2 = ASC(a2$, x)
|
|
IF a2 = ASC_DOT THEN
|
|
dp = 1
|
|
ELSE
|
|
v = v * 10 + (a2 - 48)
|
|
IF dp THEN div = div * 10
|
|
END IF
|
|
NEXT
|
|
|
|
IF dp = 1 THEN
|
|
v# = v
|
|
div# = div
|
|
IF neg THEN value# = (-v#) / div# ELSE value# = v# / div#
|
|
ELSE
|
|
IF neg THEN value# = -v ELSE value# = v
|
|
END IF
|
|
|
|
END IF
|
|
|
|
IF face_input THEN
|
|
IF face_input = 3 THEN
|
|
IF a2$ = ";" THEN
|
|
IF last_a2$ = ";" THEN face_input = 0
|
|
SLI = SLI + 1
|
|
ELSEIF a2$ = "," THEN
|
|
face_input = 2
|
|
polygon = polygon + 1
|
|
ELSE
|
|
SIDE_LIST(SLI) = value#
|
|
IF SLI >= 3 THEN
|
|
FACES = FACES + 1
|
|
IF FACES > UBOUND(FACE) THEN REDIM _PRESERVE FACE(UBOUND(FACE) * 2) AS FACE_TYPE
|
|
FACE(FACES).V1.V = SIDE_LIST(1)
|
|
FACE(FACES).V2.V = SIDE_LIST(SLI - 1)
|
|
FACE(FACES).V3.V = SIDE_LIST(SLI)
|
|
IF POLY_FACE_INDEX_FIRST(polygon) = 0 THEN POLY_FACE_INDEX_FIRST(polygon) = FACES
|
|
POLY_FACE_INDEX_LAST(polygon) = FACES
|
|
FACE(FACES).Index = polygon
|
|
END IF
|
|
|
|
file_x = file_x + 1: a2$ = ";": a = ASC_SEMICOLON: SLI = SLI + 1
|
|
|
|
|
|
END IF
|
|
GOTO done
|
|
END IF
|
|
IF face_input = 2 THEN
|
|
SIDES = value#
|
|
SLI = 0
|
|
face_input = 3
|
|
GOTO done
|
|
END IF
|
|
IF face_input = 1 THEN
|
|
POLYGONS = value#
|
|
REDIM _PRESERVE FACE(POLYGONS * 4) AS FACE_TYPE 'estimate triangles in polygons
|
|
REDIM POLY_FACE_INDEX_FIRST(POLYGONS) AS LONG
|
|
REDIM POLY_FACE_INDEX_LAST(POLYGONS) AS LONG
|
|
polygon = 1
|
|
face_input = 2
|
|
FACES = 0
|
|
GOTO done
|
|
END IF
|
|
END IF
|
|
|
|
IF mesh_input THEN
|
|
IF mesh_input = 5 THEN
|
|
IF a = ASC_SEMICOLON THEN
|
|
mesh_input = 0: face_input = 1
|
|
IF normals_input = 1 THEN
|
|
face_input = 0 'face input is unrequired on 2nd pass
|
|
skip_until$ = "MESHMATERIALLIST"
|
|
END IF
|
|
END IF
|
|
GOTO done
|
|
END IF
|
|
IF mesh_input = 4 THEN
|
|
IF a = ASC_SEMICOLON THEN
|
|
'ignore
|
|
ELSEIF a = ASC_COMMA THEN
|
|
vertex = vertex + 1
|
|
ELSE
|
|
IF normals_input = 1 THEN
|
|
IF plane = 1 THEN VERTEX(vertex).NX = value#
|
|
IF plane = 2 THEN VERTEX(vertex).NY = value#
|
|
IF plane = 3 THEN VERTEX(vertex).NZ = value#
|
|
ELSE
|
|
IF plane = 1 THEN VERTEX(vertex).X = value#
|
|
IF plane = 2 THEN VERTEX(vertex).Y = value#
|
|
IF plane = 3 THEN VERTEX(vertex).Z = value#
|
|
END IF
|
|
|
|
plane = plane + 1
|
|
IF plane = 4 THEN
|
|
plane = 1
|
|
IF vertex = VERTICES THEN mesh_input = 5
|
|
END IF
|
|
|
|
file_x = file_x + 1 'skip next character (semicolon)
|
|
|
|
END IF
|
|
GOTO done
|
|
END IF
|
|
IF mesh_input = 3 THEN
|
|
IF a2$ = ";" THEN mesh_input = 4
|
|
GOTO done
|
|
END IF
|
|
IF mesh_input = 2 THEN
|
|
VERTICES = value#
|
|
IF normals_input = 0 THEN
|
|
REDIM VERTEX(VERTICES) AS VERTEX_TYPE
|
|
REDIM TEXCO_TX(VERTICES) AS SINGLE
|
|
REDIM TEXCO_TY(VERTICES) AS SINGLE
|
|
END IF
|
|
mesh_input = 3
|
|
GOTO done
|
|
END IF
|
|
IF mesh_input = 1 THEN
|
|
IF a2$ = "{" THEN mesh_input = 2: plane = 1: vertex = 1
|
|
GOTO done
|
|
END IF
|
|
GOTO done
|
|
END IF
|
|
|
|
IF matlist_input THEN
|
|
IF matlist_input = 6 THEN
|
|
IF a2$ = "," THEN
|
|
'do nothing
|
|
ELSEIF a2$ = ";" THEN
|
|
matlist_input = 0
|
|
ELSE
|
|
polygon = polygon + 1: m = value#
|
|
FOR f = POLY_FACE_INDEX_FIRST(polygon) TO POLY_FACE_INDEX_LAST(polygon)
|
|
FACE(f).Material = m + 1
|
|
NEXT
|
|
END IF
|
|
GOTO done
|
|
END IF
|
|
IF matlist_input = 5 AND a2$ = ";" THEN matlist_input = 6: polygon = 0: face_search_start = 1: GOTO done
|
|
IF matlist_input = 4 THEN matlist_input = 5: GOTO done
|
|
IF matlist_input = 3 AND a2$ = ";" THEN matlist_input = 4: GOTO done
|
|
IF matlist_input = 2 THEN MATERIALS = value#: REDIM MATERIAL(MATERIALS) AS MATERIAL_TYPE: matlist_input = 3: GOTO done
|
|
IF matlist_input = 1 AND a2$ = "{" THEN matlist_input = 2: GOTO done
|
|
GOTO done
|
|
END IF
|
|
|
|
IF material_input THEN
|
|
IF material_input = 2 THEN
|
|
IF a2$ = ";" THEN
|
|
'do nothing
|
|
ELSEIF a2$ = "}" THEN
|
|
material_input = 0
|
|
ELSE
|
|
N = material_n
|
|
IF N = 1 THEN MATERIAL(MATERIAL).Diffuse.R = value#
|
|
IF N = 2 THEN MATERIAL(MATERIAL).Diffuse.G = value#
|
|
IF N = 3 THEN MATERIAL(MATERIAL).Diffuse.B = value#
|
|
IF N = 4 THEN MATERIAL(MATERIAL).Diffuse.A = value#
|
|
IF N = 5 THEN MATERIAL(MATERIAL).Diffuse.Intensity = value# / 100
|
|
IF N = 6 THEN MATERIAL(MATERIAL).Specular.R = value#
|
|
IF N = 7 THEN MATERIAL(MATERIAL).Specular.G = value#
|
|
IF N = 8 THEN MATERIAL(MATERIAL).Specular.B = value#
|
|
IF N = 9 THEN MATERIAL(MATERIAL).Specular.A = value#
|
|
IF N = 10 THEN MATERIAL(MATERIAL).Specular.Intensity = MATERIAL(MATERIAL).Diffuse.Intensity
|
|
|
|
'if texture_image
|
|
material_n = N + 1
|
|
|
|
END IF
|
|
GOTO done
|
|
END IF
|
|
IF material_input = 1 AND a2$ = "{" THEN material_input = 2: material_n = 1: GOTO done
|
|
GOTO done
|
|
END IF
|
|
|
|
IF texco_input THEN
|
|
IF texco_input = 4 THEN
|
|
IF a2$ = ";" THEN
|
|
IF last_a2$ = ";" THEN
|
|
texco_input = 0
|
|
GOTO finished
|
|
END IF
|
|
plane = plane + 1: IF plane = 3 THEN plane = 1
|
|
ELSEIF a2$ = "," THEN
|
|
vertex = vertex + 1
|
|
ELSE
|
|
IF plane = 1 THEN
|
|
TEXCO_TX(vertex) = value#
|
|
ELSE
|
|
TEXCO_TY(vertex) = value#
|
|
END IF
|
|
END IF
|
|
GOTO done
|
|
END IF
|
|
IF texco_input = 3 THEN
|
|
IF a2$ = ";" THEN texco_input = 4: plane = 1: vertex = 1
|
|
GOTO done
|
|
END IF
|
|
IF texco_input = 2 THEN
|
|
'vertices already known
|
|
texco_input = 3
|
|
GOTO done
|
|
END IF
|
|
IF texco_input = 1 THEN
|
|
IF a2$ = "{" THEN texco_input = 2
|
|
GOTO done
|
|
END IF
|
|
|
|
GOTO done
|
|
END IF
|
|
|
|
'mode switch?
|
|
IF a2$ = "MESHTEXTURECOORDS" THEN texco_input = 1: PRINT "[Texture Coordinates]";: GOTO done
|
|
IF a2$ = "MESHNORMALS" THEN normals_input = 1: mesh_input = 1: face_input = 0: PRINT "[Normals]";: GOTO done
|
|
IF a2$ = "MESH" THEN mesh_input = 1: PRINT "[Mesh Vertices & Faces]";: GOTO done
|
|
IF a2$ = "MESHMATERIALLIST" THEN matlist_input = 1: PRINT "[Face Material Indexes]";: GOTO done
|
|
IF LEFT$(a2$, 9) = "MATERIAL " THEN
|
|
material_input = 1: MATERIAL = MATERIAL + 1
|
|
MATERIAL(MATERIAL).Texture = 0: MATERIAL(MATERIAL).Texture_Image = texture_image
|
|
PRINT "[Material]";: GOTO done
|
|
END IF
|
|
done:
|
|
|
|
progress = progress + 1: IF progress > 5000 THEN PRINT ".";: progress = 0
|
|
|
|
IF a = ASC_SEMICOLON THEN
|
|
last_a2$ = a2$
|
|
ELSE
|
|
IF LEN(last_a2$) THEN last_a2$ = ""
|
|
END IF
|
|
|
|
LOOP
|
|
finished:
|
|
'change texture coords (with are organised per vertex to be organised by face side
|
|
'that way one vertex can share multiple materials without duplicating the vertex
|
|
PRINT "[Attaching Texture Coordinates to Face Cornders]";
|
|
f = 1
|
|
DO UNTIL f > FACES
|
|
v = FACE(f).V1.V + 1: FACE(f).V1.TX = TEXCO_TX(v): FACE(f).V1.TY = TEXCO_TY(v)
|
|
v = FACE(f).V2.V + 1: FACE(f).V2.TX = TEXCO_TX(v): FACE(f).V2.TY = TEXCO_TY(v)
|
|
v = FACE(f).V3.V + 1: FACE(f).V3.TX = TEXCO_TX(v): FACE(f).V3.TY = TEXCO_TY(v)
|
|
f = f + 1
|
|
LOOP
|
|
PRINT
|
|
PRINT "Model loaded!"
|
|
|
|
DEFSNG A-Z
|
|
|
|
END SUB
|
|
|
|
FUNCTION GLH_RGB%& (r AS SINGLE, g AS SINGLE, b AS SINGLE)
|
|
DONT_USE_GLH_COL_RGBA(1) = r
|
|
DONT_USE_GLH_COL_RGBA(2) = g
|
|
DONT_USE_GLH_COL_RGBA(3) = b
|
|
DONT_USE_GLH_COL_RGBA(4) = 1
|
|
GLH_RGB = _OFFSET(DONT_USE_GLH_COL_RGBA())
|
|
END FUNCTION
|
|
|
|
FUNCTION GLH_RGBA%& (r AS SINGLE, g AS SINGLE, b AS SINGLE, a AS SINGLE)
|
|
DONT_USE_GLH_COL_RGBA(1) = r
|
|
DONT_USE_GLH_COL_RGBA(2) = g
|
|
DONT_USE_GLH_COL_RGBA(3) = b
|
|
DONT_USE_GLH_COL_RGBA(4) = a
|
|
GLH_RGBA = _OFFSET(DONT_USE_GLH_COL_RGBA())
|
|
END FUNCTION
|
|
|
|
|
|
|