[racket] Crowdsourcing Pict3D's design

From: Neil Toronto (neil.toronto at gmail.com)
Date: Sun Mar 15 17:58:01 EDT 2015

On 03/15/2015 04:54 PM, Alexander D. Knauth wrote:
> On Mar 14, 2015, at 11:51 PM, Neil Toronto <neil.toronto at gmail.com> wrote:
>> What you need is to 1) create and combine the necessary Pict3Ds as much as possible before the game starts; and 2) reuse them as much as possible during the game.
>> You can even make the reused Pict3Ds fairly large if you freeze them. Any modern 3D card won't have any problem with this, for example:
>>   (freeze (combine (get-tube+obstacles (make-world-stream) +x 1000)))
>> Freezing takes a while, though, and has this annoying property that it takes the most time the first time the frozen Pict3D is rendered. (The actual freezing has to be done with an active OpenGL context.) I'm not sure what to do about the latter problem.
> If I made it a finite game, with a finite tube, I could probably generate the whole tube once and move the camera along it, but with an infinite lazy tube, I’m not sure how I can reuse it.

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
    (with-color (rgba "lightblue")
      ;; WOO 65536 TRIANGLES YEAH
      (move-z (cylinder origin (dir 1/4 1/4 1/2) #:segments 16384)

(define pict
    (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 ⊥

Posted on the users mailing list.