Du bist nicht angemeldet.

Werbeanzeige

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 723

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

1

04.12.2014, 17:17

3D Camera | Was ist die World Matrix?

Hi,
ich implementiere gerade eine 3D Camera mit DX11 und HLSL.

Die View und die Projection Matrix verstehe ich.
Aber was zum Bug ist die World Matrix?


Gruß Techie
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

2

04.12.2014, 18:26

Im Object Space befindet sich der Ursprung in der Mitte des Objektes (oder an einer passenden Stelle für die Rotation). Im World Space befinden sich die Objekte relativ zueinander, so dass die Objekte passend in die Welt translatiert, rotiert und skaliert werden. Um Objekt A also in den World Space zu bekommen, brauchst Du die World Matrix.

LInsoDeTeh

Treue Seele

Beiträge: 373

Wohnort: Essen, Deutschland

Beruf: Team Lead Inhouse-Entwicklung

  • Private Nachricht senden

3

04.12.2014, 21:04

Die Worldmatrix brauchst du, wenn du ein kleineres Koordinatensystem innerhalb des großen Spielweltkoordinatensystems brauchst.
Wenn du Objekte einfach nur direkt in die Welt zeichnen willst, ist die Worldmatrix in der Regel die Identitätsmatrix. Wenn du aber z.B. mehrere Dinge zeichnen willst, deren Position/Rotation/Größe du nur relativ zu einem anderen Ding kennst, brauchst du eine Worldmatrix.

Ich mach mal ein einfaches Beispiel aus meinem Spiel Galactineers. Hier ein einfacher Screenshot:

(Link)


Die Blöcke und Gebäude, die du im Hintergrund siehst, haben Koordinaten in der Spielwelt, und werden einfach mit worldMatrix = Matrix.Identity in die Welt gerendert. Doch nun zu dem Schiff im Vordergrund. Das Schiff befindet sich an einer bestimmten Position in der Welt, hat sich gerade in eine bestimmte Richtung gedreht, und die Blöcke des Schiffs sind nur 1/3 so groß, wie die der Welt drumherum!
Die Blöcke (und auch die Waffen/Antriebe) des Schiffs haben in der Schiffsdefinition aber als Koordinaten Werte zwischen (-3, -3, -3) und (3, 3, 3), nämlich relativ zum Mittelpunkt des Schiffes, und haben daher rein gar nichts mit den Koordinaten der Spielwelt zutun. Würde ich das Schiff jetzt also mit worldMatrix = Matrix.Identity zeichnen, würde es sich immer an Position (0, 0, 0) der Welt befinden, Rotation 0 haben, und dreimal so groß sein, wie es sein sollte. Denn Koordinate (-3, -3, -3) in der Schiffswelt bliebe dann Koordinate (-3, -3, -3) in der Spielwelt (Identitätsabbildung).

Also rendere ich die Blöcke und Module, die zu dem Schiff gehören, stattdessen mit
worldMatrix = ScaleMatrix(0.33) * RotationMatrix(Drehung des Schiffs) * TranslationMatrix(Position des Schiffs) (Reihenfolge beachten!).
Und somit erscheint das Schiff als ganzes an der Stelle, in der Ausrichtung und der Größe, wie es soll...

Das Inverse dieser Matrix kann ich dann übrigens dazu nutzen, einen Klick in der Spielwelt in die Schiffswelt zurückzurechnen, um herauszufinden, welchen Block des Schiffs ich gerade angeklickt habe. Aber das nur so nebenbei.

Kurz zusammengefasst: Mit der WorldMatrix kannst du zwischen zwei Welten (große gesamte Welt vs. kleine Schiffswelt) hin- und her transformieren.

Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von »LInsoDeTeh« (04.12.2014, 21:31)


Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 723

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

4

05.12.2014, 18:36

Für mich mal verständlich:
Das heißt du hast die Vektoren der Vertices der Würfel direkt angegeben. Also z.B. (20, 20, 20).
Während das Schiff relative Koordinaten zum Ursprung hat, aber die Vertex Positionen werden mit der WorldMatrix multipliziert und bekommen somit einen neuen Platz?
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

5

05.12.2014, 18:44

