Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Snorky

Frischling

  • »Snorky« ist der Autor dieses Themas

Beiträge: 34

Wohnort: Berlin

Beruf: Student

  • Private Nachricht senden

1

21.08.2003, 22:36

tbVideo, tbVector4 und andere Änderungen

Hoi,
tbVideo musste von mir leider ebenfalls ein paar Änderungen im Stile von tbMusic erfahren. Wieder das Gleiche mit dem aktualisieren des Standes von m_bPlaying und Process(). Außerdem ist eine DrawVideo()-Methode hinzu gekommen, mit der es schnell und einfach geht, das Video auf den Monitor zu bringen (aus Kapitel 9.2 geklaut ;) ).
Hier sind nur die Änderungen aufgelistet:
tbVideo.h

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// ******************************************************************
// Vertexformat
#define TB_VIDEO_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1)
struct SVideoVertex
{
    tbVector3   vPosition;
    float       fRHW;
    tbVector2   vTex0;
};

// ******************************************************************
// Klasse für ein Video
class TRIBASE_API tbVideo
{
private:
    // Variablen
    DWORD           m_dwOldFVF;
public:
    // Konstruktor und Destruktor
    tbVideo();
    ~tbVideo();

    // Methoden
    tbResult        Exit();                                 // Alles freigeben
    tbResult        DrawVideo(tbVector4 vRect = tbVector4(0.0f));   // Zeichnet das Video auf den Monitor
    inline BOOL                 // Inline-Methoden
    IsPlaying()                 {return m_bPlaying;}

tbVideo.cpp

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// ******************************************************************
// Konstruktor der tbVideoRenderer-Klasse
tbVideo::tbVideo()
{
    // Alles zurücksetzen
    ZeroMemory(this, sizeof(tbVideo));
}

// ******************************************************************
// Destruktor der tbVideo-Klasse
tbVideo::~tbVideo()
{
    Exit();
}

// ******************************************************************
// alles zurücksetzen
tbResult tbVideo::Exit()
{
    // Wiedergabe stoppen
    if(IsPlaying()) Stop();

    // Alle Schnittstellen freigeben
    TB_SAFE_RELEASE(m_pMediaControl);
    TB_SAFE_RELEASE(m_pMediaSeeking);
    TB_SAFE_RELEASE(m_pBasicAudio);
    TB_SAFE_RELEASE(m_pGraph);

    // Alles zurücksetzen
    ZeroMemory(this, sizeof(tbVideo));

    return TB_OK;
}

// ******************************************************************
// Initialisiert das Video aus einer Datei
tbResult tbVideo::Init(char* pcFilename)
{
    // Alles zurücksetzen
    Exit();

...
}

// ******************************************************************
// Verarbeitet das Video
tbResult tbVideo::Process()
{
    if(m_bPlaying)
    {
        if(GetCurrentPosition() >= (int)(m_dwDuration))
        {
            if(m_bLooping)
            {
                // Wenn Looping eingeschaltet ist und die Musik zu 
                // Ende ist, dann spielen wir sie erneut ab.
                return Play(TRUE);
            }
            else
            {
                // Ansonsten wird nicht mehr gespielt
                m_bPlaying = FALSE;
                return TB_OK;
            }
        }
    }

    return TB_OK;
}

// ******************************************************************
// Zeichnen des Videos auf den Backbuffer
tbResult tbVideo::DrawVideo(tbVector4 vRect)
{
    SVideoVertex aVertex[4];

    // Parameter prüfen
    if(vRect == tbVector4(0.0f)) vRect = tbVector4(0.0f, 0.0f, tbDirect3D::GetScreenSize().x, tbDirect3D::GetScreenSize().y);

    // Wenn die Videotextur gerade gesperrt ist, warten wir so lange,
    // bis sie es nicht mehr ist.
    while(((tbVideoRenderer*)m_pRenderer)->IsTextureLocked()) {}

    // Aktuellen Status speichern
    m_dwOldFVF = tbDirect3D::GetFVF();
    // Vertexformat und Videotextur setzen, Z-Buffer aus
    tbDirect3D::SetFVF(TB_VIDEO_FVF);
    tbDirect3D::SetTexture(0, ((tbVideoRenderer*)m_pRenderer)->GetTexture());
    tbDirect3D::SetRS(D3DRS_ZENABLE, D3DZB_FALSE);

    // Die vier Vertizes erstellen (Rechteck)
    // Links unten
    aVertex[0].vPosition = tbVector3(vRect.left, vRect.bottom, 0.0f);
    aVertex[0].fRHW = 1.0f;
    aVertex[0].vTex0 = tbVector2(0.0f, ((tbVideoRenderer*)m_pRenderer)->GetBottomRightTex().y);

    // Links oben
    aVertex[1].vPosition = tbVector3(vRect.left, vRect.top, 0.0f);
    aVertex[1].fRHW = 1.0f;
    aVertex[1].vTex0 = tbVector2(0.0f, 0.0f);

    // Rechts unten
    aVertex[2].vPosition = tbVector3(vRect.right, vRect.bottom, 0.0f);
    aVertex[2].fRHW = 1.0f;
    aVertex[2].vTex0 = ((tbVideoRenderer*)m_pRenderer)->GetBottomRightTex();

    // Rechts oben
    aVertex[3].vPosition = tbVector3(vRect.right, vRect.top, 0.0f);
    aVertex[3].fRHW = 1.0f;
    aVertex[3].vTex0 = tbVector2(((tbVideoRenderer*)m_pRenderer)->GetBottomRightTex().x, 0.0f);

    // Als Dreiecksfolge zeichnen
    tbDirect3D::GetDevice()->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, aVertex, sizeof(SVideoVertex));

