As mentioned, D3 is not in true Isometric view, it's merely at an angle. Isometric (orthographic) ignores the Z axis and thus and no true depth in the shot. It's hard to describe without just playing with it.
I find it much easier to work in 3d because the math for everything being displayed makes more sense to me.
Regardless, I posted a similar answer to another post of my camera code:
public class UlmerCam3D
{
public Vector3 CameraTarget { get { return tar; } set { tar = value; } }
public Vector3 CameraPosition { get { return pos; } set { pos = value; } }
private Vector3 Up { get; } = new Vector3(0.0f, 1.0f, 0.0f);
// a variable is modified easier in this case than a property
private Vector3 pos;
private Vector3 tar;
// phi is the angle from the vertical axis (Y-axis) expressed as radians
// NOTE: Because of the way it is oriented and the fact we don't want an upside-down camera,
// phi is *always* negative, between 0 and Pi. It does not "roll over" when changed beyond this, but instead "sticks"
public float phi;
// theta is the angle from the horizontal axis (X-axis) expressed as radians
// because of it's orientation, theta is always positive, between 0 and 2-Pi
// This min and max value roll into eachother when changed
public float theta;
// the distance between the Camera Position and Camera Target, used to calculate where the target is
public float radius;
// The graphics device and the member variables that are related to it
private static GraphicsDevice gd;
public UlmerCam3D(GraphicsDevice ingd)
{
gd = ingd;
pos = new Vector3(0f, 100f, 0f);
tar = new Vector3(0f, 0f, 0f);
theta = Utilities.halfPi;
phi = -Utilities.halfPi * .97f;
radius = 100;
//TODO : eventually move this copy-code somewhere
//Target is based on Position, that way they are always synchronus
tar.X = pos.X + radius * (float)Math.Sin(theta) * (float)Math.Cos(phi);
tar.Z = pos.Z + radius * (float)Math.Cos(theta) * (float)Math.Cos(phi);
tar.Y = pos.Y + radius * (float)Math.Sin(phi);
}
const float FIELD_OF_VIEW = Utilities.halfPi;
public Matrix BuildProjection()
{
// TODO: Only Calculate if it needs updating
return Matrix.CreatePerspectiveFieldOfView(
FIELD_OF_VIEW,
gd.DisplayMode.AspectRatio,
1f, 500f);
}
public Matrix BuildView()
{
// TODO: Only Calculate if it needs updating
return Matrix.CreateLookAt(pos, tar, new Vector3(0f, 1f, 0f));
}
public Matrix BuildWorld()
{
return Matrix.Identity;// CreateWorld(tar, Vector3.Forward, Vector3.Up);
}
private bool updateCamera = true;
public void HandleKeyboardInput()
{
// TODO: Mark that the camera pos or target changed when it does
bool w = Keyboard.GetState().IsKeyDown(Keys.W);
bool a = Keyboard.GetState().IsKeyDown(Keys.A);
bool s = Keyboard.GetState().IsKeyDown(Keys.S);
bool d = Keyboard.GetState().IsKeyDown(Keys.D);
if (!(w || a || s || d))
{
return;
}
updateCamera = true;
bool shift = Keyboard.GetState().IsKeyDown(Keys.LeftShift);
if (!shift)
{
if (w)
{
pos.X += (float)Math.Sin(theta);
pos.Z += (float)Math.Cos(theta);
}
if (s)
{
pos.X -= (float)Math.Sin(theta);
pos.Z -= (float)Math.Cos(theta);
}
if (a)
{
pos.X += (float)Math.Cos(theta);
pos.Z -= (float)Math.Sin(theta);
}
if (d)
{
pos.X -= (float)Math.Cos(theta);
pos.Z += (float)Math.Sin(theta);
}
}
else
{
if (w && phi < -Utilities.thirdPi)
{
phi += (float)Math.PI / 180;
}
if (s && phi > Utilities.halfPi * -0.97)
{
phi -= (float)Math.PI / 180;
}
if (a)
{
theta += (float)Math.PI / 180;
if (theta > Math.PI * 2)
{
theta = 0;
}
}
if (d)
{
theta -= (float)Math.PI / 180;
if (theta < 0)
{
theta = (float)Math.PI * 2;
}
}
}
//Target is based on Position, that way they are always synchronus
tar.X = pos.X + radius * (float)Math.Sin(theta) * (float)Math.Cos(phi);
tar.Z = pos.Z + radius * (float)Math.Cos(theta) * (float)Math.Cos(phi);
tar.Y = pos.Y + radius * (float)Math.Sin(phi);
}
This is technically in my monogame C# project, but is based on old DirectX 9 code I wrote way back when. Unfortunately this is way more readable than my C++ code from them and it doesn't require any hacks.
For the most part you just want the math for the Target based on the Position; then simply set Phi to -Pi/4 and Theta to Pi/4 (any multiple of it) and you'll be looking at a 45 degree plane down at 45 degrees.
Side note: You should stop thinking in degrees. I highly recommend memorizing the Unit Circle (https://www.mathsisfun.com/geometry/unit-circle.html) and getting used to thinking of Angles in terms of P (http://math.rice.edu/~pcmi/sphere/drg_txt.html.)
In your case, Pi/4 is 45 degrees, which means you want to adjust the camera "down" Pi/4, and then adjust it "over" or "around" Pi/4.