mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-13 19:01:21 +00:00
An image laid onto a model came out upside down under the ordinary box (tri-planar) projection, and on three of a cube's six faces it was also mirrored left to right, which reads as a 180 degree rotation. DecodedHeightTexture::sample() defines v = 0 as the height map's first pixel row, i.e. its top. Every projection built v from world +Z, so v grew upward and the image landed bottom row up. The one path that was already right is the projective "project from view" matrix, which measures window y downward. Both halves of the box basis were wrong: - v is now negated on all three world planes, so the top of an image sits at the top of the model. - u now carries a sign for the side of the plane the face is on, chosen so that u x v == -normal. Without it the two faces sharing a plane get one u and one of them is mirrored. The sign flips exactly where that plane's blend weight (the fourth power of a normal component) reaches zero, so the blended tri-planar sum stays continuous and the hard axis switch the old code removed does not come back. The same v convention was missing from the other mapping modes: cylindrical (which also had a left handed frame, right x up rather than up x right, so its wrap ran mirrored), spherical, the affine branch of view projection, and the flat chart fallback of the LSCM unwrap, which now reuses the box basis so a cube face unwraps to the orientation tri-planar would have given it. The basis table is exported as box_projection_axes() and the gizmo's adjust_tangent_basis() calls it instead of restating it, so the placement ring and offset handle cannot drift from the bake. All four preview shaders get the matching change, including projection_axes(), whose tangent and bitangent have to flip with the coordinate or the relief shading inverts. Re-baking an existing project now places its texture upright, so it will differ from how it looked before. Geometry already baked into a 3mf is untouched, so nothing changes until the user re-bakes. Verified by measuring the sampled texture row and column against world position for every mapping mode on all six faces of a cube, and by a full bake of a quadrant coded image, which lands each quadrant within 1e-3 mm of its expected depth.