#
# CSC 112 Ambrosia Example: a scene with some of our previous
# objects but instead of a still image, we move the camera around
# for views from all angles about the y-axis
#
# Jim Teresco, The College of Saint Rose, Fall 2015
#
from ambrosia import *
import math
# get a new scene with my own light
scene.clear()
sun = Light().intensity(1).translate(0, 500, -500)
# and the ground
ground = Plane().material(whitePlaster)
scene.add(sun)
scene.add(ground)
# we'll put some objects on the plane near the origin
# here's our old friend the snowman
snowmanEye = Sphere().material(blackPlaster).scale(.1,.1,.1)
# Now, a "Group" object to define the snowman's head.
# To construct a group, we send the group "add" messages
# in the same way we did in our "tell scene" constructs.
snowmanHead = Group()
snowmanHead.add(sphere, whitePlaster)
# left eye (which we see on the right)
# note that we translate first, so the rotations move the
# eye around on the surface of the sphere!
snowmanHead.add(snowmanEye, translate(0,0,-50)*yRot(-30)*xRot(30))
# right eye (which we see on the left)
snowmanHead.add(snowmanEye, translate(0,0,-50)*yRot(30)*xRot(30))
# carrot nose
snowmanHead.add(cone, scale(.2,.3,.2)*xRot(-90)*translate(0,0,-60), redPlaster)
# One more object to define the whole snowman. Our
# snowman is a "Group" object, and it sits at the origin
snowman = Group()
# base snowball
snowman.add(sphere, scale(1.4, 1.4, 1.4)*translate(0,70,0), whitePlaster)
# middle snowball
snowman.add(sphere, scale(1.2, 1.2, 1.2)*translate(0,190,0), whitePlaster)
# the snowman's head, as defined above, placed atop the middle
snowman.add(snowmanHead, translate(0,290,0))
# Let's add some snowmen to our scene, standing apart
# looking toward each other
scene.add(snowman, scale(.5)*yRot(60)*translate(100,0,0))
scene.add(snowman, scale(.5)*yRot(-60)*translate(-100,0,0))
# we also had a nice model of a key
# define some constants to represent sizes and positions
keyThickness = 5
keyHeadDiameter = 60
keyShaftLength = 100
keyShaftHeight = 20
keyHeadOverlap = 10 # how much does the shaft overlap the head?
keyLength = keyShaftLength + keyHeadDiameter - keyHeadOverlap
keyHoleDiameter = 15
keyHoleOffset = 5
# first, build the basic framework of a key with a round head
# the key is height 150 from end to end and is defined aligned
# along the y-axis, with the head at the top
keyBlankPart = Group()
keyBlankPart.add(cube, scale(.01, .01, .01)*
scale(keyShaftHeight, keyShaftLength, keyThickness)*
translate(0, keyShaftLength/2, 0))
keyBlankPart.add(cylinder, xRot(90)*scale(.01, .01, .01)*
scale(keyHeadDiameter, keyHeadDiameter, keyThickness)*
translate(0, keyShaftLength + keyHeadDiameter/2 -
keyHeadOverlap, 0))
# now drill a keyhole and shave off the end of the key to make it pointed -
# a job for a Difference
keyBlank = Difference()
keyBlank.add(keyBlankPart)
# the hole
keyBlank.add(cylinder, xRot(90)*scale(.01, .01, .01)*
scale(keyHoleDiameter, keyHoleDiameter, 2 * keyThickness)*
translate(0, keyLength - (keyHoleOffset + keyHoleDiameter/2), 0))
# angled cut at the base of the key
keyBlank.add(cube, zRot(45)*scale(.01, .01, .01)*
scale(keyShaftHeight, keyShaftHeight, keyShaftHeight)*
translate(-keyShaftHeight / 2, 0, 0))
# now, let's make it look like a real key by cutting in some
# ridges and notches
key = Difference()
key.add(keyBlank)
# cut a ridge along the front face
key.add(cube, scale(.01, .01, .01)*
scale(keyThickness, keyShaftLength - keyHeadOverlap, keyThickness)*
translate(keyThickness,
(keyShaftLength - keyHeadOverlap) / 2,
-keyThickness / 2))
# another ridge on the back
key.add(cube, scale(.01, .01, .01)*
scale(keyThickness, keyShaftLength - keyHeadOverlap,
keyThickness)*
translate(-keyThickness,
(keyShaftLength - keyHeadOverlap) / 2,
keyThickness / 2))
# and a few notches along the edge
key.add(cube, scale(.01, .01, .01)*
scale(keyThickness, keyThickness, 2 * keyThickness)*
zRot(45)*
translate(-keyShaftHeight / 2, .75*keyShaftLength, 0))
key.add(cube, scale(.01, .01, .01)*
scale(2 * keyThickness, 2 * keyThickness, 2 * keyThickness)*
zRot(45)*
translate(-keyShaftHeight / 2, .55 * keyShaftLength, 0))
key.add(cylinder, scale(.01, .01, .01)*
scale(2 * keyThickness, 2 * keyThickness, 2 * keyThickness)*
xRot(90)*
translate(-keyShaftHeight / 2, .25 * keyShaftLength, 0))
# Let's make a metallic gold material
goldMat = Material()
goldMat.color ((.5, .3 ,0)).reflection(0.5).specularity(.3)
# And a metallic silver material
silverMat = Material()
silverMat.color((.5, .5,.5)).reflection(0.5).specularity(.3)
# add some keys in different positions to see our key design
# and our matallic materials
scene.add(key, translate(100, 200, 0), goldMat)
scene.add(key, zRot(-70)*yRot(20)*translate(-100, 50, -50), silverMat)
scene.add(key, xyMirror()*zRot(50)*yRot(-30)*translate(0, 150, 100),
bluePlastic)
scene.add(key, yRot(70)*xRot(70)*translate(200, 100, -50),
cyanPlaster)
# an adjustment function - a very simple one that repositions the camera
# in positions so as to rotate about the y-axis
def rotateCamera(radians):
camera.pos([600*math.sin(radians), 300, 600*math.cos(radians)])
# some set up for animation rendering
# the folder where images will be stored: must exist before running!
environment.projectFolder('movieImages')
# what would we like to call our images?
image.fileName('cameraviewaround')
# set to True to view each frame as rendered, False to wait for the movie
image.viewResult(False)
# start numbering frames at 0, mostly used when generating longer movies
image.frameNumber(0)
camera.pos([0,300,-600])
# we will generate 361 frames, with the parameter being an angle
# (in radians) that will vary from 0 to 2*pi for a complete circle
# around the stars of our scene
camera.film(360, rotateCamera, [0, 2*math.pi])
camera.buildMovie()