📄 clsmd2.cls
字号:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "Cls_MD2"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
'*********************************************************************'
'*** ***'
'*** Diese Klasse decodiert und rendert Quake2 (MD2) models. ***'
'*** ***'
'*** Original autor: ***'
'*** Russel Taylor (www.solarsplace.com) ***'
'*** Keyframe-Animation & Optimierungen: ***'
'*** Marius Schmidt (www.matrixvb.da.ru) ***'
'*** ***'
'*** Neues update: ***'
'*** Ich habe ein paar Optimierungen vorgenommen, die alte ***'
'*** Animations-DLL habe ich durch die neue Version der MatrixVB ***'
'*** Mathematik-Bibliothek ausgetauscht ***'
'*** Die Animations-Funktionen der DLL kommen von Jack Hoxley ***'
'*** (www.directx4vb.com) ***'
'*** ***'
'*********************************************************************'
'HINWEIS: Wenn du einen Weg gefunden hast das Modul noch ein wenig zu
' verbessern oder eine gute Idee hast was man noch hinzuf黦en
' k鰊nte mail mir bitte (lupin003@gmx.de)
Option Explicit
'Wenn du diese beiden Deklarationen bereits in deinem Projekt hast kannst du diese beiden Zeilen l鰏chen
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
'''Informations-Header'''
'- Fasst gr鲞en und Positionen einzelner Bereiche der Datei
Private Type ModelHeaderData
magic As String * 4 'Identifiziert die Datei als QuakeII-Datei("IDP2")
Version As Long 'sollte immer 8 sein
SkinWidth As Long 'breite der texture
SkinHeight As Long 'h鰄e der texture
FrameSize As Long 'Gr鲞e eines Frames mit all seinen Daten in Bytes
NumSkins As Long 'Nummer der Texturen
NumVertices As Long 'Nummer der Punkte
numTexCoords As Long 'Anzahl der Texturkoordinaten
NumTris As Long 'Anzahl der Dreiecke
NumGLcmds As Long 'GL-commands waren spezielle Kommandos f黵 Quake um OpenGL zu verschnellern, daher m黶sen wir sie nicht beachten
NumFrames As Long 'Anzahl der Frames
OffsetSkins As Long 'Offset zu den Textur-namen (1 Name = 64bytes)
offsetTexCoords As Long 'Offset zu den Texture s-t werten
OffsetTris As Long 'Offset zu den Indizien (Leider kann man f黵 Quake-models keinen Index-Buffer benutzen, da die Textur-koordinaten auch geindext werden m黶sen)
OffsetFrames As Long 'Offset zu den Frame-daten
OffsetGLcmds As Long 'Offset zu den GL-commands
OffsetEnd As Long 'Ende der Datei -> Dateigr鲞e
End Type
Private ModelHeader As ModelHeaderData
'''Untransformierte Daten'''
'- Werden zur Berechnung des transformierten/animierten Frames verwendet
'MD2-koordinaten wurden in Byte gespeichert und dann
'erst mit der Multiplikation eines Skalierungswertes
'in float(Single)-werte umgerechnet, das spart nat黵lich
'viel Speicher, hat aber auch den Effekt zufolge das der
'Charakter manchmal so aussieht als ob er zittern w黵de (l鋝st
'sich zum beispiel besonders sch鰊 an der Stirn beobachten),
'ich finde aber allerdings das das ein ziemlich cooler Effekt ist :)
Private Type ByteVert
x As Byte 'Die Anordnung der Eintr鋑e ist ziemlich wichtig
Z As Byte
y As Byte
NormalIndex As Byte
End Type
'Dieser Typ fasst die noch nicht in float umgerechneten Punkte
Private Type FramePointData
FrameName As String * 16 'Der Name des Frames
verts() As ByteVert 'Der Byte-Vector
SngVerts() As MDLVERTEX 'Die Single-Vektoren (transformierte Byte-Koordinaten)
ScaleFac As D3DVECTOR 'Der Skalierungsfaktor f黵 jede Achse, mit ihn k鰊nen die Byte-koordinaten in float umgerechnet werden
Translate As D3DVECTOR 'Translation des Frames im 3D-Raum
End Type
'Die L鋘ge des Arrays ist die Anzahl der Vektoren.
'Das Array wird w鋒rend der Umrechnung von Byte-
'Koordinaten in DirectX-Koordinaten gebraucht
Private FramePoints() As FramePointData
'''Transformierte Texturkoordinaten'''
'- werden w鋒rend des Ladens berechnet
'Die einzelnen Textur-koordinaten f黵 alle Punkte im Objekt.
'Die Anzahl der Texturkoordinaten ist nicht immer gleich die Anzahl
'der Vertexe (da unterschiedliche Texturkoordinaten mehrmals f黵 einen
'Vertex mit gleicher Position vergeben werden k鰊nen)
Private TexCoord() As D3DVECTOR2
'''Die Indizien'''
'- Jedes Indiz verwei遲 entweder auf eine Textur-Koordinate oder einen Vektoren
'Indicies() beschreibt eine ganze Reihe an Indizien die wir brauchen um
'unser Objekt korrekt darstellen zu k鰊nen. Jedes Vertex-Indiz verwei遲 auf einen
'Punkt im FramePoints(FrameID).verts()-Array und drei dieser Indizien hinter-
'einander bilden ein Polygon, es kommt sehr oft vor das unterschiedliche Indizien auf
'ein und den selben Vertex verweisen. Au遝rdem verwei遲 jeder Textur-Index in das
'Array TexCoord
''Dieser Typ enth鋖t 6 Indizien, 3 f黵 die Vertexe und 3 f黵 die entsprechenden Textur-
''Koordinaten
Private Type ind
VertIndex(2) As Integer '3 Indizien (0-2) f黵 die Geometrie
TexIndex(2) As Integer '3 Indizien (0-2) f黵 die Texturen
End Type
Private Indicies() As ind
'''Unser fertig berechneter Frame'''
'- Frame mit Animation-tweening
'- Framedaten werden in VertexBuffer gespeichert
Private Type Frame
FrameName As String 'Name des Frames (kommt aus FramePoints)
AnimationStatus As Single 'Wo sind wir gerade in unserer Animation (in Prozent)
FrameIDFrom As Long 'Von welchen Frame kommen wir?
FrameIDTo As Long 'Zu welchen Frame wollen wir hinanimieren (normalerweise ist das FrameIDFrom + 1),
'aber wenn wir mitten in einer Animation abbrechen kann FrameIDFrom ein ganz anderer Frame sein
FrameIDTo2 As Long
FrameIDTo3 As Long
VBuffer As Direct3DVertexBuffer8 'Speichert die aktuellen Geometrie-Daten
End Type
Private CurFrame As Frame 'Der aktuelle Frame den wir berechnet haben
'Die Textur f黵 das Model
Public Texture As Direct3DTexture8
Public bUseTexture As Boolean
'''Tempor鋜e Variablen zur Berechnung des animation-tween'''
'Der neu berechnete Normalvektor
Private NV As D3DVECTOR
Private v1New As D3DVECTOR
Private v2New As D3DVECTOR
Private v3New As D3DVECTOR
'Tempor鋜es Array, nach der Berechnung des Animations-schrittes werden die Daten
'aus diesen Array dem Vertex-Buffer 黚ergeben
Private VertData() As MDLVERTEX
'Variablen um den richtigen Frame in der Animation zu finden
Private TempFrameSearchCount As Long
Public FramePrefix As String
Public AnimType As Long
Public MD2AnimSpeed As Long
Public Loaded As Boolean
'Die Rect-Struktur des Models k鰊nen wir durch zwei Vektoren speichern
Private mMin As D3DVECTOR
Private mMax As D3DVECTOR
'Hilfsvariablen
Private i As Long, t As Long
Private CountVar As Long
Private LastUpdate As Currency
Public Property Get AnimationStatus() As Single
AnimationStatus = CurFrame.AnimationStatus
End Property
Public Property Get FrameIDFrom() As Long
FrameIDFrom = CurFrame.FrameIDFrom
End Property
Public Property Get FrameIDTo() As Long
FrameIDTo = CurFrame.FrameIDTo
End Property
Public Property Get FrameIDTo2() As Long
FrameIDTo2 = CurFrame.FrameIDTo2
End Property
Public Property Get FrameIDTo3() As Long
FrameIDTo3 = CurFrame.FrameIDTo3
End Property
Public Property Get BoxMin() As D3DVECTOR
BoxMin = mMin
End Property
Public Property Get BoxMax() As D3DVECTOR
BoxMax = mMax
End Property
Public Function LoadMD2Texture(ByVal TexturePath As String) As Boolean
If Mid(TexturePath, Len(TexturePath) - 3) = ".pcx" Or Mid(TexturePath, Len(TexturePath) - 3) = ".PCX" Then
Set Texture = LoadPCX(TexturePath)
Else
Set Texture = D3DX.CreateTextureFromFileEx(D3Ddevice, TexturePath, 0, 0, D3DX_DEFAULT, 0, D3DFMT_R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, ByVal 0)
End If
End Function
Public Function LoadMD2(ByVal ModelPath As String) As Boolean
'Variablen die w鋒rend des Lade-prozesses gebraucht werden
Dim FrameID As Long, DataOffSet As Long, FileNumber As Integer
'On Error GoTo Handler:
FileNumber = FreeFile
'Datei 鰂fnen
Open ModelPath For Binary As FileNumber
'''Header auslesen'''
'Im Header stehen sehr viele wichtige Daten, wie zum Beispiel
'Offsets (Position in Byte an welcher Stelle in der Datei
'man irgendwas finden kann) oder Gr鲞en (z.B. Gr鲞e eines Frames
'oder die Anzahl an Punkten)
'Header-informationen lesen
Get #FileNumber, , ModelHeader
'Die Versions-nummer checken (es gibt nicht sehr viele unterschiedliche MD2-versionsnummern)
If ModelHeader.magic <> "IDP2" Or ModelHeader.Version <> 8 Then
LoadMD2 = False
Exit Function
End If
'Wir brauchen die Anzahl der Frames -1 (weil ein Array ja noch Frame 0 speichern kann)
ModelHeader.NumFrames = ModelHeader.NumFrames - 1
'Indizien f黵 die Polygone auslesen
'Jedes Polygon braucht 3 Indizien die auf unterschiedliche
'Vektoren verweisen und 3 Indizien die auf die richtigen Textur-
'koordinaten verweisen.
ReDim Indicies(ModelHeader.NumTris * 3)
Seek #FileNumber, ModelHeader.OffsetTris + 1
Get #FileNumber, , Indicies()
'''Textur-Koordinaten auslesen'''
'- Das indicies-array verwei遲 auf diese Textur-koordinaten
'Zwei Variablen die tempor鋜 zum auslesen benutzt werden m黶sen
Dim TexX As Integer
Dim TexY As Integer
'Textur-koordinaten-array dimensionieren
ReDim TexCoord(ModelHeader.numTexCoords)
Seek #FileNumber, ModelHeader.offsetTexCoords + 1
For t = 0 To ModelHeader.numTexCoords
Get #FileNumber, , TexX
Get #FileNumber, , TexY
TexCoord(t).x = CSng(TexX / Int(ModelHeader.SkinWidth))
TexCoord(t).y = CSng(TexY / Int(ModelHeader.SkinHeight))
Next t
'Unser VertData-Array anpassen, dieses Array wird sp鋞er f黵 die
'Berechnung der Frames verwendet
ReDim VertData(ModelHeader.NumTris * 3)
'Das Punktarray enth鋖t f黵 jeden Frame andere Punkte und die Bezeichnung des Frames
'Punktarray dimensionieren
ReDim FramePoints(ModelHeader.NumFrames)
''''FRAMES AUSLESEN''''
For FrameID = 0 To ModelHeader.NumFrames
With FramePoints(FrameID)
'Gr鲞en Anpassen
ReDim .verts(ModelHeader.NumVertices)
'Wenn man die vorgefertigen Normals benutzen m鯿hte sollte man das lightNormalIndex-Array
'dimensionieren
'ReDim FramePoints(FrameID).lightNormalIndex(ModelHeader.NumVertices)
'Der Offset wird aus den Offset an dem die Frame-daten starten plus
'FrameID mal gr鲞e eines Frames
DataOffSet = ModelHeader.OffsetFrames + 1 + (FrameID * ModelHeader.FrameSize)
'Zum offset des aktuellen Frames springen
Seek #FileNumber, DataOffSet
'Vergr鲞erungs-faktor auslesen
Get #FileNumber, , .ScaleFac.x
Get #FileNumber, , .ScaleFac.Z
Get #FileNumber, , .ScaleFac.y
'Position des Objektes auslesen
Get #FileNumber, , .Translate.x
Get #FileNumber, , .Translate.Z
Get #FileNumber, , .Translate.y
'Name des Frames ermitteln
'Der Frame-Name ist immer ein 16 Zeichen langer String (16 Byte)
Get #FileNumber, , .FrameName
''''Model-Daten auslesen''''
'Hier werden nur die Punkte ausgelesen,
'ein Punkt kommt eigentlich immer mehrmals im
'Objekt vor
'Koordinaten in Byte ermitteln
Get #FileNumber, , .verts()
'Koordinaten transformieren
ReDim .SngVerts(ModelHeader.NumTris * 3)
CountVar = 0
For i = 0 To ModelHeader.NumTris - 1
v1New = MakeVector(.ScaleFac.x * .verts(Indicies(i).VertIndex(0)).x + .Translate.x, _
.ScaleFac.y * .verts(Indicies(i).VertIndex(0)).y + .Translate.y, _
.ScaleFac.Z * .verts(Indicies(i).VertIndex(0)).Z + .Translate.Z)
v2New = MakeVector(.ScaleFac.x * .verts(Indicies(i).VertIndex(1)).x + .Translate.x, _
.ScaleFac.y * .verts(Indicies(i).VertIndex(1)).y + .Translate.y, _
.ScaleFac.Z * .verts(Indicies(i).VertIndex(1)).Z + .Translate.Z)
v3New = MakeVector(.ScaleFac.x * .verts(Indicies(i).VertIndex(2)).x + .Translate.x, _
.ScaleFac.y * .verts(Indicies(i).VertIndex(2)).y + .Translate.y, _
.ScaleFac.Z * .verts(Indicies(i).VertIndex(2)).Z + .Translate.Z)
'NV =md2lightnormals(.verts(Indicies(i).VertIndex(1)).NormalIndex)
MakeMDLVERTEX .SngVerts(MakeIndexRet), v1New, MD2LightNormals(.verts(Indicies(i).VertIndex(0)).NormalIndex), TexCoord(Indicies(i).TexIndex(0))
MakeMDLVERTEX .SngVerts(MakeIndexRet), v2New, MD2LightNormals(.verts(Indicies(i).VertIndex(1)).NormalIndex), TexCoord(Indicies(i).TexIndex(1))
MakeMDLVERTEX .SngVerts(MakeIndexRet), v3New, MD2LightNormals(.verts(Indicies(i).VertIndex(2)).NormalIndex), TexCoord(Indicies(i).TexIndex(2))
Next i
'Ein bischen Speicher frei machen
Erase .verts()
End With
Next FrameID
'Texturen auslesen
'Ich wei
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -