mirror of
https://github.com/SleepingInsomniac/pixelfaucet
synced 2025-01-23 07:27:17 +01:00
Update clipping
This commit is contained in:
parent
926a345c9b
commit
0eb0eb2449
3 changed files with 77 additions and 36 deletions
|
@ -111,22 +111,37 @@ class ThreeDee < PF::Game
|
|||
@depth_buffer,
|
||||
tri.color
|
||||
)
|
||||
|
||||
if tri.clipped
|
||||
p1 = PF::Vector[tri.p1.x.to_i, tri.p1.y.to_i]
|
||||
p2 = PF::Vector[tri.p2.x.to_i, tri.p2.y.to_i]
|
||||
p3 = PF::Vector[tri.p3.x.to_i, tri.p3.y.to_i]
|
||||
draw_triangle(p1, p2, p3, PF::Pixel.new(255, 255, 0))
|
||||
end
|
||||
end
|
||||
|
||||
tris = @projector.project(@model.tris)
|
||||
tris = @projector.project(@model.tris, sort: true)
|
||||
tris.each do |tri|
|
||||
# Rasterize all triangles
|
||||
|
||||
p1 = PF::Vector[tri.p1.x.to_i, tri.p1.y.to_i]
|
||||
p2 = PF::Vector[tri.p2.x.to_i, tri.p2.y.to_i]
|
||||
p3 = PF::Vector[tri.p3.x.to_i, tri.p3.y.to_i]
|
||||
|
||||
fill_triangle(
|
||||
PF::Vector[tri.p1.x.to_i, tri.p1.y.to_i],
|
||||
PF::Vector[tri.p2.x.to_i, tri.p2.y.to_i],
|
||||
PF::Vector[tri.p3.x.to_i, tri.p3.y.to_i],
|
||||
p1,
|
||||
p2,
|
||||
p3,
|
||||
pixel: tri.color # buffer: @depth_buffer
|
||||
)
|
||||
|
||||
if tri.clipped
|
||||
draw_triangle(p1, p2, p3, PF::Pixel.new(255, 0, 0))
|
||||
end
|
||||
end
|
||||
|
||||
string = String.build do |io|
|
||||
io << "Triangles: " << tris.size + cube_tris.size
|
||||
io << "Triangles: " << cube_tris.size + tris.size
|
||||
io << "\nPosition: "
|
||||
io << "x: " << @camera.position.x.round(2)
|
||||
io << "y: " << @camera.position.y.round(2)
|
||||
|
|
|
@ -6,18 +6,20 @@ module PF
|
|||
getter width : Int32 | Float64
|
||||
getter height : Int32 | Float64
|
||||
property near = 0.1
|
||||
property far = 1000.0
|
||||
getter fov = 90.0
|
||||
property far = 50.0
|
||||
getter fov = 70.0
|
||||
property aspect_ratio : Float64?
|
||||
property camera : Camera
|
||||
property light : Vector3(Float64) = Vector3.new(0.0, 0.0, -1.0).normalized
|
||||
property mat_proj : Matrix(Float64, 16)?
|
||||
property clipping_plane_near : Vector3(Float64)
|
||||
property near_plane_normal : Vector3(Float64) = Vector3.new(0.0, 0.0, 1.0)
|
||||
property clipping_plane_far : Vector3(Float64)
|
||||
|
||||
@fov_rad : Float64?
|
||||
|
||||
def initialize(@width, @height, @camera = Camera.new)
|
||||
@clipping_plane_near = Vector3.new(0.0, 0.0, @near)
|
||||
@clipping_plane_far = Vector3.new(0.0, 0.0, @far)
|
||||
end
|
||||
|
||||
def mat_proj
|
||||
|
@ -58,43 +60,51 @@ module PF
|
|||
def project(tris : Array(Tri), camera = @camera, sort : Bool = false)
|
||||
mat_view = camera.view_matrix
|
||||
|
||||
# only draw triangles facing the camera
|
||||
# Only draw triangles facing the camera
|
||||
tris = tris.select do |tri|
|
||||
tri.normal.dot(tri.p1 - camera.position) < 0.0
|
||||
end
|
||||
|
||||
# Iterate tris to transform into view, project, and clip
|
||||
0.upto(tris.size - 1) do
|
||||
tri = tris.pop
|
||||
# Iterate tris to transform into
|
||||
tris = tris.map do |tri|
|
||||
shade = (tri.normal.dot(light) + 1.0) / 2 # light should be normalized
|
||||
tri.color = tri.color * shade
|
||||
tri * mat_view
|
||||
end
|
||||
|
||||
tri *= mat_view
|
||||
|
||||
# Clip against the near plane
|
||||
tri.clip(plane: clipping_plane_near, plane_normal: near_plane_normal).each do |tri|
|
||||
tri *= mat_proj
|
||||
|
||||
# Invert the y axis
|
||||
tri.p1.y = tri.p1.y * -1.0
|
||||
tri.p2.y = tri.p2.y * -1.0
|
||||
tri.p3.y = tri.p3.y * -1.0
|
||||
|
||||
# scale into screen space
|
||||
tri.p1 += 1.0
|
||||
tri.p2 += 1.0
|
||||
tri.p3 += 1.0
|
||||
|
||||
tri.p1.x = tri.p1.x * 0.5 * width
|
||||
tri.p1.y = tri.p1.y * 0.5 * height
|
||||
tri.p2.x = tri.p2.x * 0.5 * width
|
||||
tri.p2.y = tri.p2.y * 0.5 * height
|
||||
tri.p3.x = tri.p3.x * 0.5 * width
|
||||
tri.p3.y = tri.p3.y * 0.5 * height
|
||||
|
||||
# Clip tris
|
||||
{
|
||||
{clipping_plane_near, Vector[0.0, 0.0, 1.0]},
|
||||
{clipping_plane_far, Vector[0.0, 0.0, -1.0]},
|
||||
}.each do |clip|
|
||||
0.upto(tris.size - 1) do
|
||||
tri = tris.pop
|
||||
tri.clip(plane: clip[0], plane_normal: clip[1]).each do |tri|
|
||||
tris.unshift(tri)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Project the triangles
|
||||
tris = tris.map do |tri|
|
||||
z = tri.z
|
||||
tri *= mat_proj
|
||||
tri.z = z
|
||||
|
||||
tri.map_points do |point|
|
||||
# Invert the y axis
|
||||
point.y *= -1.0
|
||||
|
||||
# scale into screen space
|
||||
point += 1.0
|
||||
point.x *= 0.5 * width
|
||||
point.y *= 0.5 * height
|
||||
|
||||
point
|
||||
end
|
||||
|
||||
tri
|
||||
end
|
||||
|
||||
# sort triangles, no need to do this if using a depth buffer
|
||||
tris.sort! { |a, b| b.z <=> a.z } if sort
|
||||
|
|
|
@ -12,14 +12,15 @@ module PF
|
|||
property t2 : Vector3(Float64) = Vector[0.0, 0.0, 0.0]
|
||||
property t3 : Vector3(Float64) = Vector[0.0, 0.0, 0.0]
|
||||
|
||||
property color : PF::Pixel
|
||||
property color : Pixel
|
||||
|
||||
getter clipped : Bool = false
|
||||
setter normal : Vector3(Float64)?
|
||||
|
||||
def initialize(@p1 : Vector3(Float64), @p2 : Vector3(Float64), @p3 : Vector3(Float64), @color = PF::Pixel::White, @normal = nil)
|
||||
def initialize(@p1 : Vector3(Float64), @p2 : Vector3(Float64), @p3 : Vector3(Float64), @color = PF::Pixel::White, @normal = nil, @clipped = false)
|
||||
end
|
||||
|
||||
def initialize(@p1, @p2, @p3, @t1, @t2, @t3, @color = PF::Pixel::White)
|
||||
def initialize(@p1, @p2, @p3, @t1, @t2, @t3, @color = PF::Pixel::White, @clipped = false)
|
||||
end
|
||||
|
||||
# Return the normal assuming clockwise pointing winding
|
||||
|
@ -46,6 +47,18 @@ module PF
|
|||
(@p1.z + @p2.z + @p3.z) / 3.0
|
||||
end
|
||||
|
||||
def z=(value : Float64)
|
||||
@p1.z = value
|
||||
@p2.z = value
|
||||
@p3.z = value
|
||||
end
|
||||
|
||||
def map_points
|
||||
@p1 = yield @p1
|
||||
@p2 = yield @p2
|
||||
@p3 = yield @p3
|
||||
end
|
||||
|
||||
# Multiply all points by a *Matrix*, returning a new *Tri*
|
||||
def *(mat : Matrix)
|
||||
# The transform function returns a w, which is the 4th component of the vertex
|
||||
|
@ -119,7 +132,8 @@ module PF
|
|||
Tri.new(
|
||||
inside_points[0], clip_p1, clip_p2,
|
||||
inside_texts[0], int_t1, int_t2,
|
||||
color: @color
|
||||
color: @color,
|
||||
clipped: true
|
||||
),
|
||||
}
|
||||
end
|
||||
|
@ -141,14 +155,16 @@ module PF
|
|||
Tri.new(
|
||||
inside_points[0], inside_points[1], clip_p1,
|
||||
inside_texts[0], inside_texts[1], int_t1,
|
||||
color: @color
|
||||
color: @color,
|
||||
clipped: true
|
||||
),
|
||||
# The second triangle will have the second inside point, the second intersection, then the first intersection
|
||||
# This order preserves clockwise winding
|
||||
Tri.new(
|
||||
inside_points[1], clip_p2, clip_p1,
|
||||
inside_texts[1], int_t2, int_t1,
|
||||
color: @color
|
||||
color: @color,
|
||||
clipped: true
|
||||
),
|
||||
}
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue