Skip to content

Commit b4ba42a

Browse files
committed
add Cone primitive
1 parent 0c43d8e commit b4ba42a

File tree

2 files changed

+104
-1
lines changed

2 files changed

+104
-1
lines changed

src/GeometryBasics.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ include("primitives/spheres.jl")
1717
include("primitives/cylinders.jl")
1818
include("primitives/pyramids.jl")
1919
include("primitives/particles.jl")
20+
include("primitives/Cone.jl")
2021

2122
include("interfaces.jl")
2223
include("viewtypes.jl")
@@ -56,7 +57,7 @@ export triangle_mesh, triangle_mesh, uv_mesh
5657
export uv_mesh, normal_mesh, uv_normal_mesh
5758

5859
export height, origin, radius, width, widths
59-
export HyperSphere, Circle, Sphere
60+
export HyperSphere, Circle, Sphere, Cone
6061
export Cylinder, Pyramid, extremity
6162
export HyperRectangle, Rect, Rect2, Rect3, Recti, Rect2i, Rect3i, Rectf, Rect2f, Rect3f, Rectd, Rect2d, Rect3d, RectT
6263
export before, during, meets, overlaps, intersects, finishes

src/primitives/Cone.jl

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
"""
2+
Cone{T}(origin::Point3, tip::Point3, radius)
3+
4+
A Cone is a cylinder where one end has a radius of 0. It is defined by an
5+
`origin` with a finite `radius` which linearly decreases to 0 at the `tip`.
6+
"""
7+
struct Cone{T} <: GeometryPrimitive{3, T}
8+
origin::Point3{T}
9+
tip::Point3{T}
10+
radius::T
11+
end
12+
13+
function Cone(origin::Point3{T1}, tip::Point3{T2}, radius::T3) where {T1, T2, T3}
14+
T = promote_type(T1, T2, T3)
15+
return Cone{T}(origin, tip, radius)
16+
end
17+
18+
origin(c::Cone) = c.origin
19+
extremity(c::Cone) = c.tip
20+
radius(c::Cone) = c.radius
21+
height(c::Cone) = norm(c.tip - c.origin)
22+
direction(c::Cone) = (c.tip .- c.origin) ./ height(c)
23+
24+
function rotation(c::Cone{T}) where {T}
25+
d3 = direction(c)
26+
u = Vec{3, T}(d3[1], d3[2], d3[3])
27+
if abs(u[1]) > 0 || abs(u[2]) > 0
28+
v = Vec{3, T}(u[2], -u[1], T(0))
29+
else
30+
v = Vec{3, T}(T(0), -u[3], u[2])
31+
end
32+
v = normalize(v)
33+
w = Vec{3, T}(u[2] * v[3] - u[3] * v[2], -u[1] * v[3] + u[3] * v[1],
34+
u[1] * v[2] - u[2] * v[1])
35+
return Mat{3, 3, T}(v..., w..., u...)
36+
end
37+
38+
function coordinates(c::Cone{T}, nvertices=30) where {T}
39+
nvertices += isodd(nvertices)
40+
nhalf = div(nvertices, 2)
41+
42+
R = rotation(c)
43+
step = 2pi / nhalf
44+
45+
ps = Vector{Point3{T}}(undef, nhalf + 2)
46+
for i in 1:nhalf
47+
phi = (i-1) * step
48+
ps[i] = R * Point3{T}(c.radius * cos(phi), c.radius * sin(phi), 0) + c.origin
49+
end
50+
ps[end-1] = c.tip
51+
ps[end] = c.origin
52+
53+
return ps
54+
end
55+
56+
function normals(c::Cone, nvertices = 30)
57+
nvertices += isodd(nvertices)
58+
nhalf = div(nvertices, 2)
59+
60+
R = rotation(c)
61+
step = 2pi / nhalf
62+
63+
ns = Vector{Vec3f}(undef, nhalf + 2)
64+
# shell at origin
65+
# normals are angled in z direction due to change in radius (from radius to 0)
66+
# This can be calculated from triangles
67+
z = radius(c) / height(c)
68+
norm = 1.0 / sqrt(1 + z*z)
69+
for i in 1:nhalf
70+
phi = (i-1) * step
71+
ns[i] = R * (norm * Vec3f(cos(phi), sin(phi), z))
72+
end
73+
74+
# tip - this is undefined / should be all ring angles at once
75+
# for rendering it is useful to define this as Vec3f(0), because tip normal
76+
# has no useful value to contribute to the interpolated fragment normal
77+
ns[end-1] = Vec3f(0)
78+
79+
# cap
80+
ns[end] = Vec3f(normalize(c.origin - c.tip))
81+
82+
return ns
83+
end
84+
85+
function faces(::Cone, facets=30)
86+
nvertices = facets + isodd(facets)
87+
nhalf = div(nvertices, 2)
88+
89+
faces = Vector{GLTriangleFace}(undef, nvertices)
90+
91+
# shell
92+
for i in 1:nhalf
93+
faces[i] = GLTriangleFace(i, mod1(i+1, nhalf), nhalf+1)
94+
end
95+
96+
# cap
97+
for i in 1:nhalf
98+
faces[i+nhalf] = GLTriangleFace(i, mod1(i+1, nhalf), nhalf+2)
99+
end
100+
101+
return faces
102+
end

0 commit comments

Comments
 (0)