hgkjshegfskef

hgkjshegfskef

The Ray Tracer Challenge: chapter 7 final image is flipped (camera issues) (pp. 105-107)

@jamis

Unfortunately, my final image of chapter 7 is flipped:

All the tests from the chapter pass.

My camera and ray generation are implemented as:

camera::camera(unsigned hsize, unsigned vsize, float fov) noexcept
    : hsize{hsize}, vsize{vsize}, fov{fov}, tform{} {
    float half_view = std::tan(fov / 2.f);
    float aspect = float(hsize) / float(vsize);
    if (aspect >= 1.f) {
        half_width = half_view;
        half_height = half_view / aspect;
    } else {
        half_width = half_view * aspect;
        half_height = half_view;
    }
    pixel_size = (half_width * 2.f) / hsize;
}

tform4 view(pnt3 const& from, pnt3 const& to, vec3 const& up) noexcept {
    vec3 const forward = normalize(to - from);
    vec3 const left = normalize(cross(forward, normalize(up)));
    vec3 const true_up = normalize(cross(left, forward));
    //    vec3 const true_up = -normalize(cross(left, forward));
    tform4 orientation{left.x,     left.y,     left.z,     0, //
                       true_up.x,  true_up.y,  true_up.z,  0, //
                       -forward.x, -forward.y, -forward.z, 0};
    return orientation * tform4::translate({-from.x, -from.y, -from.z});
}

ray ray_for_pixel(camera const& cam, float px, float py) noexcept {
    // offset from edge of canvas to pixel center
    float const xoffset = (px + 0.5f) * cam.pixel_size;
    float const yoffset = (py + 0.5f) * cam.pixel_size;

    // cam looks towards -z, x is to the left
    float const world_x = cam.half_width - xoffset;
    float const world_y = cam.half_height - yoffset;
    assert(-1.f <= world_x && world_x <= 1.f);
    assert(-1.f <= world_y && world_y <= 1.f);

    tform4 const inv_cam_tform = inverse(cam.tform);
    // canvas is at z=-1
    pnt3 const pixel = inv_cam_tform * pnt3{world_x, world_y, -1};
    pnt3 const origin = inv_cam_tform * pnt3{0, 0, 0};
    vec3 const direction = normalize(pixel - origin);
    return ray{origin, direction};
}

If I negate the true_up vector, as commented out, then the image is correct:

Obviously, if I negate it, some tests fail. This is a workaround, or one bug undoing the problem caused by another bug.

If I understand correctly, forward designates Z axis, which grows into the screen (assuming left hand coordinate system, X growing right and Y growing up). Then left vector designates X, since it is the result of the left hand coordinate cross product of Z and Y. Then true_up designates X and Z cross product. Flipping the sign on true_up cross is the same as making the cross of Z and X, which would point the Y axis downwards. But this is obviously wrong.

My render() is:

canvas render(camera const& cam, world const& w) noexcept {
    canvas image{cam.hsize, cam.vsize};
    image.fill({0, 0, 0});
    for (int y = cam.vsize - 1; y >= 0; --y) {
        for (unsigned x = 0; x < cam.hsize - 1; ++x) {
            image(x, y) = color_at(w, ray_for_pixel(cam, x, y));
        }
    }
    return image;
}

My canvas’s (x,y) addressing differs from the book. In the book, the canvas’s X grows right, Y grows down, like in 2D array. Since this is difficult to reason about, my canvas’s abstraction is that X grows right, and Y grows up, same as the left hand coordinate system. But it is also implemented as 2D array (addressed as 1D array), where Y grows down, so I transform the coordinates inside the canvas implementation:

canvas::canvas(unsigned int w, unsigned int h) noexcept
    : canvas_{std::make_unique<color[]>(w * h)}, w_{w}, h_{h} {}

color& canvas::operator()(unsigned int x, unsigned int y) noexcept {
    // Internally, X grows right, but Y grows down, hence the conversion
    return canvas_[(h_ - y - 1) * w_ + x];
}

This could be the reason, but I don’t think so.

Any ideas what could be going wrong? The full code is here.

First Post!

gautierdag

gautierdag

@jamis

Curious, what was the bug with this in the end?

Where Next?

Popular Pragmatic Bookshelf topics Top

belgoros
Following the steps described in Chapter 6 of the book, I’m stuck with running the migration as described on page 84: bundle exec sequel...
New
jesse050717
Title: Web Development with Clojure, Third Edition, pg 116 Hi - I just started chapter 5 and I am stuck on page 116 while trying to star...
New
simonpeter
When I try the command to create a pair of migration files I get an error. user=&gt; (create-migration "guestbook") Execution error (Ill...
New
raul
Hi Travis! Thank you for the cool book! :slight_smile: I made a list of issues and thought I could post them chapter by chapter. I’m rev...
New
gilesdotcodes
In case this helps anyone, I’ve had issues setting up the rails source code. Here were the solutions: In Gemfile, change gem 'rails' t...
New
adamwoolhether
When trying to generate the protobuf .go file, I receive this error: Unknown flag: --go_opt libprotoc 3.12.3 MacOS 11.3.1 Googling ...
New
s2k
Hi all, currently I wonder how the Tailwind colours work (or don’t work). For example, in app/views/layouts/application.html.erb I have...
New
kolossal
Hi, I need some help, I’m new to rust and was learning through your book. but I got stuck at the last stage of distribution. Whenever I t...
New
dtonhofer
@parrt In the context of Chapter 4.3, the grammar Java.g4, meant to parse Java 6 compilation units, no longer passes ANTLR (currently 4....
New
dachristenson
I’ve got to the end of Ch. 11, and the app runs, with all tabs displaying what they should – at first. After switching around between St...
New

Other popular topics Top

PragmaticBookshelf
Take your Go skills to the next level by learning how to design, develop, and deploy a distributed service. Start from the bare essential...
New
PragmaticBookshelf
Stop developing web apps with yesterday’s tools. Today, developers are increasingly adopting Clojure as a web-development platform. See f...
New
PragmaticBookshelf
Machine learning can be intimidating, with its reliance on math and algorithms that most programmers don't encounter in their regular wor...
New
PragmaticBookshelf
Ruby, Io, Prolog, Scala, Erlang, Clojure, Haskell. With Seven Languages in Seven Weeks, by Bruce A. Tate, you’ll go beyond the syntax—and...
New
Exadra37
I am thinking in building or buy a desktop computer for programing, both professionally and on my free time, and my choice of OS is Linux...
New
AstonJ
Do the test and post your score :nerd_face: :keyboard: If possible, please add info such as the keyboard you’re using, the layout (Qw...
New
PragmaticBookshelf
Author Spotlight Rebecca Skinner @RebeccaSkinner Welcome to our latest author spotlight, where we sit down with Rebecca Skinner, auth...
New
New
AstonJ
This is cool! DEEPSEEK-V3 ON M4 MAC: BLAZING FAST INFERENCE ON APPLE SILICON We just witnessed something incredible: the largest open-s...
New
CommunityNews
Open-source implementation of the classic GTA engine now running directly in your browser. Experience the reVC technology demo on DOS.Zon...
New

Sub Categories: