Join My Conversation twitter
Join My Conversation Rss

3D Camera Movement

Posted by admin | Posted in Animation | Posted on 26-03-2010

1

3D Camera Movement

Click & drag to arc camera
Ctrl-click & vertical drag to dolly
Ctrl-click & horizontal drag to zoom (field-of-view)
3D Camera Movement1000×700 source movieCtrl-dragging upper-left to lower-right gives that “depth compression” effect used occasionally in cinema (Jaws, LOTR Fellowship, etc).

Moving the Camera
The camera orientation is specified by a transform. The renderer gets the camera transform from the 3Dnode that its “camNode” property points to.

This 3Dnode may or may not be part of the 3D world hierarchy. If it is, the camera transform will be affected by movement in the 3D world. If it isn’t, it moves independent of the 3D world.

In this demo the camera is not part of the 3D world tree, but it does have a few ancestor nodes used for arcing the camera.

Rendering from the Camera’s Point of View
In order to use the perspective equation the 3D world is transformed in rendering so that the camera sits at the origin looking up the z axis:

The key to finding the right transform to use is that when it is multiplied by the camera transform it gives the identity transform (which positions the camera at the origin looking up the z axis).

Since multiplying a transform by its inverse gives the identity transform, the right transform to use is the inverse of the camera transform.

In this demo the 3D world is transformed in this way by passing the inverse of the camera’s transform as the initial parent world transform:

on stepframe()
camInverse = camNode.getWorldTransform().inverse()
camInvRot = camInverse.duplicate()
camInvRot.position = vector()
rendLightVec = camInvRot * lightVec
traverseWorld(root, camInverse)
end

stepFrame() handler of script “3Drender”So the camera adjustment is applied once at the start instead of calculating world transforms for each object then applying the camera.

Field of View
The “field of view” is related to the distance from the focal point to the projection plane:

In this demo the view height is the height of the stage. For Shockwave 3D the view height is the height of the sw3D sprite.

As the focal point gets closer to the projection plane, the field of view increases and more of the 3D world is seen through the projection plane, giving a wide-angle lens effect. When the focal point is further away the field of view is narrow which gives a telephoto lens effect.

Orthographic View
In orthographic view the projections from the 3D scene are orthogonal to the projection plane rather than converging on a focal point:

The word “orthogonal” means perpendicular in n dimensions, hence the name. In orthographic view the 2D mapping comes straight from the x and y coordinates of the 3D model. Just remove the perspective equation from the algorithm, or set persp equal to 1.

If you remove perspective to get an orthographic view you’ll see that back-face culling causes some of the faces to disappear that should be visible, because it is programmed for the view from the focal point. How would you correct this for orthographic view? A hint: vCent is the vector from the focal point (at the origin) to the center of the face. Find a different vector to use when calculating dotCam.

Cube Bounce
The programming of the cube bounce is specialized for this demo so it’s much simpler than a generalized version. Here is a brief description of what is going on in the code.

The model behind it is eight masses, one for each cube resource vertex, connected by springs (physics model). An independent model rate is used since the springs are very stiff. The vertices that exert spring force on verts[i] are stored in spgVerts[i][], with initial (resting) spring lengths stored in
spgLength[i][].

Each model frame the forces acting on each vertex combine to give total force on the vertex. The force spgVerts[i][j] exerts on verts[i] is given by a vector found like this:

repeat with j = 1 to spgVerts[i].count
vecDiff = verts[i] – spgVerts[i][j]
pCompress = 1 – (vecDiff.length() / spgLength[i][j])
vecSpring = vecDiff.getNormalized() * pCompress * stiffness
vecTotSpring = vecTotSpring + vecSpring
end repeat

Calculating total spring force on one vertex, modelFrame() method of script “cubeBounce”The force vector is found as a percentage of the original spring length and scaled according to the stiffness setting.

When a vertex moves out of bounds, it is repositioned at the boundary edge. This compresses the springs it is “attached” to which exerts force on other vertices and causes the cube to bounce and spin.

The cube bounce algorithm can be made more efficient by only calculating the force between each pair of vertices once, rather than twice. The forces between the vertices in each pair are opposites, so if vecF is the force on one then -vecF is the force on the other.

3D Resource Objects

Posted by admin | Posted in Animation | Posted on 13-03-2010

0

3D Resource Objects

Related Topics:
3D World Hierarchy
Spring Forces

In this demo, resource geometry is separated from the 3D hierarchy so that the same resource can be used multiple times in the 3D world. One advantage to this is animating the resource will animate all appearances of it—the three discs in the demo below all use the same disc resource.

Drag off objects to rotate group
3D Resource Objects - source movie

The resources in this demo are programmed as trees, and consist of a root node with the faces as its children. To use a resource in the 3D world, the “resource” property of a 3Dnode is made a reference to the root of a resource tree:

With this arrangement rendering involves traversing the 3D world tree, and when a 3Dnode uses a resource, traversing the resource tree and rendering its nodes.

Use of Inheritance
The nodes in the two types of trees in this demo, 3D world tree and resource trees, both need tree-related properties and methods but also need properties and methods unique to each type of tree. For example, nodes in the 3D world tree need a resource property to point to a resource, while nodes in a resource tree need a list of vectors to store geometry. Programming this using inheritance is a good way to go.

To do that, a script called “treeNode” is programmed as a generic tree node, with parent and child properties and methods for managing a tree. This script serves as the ancestor for 3Dnode and resNode, the two types of nodes that make up the 3D world tree and resource trees, respectively. The 3Dnode and resNode scripts contain the properties and methods unique to their respective tree types.

Inheritance is used again for the scripts that automate creation of different resources geometries such as cylinders, planes, cubes, etc. These scripts inherit the resNode script and function as the root of the resource trees. (They also inherit treeNode via resNode).

Animating the Resource
This animation uses a “spring system” which is a bunch of objects that act on each other with spring forces (as if they were connected by springs). The objects in this case are the vectors that specify the outer edge of the disc resource. These vectors are stored in the edgeVerts list of the resDisc object.

Using forces means using the physics model (position, velocity, acceleration):

– spring force
spring1 = (zInit[i] – verts[i].z) * .04
spring2 = (verts[prevI].z – verts[i].z) * .08
spring3 = (verts[nextI].z – verts[i].z) * .08

– acceleration, velocity, position
zAccel = spring1 + spring2 + spring3
zVelo[i] = zVelo[i] + zAccel
verts[i].z = verts[i].z + zVelo[i]

– dampen velocity
zVelo[i] = zVelo[i] * .9

modelFrame() method in script “discWave”

The disc resource lies in the x-y plane so the wave is created by animating the z coordinates of the edge vectors.

Three spring forces act on each vector, all given by the spring formula (restPosition – position). The first pulls the vector back to its initial position. The second two cause the vectors on either side to pull the vector in their direction, which creates the wave.

The velocity is dampened so the wave eventually dies out.

The wave is started by setting the velocity of a vector (zVelo[i]) to a non-zero number.

•What would happen if only the first spring force was used? What if only the last two were used?

This animation can be done in Shockwave 3D by animating a mesh vertexList.