Vertices rotieren funktioniert nicht

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von φConst.

    Vertices rotieren funktioniert nicht

    Guten Abend,
    ich versuche einen eigenen SpriteBatch der stark optimiert wurde zu entwickeln.
    Klappt _ alles gut, problematisch jedoch die Rotation.

    Um eine zweidimensionale Projektion zu ermöglichen nutze ich Matrix.CreateOrthographic :

    C#-Quellcode

    1. _effect.View = Matrix.CreateLookAt(new Vector3(__center, 0), new Vector3(__center, 1), new Vector3(0, 1, 0)); ;
    2. _effect.World =( Matrix.CreateScale(AbsoluteTextureSizeWidth, AbsoluteTextureSizeHeight, 1) * Matrix.CreateTranslation(GraphicsDevice.Viewport.Width - (AbsoluteTextureSizeWidth), GraphicsDevice.Viewport.Height - (AbsoluteTextureSizeHeight), 0)) * _manipulation;
    3. _effect.Projection = Matrix.CreateOrthographic(__center.X * 2, __center.Y * 2, -0.5f, 1000);


    Es funktioniert zwar, es ist aber nicht möglich das damit projizierte Sprite zu rotieren.

    Ein Sprite wird durch die Klasse

    C#-Quellcode

    1. public class Sprite
    2. {
    3. public VertexPositionTexture[] Vertices = new VertexPositionTexture[4];
    4. public short[] Indices = new short[6];
    5. public Sprite(SpriteBatchOptimized batch, Vector2 position, Matrix manipulation, Vector2 origin, float rotation, Vector2 texCoord)
    6. {
    7. // return Vector2.Transform(point - origin, Matrix.CreateRotationZ(rotation)) + origin;
    8. position = Vector2.Transform(position, Matrix.CreateRotationX(rotation));
    9. texCoord = new Vector2(texCoord.X * batch.RatioX, texCoord.Y * batch.RatioY);
    10. Vertices[0] = new VertexPositionTexture(new Vector3(position.X, position.Y, 0), new Vector2(0 + texCoord.X, batch.RatioY + texCoord.Y));
    11. Vertices[1] = new VertexPositionTexture(new Vector3(position.X + 1, position.Y, 0), new Vector2(batch.RatioX + texCoord.X, batch.RatioY + texCoord.Y));
    12. Vertices[2] = new VertexPositionTexture(new Vector3(position.X + 1, position.Y + 1, 0), new Vector2(batch.RatioX + texCoord.X, 0 + texCoord.Y));
    13. Vertices[3] = new VertexPositionTexture(new Vector3(position.X, position.Y + 1, 0), new Vector2(0 + texCoord.X, 0 + texCoord.Y));
    14. Indices[0] = (int)(0);
    15. Indices[1] = (int)(1);
    16. Indices[2] = (int)(2);
    17. Indices[3] = (int)(2);
    18. Indices[4] = (int)(3);
    19. Indices[5] = (int)(0);
    20. }
    21. }


    generiert.

    C#-Quellcode

    1. position = Vector2.Transform(position, Matrix.CreateRotationX(rotation));
    rotiert nicht die Vertices, sondern verschiebt diese nur eben auf einer Kreisbahn.
    Ferner wird keine Transformation durchgeführt wenn die Position (0,0) beträgt.

    Wie ist es möglich den Sprite zu rotieren ( nicht auf einer Kreisbahn, sondern eben die ganze Figur), selbst dann, wenn die Position ein Nullvektor ist?

    Lieben, lieben dank!
    Und Gott alleine weiß alles am allerbesten und besser.
    Vertices verschieben, sodass die mitte des rectangles(aka origin) (0,0) ist und dann rotieren, anschließend wieder zurückbewegen.

    Würde aber selbst rotieren, einfach mit trig. Funktionen herleiten:
    github.com/OctoAwesome/engenio…hics/SpriteBatcher.cs#L46
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Ja, so in etwa hab ich es nun gelöst

    C#-Quellcode

    1. public class Sprite
    2. {
    3. public VertexPositionTexture[] Vertices = new VertexPositionTexture[4];
    4. public short[] Indices = new short[6];
    5. public Sprite(SpriteBatchOptimized batch, Vector2 position, Vector2 origin, float rotation, Vector2 texCoord)
    6. {
    7. texCoord = new Vector2(texCoord.X * batch.RatioX, texCoord.Y * batch.RatioY);
    8. Vector3 __right = new Vector3(1, 0, 0);
    9. Vector3 __top = new Vector3(0, 1, 0);
    10. Vector3 __topRight = new Vector3(1, 1, 0);
    11. __right = Vector3.Transform(__right, Matrix.CreateRotationZ(rotation));
    12. __top = Vector3.Transform(__top, Matrix.CreateRotationZ(rotation));
    13. __topRight = Vector3.Transform(__topRight, Matrix.CreateRotationZ(rotation));
    14. Vertices[0] = new VertexPositionTexture(new Vector3(position.X, position.Y, 0), new Vector2(0 + texCoord.X, batch.RatioY + texCoord.Y));
    15. Vertices[1] = new VertexPositionTexture(new Vector3(position.X, position.Y, 0) + __right, new Vector2(batch.RatioX + texCoord.X, batch.RatioY + texCoord.Y));
    16. Vertices[2] = new VertexPositionTexture(new Vector3(position.X, position.Y, 0) + __topRight, new Vector2(batch.RatioX + texCoord.X, 0 + texCoord.Y));
    17. Vertices[3] = new VertexPositionTexture(new Vector3(position.X, position.Y, 0) + __top, new Vector2(0 + texCoord.X, 0 + texCoord.Y));
    18. Indices[0] = (int)(0);
    19. Indices[1] = (int)(1);
    20. Indices[2] = (int)(2);
    21. Indices[3] = (int)(2);
    22. Indices[4] = (int)(3);
    23. Indices[5] = (int)(0);
    24. }
    25. }


    Jetzt fehlt eben nur noch Rotation um Origin.
    Und Gott alleine weiß alles am allerbesten und besser.
    Deine Rotation dürfte nur funktionieren, wenn dein sprite auch 1x1 ist(soweit ich das sehe).
    wie gesagt, erzeug die Vertices für dein Rectangle, verschiebe es um -origin, dann rotiere, anschließend addiere wieder origin und deine eigentliche Position.
    Und wie gesagt, da du vermutlich Performance möchtest ist wohl sin/cos angebracht, anstelle von Rotationsmatrizen(welche im Endeffekt nichts anderes machen, nur mit einigem an Overhead)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Entweder versteh ich dich nicht, oder du liegst falsch :D

    -Origin
    -Origin + (Size.X,0)
    -Origin + (0,Size.Y)
    -Origin + Size

    sind deine vier punkte, dann kommt die Rotation(eben Sin/Cos), auch wenn auf github nen TODO steht, sollte das glaub ich passen :D, anschließend
    +Position+Origin
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---