Computer Graphics Workshop '97 PS3 Solutions | 1/13/97 |
(define M_PI 3.14159265358979323846) (define (compute-torus-major-vector major-radius x-res x-index) (let* ((theta (* (* 2.0 M_PI) (/ x-index x-res))) (x (* major-radius (cos theta))) (y 0.0) (z (* major-radius (sin theta)))) (new-SbVec3f x y z))) (define (compute-torus-minor-vector major-radius minor-radius x-res y-res x-index y-index) (let* ((theta (* (* 2.0 M_PI) (/ x-index x-res))) (phi (* (* 2.0 M_PI) (/ y-index y-res))) (x (* (* minor-radius (cos phi)) (cos theta))) (y (* minor-radius (sin phi))) (z (* (* minor-radius (cos phi)) (sin theta)))) (new-SbVec3f x y z))) (define (compute-point-on-torus major-radius minor-radius x-res y-res x-index y-index) (let ((major-vector (compute-torus-major-vector major-radius x-res x-index)) (minor-vector (compute-torus-minor-vector major-radius minor-radius x-res y-res x-index y-index))) (-> major-vector 'operator+ minor-vector)))
(load "ps3-1") ;; compute-torus-polygons was given in the problem set (define (compute-torus-polygons major-radius minor-radius x-res y-res x-index y-index) (if (not (= y-index y-res)) (begin (let ((p1 (compute-point-on-torus major-radius minor-radius x-res y-res x-index y-index)) (p2 (compute-point-on-torus major-radius minor-radius x-res y-res x-index (1+ y-index))) (p3 (compute-point-on-torus major-radius minor-radius x-res y-res (1+ x-index) (1+ y-index))) (p4 (compute-point-on-torus major-radius minor-radius x-res y-res (1+ x-index) y-index))) (if (= x-index (- x-res 1)) (cons p1 (cons p2 (cons p3 (cons p4 (compute-torus-polygons major-radius minor-radius x-res y-res 0 (1+ y-index)))))) (cons p1 (cons p2 (cons p3 (cons p4 (compute-torus-polygons major-radius minor-radius x-res y-res (1+ x-index) y-index)))))))) '())) ;;; SICP-ish simple object system for dealing similarly ;;; with Scheme and C++ objects using "send" (define (send object message . args) (if (C++-object? object) (eval `(-> ,object ',message ,@args)) (let ((method (get-method object message))) (if (not (no-method? method)) (apply method (cons object args)) (error "No method named" message))))) (define (get-method object message) (object message)) (define (no-method method) 'no-method) (define (no-method? method) (eq? method 'no-method)) (define (new-Torus major-radius minor-radius x-res y-res) (define root (new-SoSeparator)) (send root 'ref) (define hints (new-SoShapeHints)) (define coords (new-SoCoordinate3)) (define mat (new-SoMaterial)) (define face-set (new-SoFaceSet)) (send root 'addChild hints) (send (send hints 'creaseAngle) 'setValue 0.5) (send (send hints 'shapeType) 'setValue SoShapeHints::SOLID) (send (send hints 'vertexOrdering) 'setValue SoShapeHints::COUNTERCLOCKWISE) (send root 'addChild coords) (send root 'addChild mat) (send root 'addChild face-set) (let ((self (lambda (message) (cond ((eq? message 'getGeometry) (lambda (self) root)) ((eq? message 'generate) (lambda (self) (let* ((points (compute-torus-polygons major-radius minor-radius x-res y-res 0 0)) (num-points (length points))) ;; set-mfield-values! sets the values of the passed ;; mfield, starting at the given index, from the ;; passed list of values. ;; Note that the elements of this list must be valid ;; objects for use in the set1Value method. (set-mfield-values! (send coords 'point) 0 points) ;; Truncate list if necessary (i.e., when ;; reducing resolution) (send (send coords 'point) 'setNum num-points) ;; update the values in the face set: ;; (num-points / 4) polygons of four vertices each. (let loop ((i 0)) (send (send face-set 'numVertices) 'set1Value i 4) (if (< i (/ num-points 4)) (loop (1+ i)))) ;; Truncate numVertices as well, if necessary (send (send face-set 'numVertices) 'setNum (/ num-points 4))))) ((eq? message 'setColor) (lambda (self r g b) (send (send mat 'diffuseColor) 'setValue r g b))) ((eq? message 'setCreaseAngle) (lambda (self new-angle) (send (send hints 'creaseAngle) 'setValue new-angle))) ((eq? message 'setVertexOrdering) (lambda (self new-ordering) (send (send hints 'vertexOrdering) 'setValue new-ordering))) ((eq? message 'setShapeType) (lambda (self new-type) (send (send hints 'shapeType) 'setValue new-type))) ((eq? message 'setMajorRadius) (lambda (self new-major-radius) (set! major-radius new-major-radius) (send self 'generate))) ((eq? message 'setMinorRadius) (lambda (self new-minor-radius) (set! minor-radius new-minor-radius) (send self 'generate))) ((eq? message 'setHorizResolution) (lambda (self new-horiz-res) (set! x-res new-horiz-res) (send self 'generate))) ((eq? message 'setVertResolution) (lambda (self new-vert-res) (set! y-res new-vert-res) (send self 'generate))) (else (no-method message)))))) ;;; Initialization code goes here (send self 'generate) ;; generate when first constructed self)) (define my-torus (new-Torus 10.0 3.0 20 10)) (define viewer (examiner (send my-torus 'getGeometry)))
(load "ps3-1") ;; compute-torus-points was given in the problem set (define (compute-torus-points major-radius minor-radius x-res y-res) (define (vert-loop vert-step horiz-step) (if (<= vert-step y-res) (cons (compute-point-on-torus major-radius minor-radius x-res y-res horiz-step vert-step) (vert-loop (1+ vert-step) horiz-step)) '())) (define (horiz-loop step) (if (<= step x-res) (cons (vert-loop 0 step) (horiz-loop (1+ step))) '())) (let ((slices-list (horiz-loop 0))) (apply append slices-list))) ;;; SICP-ish simple object system for dealing similarly ;;; with Scheme and C++ objects using "send" (define (send object message . args) (if (C++-object? object) (eval `(-> ,object ',message ,@args)) (let ((method (get-method object message))) (if (not (no-method? method)) (apply method (cons object args)) (error "No method named" message))))) (define (get-method object message) (object message)) (define (no-method method) 'no-method) (define (no-method? method) (eq? method 'no-method)) (define (new-Torus major-radius minor-radius x-res y-res) (define root (new-SoSeparator)) (send root 'ref) (define hints (new-SoShapeHints)) (define coords (new-SoCoordinate3)) (define mat (new-SoMaterial)) (define quad-mesh (new-SoQuadMesh)) (send root 'addChild hints) (send (send hints 'creaseAngle) 'setValue 0.5) (send (send hints 'shapeType) 'setValue SoShapeHints::SOLID) (send (send hints 'vertexOrdering) 'setValue SoShapeHints::CLOCKWISE) (send root 'addChild coords) (send root 'addChild mat) (send root 'addChild quad-mesh) (let ((self (lambda (message) (cond ((eq? message 'getGeometry) (lambda (self) root)) ((eq? message 'generate) (lambda (self) (let* ((points (compute-torus-points major-radius minor-radius x-res y-res)) (num-points (length points))) ;; Same code as in ps3-2 (set-mfield-values! (send coords 'point) 0 points) (send (send coords 'point) 'setNum num-points) ;; Set up the verticesPerRow and verticesPerColumn ;; fields for the QuadMesh node. (send (send quad-mesh 'verticesPerRow) 'setValue (1+ y-res)) (send (send quad-mesh 'verticesPerColumn) 'setValue (1+ x-res))))) ((eq? message 'setColor) (lambda (self r g b) (send (send mat 'diffuseColor) 'setValue r g b))) ((eq? message 'setCreaseAngle) (lambda (self new-angle) (send (send hints 'creaseAngle) 'setValue new-angle))) ((eq? message 'setVertexOrdering) (lambda (self new-ordering) (send (send hints 'vertexOrdering) 'setValue new-ordering))) ((eq? message 'setShapeType) (lambda (self new-type) (send (send hints 'shapeType) 'setValue new-type))) ((eq? message 'setMajorRadius) (lambda (self new-major-radius) (set! major-radius new-major-radius) (send self 'generate))) ((eq? message 'setMinorRadius) (lambda (self new-minor-radius) (set! minor-radius new-minor-radius) (send self 'generate))) ((eq? message 'setHorizResolution) (lambda (self new-horiz-res) (set! x-res new-horiz-res) (send self 'generate))) ((eq? message 'setVertResolution) (lambda (self new-vert-res) (set! y-res new-vert-res) (send self 'generate))) (else (no-method message)))))) ;;; Initialization code goes here (send self 'generate) ;; generate when first constructed self)) (define my-torus (new-Torus 10.0 3.0 20 10)) (define viewer (examiner (send my-torus 'getGeometry)))
$Id: index.html,v 1.5 1997/01/10 18:42:05 kbrussel Exp $