Add writeup
This commit is contained in:
parent
00000170e4
commit
00000180d3
9 changed files with 114 additions and 19 deletions
2
assignment-1/.gitignore
vendored
2
assignment-1/.gitignore
vendored
|
@ -1,3 +1,5 @@
|
||||||
/target
|
/target
|
||||||
|
/assignment-1
|
||||||
*.ppm
|
*.ppm
|
||||||
*.zip
|
*.zip
|
||||||
|
*.pdf
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
.PHONY: clean
|
.PHONY: all clean
|
||||||
|
|
||||||
|
DOCKER := docker
|
||||||
|
ZIP := zip
|
||||||
|
PANDOC := pandoc
|
||||||
|
|
||||||
HANDIN := hw1a.michael.zhang.zip
|
HANDIN := hw1a.michael.zhang.zip
|
||||||
|
BINARY := assignment-1
|
||||||
BINARY := target/release/assignment-1
|
WRITEUP := writeup.pdf
|
||||||
|
SOURCES := $(shell find -name "*.rs")
|
||||||
|
|
||||||
all: $(HANDIN)
|
all: $(HANDIN)
|
||||||
|
|
||||||
$(BINARY):
|
$(BINARY): $(SOURCES)
|
||||||
docker run \
|
$(DOCKER) run \
|
||||||
--rm \
|
--rm \
|
||||||
-v "$(shell pwd)":/usr/src/myapp \
|
-v "$(shell pwd)":/usr/src/myapp \
|
||||||
-v cargo-registry:/usr/local/cargo \
|
-v cargo-registry:/usr/local/cargo \
|
||||||
|
@ -15,9 +20,13 @@ $(BINARY):
|
||||||
-w /usr/src/myapp \
|
-w /usr/src/myapp \
|
||||||
rust \
|
rust \
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
mv target/release/assignment-1 $@
|
||||||
|
|
||||||
$(HANDIN): $(BINARY) Cargo.toml Cargo.lock README.md
|
$(HANDIN): $(BINARY) $(WRITEUP) Cargo.toml Cargo.lock README.md
|
||||||
zip -r $@ src $<
|
$(ZIP) -r $@ src $<
|
||||||
|
|
||||||
|
writeup.pdf: writeup.md
|
||||||
|
$(PANDOC) -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(HANDIN) $(BINARY)
|
rm -f $(HANDIN) $(BINARY) $(WRITEUP)
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
# Raycaster
|
|
BIN
assignment-1/doc/fov.jpg
Normal file
BIN
assignment-1/doc/fov.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
BIN
assignment-1/doc/map.jpg
Normal file
BIN
assignment-1/doc/map.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
assignment-1/doc/rot.jpg
Normal file
BIN
assignment-1/doc/rot.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
|
@ -59,7 +59,13 @@ fn main() -> Result<()> {
|
||||||
move |px: usize, py: usize| {
|
move |px: usize, py: usize| {
|
||||||
let x_component = pixel_base_x * px as f64;
|
let x_component = pixel_base_x * px as f64;
|
||||||
let y_component = pixel_base_y * py as f64;
|
let y_component = pixel_base_y * py as f64;
|
||||||
view_window.upper_left + x_component + y_component
|
|
||||||
|
// Without adding this, we would be getting the top-left of the pixel's
|
||||||
|
// rectangle. We want the center, so add half of the pixel size as
|
||||||
|
// well.
|
||||||
|
let center_offset = (pixel_base_x + pixel_base_y) / 2.0;
|
||||||
|
|
||||||
|
view_window.upper_left + x_component + y_component + center_offset
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
73
assignment-1/writeup.md
Normal file
73
assignment-1/writeup.md
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
---
|
||||||
|
geometry: margin=2cm
|
||||||
|
output: pdf_document
|
||||||
|
---
|
||||||
|
|
||||||
|
# Raycaster
|
||||||
|
|
||||||
|
Determining the viewing window for the raycaster for this assignment involved
|
||||||
|
creating a "virtual" screen in world coordinates, mapping image pixels into that
|
||||||
|
virtual screen, and then casting a ray through each pixel's world coordinate to
|
||||||
|
see where it would intersect objects.
|
||||||
|
|
||||||
|
### Creating a virtual screen
|
||||||
|
|
||||||
|
The virtual screen is determined first using the eye's position and where it's
|
||||||
|
looking. This gives us a single 3d vector, but it doesn't give us a 2d screen in
|
||||||
|
the world. This is where the field of view (FOV) comes in; the FOV determines
|
||||||
|
how many degrees the screen should take up.
|
||||||
|
|
||||||
|
![Field of view](doc/fov.jpg){width=180px}
|
||||||
|
|
||||||
|
Changing the angle of the field of view would result in a wider or narrower
|
||||||
|
screen, which when paired with the aspect ratio (width / height), would produce
|
||||||
|
a bigger or smaller viewing screen, like the orange box in the above diagram
|
||||||
|
shows. Simply put, FOV affects how _much_ of the frame you're able to see.
|
||||||
|
|
||||||
|
Curiously, distance from the eye actually doesn't really affect the viewing
|
||||||
|
screen very much. The reason is the screen is only used to determine how to
|
||||||
|
project rays. As the two black rectangles in the diagram above demonstrates,
|
||||||
|
changing the distance would still allow the viewer to see the same amount of the
|
||||||
|
scene. (using the word _amount_ very loosely here to mean percentage of the
|
||||||
|
landscape, rather than # of pixels, which is determined by the actual image
|
||||||
|
dimensions)
|
||||||
|
|
||||||
|
The up-direction vector controls the rotation of the scene. Without the
|
||||||
|
up-direction, it would not be possible to tell which rotation the screen should
|
||||||
|
be in:
|
||||||
|
|
||||||
|
![Rotation determined by up direction](doc/rot.jpg){width=240px}
|
||||||
|
|
||||||
|
Together, all of these parameters can uniquely determine a virtual screen
|
||||||
|
location, that we can use to cast rays through and fill pixels. We can change
|
||||||
|
any of these to produce an image with a more exaggerated view of the scene for
|
||||||
|
example; simply move the eye position to be incredibly close to the object that
|
||||||
|
we are observing, and increase the field of view to cover the entire object.
|
||||||
|
|
||||||
|
Because the rays are going in much different directions and travelling different
|
||||||
|
distances, the corners of the image will seem more stretched than if we were
|
||||||
|
observing the object from afar and all the rays are in approximately the same
|
||||||
|
part of the virtual screen.
|
||||||
|
|
||||||
|
One other point to make is that we're currently using a rectangle for our
|
||||||
|
virtual screen, which automatically does a bit of the distortion. If instead we
|
||||||
|
were to use a curved lens-like shape, then the rays pointing to any pixel of the
|
||||||
|
screen would be travelling the same distance. Moving the eye position closer to
|
||||||
|
the object would still generate distortion, but to a lesser extent.
|
||||||
|
|
||||||
|
### Mapping image pixels
|
||||||
|
|
||||||
|
After the rectangle has been determined, we can simply pick one corner to start
|
||||||
|
as an anchor, and then find out what pixel values would correspond to it. For
|
||||||
|
example, in the image below:
|
||||||
|
|
||||||
|
![Mapping image pixels](doc/map.jpg){width=240px}
|
||||||
|
|
||||||
|
I would pick a starting point like $A$, and then take the vector $B-A$ and
|
||||||
|
subdivide it into 4 pieces, letting $\Delta x = \frac{B-A}{4}$. Then, same thing
|
||||||
|
for the $y$ direction, I would set $\Delta y = \frac{D-A}{4}$. Taking $A +
|
||||||
|
x_i \times \Delta x + y_i \times \Delta y$ yields the precise coordinate
|
||||||
|
location for any pixel.
|
||||||
|
|
||||||
|
(Technically really we would want the middle of the pixel, so just add
|
||||||
|
$\frac{\Delta x + \Delta y}{2}$ to the point to get that)
|
12
flake.nix
12
flake.nix
|
@ -12,9 +12,15 @@
|
||||||
toolchain = pkgs.fenix.stable;
|
toolchain = pkgs.fenix.stable;
|
||||||
in rec {
|
in rec {
|
||||||
devShell = pkgs.mkShell {
|
devShell = pkgs.mkShell {
|
||||||
packages =
|
packages = (with pkgs; [
|
||||||
(with pkgs; [ cargo-watch cargo-deny cargo-edit zip unzip ])
|
cargo-watch
|
||||||
++ (with toolchain; [
|
cargo-deny
|
||||||
|
cargo-edit
|
||||||
|
pandoc
|
||||||
|
zip
|
||||||
|
unzip
|
||||||
|
texlive.combined.scheme-full
|
||||||
|
]) ++ (with toolchain; [
|
||||||
cargo
|
cargo
|
||||||
rustc
|
rustc
|
||||||
clippy
|
clippy
|
||||||
|
|
Loading…
Reference in a new issue