    // Wiederherstellen des alten Status
    tbDirect3D::SetFVF(m_dwOldFVF);
    tbDirect3D::SetTexture(0, NULL);

    return TB_OK;
}

// ******************************************************************


Wie man sieht hab ich einen 4D-Vector eingefügt, immer tbColor zu mißbrauchen ging mir langsam gegens Prinzip und zwei 2D-Vektoren kann man doch auch zusammenfassen. 4D/Rects kann man sowieso irgendwann mal gebrauchen, spätestens in 2D ;D .
Hier die tbVector4.h; nicht vergessen in die TriBase.h irgendwo nach tbColor zu includen.

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/********************************************************************
     _________        __    _____
    /\___  ___\      /\_\  /\  __\
    \/__/\ \__/ _  __\/_/_ \ \ \_\\   ____    _____      __
        \ \ \  /\`´__\ /\ \ \ \  __\ /\ __\_ /\  __\   /´__`\
         \ \ \ \ \ \/  \ \ \ \ \ \_\\\ \\_\ \\ \____\ /\  __/
          \ \_\ \ \_\   \ \_\ \ \____\\ \___\ \ \____\\ \____\
           \/_/  \/_/    \/_/  \/____/ \/__/   \/____/ \/____/

    tbVector4.h
    ===========
    Diese Datei ist Teil der TriBase-Engine.

    Zweck:
    Rechnen mit 4D-Vektoren

    Autor:
    Snorky
    [21.8.03]

********************************************************************/

#ifndef __TBVECTOR4__
#define __TBVECTOR4__

// Die 4D-Vektor-Klasse
class TRIBASE_API tbVector4
{
public:
    // Variablen
    union
    {
        struct
        {
            float x1;   // Koordinaten
            float y1;
            float x2;
            float y2;
        };

        struct
        {
            float left; // Texturkoordinaten
            float top;
            float right;
            float bottom;
        };

        struct
        {
            tbVector2 vTopLeft;
            tbVector2 vBottomRight;
        };

