1
0
mirror of https://github.com/fadden/6502bench.git synced 2026-04-25 05:22:03 +00:00

Switch to left-handed coordinate system

There's no "standard" coordinate system, so the choice is arbitrary.
However, an examination of the Transporter mesh in Elite revealed
that the mesh was designed for a left-handed coordinate system.  We
can compensate for that trivially in the Elite visualizer, but we
might as well match what they're doing.  (The only change required
in the code is a couple of sign changes on the Z coordinate, and an
update to the rotation matrix.)

This also downsizes Matrix44 to Matrix33, exposes the rotation mode
enum, and adds a left-handed ZYX rotation mode.

This does mean that meshes that put the front at +Z will show their
backsides initially, since we're now oriented as if we're flying
the ships rather than facing them.  I considered adding a 180-degree
Y rotation (with a tweak to the rotation matrix handedness to correct
the first rotation axis) to have them facing by default, but figured
that might be confusing since +Z is supposed to be away.

Anybody who really wants it to be the other way can trivially flip
the coordinates in their visualizer (negate xc/zc).

The Z coordinates in the visualization test project were flipped so
that the design is still facing the viewer at rotation (0,0,0).
This commit is contained in:
Andy McFadden
2020-03-14 10:25:17 -07:00
parent 8ff1fa7034
commit b3dacc2613
8 changed files with 94 additions and 59 deletions
+18 -8
View File
@@ -246,8 +246,18 @@ namespace SourceGen {
scale = (scale * zadj) / (zadj + 0.3);
}
Matrix44 rotMat = new Matrix44();
rotMat.SetRotationEuler(eulerX, eulerY, eulerZ);
// In a left-handed coordinate system, +Z is away from the viewer. The
// visualizer expects a left-handed system with the "nose" aimed toward +Z,
// which leaves us looking at the back end of things. We can add a 180 degree
// rotation about Y so we're looking at the front instead, though this
// effectively reverses the direction of rotation about X. We can compensate
// for it by reversing the handedness of the X rotation.
//eulerY = (eulerY + 180) % 360;
// Form rotation matrix.
Matrix33 rotMat = new Matrix33();
rotMat.SetRotationEuler(eulerX, eulerY, eulerZ, Matrix33.RotMode.ZYX_LLL);
//Debug.WriteLine("ROT: " + rotMat);
if (doBfc) {
// Mark faces as visible or not. This is determined with the surface normal,
@@ -264,9 +274,9 @@ namespace SourceGen {
face.IsVisible = true;
continue;
}
Vector3 camVec = rotMat.Multiply(face.Vert.Vec);
Vector3 camVec = rotMat.Multiply(face.Vert.Vec); // transform
camVec = camVec.Multiply(-scale); // scale to [-1,1] and negate to get -C
camVec = camVec.Add(new Vector3(0, 0, zadj)); // translate
camVec = camVec.Add(new Vector3(0, 0, -zadj)); // translate
// Now compute the dot product of the camera vector.
double dot = Vector3.Dot(camVec, rotNorm);
@@ -278,7 +288,7 @@ namespace SourceGen {
// For orthographic projection, the camera is essentially looking
// down the Z axis at every X,Y, so we can trivially check the
// value of Z in the transformed normal.
face.IsVisible = (rotNorm.Z >= 0);
face.IsVisible = (rotNorm.Z <= 0);
}
}
}
@@ -300,9 +310,9 @@ namespace SourceGen {
double x0, y0, x1, y1;
if (doPersp) {
// +Z on the shape is closer to the viewer, so we negate it here
double z0 = -trv0.Z * scale;
double z1 = -trv1.Z * scale;
// Left-handed system, so +Z is away from viewer.
double z0 = trv0.Z * scale;
double z1 = trv1.Z * scale;
x0 = (trv0.X * scale * zadj) / (zadj + z0);
y0 = (trv0.Y * scale * zadj) / (zadj + z0);
x1 = (trv1.X * scale * zadj) / (zadj + z1);