⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clsmd2.cls

📁 一个游戏的原代码
💻 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 + -