mirror of
https://github.com/SleepingInsomniac/pixelfaucet
synced 2024-11-16 07:47:36 +01:00
Handle texture coords when clipping
This commit is contained in:
parent
2d44da33b4
commit
2e6fca44e3
5 changed files with 53 additions and 25 deletions
|
@ -1,9 +1,11 @@
|
|||
v 0.0 0.0 0.0
|
||||
v 0.0 1.0 0.0
|
||||
v 1.0 1.0 0.0
|
||||
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
v 1.0 0.0 1.0
|
||||
v 0.0 1.0 1.0
|
||||
v 0.0 0.0 1.0
|
||||
|
@ -14,7 +16,7 @@ vt 1.0 0.0
|
|||
|
||||
vt 0.0 1.0
|
||||
vt 1.0 0.0
|
||||
vt 1.0 0.0
|
||||
vt 1.0 1.0
|
||||
|
||||
# south
|
||||
f 1/1 2/2 3/3
|
||||
|
|
|
@ -36,15 +36,18 @@ module PF
|
|||
end
|
||||
|
||||
def forward_vector
|
||||
Transform3d.apply(Vector3.new(0.0, 0.0, 1.0), rotation_matrix)
|
||||
v, w = Transform3d.apply(Vector3.new(0.0, 0.0, 1.0), rotation_matrix)
|
||||
v
|
||||
end
|
||||
|
||||
def strafe_vector
|
||||
Transform3d.apply(Vector3.new(1.0, 0.0, 0.0), rotation_matrix)
|
||||
v, w = Transform3d.apply(Vector3.new(1.0, 0.0, 0.0), rotation_matrix)
|
||||
v
|
||||
end
|
||||
|
||||
def up_vector
|
||||
Transform3d.apply(Vector3.new(0.0, 1.0, 0.0), rotation_matrix)
|
||||
v, w = Transform3d.apply(Vector3.new(0.0, 1.0, 0.0), rotation_matrix)
|
||||
v
|
||||
end
|
||||
|
||||
def matrix
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
module PF
|
||||
# Mesh represents a collection of points and triangles
|
||||
# TODO: Keep points in a collection, removing duplicates, and keep triangle verticies pointing to the points in that collection
|
||||
class Mesh
|
||||
setter tris = [] of Tri
|
||||
property origin : Vector3(Float64) = Vector[0.0, 0.0, 0.0]
|
||||
|
@ -6,6 +8,7 @@ module PF
|
|||
property position : Vector3(Float64) = Vector[0.0, 0.0, 0.0]
|
||||
|
||||
# Load an obj file
|
||||
# TODO: Load meshes specified by the obj file
|
||||
def self.load_obj(path, use_normals : Bool = false)
|
||||
verticies = [] of Vector3(Float64)
|
||||
texture_verticies = [] of Vector3(Float64)
|
||||
|
@ -64,6 +67,7 @@ module PF
|
|||
tris << tri
|
||||
|
||||
# Split a square into triangles
|
||||
# TODO: Handle texture points
|
||||
if face_verts.size > 3
|
||||
tri = Tri.new(face_verts[0], face_verts[2], face_verts[3], normal: normal)
|
||||
tris << tri
|
||||
|
|
|
@ -54,6 +54,7 @@ module PF
|
|||
@fov_rad ||= 1.0 / Math.tan(@fov * 0.5 / 180.0 * Math::PI)
|
||||
end
|
||||
|
||||
# Project an array of Triangles into screen space
|
||||
def project(tris : Array(Tri), camera = @camera)
|
||||
mat_view = camera.view_matrix
|
||||
|
||||
|
@ -96,6 +97,7 @@ module PF
|
|||
end
|
||||
|
||||
# sort triangles
|
||||
# TODO: Z-buffer
|
||||
tris.sort! { |a, b| b.z <=> a.z }
|
||||
|
||||
# Clip against the edges of the screen
|
||||
|
|
|
@ -12,8 +12,6 @@ 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 texture : Sprite*? = nil
|
||||
|
||||
property color : PF::Pixel
|
||||
|
||||
setter normal : Vector3(Float64)?
|
||||
|
@ -21,7 +19,7 @@ module PF
|
|||
def initialize(@p1 : Vector3(Float64), @p2 : Vector3(Float64), @p3 : Vector3(Float64), @color = PF::Pixel.white, @normal = nil)
|
||||
end
|
||||
|
||||
def initialize(@p1, @p2, @p3, @t1, @t2, @t3, @texture = nil, @color = PF::Pixel.white)
|
||||
def initialize(@p1, @p2, @p3, @t1, @t2, @t3, @color = PF::Pixel.white)
|
||||
end
|
||||
|
||||
# Return the normal assuming clockwise pointing winding
|
||||
|
@ -50,14 +48,15 @@ module PF
|
|||
|
||||
# Multiply all points by a *Matrix*, returning a new *Tri*
|
||||
def *(mat : Matrix)
|
||||
pp1, w1 = Transform3d.apply(@p1, mat)
|
||||
pp2, w2 = Transform3d.apply(@p2, mat)
|
||||
pp3, w3 = Transform3d.apply(@p3, mat)
|
||||
|
||||
Tri.new(
|
||||
Transform3d.apply(@p1, mat),
|
||||
Transform3d.apply(@p2, mat),
|
||||
Transform3d.apply(@p3, mat),
|
||||
pp1, pp2, pp3,
|
||||
@t1,
|
||||
@t2,
|
||||
@t3,
|
||||
@texture,
|
||||
@color
|
||||
)
|
||||
end
|
||||
|
@ -69,70 +68,88 @@ module PF
|
|||
plane_normal = plane_normal.normalized
|
||||
|
||||
# Create two temporary storage arrays to classify points either side of plane
|
||||
inside_points = StaticArray(Vector3(Float64), 3).new(Vector[0.0, 0.0, 0.0])
|
||||
inside_points = uninitialized StaticArray(Vector3(Float64), 3)
|
||||
inside_count = 0
|
||||
outside_points = StaticArray(Vector3(Float64), 3).new(Vector[0.0, 0.0, 0.0])
|
||||
outside_points = uninitialized StaticArray(Vector3(Float64), 3)
|
||||
outside_count = 0
|
||||
|
||||
# Create the same for texture points
|
||||
inside_texts = uninitialized StaticArray(Vector3(Float64), 3)
|
||||
outside_texts = uninitialized StaticArray(Vector3(Float64), 3)
|
||||
|
||||
# Classify each point as inside or outside of the plane
|
||||
{p1, p2, p3}.each do |p|
|
||||
{ {p1, t1}, {p2, t2}, {p3, t3} }.each do |p, t|
|
||||
# Get the distance of the point to the clipping plane
|
||||
distance = plane_normal.x * p.x + plane_normal.y * p.y + plane_normal.z * p.z - plane_normal.dot(plane)
|
||||
|
||||
# If the distance is positive, our point lies on inside of plane
|
||||
# If the distance is positive, our point lies on inside of the plane
|
||||
if distance >= 0
|
||||
inside_points[inside_count] = p
|
||||
inside_texts[inside_count] = t
|
||||
inside_count += 1
|
||||
else
|
||||
outside_points[outside_count] = p
|
||||
outside_texts[outside_count] = t
|
||||
outside_count += 1
|
||||
end
|
||||
end
|
||||
|
||||
# Clip the entire triangle
|
||||
return Tuple.new if inside_count == 0
|
||||
|
||||
# All points are inside of the plane
|
||||
# No clipping required, return the original triangle
|
||||
return {self} if inside_count == 3
|
||||
|
||||
# Clip two points of the tri into one tri
|
||||
# One point inside the plane, 2 outside
|
||||
if inside_count == 1 && outside_count == 2
|
||||
# One point inside the plane
|
||||
# the two intersection points and the one inside point form a new triangle
|
||||
clip_p1, t = G3d.line_intersects_plane(plane, plane_normal, inside_points[0], outside_points[0])
|
||||
int_t1 = (outside_texts[0] - inside_texts[0]) * t + inside_texts[0]
|
||||
|
||||
i_p1, t1 = G3d.line_intersects_plane(plane, plane_normal, inside_points[0], outside_points[0])
|
||||
i_p2, t2 = G3d.line_intersects_plane(plane, plane_normal, inside_points[0], outside_points[1])
|
||||
clip_p2, t = G3d.line_intersects_plane(plane, plane_normal, inside_points[0], outside_points[1])
|
||||
int_t2 = (outside_texts[1] - inside_texts[0]) * t + inside_texts[0]
|
||||
|
||||
return {
|
||||
Tri.new(
|
||||
inside_points[0], i_p1, i_p2,
|
||||
inside_points[0], clip_p1, clip_p2,
|
||||
inside_texts[0], int_t1, int_t2,
|
||||
color: @color
|
||||
),
|
||||
}
|
||||
end
|
||||
|
||||
# Clip one point of the tri, return two tris
|
||||
if inside_count == 2 && outside_count == 1
|
||||
# Two points are inside the plane, this will form a quad
|
||||
# We must now split the quad into two new triangles
|
||||
|
||||
# Calculate the two intersection points
|
||||
i_p1, t1 = G3d.line_intersects_plane(plane, plane_normal, inside_points[0], outside_points[0])
|
||||
i_p2, t2 = G3d.line_intersects_plane(plane, plane_normal, inside_points[1], outside_points[0])
|
||||
clip_p1, t = G3d.line_intersects_plane(plane, plane_normal, inside_points[0], outside_points[0])
|
||||
int_t1 = (outside_texts[0] - inside_texts[0]) * t + inside_texts[0]
|
||||
|
||||
clip_p2, t = G3d.line_intersects_plane(plane, plane_normal, inside_points[1], outside_points[0])
|
||||
int_t2 = (outside_texts[0] - inside_texts[1]) * t + inside_texts[1]
|
||||
|
||||
return {
|
||||
# The first triangle will have the two inside points, and first intersection point
|
||||
Tri.new(
|
||||
inside_points[0], inside_points[1], i_p1,
|
||||
inside_points[0], inside_points[1], clip_p1,
|
||||
inside_texts[0], inside_texts[1], int_t1,
|
||||
color: @color
|
||||
),
|
||||
# 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], i_p2, i_p1,
|
||||
inside_points[1], clip_p2, clip_p1,
|
||||
inside_texts[1], int_t2, int_t1,
|
||||
color: @color
|
||||
),
|
||||
}
|
||||
end
|
||||
|
||||
# No points are inside the plane
|
||||
# Return an empty tuple with no triangles
|
||||
# So the compiler doesn't complain about nil return type
|
||||
Tuple.new
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue