With Director 8.5 Macromedia (with
Intel's help) have introduced
extensive 3d authoring capabilities
in Director.
Panorama makers benefit from
this too because they now have a
Shockwave3d
alternative to dedicated vr viewers
(Quicktime VR, Zoom, Java pano viewers etc).
Not only can panoramas be presented
very nicely solo in Shockwave3d - the web
output of Director 8.5 - but they
can be enhanced with streaming media,
3d models and directional indicators.
More than this - the particular dynamic
authoring possibilities of the
Director8.5 3d handling mean it is
possible to use panoramic
backgrounds in a 3d content creation
mode - a panoramic scene can be
scrolled/tilted freely as objects,
lights, particles, characters etc
are added via scripting and the results
seen in realtime.
A real world 3d-looking panoramic
background image
can provide strong cues for
the arrangement and proportions,
lighting and animation
of the foreground 3d elements.
The simplest way to put a panorama
into Shockwave3d is to create a
sphere primitive and map a "spherical"
panoramic image to its
interior - place a camera in its
centre - and you are almost done.
Some "mouse down" behavior for this
sprite is necessary to provide
a panoramic UI. One needs to able
to pan left or right, up or down
from a fixed position. The camera
should remain "unrolled" ie not
turned on an axis lengthways through
the lens. The user should be
constrained from going past 90 degrees
up and down. The following
Behavior script does this:
on mouseDown me
set startV
= the mouseV
set
startH = the mouseH
repeat
while the mouseDown
mypan = member("newBox").cameraRotation[2]
mytilt = member("newBox").cameraRotation[1]
myroll = member("newBox").cameraRotation[3]
set tDX = -(the mouseH - startH) / 150.0
set tDY = -(the mouseV - startV) / 150.0
mypan =mypan + tDX
mytilt = mytilt + tDY
if mytilt >90 then
set startV= the MouseV
set tDY = -(the mouseV - startV) / 150.0
if tDY > 0 then
set tDY = 0
end if
end if
if mytilt <-90 then
set startV= the MouseV
set tDY = -(the mouseV - startV) / 150.0
if tDY < 0 then
set tDY = 0
end if
end if
member("newBox").cameraRotation
= vector(mytilt, mypan, 0)
updatestage
end repeat
end
where "newBox" is the name of the
3d member containing the panoramic "set".
Note the code which tracks the tilt
of the default camera also tracks the up or
down direction of the mouse dragging
so that tilting is stopped appropriately at
nadir and zenith of the panorama.
A sphere has problems for pano display
in Shockwave3d because it is
approximated by polygons inexactly
and unless the polygon number in
the sphere is set high there will
be distortions in the scene.
A box primitive is better but there
is a problem
with seams at the edges showing
with software rendering - so a better
solution is to take 6 cubic images
ie 90 degrees by 90 degrees and map
them onto 6 square planes arranged
appropriately - then each can be
moved slightly closer to the camera so
they overlap a little - and this
will remove this seam issue.
Also one wants the panoramic image
to be lit with its original colors
so ambient must be set to 100 percent
in the shader settings for these
planes.
Thus we have the following Movie Script
that generates the 6 planes "box"
set for displaying the panorama.
You can see that the panorama is
generated dynamically rather than
referencing a prebuilt 3d file.
Textures should be powers of 2
in dimensions so cubic textures should
be 256*256 or 512*512 etc ....
512*512 in this case:
on prepareMovie
member("newBox").resetWorld()
mr1 =
member("newBox").newModelResource("myPlaneResource", #plane, #both)
mr1.length
= 40
mr1.width
= 40
md1 =
member("newBox").newModel("myPlane1")
md2
= member("newBox").newModel("myPlane2")
md3
= member("newBox").newModel("myPlane3")
md4
= member("newBox").newModel("myPlane4")
md5
= member("newBox").newModel("myPlane5")
md6
= member("newBox").newModel("myPlane6")
md1.resource
= member("newBox").modelResource("myPlaneResource")
md2.resource
= member("newBox").modelResource("myPlaneResource")
md3.resource
= member("newBox").modelResource("myPlaneResource")
md4.resource
= member("newBox").modelResource("myPlaneResource")
md5.resource
= member("newBox").modelResource("myPlaneResource")
md6.resource
= member("newBox").modelResource("myPlaneResource")
mt1 =
member("newBox").newTexture("myFrontTexture",#fromCastMember,member("gpo01"))
mt2
= member("newBox").newTexture("myRightTexture",#fromCastMember,member("gpo02"))
mt3
= member("newBox").newTexture("myBackTexture",#fromCastMember,member("gpo03"))
mt4
= member("newBox").newTexture("myLeftTexture",#fromCastMember,member("gpo04"))
mt5
= member("newBox").newTexture("myTopTexture",#fromCastMember,member("gpo05"))
mt6
= member("newBox").newTexture("myBottomTexture",#fromCastMember,member("gpo06"))
ms1 =
member("newBox").newShader("myFrontShader", #standard)
ms2
= member("newBox").newShader("myRightShader", #standard)
ms3
= member("newBox").newShader("myBackShader", #standard)
ms4
= member("newBox").newShader("myLeftShader", #standard)
ms5
= member("newBox").newShader("myTopShader", #standard)
ms6
= member("newBox").newShader("myBottomShader", #standard)
ms1.texture
= mt1
ms2.texture
= mt2
ms3.texture
= mt3
ms4.texture
= mt4
ms5.texture
= mt5
ms6.texture
= mt6
(member
1 of castLib 1).model[1].shaderList[1] = (member 1 of castLib 1).shader[2]
(member
1 of castLib 1).model[2].shaderList[1] = (member 1 of castLib 1).shader[3]
(member
1 of castLib 1).model[3].shaderList[1] = (member 1 of castLib 1).shader[4]
(member
1 of castLib 1).model[4].shaderList[1] = (member 1 of castLib 1).shader[5]
(member
1 of castLib 1).model[5].shaderList[1] = (member 1 of castLib 1).shader[6]
(member
1 of castLib 1).model[6].shaderList[1] = (member 1 of castLib 1).shader[7]
ms1.ambient
= rgb(255, 255, 255)
ms2.ambient
= rgb(255, 255, 255)
ms3.ambient
= rgb(255, 255, 255)
ms4.ambient
= rgb(255, 255, 255)
ms5.ambient
= rgb(255, 255, 255)
ms6.ambient
= rgb(255, 255, 255)
ms1.diffuse
= rgb(0, 0, 0)
ms2.diffuse
= rgb(0, 0, 0)
ms3.diffuse
= rgb(0, 0, 0)
ms4.diffuse
= rgb(0, 0, 0)
ms5.diffuse
= rgb(0, 0, 0)
ms6.diffuse
= rgb(0, 0, 0)
ms1.emissive
= rgb(0, 0, 0)
ms2.emissive
= rgb(0, 0, 0)
ms3.emissive
= rgb(0, 0, 0)
ms4.emissive
= rgb(0, 0, 0)
ms5.emissive
= rgb(0, 0, 0)
ms6.emissive
= rgb(0, 0, 0)
ms1.specular
= rgb(0, 0, 0)
ms2.specular
= rgb(0, 0, 0)
ms3.specular
= rgb(0, 0, 0)
ms4.specular
= rgb(0, 0, 0)
ms5.specular
= rgb(0, 0, 0)
ms6.specular
= rgb(0, 0, 0)
md1.translate
(0, 0, -19.85)
md2.translate
(19.85, 0, 0)
md3.translate
(0, 0, 19.85)
md4.translate
(-19.85, 0, 0)
md5.translate
(0, 19.85, 0)
md6.translate
(0, -19.85, 0)
md1.rotate
(0, 180, 0)
md2.rotate
(0, 90, 0)
md3.rotate
(0, 0, 0)
md4.rotate
(0, -90, 0)
md5.rotate
(-90, 180, 0)
md6.rotate
(90, 0, 0)
member("newBox").newLight("myAmbient",
#ambient)
member("newBox").light("myAmbient").color
= rgb(255, 255, 255)
member("newBox").camera("defaultView").fieldOfView
= 100
member("newBox").cameraPosition
= vector(0,0,0)
end
prepareMovie
The images for the sides of the six plane "box" are members "gpo01" etc.
Essential software for creating panoramas
and working with
different panoramic perspective representations
is Prof.
Helmut Dersch's great Panorama Tools.
www.fh-furtwangen.de/~dersch
There is an active mailing list linked
to his site.
The latest PovRay will render "spherical"
panoramas directly and these can
be converted into a cubic
representation with Panorama Tools
very quickly - this is a
simple way of producing synthetic
rendered backgrounds
for this kind of scene. Or 6 separate
renders to make cubic
"sides" can be done in any 3d program.
copyright:
Peter Murphy 11 Oct 2001