[C# / XNA 4.0] Camera rotation speed

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Hyperz
  • Registratie: Augustus 2009
  • Laatst online: 04-07 19:15
Hey, ik ben me onlangs beginnen verdiepen in 3D programmeren met XNA omdat me dat nogal interessant leek, ondanks het feit dat wiskunde één van mijn zwakke punten is. Nu heb ik al een paar van de basics onder de knie en ben momenteel bezig met een FPS-style camera class te maken aan de hand van deze tutorial.


C#:
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
public class Camera3D
{
    public const float RotationSpeed = 0.5f;
    public const float MoveSpeed = 30.0f;

    private float xRot;
    private float yRot;
    private MouseState initialMouseState;
    private Viewport viewport;

    public Vector3 Position { get; set; }
    public Vector3 LookAt { get; set; }
    public Matrix Rotation { get; set; }
    public Matrix Projection {get; set;}
    public Matrix View { get; set; }

    public Camera3D(GraphicsDevice graphicsDevice, Vector3 position, Vector3 lookAt, float fieldOfView)
    {
        float aspectRatio = (float)graphicsDevice.DisplayMode.Width / (float)graphicsDevice.DisplayMode.Height;
        float fov = MathHelper.ToRadians(fieldOfView);

        this.Position = position;
        this.LookAt = lookAt;
        this.View = Matrix.CreateLookAt(Position, LookAt, Vector3.Up);
        this.Projection = Matrix.CreatePerspectiveFieldOfView(fov, aspectRatio, 0.01f, 10000.0f);
        this.viewport = graphicsDevice.Viewport;

        Mouse.SetPosition(viewport.Width / 2, viewport.Height / 2);

        this.initialMouseState = Mouse.GetState();
        this.xRot = MathHelper.PiOver2;
        this.yRot = -MathHelper.Pi / 10.0f;
    }

    public Camera3D(GraphicsDevice graphicsDevice, float fieldOfView)
        : this(graphicsDevice, Vector3.Zero, Vector3.Zero, fieldOfView)
    {
    }

    public Camera3D(GraphicsDevice graphicsDevice)
        : this(graphicsDevice, Vector3.Zero, Vector3.Zero, 45.0f)
    {
    }

    public void Update(GameTime gameTime)
    {
        var gt = (float)gameTime.ElapsedGameTime.TotalSeconds;
        var ks = Keyboard.GetState();
        var ms = Mouse.GetState();
        var moveVector = Vector3.Zero;

        if (ks.IsKeyDown(Keys.Z)) moveVector += Vector3.Forward;
        if (ks.IsKeyDown(Keys.S)) moveVector += Vector3.Backward;
        if (ks.IsKeyDown(Keys.Q)) moveVector += Vector3.Left;
        if (ks.IsKeyDown(Keys.D)) moveVector += Vector3.Right;
        if (ks.IsKeyDown(Keys.C)) moveVector += Vector3.Down;
        if (ks.IsKeyDown(Keys.Space)) moveVector += Vector3.Up;

        moveVector *= gt;

        if (ms != initialMouseState)
        {
            float xDifference = ms.X - initialMouseState.X;
            float yDifference = ms.Y - initialMouseState.Y;

            this.xRot -= Camera3D.RotationSpeed * xDifference * gt;
            this.yRot -= Camera3D.RotationSpeed * yDifference * gt;

            Mouse.SetPosition(this.viewport.Width / 2, this.viewport.Height / 2);
        }

        Vector3 rotatedVector, originalTarget, originalUpVector, rotatedTarget, rotatedUpVector;

        this.Rotation = Matrix.CreateRotationX(this.yRot) * Matrix.CreateRotationY(this.xRot);
        rotatedVector = Vector3.Transform(moveVector, this.Rotation);
        this.Position += Camera3D.MoveSpeed * rotatedVector;

        originalTarget = new Vector3(0, 0, -1);
        originalUpVector = new Vector3(0, 1, 0);

        rotatedTarget = Vector3.Transform(originalTarget, this.Rotation);
        this.LookAt = this.Position + rotatedTarget;

        rotatedUpVector = Vector3.Transform(originalUpVector, this.Rotation);

        this.View = Matrix.CreateLookAt(this.Position, this.LookAt, rotatedUpVector);
    }

    public override string ToString()
    {
        return String.Format("CAM Pos:{0}\nCAM Pov:{1}\n", this.Position, this.LookAt);
    }
}


Alles lijkt goed te werken, behalve dat bij een lage framerate de camera rotatie sneller/gevoeliger is dan bij een hoge framerate. Nu begrijp ik niet goed waarom. Ik dacht dat dit stukje dit moest verhelpen (* gt):


C#:
1
2
            this.xRot -= Camera3D.RotationSpeed * xDifference * gt;
            this.yRot -= Camera3D.RotationSpeed * yDifference * gt;


Ik heb nog geprobeerd verschillende variables aan te passen aan de gametime maar zonder succes :-( . Iemand die weet waar het probleem zit?

Alvast bedankt.

Asus P8P67 EVO | i5 2500k (4.8 GHz) | Sapphire HD 7970 Vapor-X GHz Ed. | 8 GB DDR3 1600 | 1 TB HDD


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04-07 17:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Logisch, je moet niet vermenigvuldigen met de frametijd aangezien de muisbewegingen zelf niet frametijd-afhankelijk zijn :). De muisbewegingen zijn een accumulatie sinds de vorige frame, en dus een relatieve afstand. Niet een snelheid.

[ Voor 36% gewijzigd door .oisyn op 13-10-2010 11:13 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 01-07 21:58
Je moet bewegingen altijd laten afhangen van gameTime.ElapsedGameTime.TotalSeconds (of TotalMiliSeconds).

Maar ik zie dat dat in jouw geval al geburt. Wel zie ik dat initial mouse state niet geupdate wordt aan het einde van de update methode.

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04-07 17:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

roy-t schreef op woensdag 13 oktober 2010 @ 11:00:
Je moet bewegingen altijd laten afhangen van gameTime.ElapsedGameTime.TotalSeconds (of TotalMiliSeconds).
Nonsens. Je moet rekening houden met grootheden. Als je te maken hebt met een snelheid dan moet je die inderdaad omzetten naar afstand door te vermenigvuldigen met de tijd (want afstand = snelheid * tijd). Muisinput is geen snelheid, maar afstand. Je zou er wel eerst een snelheid van kunnen maken door te delen door tijd (want snelheid = afstand / tijd), alleen maar om 'm later weer te vermenigvuldigen met tijd om de afstand terug te krijgen. Nutteloos dus.

[ Voor 20% gewijzigd door .oisyn op 13-10-2010 11:17 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 01-07 21:58
Ah shit je hebt gelijk.

Hmm met diff (beweging van de muis) constant
verandering = diff * spf; geeft dat bij een lager fps het lijkt alsof er meer bewogen is per seconden.

verandering = diff/spf; klopt wel.


Edit: idd niet fps maar seconds per frame

[ Voor 11% gewijzigd door roy-t op 13-10-2010 13:08 ]

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04-07 17:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, het is gewoon
verandering = diff

Logisch ook, want die dingen betekenen hetzelfde.

(En ik neem aan dat je met fps eigenlijk spf bedoelt?)

De code wordt dus:
C#:
1
2
            this.xRot -= Camera3D.RotationSpeed * xDifference; 
            this.yRot -= Camera3D.RotationSpeed * yDifference;

[ Voor 56% gewijzigd door .oisyn op 13-10-2010 12:18 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Hyperz
  • Registratie: Augustus 2009
  • Laatst online: 04-07 19:15
En dat lijkt dus perfect te werken. Ik dacht echt dat ik ergens anders een fout gemaakt had aangezien dat stukje code een vrijwel directe copy/paste is van die tutorial. Dus eigenlijk bevat die tutorial dan een fout :?. In ieder geval bedankt voor de oplossing!
roy-t schreef op woensdag 13 oktober 2010 @ 11:00:
Wel zie ik dat initial mouse state niet geupdate wordt aan het einde van de update methode.
Dat hoeft ook niet aangezien ik de cursor terug in het midden plaats. Moest dat stukje niet goed werken zou ik het snel merken wanneer ik de muis beweeg :).

Asus P8P67 EVO | i5 2500k (4.8 GHz) | Sapphire HD 7970 Vapor-X GHz Ed. | 8 GB DDR3 1600 | 1 TB HDD


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04-07 17:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hyperz schreef op woensdag 13 oktober 2010 @ 13:03:
Dus eigenlijk bevat die tutorial dan een fout :?
Klopt, en dat niet alleen, alle users op het forum doen het ook allemaal fout :D. Frappant dat nog niemand iets gemerkt heeft, waarschijnlijk lopen hun framerates allemaal vrij constant. Ik ga eens een account aanmaken :P

.edit: blijkbaar lukt posten niet. 't Is ook niet echt een heel fantastische site. Was riemers trouwens geen gotter?
.edit2: riemerg

[ Voor 21% gewijzigd door .oisyn op 13-10-2010 13:42 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 01-07 21:58
.oisyn schreef op woensdag 13 oktober 2010 @ 13:13:
[...]

Klopt, en dat niet alleen, alle users op het forum doen het ook allemaal fout :D. Frappant dat nog niemand iets gemerkt heeft, waarschijnlijk lopen hun framerates allemaal vrij constant. Ik ga eens een account aanmaken :P

.edit: blijkbaar lukt posten niet. 't Is ook niet echt een heel fantastische site. Was riemers trouwens geen gotter?
.edit2: riemerg
Standaard loopt XNA in fixed time step modus, waardoor je (totdat je te veel gaat tekenen) inderdaad een constante framerate hebt.

Verder staan er meer subtiele foutjes op Riemer's website, maar zijn boek schijnt wel erg goed te zijn.

~ Mijn prog blog!

Pagina: 1