Post by shadow008 on Mar 31, 2011 13:05:51 GMT -5
So here's what ive been doing for animation:
(hope thats everything )
So basically, that works out just fine. BUT ITS SLOW!!! And 99% of the lag comes from none other than the interpolation. That one line of glVertexfv() brings frame rates down from about a max of 400 to around 80.... HORREY SHEIT! Theres gotta be a better method. I was thinking that the interpolated verticies could be updated maybe once every 3 frames. MAY cause jumpy animation, but i can risk that. Unfortunately, i dont have the patience to work with this code anymore. It works, but isnt very useful when it brings down framerate to absolutely nothing.
I guess what im asking is: Is there either a better way to do animation(that wont take forever to write an importer) or should this just be optimized to be able to run at decent framerates?
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Data types
struc SMD2_header
' File information
dim ident
dim version
dim skinwidth ' Width of skin texture (pixels)
dim skinheight ' Height of skin texture (pixels)
dim framesize
' Number of different components
dim num_skins ' Skins
dim num_xyz ' Vertices (x, y, z)
dim num_st ' Texture coordinates (s, t)
dim num_tris ' Triangles
dim num_glcmds ' GL Commands (which we aren't going to use)
dim num_frames ' Frames
' File offset of different components
dim ofs_skins ' Skins
dim ofs_st ' Texture coordinates (s,t)
dim ofs_tris ' Triangles
dim ofs_frames ' Frames
dim ofs_glcmds ' GL Commands (which we aren't going to use)
dim ofs_end ' End of file
endstruc
struc SMD2_vertex
dim v#(2) ' Vertex
dim normal as single ' Index of normal (into some lookup table. I can't find any info on this table, so normals and lighting aren't currently implemented.)
endstruc
struc SMD2_triangle
dim index_xyz(2) ' Index of triangle vertices
dim index_st(2) ' Index of texture coordinates
endstruc
struc SMD2_frame
dim scale#(2), translate#(2) ' Scaling and translation
dim name$ ' Display name
dim SMD2_vertex &verts() ' Vertices
endstruc
type MD2_Model
dim SMD2_header header ' Header data
dim &skins () ' Skin textures
dim &st# ()() ' Texture coordinates (compressed)
dim SMD2_triangle &tris () ' Triangles
dim SMD2_frame &frames() ' Frames
dim CurrentFrame as single
dim SMD2_frame theFrame2
dim SMD2_frame theFrame
dim frameNum
dim frameNum2
dim fileDir as string
dim filefolder as string
dim theFile as single
dim pos(2) as single
dim rot(2) as single
dim scale(2) as single
dim prefirst
dim prelast
dim interp
dim hold
dim first
dim still
end type
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Functions
''''''''''''''''''''''
' Internal functions
function LoadMD2Header(&theHeader as SMD2_header, theFile)
' Expects:
' &theHeader = points to the destination header data
' file = file handle to read from
theHeader.ident = ReadInt (theFile)
theHeader.version = ReadInt (theFile)
theHeader.skinwidth = ReadInt (theFile)
theHeader.skinheight = ReadInt (theFile)
theHeader.framesize = ReadInt (theFile)
theHeader.num_skins = ReadInt (theFile)
theHeader.num_xyz = ReadInt (theFile)
theHeader.num_st = ReadInt (theFile)
theHeader.num_tris = ReadInt (theFile)
theHeader.num_glcmds = ReadInt (theFile)
theHeader.num_frames = ReadInt (theFile)
theHeader.ofs_skins = ReadInt (theFile)
theHeader.ofs_st = ReadInt (theFile)
theHeader.ofs_tris = ReadInt (theFile)
theHeader.ofs_frames = ReadInt (theFile)
theHeader.ofs_glcmds = ReadInt (theFile)
theHeader.ofs_end = ReadInt (theFile)
return 0
endfunction
function LoadMD2Skins(&theModel as MD2_Model, theFile)
' Expects:
' &theModel = points to the destination model
' file = file handle to read from
' Seek to skin texture names
Seek (theFile, theModel.header.ofs_skins)
dim tempStr$, i2
' Allocate skin texture handles
alloc theModel.skins, theModel.header.num_skins - 1
' Load textures
for i = 0 to theModel.header.num_skins - 1
' Read texture name
tempStr$ = ""
for i2 = 1 to 64: tempStr$ = tempStr$ + ReadChar (theFile): next ' Read name
while Len (tempStr$) > 0 and Right$ (tempStr$, 1) <= " " ' Trim whitespace from right
tempStr$ = Left$ (tempStr$, Len (tempStr$) - 1)
wend
' Load texture
theModel.skins (i) = LoadMipmapTexture (theModel.FileFolder + tempStr$)
if theModel.skins (i) <= 0 then
print "Failed to load texture: " + tempStr$
endif
next
return 0
endfunction
function LoadMD2ST(&theModel as MD2_Model, theFile)
' Expects:
' &theModel = points to the destination model
' file = file handle to read from
' Allocate texture coordinates
alloc theModel.st#, theModel.header.num_st - 1, 1
' Seek to texture coordinates
Seek (theFile, theModel.header.ofs_st)
' Load texture coordinates
for i = 0 to theModel.header.num_st - 1
theModel.st# (i)(0) = ReadWord (theFile)
theModel.st# (i)(1) = ReadWord (theFile)
next
return 0
endfunction
function LoadMD2Tris(&theModel as MD2_Model, theFile)
' Expects:
' &theModel = points to the destination model
' file = file handle to read from
' Allocate triangles
alloc theModel.tris, theModel.header.num_tris - 1
' Seek to triangles
Seek (theFile, theModel.header.ofs_tris)
dim i2
' Load triangles
for i = 0 to theModel.header.num_tris - 1
for i2 = 0 to 2
theModel.tris (i).index_xyz (i2) = ReadWord (theFile)
next
for i2 = 0 to 2
theModel.tris (i).index_st (i2) = ReadWord (theFile)
next
next
return 0
endfunction
function LoadMD2Frames(&theModel as MD2_Model, theFile)
' Expects:
' &theModel = points to the destination model
' file = file handle to read from
dim &theFrame as SMD2_frame
' Allocate frames
alloc theModel.frames, theModel.header.num_frames - 1
' Seek to frames
Seek (theFile, theModel.header.ofs_frames)
dim i2, tempStr$,i3
' Load frames
for i = 0 to theModel.header.num_frames - 1
&theFrame = &theModel.frames (i)
for i2 = 0 to 2
theFrame.scale# (i2) = ReadFloat (theFile)
next
for i2 = 0 to 2
theFrame.translate# (i2) = ReadFloat (theFile)
next
tempStr$ = ""
for i2 = 1 to 16: tempStr$ = tempStr$ + ReadChar (theFile): next ' Read name
while Len (tempStr$) > 0 and Right$ (tempStr$, 1) <= " " ' Trim whitespace from right
tempStr$ = Left$ (tempStr$, Len (tempStr$) - 1)
wend
theFrame.name$ = tempStr$
' Allocate vertices
alloc theFrame.verts, theModel.header.num_xyz
' Read vertices
for i2 = 0 to theModel.header.num_xyz - 1
for i3 = 0 to 2
theFrame.verts (i2).v# (i3) = ReadByte (theFile)
next
theFrame.verts (i2).normal = ReadByte (theFile)
next
next
return 0
endfunction
''''''''''''''''''
' Main functions
' LoadMD2
' Input: theFileName$ = file to load
' Output: theModel = MD2 model
function LoadMD2(&theModel as MD2_Model,FilePath as string,FileName as string)
' Open file
TheModel.theFile = OpenFileRead (FilePath+FileName)
if FileError() <> "" then
printr fileError()
end
return 0
endif
theModel.FileFolder = FilePath
theModel.interp = false
theModel.First = true
' Allocate model
'alloc theModel
' Read header
LoadMD2Header(theModel.header, TheModel.theFile)
' Read data
LoadMD2Skins(theModel, TheModel.theFile) ' Skins
LoadMD2ST(theModel, TheModel.theFile) ' Texture coordinates (s, t)
LoadMD2Tris(theModel, TheModel.theFile) ' Triangles
LoadMD2Frames(theModel, TheModel.theFile) ' Frames
' Close file and return
CloseFile (TheModel.theFile)
return 0
endfunction
function SetNextFrame(&Model as MD2_Model,frame)
Model.frameNum2 = frame
return 0
endfunction
function SetFrame(&Model as MD2_Model,frame)
Model.frameNum = frame
return 0
endfunction
function UpdateMD2(&theModel as MD2_Model,FirstFrame,LastFrame,Speed as single,Pos() as single, Rot() as single,Scale() as single)
return 0
endfunction
function DrawMD2(&theModel as MD2_Model,FirstFrame,LastFrame,Speed as single,pos() as single,rot() as single,scale() as single)
dim Direction = LastFrame - FirstFrame,change = false,SMD2_triangle &theTriangle, i2
if theModel.first then
theModel.prefirst = FirstFrame
theModel.prelast = LastFrame
theModel.first = false
else
if theModel.prefirst <> FirstFrame then
theModel.preFirst = FirstFrame
change = true
themodel.interp = true
themodel.hold = theModel.framenum
endif
if theModel.prelast <> LastFrame then
theModel.prelast = LastFrame
change = true
themodel.interp = true
themodel.hold = theModel.framenum
endif
endif
if theModel.frameNum < FirstFrame and Direction > 0 and not themodel.interp then
SetFrame(theModel,FirstFrame)
if LastFrame - FirstFrame > 0 then
SetNextFrame(theModel,FirstFrame + 1)
else
SetNextFrame(theModel,FirstFrame)
theModel.still = true
endif
endif
if not theModel.still then
theModel.CurrentFrame = theModel.CurrentFrame + Speed
if theModel.CurrentFrame >= 1 then
theModel.CurrentFrame = theModel.CurrentFrame - 1
themodel.interp = false
theModel.FrameNum = theModel.FrameNum2
theModel.still = true
endif
endif
if Direction > 0 then
if theModel.FrameNum2 < LastFrame+1 then
if theModel.FrameNum2 = FirstFrame and theModel.FrameNum = LastFrame then
else
SetNextFrame(theModel,theModel.FrameNum + 1)
endif
elseif theModel.FrameNum2 > LastFrame then
SetNextFrame(theModel,FirstFrame)
endif
else
endif
if themodel.interp then
SetFrame(theModel,themodel.hold)
SetNextFrame(theModel,FirstFrame)
endif
if theModel.frameNum2 > theModel.header.num_frames-1 then
SetNextFrame(theModel,theModel.header.num_frames-1)
endif
dim tempVec# (2)
dim theHeader as SMD2_header = theModel.header
theModel.theFrame = theModel.frames (theModel.FrameNum)
theModel.theFrame2 = theModel.frames (theModel.FrameNum2)
' Bind texture
glEnable (GL_CULL_FACE)
glCullFace (GL_FRONT)
glEnable (GL_TEXTURE_2D)
glBindTexture (GL_TEXTURE_2D, theModel.skins (0))
' Setup texture scaling
glMatrixMode (GL_TEXTURE)
glPushMatrix ()
glScalef (1.0 / theHeader.skinWidth, -1.0 / theHeader.skinHeight, 1)
glMatrixMode (GL_MODELVIEW)
' Apply model scaling
glPushMatrix ()
glrotatef(-rot(2)-90,1,0,0)
glrotatef(-rot(0),0,1,0)
glrotatef(-rot(1)-90,0,0,1)
'tempVec# = theModel.theFrame.translate# * (1 - theModel.CurrentFrame) + theModel.theFrame2.translate# * theModel.CurrentFrame
'glTranslatef (tempVec# (0), tempVec# (1), tempVec# (2))
tempVec# = theModel.theFrame.scale# * (1 - theModel.CurrentFrame) + theModel.theFrame2.scale# * theModel.CurrentFrame
glScalef (tempVec# (0), tempVec# (1), tempVec# (2))
if theModel.frameNum = theModel.frameNum2 then
theModel.still = true
else
theModel.still = false
endif
glpushmatrix()
'1 '0
gltranslatef(pos(1),pos(2),pos(0))
glScalef(scale(0),scale(1),scale(2))
glBegin (GL_TRIANGLES)
for i = 0 to theHeader.num_tris - 1
&theTriangle = &theModel.tris (i)
for i2 = 0 to 2
'glNormal3fv (theModel.theFrame.verts (theTriangle.index_xyz (i2)).normal)
glTexCoord2fv (theModel.st# (theTriangle.index_st (i2)))
if not theModel.still then
glVertex3fv (theModel.theFrame.verts (theTriangle.index_xyz (i2)).v# * (1 - theModel.CurrentFrame) + theModel.theFrame2.verts (theTriangle.index_xyz (i2)).v# * theModel.CurrentFrame)
else
glVertex3fv (theModel.theFrame.verts (theTriangle.index_xyz (i2)).v#)
endif
next
next
glEnd ()
glpopmatrix()
' Restore modelview matrix
glPopMatrix ()
' Restore texture matrix
glMatrixMode (GL_TEXTURE)
glPopMatrix ()
glMatrixMode (GL_MODELVIEW)
glCullFace (GL_BACK)
return 0
endfunction
(hope thats everything )
So basically, that works out just fine. BUT ITS SLOW!!! And 99% of the lag comes from none other than the interpolation. That one line of glVertexfv() brings frame rates down from about a max of 400 to around 80.... HORREY SHEIT! Theres gotta be a better method. I was thinking that the interpolated verticies could be updated maybe once every 3 frames. MAY cause jumpy animation, but i can risk that. Unfortunately, i dont have the patience to work with this code anymore. It works, but isnt very useful when it brings down framerate to absolutely nothing.
I guess what im asking is: Is there either a better way to do animation(that wont take forever to write an importer) or should this just be optimized to be able to run at decent framerates?