Add more to the writeup
This commit is contained in:
parent
00000230ee
commit
000002404e
7 changed files with 128 additions and 25 deletions
|
@ -36,7 +36,7 @@ examples/%.ppm: examples/%.txt
|
|||
examples/%.png: examples/%.ppm
|
||||
convert $< $@
|
||||
|
||||
writeup.pdf: writeup.md
|
||||
writeup.pdf: writeup.md $(EXAMPLES_PNG)
|
||||
$(PANDOC) -o $@ $<
|
||||
|
||||
clean:
|
||||
|
|
21
assignment-1/examples/fov-demo-1.txt
Normal file
21
assignment-1/examples/fov-demo-1.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
imsize 640 480
|
||||
eye 0 0 15
|
||||
viewdir 0 0 -1
|
||||
hfov 60
|
||||
updir 0 1 0
|
||||
bkgcolor 0.1 0.1 0.1
|
||||
|
||||
mtlcolor 0 0.5 0.5
|
||||
sphere -1 -2 -5 2
|
||||
sphere 3 -5 -1 0.5
|
||||
|
||||
mtlcolor 0.5 0.5 1
|
||||
sphere 1 2 -3 3
|
||||
sphere -6 3 -4 1
|
||||
|
||||
mtlcolor 0.5 0 0.5
|
||||
sphere 5 5 -1 1
|
||||
sphere -6 -4 -8 7
|
||||
|
||||
mtlcolor 0.5 1 0.5
|
||||
cylinder 5 1 -2 1 -2 1 1 2
|
21
assignment-1/examples/fov-demo-2.txt
Normal file
21
assignment-1/examples/fov-demo-2.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
imsize 640 480
|
||||
eye 0 0 15
|
||||
viewdir 0 0 -1
|
||||
hfov 30
|
||||
updir 0 1 0
|
||||
bkgcolor 0.1 0.1 0.1
|
||||
|
||||
mtlcolor 0 0.5 0.5
|
||||
sphere -1 -2 -5 2
|
||||
sphere 3 -5 -1 0.5
|
||||
|
||||
mtlcolor 0.5 0.5 1
|
||||
sphere 1 2 -3 3
|
||||
sphere -6 3 -4 1
|
||||
|
||||
mtlcolor 0.5 0 0.5
|
||||
sphere 5 5 -1 1
|
||||
sphere -6 -4 -8 7
|
||||
|
||||
mtlcolor 0.5 1 0.5
|
||||
cylinder 5 1 -2 1 -2 1 1 2
|
9
assignment-1/examples/up-dir-demo-1.txt
Normal file
9
assignment-1/examples/up-dir-demo-1.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
imsize 640 480
|
||||
eye 0 0 8
|
||||
viewdir 0 0 -1
|
||||
hfov 60
|
||||
updir 0 1 0
|
||||
bkgcolor 1 1 1
|
||||
|
||||
mtlcolor 0.5 1 0.5
|
||||
cylinder 0 0 -4 1 0 0 1 8
|
9
assignment-1/examples/up-dir-demo-2.txt
Normal file
9
assignment-1/examples/up-dir-demo-2.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
imsize 640 480
|
||||
eye 0 0 8
|
||||
viewdir 0 0 -1
|
||||
hfov 60
|
||||
updir 1 1 0
|
||||
bkgcolor 1 1 1
|
||||
|
||||
mtlcolor 0.5 1 0.5
|
||||
cylinder 0 0 -4 1 0 0 1 8
|
|
@ -57,7 +57,7 @@ impl ObjectKind for Cylinder {
|
|||
|
||||
let discriminant = b * b - 4.0 * a * c;
|
||||
|
||||
let mut solutions = match discriminant {
|
||||
let possible_side_solutions = match discriminant {
|
||||
// Discriminant < 0, means the equation has no solutions.
|
||||
d if d < 0.0 => vec![],
|
||||
|
||||
|
@ -76,6 +76,16 @@ impl ObjectKind for Cylinder {
|
|||
_ => unreachable!("Invalid determinant value: {discriminant}"),
|
||||
};
|
||||
|
||||
// Filter out solutions that don't have a valid Z position.
|
||||
let side_solutions = possible_side_solutions.into_iter().filter(|t| {
|
||||
let ray_point = ray.eval(*t);
|
||||
let rotated_ray_point = rotation_matrix * ray_point;
|
||||
let z = rotated_ray_point.z - rotated_cylinder_center.z;
|
||||
|
||||
// Check to see if z is between -len/2 and len/2
|
||||
z.abs() < self.length / 2.0
|
||||
});
|
||||
|
||||
// We also need to add solutions for the two ends of the cylinder, which
|
||||
// uses a similar method except backwards: check intersection points
|
||||
// with the correct z-plane and then see if the points are within the
|
||||
|
@ -96,26 +106,19 @@ impl ObjectKind for Cylinder {
|
|||
(o.z + c.z - self.length / 2.0) / r.z,
|
||||
]
|
||||
};
|
||||
|
||||
// Filter out all the solutions where the z does not lie in the circle
|
||||
solutions.extend(possible_z_intersections.into_iter().filter(|t| {
|
||||
let end_solutions = possible_z_intersections.into_iter().filter(|t| {
|
||||
let ray_point = ray.eval(*t);
|
||||
ray_point.x.powi(2) + ray_point.y.powi(2) <= self.radius.powi(2)
|
||||
}));
|
||||
});
|
||||
|
||||
// Filter out solutions that don't have a valid Z position.
|
||||
let solutions = solutions
|
||||
.into_iter()
|
||||
.filter(|t| {
|
||||
let ray_point = ray.eval(*t);
|
||||
let rotated_ray_point = rotation_matrix * ray_point;
|
||||
let z = rotated_ray_point.z - rotated_cylinder_center.z;
|
||||
|
||||
// Check to see if z is between -len/2 and len/2
|
||||
z.abs() < self.length / 2.0
|
||||
})
|
||||
.filter_map(|t| NotNan::new(t).ok());
|
||||
let solutions = side_solutions.into_iter().chain(end_solutions.into_iter());
|
||||
|
||||
// Return the minimum solution
|
||||
solutions.min().map(|t| t.into_inner())
|
||||
solutions
|
||||
.filter_map(|t| NotNan::new(t).ok())
|
||||
.min()
|
||||
.map(|t| t.into_inner())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ output: pdf_document
|
|||
|
||||
# Raycaster
|
||||
|
||||
#### Michael Zhang \<zhan4854@umn.edu\>
|
||||
|
||||
---
|
||||
|
||||
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
|
||||
|
@ -22,7 +26,15 @@ how many degrees the screen should take up.
|
|||
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.
|
||||
shows. Simply put, FOV affects how _much_ of the frame you're able to see. An
|
||||
example is shown here:
|
||||
|
||||
![](examples/fov-demo-1.png){width=180px}\ ![](examples/fov-demo-2.png){width=180px}
|
||||
|
||||
The left image uses an FOV of 60, while the right image uses an FOV of 30. As
|
||||
you can see, the left side has a wider range of vision, which allows it to see
|
||||
more of the world. (both images can be found in the `examples` directory of the
|
||||
handin zip)
|
||||
|
||||
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
|
||||
|
@ -34,10 +46,16 @@ 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:
|
||||
be in.
|
||||
|
||||
![Rotation determined by up direction](doc/rot.jpg){width=240px}
|
||||
|
||||
To see what this looks like, consider the following images, where the left side
|
||||
uses an up direction of $(0, 1, 0)$, while the right side uses $(1, 1, 0)$ (both
|
||||
images can be found in the `examples` directory of the handin zip)
|
||||
|
||||
![](examples/up-dir-demo-1.png){width=180px}\ ![](examples/up-dir-demo-2.png){width=180px}
|
||||
|
||||
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
|
||||
|
@ -76,7 +94,8 @@ $\frac{\Delta x + \Delta y}{2}$ to the point to get that)
|
|||
|
||||
Because of the way I implemented parallel projection, it's recommended to
|
||||
either put the eye much farther back, or use `--distance` to force a much bigger
|
||||
distance from the eye for the raycaster. This is due to the size of the image.
|
||||
distance from the eye for the raycaster. See the `--help` to see how this option
|
||||
is used.
|
||||
|
||||
### Cylinder Intersection Notes
|
||||
|
||||
|
@ -84,9 +103,30 @@ First, we will transform the current point into the vector space of the
|
|||
cylinder, so that the cylinder location is $(0, 0, 0)$ and the direction vector
|
||||
is normalized into $(0, 0, 1)$.
|
||||
|
||||
Then it's a matter of determining if the $x$ and $y$ coordinates fall into the
|
||||
space constrained by the equation $(ox + t\times rx - cx)^2 + (oy + t\times ty -
|
||||
cy)^2 = r^2$ and if $z \le L$.
|
||||
This can be done by using a rotation matrix (since we are sure this
|
||||
transformation is just a rotation). This rotation is actually a 2D rotation,
|
||||
around the normal between the cylinder direction and $(0, 0, 1)$. We then
|
||||
rotate everything we are working with (the cylinder and the ray) into this
|
||||
coordinate system to make calculations easier.
|
||||
|
||||
See the comments in the code for a more detailed explanation of the equation
|
||||
used.
|
||||
Then it's a matter of determining if the $x$ and $y$ coordinates fall into the
|
||||
space constrained by the equation $(o_x + t\times r_x - c_x)^2 + (o_y + t\times
|
||||
r_y - c_y)^2 = r^2$ and if $z \le L$. I can solve this using the quadratic
|
||||
formula the same way as the sphere case.
|
||||
|
||||
We want a quadratic equation of the form $At^2 + Bt + C = 0$. The values for
|
||||
$A$, $B$, and $C$ are:
|
||||
|
||||
- $A = r_x^2 + r_y^2$
|
||||
- $B = 2(r_x(o_x - c_x) + r_y(o_y - c_y))$
|
||||
- $C = (c_x - o_x)^2 + (c_y - o_y)^2 - r^2$
|
||||
|
||||
Solving this for $t$ yields 0-2 solutions depending on if the equation was
|
||||
satisfied or not. Then, we can plug any solutions we get back into the ray
|
||||
equation and determine if the $z$-coordinate is in the range of the cylinder
|
||||
that we want.
|
||||
|
||||
We will also have to do this for the ends of the cylinder, but just backwards.
|
||||
So we would start with the $z$-coordinate, solve for $t$s where the ray hits
|
||||
that $z$-plane, and then check the $x$ and $y$ values to see if they satisfy the
|
||||
ray equation as well.
|
||||
|
|
Loading…
Reference in a new issue