问题
I recently posted a question about a texture issue I was having. And I think I've discovered the culprit of my problem, but I'm unsure how to handle this, or what I should be doing. Here is the link to the question I had asked:
DirectX Texturing Inversion Issues
After asking that question I got to work just sitting there toying with everything, and eventually ended up just randomly trying to switch from a left handed coordinate system, to a right handed one. Changing to a right handed coordinate system fixed the texturing issue. I would like to know why using a left handed coordinate system results in this sort of texturing glitch. DirectX uses a left handed coordinate system. So why is it slightly broken in my example?
Here is a picture of what my scene looks like using a left handed Projection:
And here is a picture of using a right handed projection:
As I explained in my previous question, the red dot is supposed to be at the top left. It looks just fine in Blender. But when loaded into a left handed coordinate system, it's flipped horizontally on the x axis. When using the right handed system, it's seemingly fixed.
Does anyone know what's going on here?
Here is my camera class:
using SharpDX;
using System;
namespace VoidwalkerEngine.Framework.DirectX
{
public enum CameraMode
{
FreeLook,
Orbit
}
public class Camera
{
/// <summary>
/// The name of this camera
/// </summary>
public string Name { get; set; }
/// <summary>
/// The eye location of this camera
/// </summary>
public Vector3 Location { get; set; }
/// <summary>
/// The Pitch of this Camera, as Radians
/// </summary>
public float Pitch { get; set; }
/// <summary>
/// The Yaw of this Camera, as Radians
/// </summary>
public float Yaw { get; set; }
/// <summary>
/// The Roll of this Camera, as Radians
/// </summary>
public float Roll { get; set; }
/// <summary>
/// The NearZ of this Camera
/// </summary>
public float NearZ { get; set; }
/// <summary>
/// The FarZ of this Camera
/// </summary>
public float FarZ { get; set; }
/// <summary>
/// The Field of View of this Camera, value should be
/// between 0.70 and 1.20
/// </summary>
public float FieldOfView { get; set; }
public float AspectRatio { get; set; }
public float LookSpeed { get; set; }
public float MoveSpeed { get; set; }
/// <summary>
/// Determines if this Camera is currently accelerating.
/// </summary>
public bool IsAccelerating { get; set; }
/// <summary>
/// The acceleration speed multiplier of this Camera.
/// </summary>
public float AccelerationMultiplier { get; set; }
public CameraMode Mode { get; set; }
public float ViewportWidth;
public float ViewportHeight;
/// <summary>
/// The BoundingSphere of this Camera
/// </summary>
public BoundingSphere Bounds
{
get
{
return new BoundingSphere()
{
Center = this.Location,
Radius = 2.0f
};
}
}
/// <summary>
/// The Target Vector of this Camera
/// </summary>
public Vector3 Target
{
get
{
return new Vector3(
(float)Math.Sin(this.Yaw),
(float)Math.Tan(this.Pitch),
(float)Math.Cos(this.Yaw));
}
}
/// <summary>
/// The Frustum of this Camera
/// </summary>
public BoundingFrustum Frustum
{
get
{
return new BoundingFrustum(this.ModelViewProjectionMatrix);
}
}
public Matrix ModelViewMatrix
{
get
{
return Matrix.LookAtLH(this.Location, Location + Target, Up);
}
}
public Matrix ProjectionMatrix
{
get
{
// Changing this to Matrix.PerspectiveFovRH() fixes the issue...but why?
return Matrix.PerspectiveFovLH(FieldOfView, AspectRatio, NearZ, FarZ);
}
}
public Matrix ModelViewProjectionMatrix
{
get
{
return ModelViewMatrix * ProjectionMatrix;
}
}
//public CardinalDirectionType Direction
//{
// get
// {
// return VoidwalkerMath.GetCardinalDirection(VoidwalkerMath.ToDegrees(Yaw));
// }
//}
public Vector3 Forward
{
get
{
return new Vector3((float)Math.Cos(Pitch), 0, (float)Math.Sin(Pitch));
}
}
public Vector3 Right
{
get
{
return new Vector3(Forward.X, 0, -Forward.X);
}
}
public Vector3 Up
{
get
{
return new Vector3(-(float)Math.Sin(Roll), (float)Math.Cos(Roll), 0);
}
}
public Camera()
{
}
public Camera(string name)
: this()
{
this.Name = name;
this.Location = new Vector3();
}
public void ToOrigin()
{
Transform(Vector3.Zero, 0, 0, 0);
}
public void Transform(Vector3 location, float pitch, float yaw, float roll)
{
this.Location = location;
this.Pitch = pitch;
this.Yaw = yaw;
this.Roll = roll;
}
public float GetCurrentMoveSpeed()
{
if (IsAccelerating)
{
return this.MoveSpeed * this.AccelerationMultiplier;
}
return this.MoveSpeed;
}
public void TranslateLeft(float deltaTime)
{
float moveSpeed = GetCurrentMoveSpeed();
this.Location = new Vector3(
Location.X - (float)Math.Sin(Yaw + MathUtil.PiOverTwo) * moveSpeed * deltaTime,
Location.Y,
Location.Z - (float)Math.Cos(Yaw + MathUtil.PiOverTwo) * moveSpeed * deltaTime);
}
public void TranslateRight(float deltaTime)
{
float moveSpeed = GetCurrentMoveSpeed();
this.Location = new Vector3(
Location.X + (float)Math.Sin(Yaw + MathUtil.PiOverTwo) * moveSpeed * deltaTime,
Location.Y,
Location.Z + (float)Math.Cos(Yaw + MathUtil.PiOverTwo) * moveSpeed * deltaTime);
}
public void TranslateForward(float deltaTime)
{
float degreesX = MathUtil.RadiansToDegrees(Pitch) * 0.01745329F; // X rotation
float degreesY = MathUtil.RadiansToDegrees(Yaw) * 0.01745329F; // Y rotation
float moveSpeed = GetCurrentMoveSpeed();
this.Location = new Vector3(
this.Location.X + (float)(moveSpeed * Math.Sin(degreesY) * Math.Cos(degreesX)) * deltaTime,
this.Location.Y + (float)(moveSpeed * Math.Sin(degreesX)) * deltaTime,
this.Location.Z + (float)(moveSpeed * Math.Cos(degreesY) * Math.Cos(degreesX)) * deltaTime);
}
public void TranslateBackward(float deltaTime)
{
float degreesX = MathUtil.RadiansToDegrees(Pitch) * 0.01745329F; // X rotation
float degreesY = MathUtil.RadiansToDegrees(Yaw) * 0.01745329F; // Y rotation
float moveSpeed = GetCurrentMoveSpeed();
this.Location = new Vector3(
this.Location.X - (float)(moveSpeed * Math.Sin(degreesY) * Math.Cos(degreesX)) * deltaTime,
this.Location.Y - (float)(moveSpeed * Math.Sin(degreesX)) * deltaTime,
this.Location.Z - (float)(moveSpeed * Math.Cos(degreesY) * Math.Cos(degreesX)) * deltaTime);
}
public void TransformYawPitch(float dx, float dy)
{
Yaw += dx * LookSpeed;
Pitch -= dy * LookSpeed;
const float pitchClamp = 1.56f;
if (Pitch <= -pitchClamp)
{
Pitch = -pitchClamp;
}
if (Pitch >= pitchClamp)
{
Pitch = pitchClamp;
}
}
public void TranslateUp(float deltaTime)
{
this.Location = new Vector3(
this.Location.X,
this.Location.Y + GetCurrentMoveSpeed() * deltaTime,
this.Location.Z); // TODO implement up/down based upon roll orientation.
}
public void TranslateDown(float deltaTime)
{
this.Location = new Vector3(
this.Location.X,
this.Location.Y - GetCurrentMoveSpeed() * deltaTime,
this.Location.Z);
}
public void LookAt(Vector3 location, float pitch, float yaw, float roll)
{
this.Location = location;
this.Pitch = pitch;
this.Yaw = yaw;
this.Roll = roll;
}
public void SetAspectRatio(int width, int height)
{
this.ViewportWidth = width;
this.ViewportHeight = height;
this.AspectRatio = width / (float)height;
}
}
}
If I'm doing something incredibly stupid, please feel free to call me out on it. I've already spent 2 days trying to figure this out.
来源:https://stackoverflow.com/questions/62205875/directx-coordinate-system-causes-texture-flipping