        RECT        rect;       // RECT-Struktur
        float       c[4];       // Array der Koordinaten
        D3DCOLORVALUE   D3DColorValue;  // Farbe als D3DCOLORVALUE
    };

    // Konstruktoren
    inline tbVector4()                                                                                                              {}
    inline tbVector4(const float f) : x1(f), y1(f), x2(f), y2(f)                                                                    {}
    inline tbVector4(const float _x1, const float _y1, const float _x2, const float _y2) : x1(_x1), y1(_y1), x2(_x2), y2(_y2)       {}
    inline tbVector4(const float* pfComponent) : x1(pfComponent[0]), y1(pfComponent[1]), x2(pfComponent[2]), y2(pfComponent[3])     {}
    inline tbVector4(const tbVector2 _vTopLeft, const tbVector2 _vBottomRight) : vTopLeft(_vTopLeft), vBottomRight(_vBottomRight)   {}
    inline tbVector4(const D3DCOLORVALUE& c) : D3DColorValue(c)                                                                     {}
    inline tbVector4(const tbColor _vColor) : x1(_vColor.r), y1(_vColor.g), x2(_vColor.b), y2(_vColor.a)                            {}
    inline tbVector4(const RECT _rect) : rect(_rect)                                                                                {}
    
    // Casting-Operatoren
    inline operator float* ()           {return (float*)(c);}
    inline operator D3DCOLORVALUE& ()   {return D3DColorValue;}
    inline operator tbColor ()          {return tbColor(x1, y1, x2, y2);}

    // Arithmetische Operatoren
    inline tbVector4 operator + (const tbVector4& v) const                  {return tbVector4(x1 + v.x1, y1 + v.y1, x2 + v.x2, y2 + v.y2);}
    inline tbVector4 operator - (const tbVector4& v) const                  {return tbVector4(x1 - v.x1, y1 - v.y1, x2 - v.x2, y2 - v.y2);}
    inline tbVector4 operator - () const                                    {return tbVector4(-x1, -y1, -x2, -y2);}
    inline tbVector4 operator * (const tbVector4& v) const                  {return tbVector4(x1 * v.x1, y1 * v.y1, x2 * v.x2, y2 * v.y2);}
    inline tbVector4 operator * (const float f) const                       {return tbVector4(x1 * f, y1 * f, x2 * f, y2 * f);}
    inline tbVector4 operator / (const tbVector4& v) const                  {return tbVector4(x1 / v.x1, y1 / v.y1, x2 / v.x2, y2 / v.y2);}
    inline tbVector4 operator / (const float f) const                       {return tbVector4(x1 / f, y1 / f, x2 / f, y2 / f);}
    inline friend tbVector4 operator * (const float f, const tbVector4& v)  {return tbVector4(v.x1 * f, v.y1 * f, v.x2 * f, v.y2 * f);}

    // Zuweisungsoperatoren
    inline tbVector4 operator = (const tbVector4& v)    {x1 = v.x1; y1 = v.y1; x2 = v.x2; y2 = v.y2; return *this;}
    inline tbVector4 operator += (const tbVector4& v)   {x1 += v.x1; y1 += v.y1; x2 += v.x2; y2 += v.y2; return *this;}
    inline tbVector4 operator -= (const tbVector4& v)   {x1 -= v.x1; y1 -= v.y1; x2 -= v.x2; y2 -= v.y2; return *this;}
    inline tbVector4 operator *= (const tbVector4& v)   {x1 *= v.x1; y1 *= v.y1; x2 *= v.x2; y2 *= v.y2; return *this;}
    inline tbVector4 operator *= (const float f)        {x1 *= f; y1 *= f; x2 *= f; y2 *= f; return *this;}
    inline tbVector4 operator /= (const tbVector4& v)   {x1 /= v.x1; y1 /= v.y1; x2 /= v.x2; y2 /= v.y2; return *this;}
    inline tbVector4 operator /= (const float f)        {x1 /= f; y1 /= f; x2 /= f; y2 /= f; return *this;}