Jo, so ist es. Wie von den anderen bereits erwähnt, werden die Vertizes in Modelspace (auch Objectspace genannt). Und dann schiebt man die einfach an die gewünschte Stelle in der Welt. Kann man natürlich auch anders machen, aber in der Spieleprogrammierung ist das wohl das üblichste.

birdfreeyahoo

Alter Hase

Beiträge: 766

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

6

05.12.2014, 18:48

Ja, genau. Eine sehr schöne Erklärung, die ich mal gelesen habe:

Es ist wie wenn du eine Miniaturstadt baust. Du baust ein Haus nicht auf dem Feld, sondern du stellst es zunächst an deinem Arbeitstisch zusammen und platzierst es dann in die Stadt.
Genauso ist es hier. Du baust etwas. Du sagst das Vertex ist dort und dort, oder du baust dein 3D-Modell, dein Mittelpunkt ist der Objektmittelpunkt.
Dann gehst du mit dem fertig gebauten Haus hin und sagst, dorthin möchte ich es stellen und es so drehen und so skalieren. Das ist dann die Weltmatrix, in der gibst du das an.

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 723

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

7

05.12.2014, 19:02

birdfreeyahoo's Erklärung ist ja mal nice, Danke ;)
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 723

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

8

05.12.2014, 23:47

Anscheinend mache ich irgendetwas falsch beim berechnen. Wenn ich mit der WVP multipliziere, dann sehe ich nichts.

Mein Dreieck befindet sich auf den Koordinaten:
(0.0f, 0.5f, 0.0f, 1.0f)
(0.5f, -.5f, 0.0f, 1.0f)
(-.5f, -.5f, 0.0f, 1.0f)

Meine View wird wie folgt berechnet:

C#-Quelltext

1
2
3
4
5
6
7
position    = new Vector3(0, 0, -5);
target      = Vector3.Zero;
up          = Vector3.UnitY;

//...

view = Matrix.LookAtLH(position, target, up)


Projektion:

C#-Quelltext

1
projection = Matrix.PerspectiveFovLH((float)Math.PI / 3.0f, (float)form.Width / (float)form.Height, 0.0f, 100.0f);


World Matrix:

C#-Quelltext

1
world = Matrix.Identity;


Das gesamte Ding:

C#-Quelltext

1
2
3
4
5
Context.VertexShader.SetConstantBuffer(0, WVP);
var ViewProjection = Matrix.Multiply(view, projection);
var WorldViewProject = world * ViewProjection;
WorldViewProject.Transpose();
context.UpdateSubresource(ref WorldViewProject, WVP);


Und letzt endlich der Vertex Shader:

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
cbuffer PerObject : register(b0)
{
    float4x4 WVP;
}

struct VOut
{
    float4 position : SV_POSITION;
    float4 color    : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = mul(position, WVP);
    // output.position = position;
        // Sobald ich nicht mehr mit der WVP multipliziere passt alles, dann sehe ich etwas auf dem Screen
       
    output.color = color;

    return output;
}

float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

LInsoDeTeh

Treue Seele

Beiträge: 373

Wohnort: Essen, Deutschland

Beruf: Team Lead Inhouse-Entwicklung

  • Private Nachricht senden

9

06.12.2014, 00:09

Zwei Dinge:
Bei Matrizen, stehen in der Multiplikation die, die zuerst ausgeführt werden, ganz rechts. Mal ganz unmathematisch ausgedrückt :-)
Es muss also Projection *View * World sein, nicht andersherum.

Und zuletzt verstehe ich auch nicht, warum du WorldViewProject.Transpose(); machst. Was willst du denn mit der Transponierten? Das würde nur Sinn machen, wenn du die anderen Matrizen auch vorher transponieren würdest, aber dann würde sich die Reihenfolge wieder umdrehen.

Probier's doch also mal so:

C-/C++-Quelltext

1
2
3
Context.VertexShader.SetConstantBuffer(0, WVP);
var WorldViewProject = projection * view * world;
context.UpdateSubresource(ref WorldViewProject, WVP);

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 723

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

10

06.12.2014, 00:44

Ich habe es ausprobiert, leider bleibt bei mir der Screen leer :'(

Die Fixed Pipeline war doch so viel einfacher...

EDIT:
Ist es möglich, dass ich das Dreieck von der falschen Seite sehe?
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Julién« (06.12.2014, 00:53)


Werbeanzeige