5 Combining Scenes
In 3D space, the terms horizontal and vertical are ambiguous.
When there’s no unique or preferred way to view an object, even the terms top, bottom, left, right, front and back are ambiguous.
> (define p1 (rotate-y (ellipsoid origin (dir 1/4 1/4 1)) -30))
> (define camera (basis 'camera (point-at (pos 1 1 4) (dir -1 -1 0))))
> (combine (move-z p1 4) (with-emitted (emitted "green") (arrow (pos 0.75 0 4.25) (dir -0.45 0 -0.25))) (with-emitted (emitted "red") (arrow (pos 1.05 0 3.25) (dir -0.5 0 0))) camera)
In general, combining two 3D scenes relationally requires specifying a lot of data.
Allowing Pict3D instances to be combined by naming groups in each instance to attach together.
Making it easy to add such groups at specific points with specific orientations.
> (define-values (v dv) (surface/normal p1 +x))
> (define left (basis 'left (point-at v dv)))
> (define p2 (with-color (rgba "deepskyblue" 0.75) (cube origin 1/4)))
> (define top (basis 'top (point-at (surface p2 +z) -z)))
> (define p2/top (move-z (combine p2 top) 4))
> p2/top
(We refer to the group named 'left using the tag path '(left).)
Recreate p1/left with a rotated left basis, and then recreate p3.
Recreate p2/top with a rotated top basis, and then recreate p3.
Replace the group named 'left in p3 with the same group rotated 30 degrees.
> (combine (replace-group p3 '(left) (λ (p) (rotate-z p 30))) camera)
> (define top (basis 'top (point-at (surface p2 +z) +z)))
> (define p2/top (move-z (combine p2 top) 4))
> p2/top
> (combine (pin p1/left '(left) p2/top '(top)) camera)
5.1 Scene Combiners
(remove-in-group world '(player cannon))
(remove-in-group world '(cannon))
(remove-in-group world '())
procedure
pict : Pict3D name : (U #f Tag)
procedure
pict : Pict3D
procedure
(group-contents pict) → Pict3D
pict : Pict3D
If pict is a group, group-tag returns its name and group-contents returns its contents. If pict isn’t a group, group-tag returns #f and group-contents returns pict.
(group-contents (group p n)) is equivalent to p.
(group (group-contents p) (group-tag p)) is equivalent to p.
procedure
(remove-group pict path) → Pict3D
pict : Pict3D path : (Listof Tag)
procedure
(remove-in-group pict path) → Pict3D
pict : Pict3D path : (Listof Tag)
procedure
(replace-group pict path f) → Pict3D
pict : Pict3D path : (Listof Tag) f : (-> Pict3D Pict3D)
procedure
(replace-in-group pict path f) → Pict3D
pict : Pict3D path : (Listof Tag) f : (-> Pict3D Pict3D)
procedure
pict1 : Pict3D path1 : (U (Listof Tag) Affine) pict2 : Pict3D path2 : (U (Listof Tag) Affine) = '()
Transforms pict2 so that its group with path path2 aligns with the group in pict1 with path path1.
Combines the result with pict1.
If there is more than one group with path1 in pict1, join raises an error, and likewise for path2 in pict2.
Recall that the tag path '() represents the entire Pict3D. Thus, when path2 is '() or is omitted, the origin and coordinate axes are used for alignment.
> (define p1 (combine (cylinder origin 1/2) (basis 'top (point-at (pos 0 0 1/2) +z))))
> p1 > (define p2 (cone origin 1/2))
> p2 > (join p1 '(top) (move-z p2 1/2))
> (join p1 '(top) (combine p2 (basis 'bot (point-at (pos 0 0 -1/2) +z))) '(bot))
(combine pict1 (relocate pict2 (find-group-transform pict2 path2) (find-group-transform pict1 path1)))
procedure
pict1 : Pict3D path1 : (U (Listof Tag) Affine) pict2 : Pict3D path2 : (U (Listof Tag) Affine) = '()
Like join, glue accepts affine transformations as well as tag paths.
Ungroups the group path2 in pict2.
Puts pict2 inside the group path1 in pict1.
(let ([pict2 (ungroup (set-origin pict2 path2) path2)]) (replace-in-group pict1 path1 (λ (p) (combine p pict2))))
Like join, pin accepts an affine transformation for its second argument.
Use weld instead of pin when you don’t intend to update the group with path path1 in the result. For example, use pin to attach a swinging arm to a robot body, and use weld to place a roof on top of a house. (Unless you intend to blow up the house later. Then you’ll need to pin the roof.)
Like glue, weld accepts an affine transformation for its second argument.
procedure
pict1 : Pict3D path1 : (Listof Tag) pict2 : Pict3D path2 : (U (Listof Tag) Affine) = '()
procedure
pict1 : Pict3D path1 : (Listof Tag) pict2 : Pict3D path2 : (U (Listof Tag) Affine) = '()
procedure
pict1 : Pict3D path1 : (U (Listof Tag) Affine) pict2 : Pict3D path2 : (U (Listof Tag) Affine) = '()
procedure
pict1 : Pict3D path1 : (U (Listof Tag) Affine) pict2 : Pict3D path2 : (U (Listof Tag) Affine) = '()
procedure
(map-group/transform pict path f) → (Listof A)
pict : Pict3D path : (Listof Tag) f : (-> Affine Pict3D A)
procedure
(find-group-transform pict path) → Affine
pict : Pict3D path : (Listof Tag)
If multiple groups with path exist, find-group-transform raises an error.
This is used in the implementations of functions like join and set-origin.
(map-group/transform pict path (λ ([t : Affine] _) t))