08-15-2025, 01:43 AM
I got no idea why as the animations for both lower and upper work as do animations for the upper model...any animation index for the lower above 2(theres 12 in total) though and it errors! (line 102 in main code) any one got any ideas? I think its the MD3_Verts array but nothing i do seems to fix it!!!!!!!
Thanks
Unseen
Thanks
Unseen
Code: (Select All)
'///////////////////////////////////////////////////////////////////////////////////////////////////////////////
'// Unseen GDK_GL - Examples - MD3 Group Models \\
'///////////////////////////////////////////////////////////////////////////////////////////////////////////////
REM $INCLUDE:'UnseenGDK_DEV\GDK2_GL.bi'
Debug%% = GDK_TRUE
DIM SHARED Player AS GDK2_GL_MD3_Group_Model '// Holds all the data - md3 character models have lower, upper and head and can have a weapon
DIM SHARED MainLight AS GDK2_Light
'///////////////////////////////////// System Initialisation ////////////////////////////////////////////////
GDK2_System_New "UnseenGDK_Dev\Projects\Predator\", 800, 600, GDK_FALSE, "Md3 Dev"
_DISPLAYORDER _GLRENDER , _SOFTWARE
'_DISPLAYORDER _SOFTWARE , _GLRENDER
_MOUSEHIDE
GDK_Init_GL = GDK_TRUE '// Set the _GL sub to initialise mode - i.e Load things
GDK_Allow_GL = GDK_TRUE '// Allow the GL sub to run
GDK_System.FPS = 30 '// set maximum of 30 fps
COLOR _RGB32(255, 255, 255), _RGBA32(0, 0, 0, 0)
'//////////////////////////////////////// Main Loop ////////////////////////////////////////////////////////////
DO
GDK2_System_Update '// Update input handlers, set fps/limit
IF GDK_Init_GL = GDK_FALSE THEN '// stuff should be loaded
GDK2_GL_MD3_Group_Update_Animation Player
END IF
LOOP UNTIL GDK_KB(0).ESC '// Quit on ESCAPE
SYSTEM
'///////////////////////////////////////////////////////////////////////////////////////////////////////////////
REM $INCLUDE:'UnseenGDK_Dev\GDK2_GL.bm'
'///////////////////////////////////////////////////////////////////////////////////////////////////////////////
SUB _GL
IF GDK_Allow_GL = GDK_TRUE THEN
'// Bog standard Open_GL Setup \\
_GLCLEARDEPTH 1
_GLCLEARCOLOR 0, 0, 0, 1
_GLENABLE _GL_DEPTH_TEST
_GLENABLE _GL_LIGHTING
_GLENABLE _GL_TEXTURE_2D
_GLMATRIXMODE _GL_PROJECTION
_GLLOADIDENTITY
_GLUPERSPECTIVE 65, GDK_System.WH.X / GDK_System.WH.Y, 1, 1000
_GLMATRIXMODE _GL_MODELVIEW
_GLLOADIDENTITY
_GLVIEWPORT 0, 0, GDK_System.WH.X, GDK_System.WH.Y
_GLENABLE MainLight.ID ' Enable the specific light source (GL_LIGHT0)
IF GDK_Init_GL = GDK_TRUE THEN '/////// Load Loop //////
' Initialize the light source here
MainLight.ID = _GL_LIGHT0 ' Use OpenGL's first light source
MainLight.Type = 1 ' Directional light
' Direction of the light (e.g., coming from top-front-right)
MainLight.Direction.X = 0
MainLight.Direction.Y = 1 ' Y is UP, so this is from above
MainLight.Direction.Z = -1 ' Z is OUT of screen, so this is from OUT (behind camera)
' Normalize the direction vector
DIM LightDirLength AS SINGLE
LightDirLength = SQR(MainLight.Direction.X * MainLight.Direction.X + MainLight.Direction.Y * MainLight.Direction.Y + MainLight.Direction.Z * MainLight.Direction.Z)
IF LightDirLength > 0 THEN
MainLight.Direction.X = MainLight.Direction.X / LightDirLength
MainLight.Direction.Y = MainLight.Direction.Y / LightDirLength
MainLight.Direction.Z = MainLight.Direction.Z / LightDirLength
END IF
MainLight.Color.R = 1 ' white light
MainLight.Color.G = 1
MainLight.Color.B = 1
MainLight.Intensity = 1 ' Full intensity
MainLight.Enabled = 1 ' Enable the light
' Set up the light properties in OpenGL
DIM AmbientColor AS GDK2_Color_3 ' Declare a temporary variable for ambient color
AmbientColor.R = .15 ' Set its RGB components
AmbientColor.G = .15
AmbientColor.B = .15
_GLLIGHTFV MainLight.ID, _GL_AMBIENT, _OFFSET(AmbientColor) ' Pass its offset
' Diffuse light (main color reflected from surfaces)
_GLLIGHTFV MainLight.ID, _GL_DIFFUSE, _OFFSET(MainLight.Color)
' Specular light (highlights, if desired)
DIM SpecularColor AS GDK2_Color_3
SpecularColor.R = 0.5
SpecularColor.G = 0.5
SpecularColor.B = 0.5
_GLLIGHTFV MainLight.ID, _GL_SPECULAR, _OFFSET(SpecularColor)
' Position for directional lights. The W component determines type.
' If W is 0, it's directional. If W is 1, it's positional.
DIM LightPosition(3) AS SINGLE
LightPosition(0) = MainLight.Direction.X
LightPosition(1) = MainLight.Direction.Y
LightPosition(2) = MainLight.Direction.Z
LightPosition(3) = 0 ' W=0 for directional light
_GLLIGHTFV MainLight.ID, _GL_POSITION, _OFFSET(LightPosition(0))
GDK2_GL_MD3_Group_Load_new Player, "lower.md3", "upper.md3", "head.md3", "predator_legs.tga", "predator_torso.tga", "predator_head.tga", "Animation.cfg"
GDK2_GL_MD3_Group_Set_Animation Player, 0, 2 '// model group, lower(0)/Upper(1)/both(2) and then the animation
GDK2_GL_MD3_Group_Set_Animation Player, 1, 5
GDK_Init_GL = GDK_FALSE '// Everything is sorted now so lets render!!!
ELSE '////// Render Loop //////
GDK_GL_CLS '// Clear the screen and depth buffer and reset the view matrix to 0,0,0
PRINT Player.Lower_Anim.Frame, Player.Upper_Anim.Frame
_GLTRANSLATEF 0, -10, -120 '// Move the camera into the scene
_GLROTATEF 270, 1, 0, 0 '// Adjust for model handedness
_GLROTATEF 270, 0, 0, 1 '// make the character face us
GDK2_GL_MD3_Group_Render_new Player
_DISPLAY
END IF
END IF
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////////////////////
'///////////////////////////////////////////////////////////////////////////////////////////////////////////////
SUB GDK2_GL_MD3_Group_Load_new (Model AS GDK2_GL_MD3_Group_Model, Lower$, Upper$, Head$, Lower_Skin$, Upper_Skin$, Head_Skin$, CFG_File$)
DIM Slash_Pos AS INTEGER
DIM Tab_FindPos AS INTEGER
DIM TempAnim AS GDK2_Animation ' Declare here to get its size
DIM SizeOfAnimUDT AS LONG '// Get the size of the GDK2_Animation UDT using LEN on the temporary variable
SizeOfAnimUDT = LEN(TempAnim) ' Correct way to get the size in QB64
GDK2_GL_Model_Load_MD3 Model.Lower, Lower$
GDK2_GL_Model_Load_MD3 Model.Upper, Upper$
GDK2_GL_Model_Load_MD3 Model.Head, Head$
Model.Lower.Skin = GDK_GL_LOAD_TEXTURE(Lower_Skin$)
Model.Upper.Skin = GDK_GL_LOAD_TEXTURE(Upper_Skin$)
Model.Head.Skin = GDK_GL_LOAD_TEXTURE(Head_Skin$)
IF LEN(CFG_File$) > 0 THEN '// animation file
FFile& = FREEFILE
OPEN CFG_File$ FOR INPUT AS #FFile&
DO
LINE INPUT #FFile&, Data_Line$
IF INSTR(Data_Line$, "TORSO") THEN
Model.Upper_Anim_Count = Model.Upper_Anim_Count + 1
ELSEIF INSTR(Data_Line$, "LEGS") THEN
Model.Lower_Anim_Count = Model.Lower_Anim_Count + 1
ELSEIF INSTR(Data_Line$, "BOTH") THEN
Model.Both_Anim_Count = Model.Both_Anim_Count + 1
END IF
LOOP WHILE NOT EOF(FFile&)
CLOSE #FFile&
DIM Lower(Model.Lower_Anim_Count - 1) AS GDK2_Animation
DIM Upper(Model.Upper_Anim_Count - 1) AS GDK2_Animation
DIM Both(Model.Both_Anim_Count - 1) AS GDK2_Animation
FFile& = FREEFILE
OPEN CFG_File$ FOR INPUT AS #FFile&
DO
LINE INPUT #FFile&, Data_Line$
IF INSTR(Data_Line$, "TORSO") OR INSTR(Data_Line$, "LEGS") OR INSTR(Data_Line$, "BOTH") THEN
'// Extract the animation name first, as it's at the end after "//"
Slash_Pos = INSTR(Data_Line$, "/")
'Anim_Name$ = LTRIM$(RTRIM$(MID$(Data_Line$, Slash_Pos + 2))) ' Get text after "//"
'// Now process the numeric part before "//"
Working_Data_Line$ = LTRIM$(RTRIM$(LEFT$(Data_Line$, Slash_Pos - 1))) ' Get text before "//"
'// Extract Start_Frame
Tab_FindPos = INSTR(Working_Data_Line$, CHR$(9))
IF Tab_FindPos > 0 THEN
Start_Frame& = INT(VAL(LEFT$(Working_Data_Line$, Tab_FindPos)))
Working_Data_Line$ = MID$(Working_Data_Line$, Tab_FindPos + 1) ' Resize string
END IF
Working_Data_Line$ = LTRIM$(RTRIM$(Working_Data_Line$))
'// Extract Num_Frames
Tab_FindPos = INSTR(Working_Data_Line$, CHR$(9))
IF Tab_FindPos > 0 THEN
Num_Frames& = INT(VAL(LEFT$(Working_Data_Line$, Tab_FindPos)))
Working_Data_Line$ = MID$(Working_Data_Line$, Tab_FindPos + 1) ' Resize string
END IF
Working_Data_Line$ = LTRIM$(RTRIM$(Working_Data_Line$))
'// Extract Loop_Frames
Tab_FindPos = INSTR(Working_Data_Line$, CHR$(9))
IF Tab_FindPos > 0 THEN
Loop_Frames& = INT(VAL(LEFT$(Working_Data_Line$, Tab_FindPos)))
Working_Data_Line$ = MID$(Working_Data_Line$, Tab_FindPos + 1) ' Resize string
END IF
Working_Data_Line$ = LTRIM$(RTRIM$(Working_Data_Line$))
'// Extract Anim_FPS (the rest of the string after the last tab)
Anim_FPS = 1 / INT(VAL(Working_Data_Line$))
IF INSTR(Data_Line$, "LEGS") THEN
GDK2_Animation_New Lower(LowerIndex), Start_Frame&, Start_Frame& + Num_Frames& - 1, Anim_FPS
LowerIndex = LowerIndex + 1
ELSEIF INSTR(Data_Line$, "TORSO") THEN
GDK2_Animation_New Upper(UpperIndex), Start_Frame&, Start_Frame& + Num_Frames& - 1, Anim_FPS
UpperIndex = UpperIndex + 1
ELSEIF INSTR(Data_Line$, "BOTH") THEN
GDK2_Animation_New Both(BothIndex), Start_Frame&, Start_Frame& + Num_Frames& - 1, Anim_FPS
BothIndex = BothIndex + 1
END IF
END IF
LOOP WHILE NOT EOF(FFile&)
CLOSE #FFile&
Model.Lower_Anim_Data = _MEMNEW(Model.Lower_Anim_Count * SizeOfAnimUDT)
Model.Upper_Anim_Data = _MEMNEW(Model.Upper_Anim_Count * SizeOfAnimUDT)
Model.Both_Anim_Data = _MEMNEW(Model.Both_Anim_Count * SizeOfAnimUDT)
_MEMPUT Model.Lower_Anim_Data, Model.Lower_Anim_Data.OFFSET, Lower()
_MEMPUT Model.Upper_Anim_Data, Model.Upper_Anim_Data.OFFSET, Upper()
_MEMPUT Model.Both_Anim_Data, Model.Both_Anim_Data.OFFSET, Both()
END IF
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////////////////////
SUB GDK2_GL_MD3_Group_Render_new (Model AS GDK2_GL_MD3_Group_Model)
_GLPUSHMATRIX
GDK2_GL_Model_Render_MD3_New Model.Lower, Model.Lower_Anim.Frame '// Render Legs
MD3_Orientate_Using_Tag Model.Upper, Model.Upper_Anim.Frame, Model.Lower, Model.Lower_Anim.Frame
GDK2_GL_Model_Render_MD3_New Model.Upper, Model.Upper_Anim.Frame '// Render Torso
MD3_Orientate_Using_Tag Model.Head, 0, Model.Upper, Model.Upper_Anim.Frame
GDK2_GL_Model_Render_MD3_New Model.Head, 0 '// Render Head
_GLPOPMATRIX
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////////////////////
SUB GDK2_GL_Model_Render_MD3_New (Model AS GDK2_GL_MODEL, Frame%)
' Declarations for scalar variables and static arrays - using your specified dimensions
DIM TmpMD3 AS GDK_GL_MD3_Header '// stores the model header info
DIM VB_Vert(8, Model.Num_Tris - 1) AS SINGLE '// Vertex buffer (X,Y,Z for 3 vertices per triangle slot)
DIM TC(5, Model.Num_Tris - 1) AS SINGLE '// Texture coordinate array (U,V for 3 vertices per triangle slot)
DIM Norm(8, Model.Num_Tris - 1) AS SINGLE '// Normal buffer (X,Y,Z for 3 vertices per triangle slot)
DIM T_BytePos AS LONG, V_BytePos AS _UNSIGNED LONG, ST_BytePos AS LONG ' N_BytePos is no longer needed
' Variables for normal decoding
DIM CurrentNormal AS _UNSIGNED INTEGER
DIM lat_encoded AS _UNSIGNED _BYTE
DIM lng_encoded AS _UNSIGNED _BYTE
' Get header info
_MEMGET Model.Header, Model.Header.OFFSET, TmpMD3
DIM MD3_Surface(TmpMD3.Num_Surfaces - 1) AS GDK_GL_MD3_Surface
_MEMGET Model.Surface_Data, Model.Surface_Data.OFFSET, MD3_Surface()
' Loop through each surface
FOR j& = 0 TO TmpMD3.Num_Surfaces - 1
REDIM MD3_Tris(MD3_Surface(j&).Num_Tris - 1) AS GDK_GL_MD3_Triangle
REDIM MD3_Verts((MD3_Surface(j&).Num_Verts * MD3_Surface(j&).Num_Frames) - 1) AS GDK_GL_MD3_Vertex
REDIM MD3_TexCoord(MD3_Surface(j&).Num_Verts - 1) AS GDK_GL_MD3_TexCoord
_MEMGET Model.Tri_Data, Model.Tri_Data.OFFSET + T_BytePos, MD3_Tris()
_MEMGET Model.Vert_Data, Model.Vert_Data.OFFSET + V_BytePos, MD3_Verts()
_MEMGET Model.ST_Data, Model.ST_Data.OFFSET + ST_BytePos, MD3_TexCoord()
Frame_Offset& = MD3_Surface(j&).Num_Verts * Frame%
' Loop through each triangle in the current surface
FOR i& = 0 TO MD3_Surface(j&).Num_Tris - 1
' 1. Process Vertex Positions (X, Y, Z for 3 vertices)
VB_Vert(0, i& + VB_Offset&) = (MD3_Verts(Frame_Offset& + MD3_Tris(i&).X).X / 64) * Model.Scale
VB_Vert(1, i& + VB_Offset&) = (MD3_Verts(Frame_Offset& + MD3_Tris(i&).X).Y / 64) * Model.Scale
VB_Vert(2, i& + VB_Offset&) = (MD3_Verts(Frame_Offset& + MD3_Tris(i&).X).Z / 64) * Model.Scale
VB_Vert(3, i& + VB_Offset&) = (MD3_Verts(Frame_Offset& + MD3_Tris(i&).Y).X / 64) * Model.Scale
VB_Vert(4, i& + VB_Offset&) = (MD3_Verts(Frame_Offset& + MD3_Tris(i&).Y).Y / 64) * Model.Scale
VB_Vert(5, i& + VB_Offset&) = (MD3_Verts(Frame_Offset& + MD3_Tris(i&).Y).Z / 64) * Model.Scale
VB_Vert(6, i& + VB_Offset&) = (MD3_Verts(Frame_Offset& + MD3_Tris(i&).Z).X / 64) * Model.Scale
VB_Vert(7, i& + VB_Offset&) = (MD3_Verts(Frame_Offset& + MD3_Tris(i&).Z).Y / 64) * Model.Scale
VB_Vert(8, i& + VB_Offset&) = (MD3_Verts(Frame_Offset& + MD3_Tris(i&).Z).Z / 64) * Model.Scale
' 2. Process Texture Coordinates (U, V for 3 vertices)
TC(0, i& + VB_Offset&) = MD3_TexCoord(MD3_Tris(i&).X).Left
TC(1, i& + VB_Offset&) = MD3_TexCoord(MD3_Tris(i&).X).Right
TC(2, i& + VB_Offset&) = MD3_TexCoord(MD3_Tris(i&).Y).Left
TC(3, i& + VB_Offset&) = MD3_TexCoord(MD3_Tris(i&).Y).Right
TC(4, i& + VB_Offset&) = MD3_TexCoord(MD3_Tris(i&).Z).Left
TC(5, i& + VB_Offset&) = MD3_TexCoord(MD3_Tris(i&).Z).Right
' 3. Process Normal Vectors (X, Y, Z for 3 vertices)
' Vertex 1 Normal: Get from MD3_Verts(index).NormalField
CurrentNormal = MD3_Verts(Frame_Offset& + MD3_Tris(i&).X).Normal ' **ASSUMPTION: MD3_Vertex UDT has a field named Normal**
MD3_DecodeNormalVector CurrentNormal, Nx, Ny, Nz
MD3_NormalizeVector Nx, Ny, Nz
Norm(0, i& + VB_Offset&) = Nx
Norm(1, i& + VB_Offset&) = Ny
Norm(2, i& + VB_Offset&) = Nz
' Vertex 2 Normal
CurrentNormal = MD3_Verts(Frame_Offset& + MD3_Tris(i&).Y).Normal ' **ASSUMPTION: MD3_Vertex UDT has a field named Normal**
MD3_DecodeNormalVector CurrentNormal, Nx, Ny, Nz
MD3_NormalizeVector Nx, Ny, Nz
Norm(3, i& + VB_Offset&) = Nx
Norm(4, i& + VB_Offset&) = Ny
Norm(5, i& + VB_Offset&) = Nz
' Vertex 3 Normal
CurrentNormal = MD3_Verts(Frame_Offset& + MD3_Tris(i&).Z).Normal ' **ASSUMPTION: MD3_Vertex UDT has a field named Normal**
MD3_DecodeNormalVector CurrentNormal, Nx, Ny, Nz
MD3_NormalizeVector Nx, Ny, Nz
Norm(6, i& + VB_Offset&) = Nx
Norm(7, i& + VB_Offset&) = Ny
Norm(8, i& + VB_Offset&) = Nz
NEXT
VB_Offset& = VB_Offset& + MD3_Surface(j&).Num_Tris
' Update byte positions for the next surface
T_BytePos = T_BytePos + (LEN(MD3_Tris(0)) * MD3_Surface(j&).Num_Tris)
V_BytePos = V_BytePos + (LEN(MD3_Verts(0)) * (MD3_Surface(j&).Num_Verts * MD3_Surface(j&).Num_Frames))
ST_BytePos = ST_BytePos + (LEN(MD3_TexCoord(0)) * MD3_Surface(j&).Num_Verts)
NEXT
'// All data stored into memory - lets render !! \\
_GLENABLECLIENTSTATE _GL_VERTEX_ARRAY
_GLENABLECLIENTSTATE _GL_TEXTURE_COORD_ARRAY
_GLENABLECLIENTSTATE _GL_NORMAL_ARRAY
_GLBINDTEXTURE _GL_TEXTURE_2D, Model.Skin
_GLVERTEXPOINTER 3, _GL_FLOAT, 0, _OFFSET(VB_Vert())
_GLTEXCOORDPOINTER 2, _GL_FLOAT, 0, _OFFSET(TC())
_GLNORMALPOINTER _GL_FLOAT, 0, _OFFSET(Norm())
_GLDRAWARRAYS _GL_TRIANGLES, 0, Model.Num_Tris * 3
_GLDISABLECLIENTSTATE _GL_VERTEX_ARRAY
_GLDISABLECLIENTSTATE _GL_TEXTURE_COORD_ARRAY
_GLDISABLECLIENTSTATE _GL_NORMAL_ARRAY
END SUB
'///////////////////////////////////////////////////////////////////////////////////////////////////////////////


![[Image: new-gdk-gl-features.png]](https://i.ibb.co/RpKCVjcJ/new-gdk-gl-features.png)