It seems there's a bug where setting screen.transform doesn't get picked up right away. You can work around it for now by drawing something to a surface right after setting the transformation, then the next time you draw to the screen the new matrix will get picked up.
Anyway, this might help illustrate how everything comes together, we'll rotate the entire screen and then project it into 3D:
var wh = screen.width / 2;
var hh = screen.height / 2;
screen.transform = new Transform()
.translate(-wh, -hh)
.scale(1 / wh, 1 / wh)
.rotate(0.2, 0.0, 1.0, 0.0)
.translate(0, 0, -1.0)
.project3D(90, wh / hh, 0.1, 2.0);
// workaround for miniSphere bug
new Shape(ShapeType.Points, new VertexList([{}])).draw(new Surface(1, 1));
- .translate() by half the screen size. We want to rotate the whole screen, so we have to move the origin to the center (instead of top-left).
- .scale() fits the "world" within (-1,-1)-(1,1) so we don't have to put the farplane insanely far away from the camera.
- .rotate() to rotate the entire "world" (the screen) by 0.2 radians (about 11 degrees). This might reveal stuff that's drawn offscreen!
- .translate() again, -1.0 along Z to ensure the rotated image fits within the frustum (we can't do the Z-translation in the first step because it would screw up the rotation).
- .project3D(), to apply the projection. This should always be the last transformation you apply!
Fun thing about the Z coordinate: while the near- and farplanes are specified as positive values, Z coordinates of things you draw should actually be negative! 0 is exactly at the camera (and will be clipped, because you can't have a nearplane at 0), and moves in the negative direction "away" from the screen. That caught me off-guard for a bit when I first starting playing around with 3D.