    // Vergleichsoperatoren
    inline bool operator == (const tbVector4& v) const  {if(x1 != v.x1) return false; if(y1 != v.y1) return false; if(x2 != v.x2) return false; return y2 == v.y2;}
    inline bool operator != (const tbVector4& v) const  {if(x1 != v.x1) return true; if(y1 != v.y1) return true; if(x2 != v.x2) return true; return y2 != v.y2;}
};

// ******************************************************************
// Funktionen deklarieren
inline float        tbVector4Length(const tbVector4& v)                                                 {return sqrtf(v.x1 * v.x1 + v.y1 * v.y1 + v.x2 * v.x2 + v.y2 * v.y2);}
inline float        tbVector4LengthSq(const tbVector4& v)                                               {return v.x1 * v.x1 + v.y1 * v.y1 + v.x2 * v.x2 + v.y2 * v.y2;}
inline tbVector4    tbVector4Min(const tbVector4& v1, const tbVector4& v2)                              {return tbVector4(TB_MIN(v1.x1, v2.x1), TB_MIN(v1.y1, v2.y1), TB_MIN(v1.x2, v2.x2), TB_MIN(v1.y2, v2.y2));}
inline tbVector4    tbVector4Max(const tbVector4& v1, const tbVector4& v2)                              {return tbVector4(TB_MAX(v1.x1, v2.x1), TB_MAX(v1.y1, v2.y1), TB_MAX(v1.x2, v2.x2), TB_MAX(v1.y2, v2.y2));}
inline tbVector4    tbVector4Random()                                                                   {return tbVector4(tbFloatRandom(-1.0f, 1.0f), tbFloatRandom(-1.0f, 1.0f), tbFloatRandom(-1.0f, 1.0f), tbFloatRandom(-1.0f, 1.0f));}

// ******************************************************************

#endif __TBVECTOR4__

Die leere cpp-Datei kann man sich ja dann selbst aus der 3D-Klasse nehmen, wer braucht.

Kommen wir zu den anderen Änderungen, da wäre einmal die tbINIReader, die um eine Write-Funktion erweitert wurde, schließlich ist es von Vorteil, nicht nur lesen, sondern auch schreiben zu können. Dann kann man in die ini schreiben, dass das Intro nicht noch mal abgespielt zu werden braucht, um ein Anwendungsbeispiel zu nennen.

Quellcode

1
2
3
4
    // Schreibt einen String in die INI-Datei
    tbResult WriteINIString(char* pcSection,
                            char* pcKey,
                            char* pcString);

und die Definition:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
// ******************************************************************
// Schreibt einen String in die INI-Datei
tbResult tbINIReader::WriteINIString(char* pcSection,
                                     char* pcKey,
                                     char* pcString)
{
    // String schreiben
    WritePrivateProfileString(pcSection, pcKey, pcString, pcFilePath);

    return TB_OK;
}

// ******************************************************************


Außerdem hab ich festgestellt, dass das Programm mit einem Speicherlese-Fehler abbrechen kann, wenn der temporäre String zum lesen aus INI-Dateien nicht mit Nullen vorinitialisiert wird. Also um den Fehler zu vermeiden muss man überall wo Strings für INI-Leseaktionen definiert werden, sie danach auch noch benullen, z.B.

Quellcode

1
2
    char    acString[256];
    ZeroMemory(acString, sizeof(acString));

Das müßte auch in der tb2DSprite und tb2DVolumeSprite getan werden und zwar sowohl in der ReadINISpriteInfo(), als auch in der Init() und das an mehreren Stellen. Danach ist das Proggy bei mir jedenfalls nicht mehr unter Extremeinsatz rausgeflogen. :jojo:

So ich glaube, das wars. Tageswerk vollbracht :-D

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

21.08.2003, 22:47

