Would it work so that you could all instances of:
(pin
 (combine pict1 (basis 'b1 (point-at v1 v2))) ‘(b1)
 (combine pict2 (basis ‘b2 (point-at v3 v4))) ‘(b2))
Could be replaced with:
(combine
 pict1
 (transform pict2 (my-point-at v1 v2 v3 v4)))
I tried doing that with my game, and nothing weird happened, but am I missing 
something?

And if it does work like that, then would it make sense for you to extend 
point-at so that when it takes 4 arguments it does this?
Or should it be a separate function?

Or, would it make sense to provide a function like this?
(define (from-to t1 t2)  ; It would probably need a better name, but I think it 
could be very useful and intuitive
  (affine-compose t2 (affine-inverse t1)))
So then my-point-at could be defined as
(define (my-point-at v1 v2 v3 v4)
  (from-to (point-at v1 v2) (point-at v3 v4)))
And instances of
(pin
 (combine pict1 (basis ‘b1 t1)) ‘(b1)
 (combine pict2 (basis ‘b2 t2)) ‘(b2))
 could be replaced with
(combine pict1 (transform pict2 (from-to t2 t1)))

Would that make sense?


On Mar 16, 2015, at 7:12 AM, Neil Toronto <neil.toro...@gmail.com> wrote:

> It should work fine for what you want to do with it. (It's exactly what I 
> thought of when I read your spec for it.) The only possible thing that can go 
> wrong with affine transformations is unwanted shear [1], and `point-at` never 
> produces a transformation that shears. Aside from the z-axis stretch, it's 
> all rigid.
> 
> If you want to control *rotation* around the v1-v2 and v3-v4 axes, you'll 
> need to add a couple of arguments corresponding to the #:up and #:angle 
> arguments of `point-at`. I don't know how you'd pass those along to the two 
> `point-at` calls or how they'd interact. That doesn't mean something 
> reasonable is impossible, though.
> 
> To understand `point-at` better, run the following program and play with the 
> #:up and #:angle arguments. Most of the code retesselates the vertices of an 
> octahedron to try to get a uniform distribution of directions. The important 
> stuff is at the end.
> 
> 
> #lang racket
> 
> (require pict3d)
> 
> (define (retesselate dvs)
>  (match-define (list dv0 dv1 dv2) dvs)
>  (define dv01 (dir-normalize (dir-scale (dir+ dv0 dv1) 0.5)))
>  (define dv12 (dir-normalize (dir-scale (dir+ dv1 dv2) 0.5)))
>  (define dv20 (dir-normalize (dir-scale (dir+ dv2 dv0) 0.5)))
>  (list (list dv0 dv01 dv20)
>        (list dv1 dv12 dv01)
>        (list dv2 dv20 dv12)
>        (list dv01 dv12 dv20)))
> 
> (define octahedron-dirs
>  (list (list +x +y +z)
>        (list +y -x +z)
>        (list -x -y +z)
>        (list -y +x +z)
>        (list +y +x -z)
>        (list -x +y -z)
>        (list -y -x -z)
>        (list +x -y -z)))
> 
> (define dvs
>  (remove-duplicates
>   (append*
>    (for/fold ([dvss  octahedron-dirs]) ([_  (in-range 3)])
>      (append* (map retesselate dvss))))))
> 
> (combine
> (for/list ([dv  (in-list dvs)])
>   (basis 'camera (point-at (pos+ origin dv 2) origin
>                            #:up +z #:angle 0))))
> 
> 
> With the default #:up +z, there's a singularity at +z and another at -z, 
> where `point-at` isn't smooth. (Generally, with #:angle 0, the red x axes 
> point to their counterclockwise neighbors. At a pole, the only 
> counterclockwise neighbor is the pole itself.) Using #:up +x, the 
> singularities are at +x and -x. There's nothing we can do about this: we're 
> looking straight down the barrel of the Hairy Ball Theorem [2]. The 
> `point-at` function must have at least one cowlick.
> 
> All this complexity comes from trying to make a rigid transformation that's 
> in some way reasonable when specified using only 5 degrees of freedom: a 
> position and a normalized direction. The result is mostly intuitive, and 
> works well enough.
> 
> Neil ⊥
> 
> [1] http://en.wikipedia.org/wiki/Shear_mapping
> [2] http://en.wikipedia.org/wiki/Hairy_ball_theorem
> 
> On 03/15/2015 07:38 PM, Alexander D. Knauth wrote:
>> Does the attached file look like a good implementation of my-point-at, or 
>> would it do things I wouldn’t expect for things not on the line between the 
>> two points, or ?  I’m asking because I don’t think I completely understand 
>> point-at and what it does.
>> 
>> 
>> 
>> 
>> On Mar 15, 2015, at 6:29 PM, Alexander D. Knauth <alexan...@knauth.org> 
>> wrote:
>> 
>>> Thanks!
>>> 
>>> Actually, now that I think about it something like this would be really 
>>> helpful, and probably make more sense:
>>> Maybe a version of point-at that would let you specify which pos’s should 
>>> match up where?
>>> 
>>> (my-point-at v1 v2 v3 v4 #:normalize? #f)   ; maps v1 to v3 and v2 to v4
>>> (my-point-at (pos 0 0 0) (pos 1 0 0) v1 v2 #:normalize? #f)   ; maps the 
>>> origin to v1, and (pos 1 0 0) to v2.
>>> (my-point-at (pos 0 0 0) (pos 0 0 1) v1 v2)   ; equivalent to (point-at v1 
>>> v2)
>>> (my-point-at v1 dv1 v2 dv2)   ; equivalent to (my-point-at v1 (pos+ v1 dv1) 
>>> v2 (pos+ v2 dv2))
>>> 
>>> On Mar 15, 2015, at 5:58 PM, Neil Toronto <neil.toro...@gmail.com> wrote:
>>> 
>>>> I'd generate a few different kinds of segments and then transform them 
>>>> into place. Don't use `rotate` for that, though - there's an easier way.
>>>> 
>>>> Transforming a shape is pretty fast. Here's an insane example, using many 
>>>> more segments for a cylinder than you'd normally ever need:
>>>> 
>>>> 
>>>> #lang racket
>>>> 
>>>> (require pict3d)
>>>> 
>>>> (define v1 (pos 1 1 1))
>>>> (define v2 (pos 2 3 2))
>>>> (define cyl
>>>> (time
>>>>  (with-color (rgba "lightblue")
>>>>    ;; WOO 65536 TRIANGLES YEAH
>>>>    (move-z (cylinder origin (dir 1/4 1/4 1/2) #:segments 16384)
>>>>            1/2))))
>>>> 
>>>> (define pict
>>>> (time
>>>>  (combine (sphere v1 0.2)
>>>>           (sphere v2 0.2)
>>>>           (transform cyl (point-at v1 v2 #:normalize? #f)))))
>>>> 
>>>> (time (pict3d->bitmap pict))
>>>> (time (pict3d->bitmap pict))
>>>> 
>>>> 
>>>> On my computer, creating `cyl` takes 5 seconds. Transforming it takes no 
>>>> measurable time. Rendering it the first time takes 1.5 seconds, and 
>>>> rendering it the second time takes 11 milliseconds. (Cylinders are frozen, 
>>>> so they'll always render faster the second time.)
>>>> 
>>>> To stretch the cylinder between two points, the program
>>>> 
>>>> 1. Creates the cylinder so that its bottom is at the origin and its
>>>>   top is at (pos 0 0 1).
>>>> 
>>>> 2. Uses `point-at` without normalization to move the origin to `v1` and
>>>>   move (pos 0 0 1) to `v2`.
>>>> 
>>>> Based on this and your other feedback, I think Pict3D needs
>>>> 
>>>> * A `rotate-around` function that rotates a shape around a given point
>>>>  (with the default being the center of its bounding box).
>>>> 
>>>> * A note in the docs for `rotate` et al that explain they rotate around
>>>>  the origin.
>>>> 
>>>> * A "How Do I" section that includes things like the above example.
>>>> 
>>>> * Notes in the docs about performance characteristics of different
>>>>  functions (e.g. that `cylinder` and `cone` return frozen Pict3Ds, and
>>>>  what that means you can expect from them).
>>>> 
>>>> I expect performance characteristics to change, though, so that last one 
>>>> might be late coming.
>>>> 
>>>> Neil ⊥
>>>> 
>>> 
>>> 
>>> ____________________
>>>  Racket Users list:
>>>  http://lists.racket-lang.org/users
>> 
> 


____________________
  Racket Users list:
  http://lists.racket-lang.org/users

Reply via email to