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

1

16.01.2011, 12:11

Bedeutung der Vertexkoordinaten

Hallo,
zur Zeit arbeite ich an meinem tieferen Verständnis für die 3D-Programmierung. Dazu habe ich ein Beispielprogramm aus dem Netz so modifiziert, dass ein rotierender Würfel dargestellt wird.
Hier erstmal der Code:

C-/C++-Quelltext

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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9.h>

#define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)

#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

PDIRECT3DDEVICE9 pD3DDevice = NULL;
PDIRECT3DVERTEXBUFFER9 v_buffer = NULL;
PDIRECT3DINDEXBUFFER9 i_buffer = NULL;
struct CUSTOMVERTEX {float x,y,z; DWORD color;};

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hWnd;
    WNDCLASSEX wc;

    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = "WindowClass";

    RegisterClassEx(&wc);

    hWnd = CreateWindowEx(NULL, "WindowClass", "Our Direct3D Program",
                        WS_OVERLAPPEDWINDOW, 0, 0, 800, 600,
                        NULL, NULL, hInstance, NULL);

    ShowWindow(hWnd, nCmdShow);

    PDIRECT3D9 pD3D = Direct3DCreate9(D3D_SDK_VERSION);

    D3DPRESENT_PARAMETERS d3dpp;

    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
    d3dpp.BackBufferWidth = 800;
    d3dpp.BackBufferHeight = 600;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

    pD3D->CreateDevice(D3DADAPTER_DEFAULT,
                    D3DDEVTYPE_HAL,
                    hWnd,
                    D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                    &d3dpp,
                    &pD3DDevice);

    CUSTOMVERTEX vertices[] =
    {
        { 0.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0), },
        { 10.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255), },
        { 10.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
        { 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(0, 0, 255), },
        { 0.0f, 10.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255), },
        { 10.0f, 10.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0), },
        { 10.0f, 10.0f, 10.0f, D3DCOLOR_XRGB(0, 0, 255), },
        { 0.0f, 10.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
};

pD3DDevice->CreateVertexBuffer(8*sizeof(CUSTOMVERTEX),
                        0,
                        CUSTOMFVF,
                        D3DPOOL_MANAGED,
                        &v_buffer,
                        NULL);

    VOID* pVoid;    // a void pointer

    // lock v_buffer and load the vertices into it
    v_buffer->Lock(0, 0, (void**)&pVoid, 0);
    memcpy(pVoid, vertices, sizeof(vertices));
    v_buffer->Unlock();

// create the indices using an int array
short indices[] =
{
    0, 1, 2, //unten
    0, 2, 3,
    0, 1, 5, //vorn
    0, 4, 5, 
    1, 2, 6, //rechts
    1, 5, 6,
    2, 3, 6, //hinten
    3, 6, 7,
    0, 3, 7, //rechts
    0, 4, 7,
    4, 5, 6, //oben
    4, 5, 7
};

// create a index buffer interface called i_buffer
pD3DDevice->CreateIndexBuffer(36*sizeof(short),
                        0,
                        D3DFMT_INDEX16,
                        D3DPOOL_MANAGED,
                        &i_buffer,
                        NULL); 

    // lock i_buffer and load the indices into it
    i_buffer->Lock(0, 0, (void**)&pVoid, 0);
    memcpy(pVoid, indices, sizeof(indices));
    i_buffer->Unlock();

    pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);  // turn off the 3D lighting
    pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);   // turn off culling
    pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);    // turn on the z-buffer

    MSG msg;

    while(TRUE)
    {
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if(msg.message == WM_QUIT)
            break;

            pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    pD3DDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

    pD3DDevice->BeginScene();

    pD3DDevice->SetFVF(CUSTOMFVF);

    // set the view transform
    D3DXMATRIX matView; // the view transform matrix
    D3DXMatrixLookAtLH(&matView,
    &D3DXVECTOR3 (5.0f, 5.0f, -50.0f),  // the camera position
    &D3DXVECTOR3 (5.0f, 5.0f, 0.0f),    // the look-at position
    &D3DXVECTOR3 (0.0f, 1.0f, 0.0f));   // the up direction
    pD3DDevice->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView
    
    // set the projection transform
    D3DXMATRIX matProjection;   // the projection transform matrix
    D3DXMatrixPerspectiveFovLH(&matProjection,
                            D3DXToRadian(45),   // the horizontal field of view
                            800.0f / 600.0f, // aspect ratio
                            1.0f,   // the near view-plane
                            100.0f);    // the far view-plane
    pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection

    // set the world transform
    static float index = 0.0f; index+=0.1f; // an ever-increasing float value
    D3DXMATRIX matRotateY;  // a matrix to store the rotation for each triangle
    D3DXMatrixRotationY(&matRotateY, index);    // the rotation matrix
    pD3DDevice->SetTransform(D3DTS_WORLD, &(matRotateY));   // set the world transform

// select the vertex buffer to display
pD3DDevice->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
pD3DDevice->SetIndices(i_buffer);

// draw the pyramid
pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);

    pD3DDevice->EndScene(); 

    pD3DDevice->Present(NULL, NULL, NULL, NULL);
    }

        v_buffer->Release();
    i_buffer->Release();
    pD3DDevice->Release();
    pD3D->Release();

    return msg.wParam;
}


// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_DESTROY:
            {
                PostQuitMessage(0);
                return 0;
            } break;
    }

    return DefWindowProc (hWnd, message, wParam, lParam);
}