Wieder einmal sehr vorbildlich! :)
Bei tbVector4 würde ich auch noch ein struct mit float x, y, z, w machen. Dann können wir noch eine tbVector3TransformCoords machen, die als Ausgabe einen 4D-Vektor hat (das ist der Vektor vor der Projektion, also vor der Division durch w).

Snorky

Frischling

  • »Snorky« ist der Autor dieses Themas

Beiträge: 34

Wohnort: Berlin

Beruf: Student

  • Private Nachricht senden

3

22.08.2003, 00:07

Wie meinen? ???

Quellcode

1
2
3
4
5
6
7
        struct
        {
            float x;
            float y;
            float z;
            float w;
        };

in die tbVector4-Klasse einzufügen ist ja keen Ding, aber was Du mit dem tbVector3TransformCoords() meinst kann ich nicht nachvollziehen.
Also rate ich mal, dass Du in der tbUtils folgendes stehen haben möchtest?
h:

Quellcode

1
TRIBASE_API tbVector4   tbVector4TransformCoords(const tbVector4& v, const tbMatrix& m, float* pfOutW = NULL);                                                                                                                                                                                                                          // 4D-Vektor mit Matrix multiplizieren

cpp:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 4D-Positionsvektor transformieren
TRIBASE_API tbVector4 tbVector4TransformCoords(const tbVector4& v,
                                               const tbMatrix& m,
                                               float* pfOutW) // = NULL
{
    // Vektor mit Matrix multiplizieren
    tbVector4 vResult(v.x * m.m11 + v.y * m.m21 + v.z * m.m31 + v.w * m.m41,
                      v.x * m.m12 + v.y * m.m22 + v.z * m.m32 + v.w * m.m42,
                      v.x * m.m13 + v.y * m.m23 + v.z * m.m33 + v.w * m.m43,
                      v.x * m.m14 + v.y * m.m24 + v.z * m.m34 + v.w * m.44);

    // Wenn erwünscht, w berechnen und kopieren
    if(pfOutW != NULL)
    {
        float w = v.x * m.m14 + v.y * m.m24 + v.z * m.m34 + v.w * m.m44;
        *pfOutW = w;
    }

    return vResult;
}

Macht der Code Sinn? :headscratch:

Snorky

Frischling

  • »Snorky« ist der Autor dieses Themas

Beiträge: 34

Wohnort: Berlin

Beruf: Student

  • Private Nachricht senden

4

22.08.2003, 00:16

Vielleicht, wenn man in der einen Zeile noch das m einfügt, so dass es
+ v.w * m.m44);
heißt? Dann sieht wenigstens der Compiler einen Sinn darin ^_^

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

5

22.08.2003, 08:32

Ich meinte eigentlich eine tbVector3TransformCoords-Version die einen 4D-Vektor zurückgibt:

Quellcode

1
2
3
4
5
6
7
8
9
10
// 3D-Positionsvektor transformieren (Ausgabe: 4D)
TRIBASE_API tbVector4 tbVector3TransformCoordsTo4(const tbVector3& v,
                                                            const tbMatrix& m)
{
    // Vektor mit Matrix multiplizieren
    return tbVector4(v.x * m.m11 + v.y * m.m21 + v.z * m.m31 + m.m41,
                      v.x * m.m12 + v.y * m.m22 + v.z * m.m32 + m.m42,
                         v.x * m.m13 + v.y * m.m23 + v.z * m.m33 + m.m43,
                         v.x * m.m14 + v.y * m.m24 + v.z * m.m34 + m.m44);
}


Du musst ja wissen: wenn man einen 3D-Vektor transformiert, mit einer 4x4-Matrix, wandelt man den Vektor intern ja in einen 4D-Vektor um, dessen vierte Spalte 1 ist.
Eine Transform-Funktion für 4D-Vektoren wird man kaum brauchen.

Werbeanzeige