Das Programm läuft in einem 800x600 Fenster. Der Würfel wird annähernd zentral dargestellt.
Jetzt frage ich mich, wie sich diese Position berechnet.
Hier werden die Vertizes festgelegt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
    CUSTOMVERTEX vertices[] =
    {
        { 0.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0), },
        { 10.0f, 0.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255), },
        { 10.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
        { 0.0f, 0.0f, 10.0f, D3DCOLOR_XRGB(0, 0, 255), },
        { 0.0f, 10.0f, 0.0f, D3DCOLOR_XRGB(0, 0, 255), },
        { 10.0f, 10.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0), },
        { 10.0f, 10.0f, 10.0f, D3DCOLOR_XRGB(0, 0, 255), },
        { 0.0f, 10.0f, 10.0f, D3DCOLOR_XRGB(255, 0, 0), },
};

Alleine von diesen ausgehend, müsste der Würfel in der linken, unteren Ecke platziert sein.
Allerdings gibt es ja auch noch die Kamera- und Sichtmatrix. Deren Parameter verstehe ich noch nicht so ganz.
Mein Ziel ist es, vor dem Programmstart zu wissen, wo der Würfel ist (z.B. das ich ihn exakt an Position x100,y100 setzten kann). Bisher läuft bei mir alles über ausprobieren und abschätzen.
Bzw. einmal anders formuliert: Wie müssten die Matrizen aussehen, damit die Vertexkoordinaten den Bildschirmkoordinaten entsprechen? (bis zum Schritt der Projektion, dieses Verfahren ist mir geläufig)

DerMark

Treue Seele

Beiträge: 324

Wohnort: Emsdetten

Beruf: Softwareentwickler

  • Private Nachricht senden

2

16.01.2011, 12:25

Zitat

Wie müssten die Matrizen aussehen, damit die Vertexkoordinaten den Bildschirmkoordinaten entsprechen? (bis zum Schritt der Projektion, dieses Verfahren ist mir geläufig)
Das ist etwas schwierig, du könntest wohl eine orthogonale Projektionsmatrix erzeugen, und die Viewmatrix auf der Identitätsmatrix belassen.


Ansonsten schaue hier mal nach das sollte es recht gut erklären:
http://msdn.microsoft.com/en-us/library/…9(v=VS.85).aspx


mfg Mark

Edit: Oder in einer Kurzform wieso dein Würfel so aussieht wie er momentan aussieht:
Deine Kamera wird mithilfe der Viewmatrix ausgerichtet, aktuell quasi ziemlich weit nach hinten geschoben und auf den Punkt 5,5,0 blickend.
Durch die Projektionsmatrix definierst du mehr oder weniger die Linse deiner Kamera, aktuell also mit einem 45° Öffnungswinkel und eine Blickreichweite von ca 100 Welteinheiten.

Deine Worldmatrix mit der du übrigens dein Würfel positionieren kannst benutzt du zwar setzt aber nur die Rotation des Würfels, da müsstest du die Translation mit einbeuziehen und kannst so deine Position des Würfels bestimmen.

Willst du also deinen Würfel auf 100,100,100 positionieren, musst du eine entsprechende Weltmatrix erstellen und setzen.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »DerMark« (16.01.2011, 12:33)


buggypixels

Treue Seele

Beiträge: 125

Wohnort: Meerbusch

Beruf: Programmierer

  • Private Nachricht senden

3

25.01.2011, 13:07

Es gibt generell zwei Arten, wie man die Projektionsmatrix verwenden kann. Einmal die normale. Dann liegt der Ursprung Deines Koordinatensystems in der Mitte und Du haste eine wunderbare dreidimensionale Darstellung. Hier kannst Du KEINE Bildschirmposition angeben. Denn in dem Fall hängt
die Bildschirmposition ja von der z-Achse ab, oder wie "tief" Dein Objekt im Raum ist.
Ein anderer Ansatz ist die sogenannte orthogonale Projektionsmatrix. Das ist quasi eine flache Draufsicht. Hier kannst Du als Höhe und Breite dann Deine Fenstergröße angeben und dann könntest Du die Position in Bildschirmparametern angeben. Dieses ist aber KEINE 3D Ansicht (weil Du quasi genau von oben draufschaust und die Tiefe geht verloren). Schau mal genau von oben auf eine Tasse. Das entspricht quasi der orthogonalen Ansicht. Man verwendet das eigentlich auch nur bei 2D Darstellungen oder in Spielen für Menüs/HUD und alles was zweidimensional ist.

In Deinem Beispiel verwendest Du die normale Projektionsmatrix (schau mal den Teil mit ProjectionMatrix) und dann liegt der Ursprung Deines Koordinatensystem im Zentrum.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

26.01.2011, 09:04

Dieses ist aber KEINE 3D Ansicht (weil Du quasi genau von oben draufschaust und die Tiefe geht verloren). Schau mal genau von oben auf eine Tasse. Das entspricht quasi der orthogonalen Ansicht. Man verwendet das eigentlich auch nur bei 2D Darstellungen oder in Spielen für Menüs/HUD und alles was zweidimensional ist.

Es ist eine 3D-Ansicht. Nur eben ohne Tiefenwirkung. Wird übrigens nicht nur für 2D oder Menüs benutzt, sondern auch in jedem Modeller oder CAD Programm.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

5

17.02.2011, 10:03

Danke für die gute Erklärung. Nochmal zur normalen Transformationsmatrix: Wenn das Zentrum die Bildschirmmitte ist, gehen die sichtbaren Koordinaten also von -400 bis 400 (x) und -300 bis 300 (y), wenn man eine 800x600 Auflösung nutzt?

Werbeanzeige