Models & Hierarchies - University of California, San Diego

Download Report

Transcript Models & Hierarchies - University of California, San Diego

Models & Hierarchies
CSE167: Computer Graphics
Instructor: Steve Rotenberg
UCSD, Fall 2006
Normals





The concept of normals is essential to lighting
Intuitively, we might think of a flat triangle as having a
constant normal across the front face
However, in computer graphics, it is most common to
specify normals and perform lighting at the vertices
This gives us a method of modeling smooth surfaces as
a mesh of triangles with ‘shared’ normals at the vertices
We will talk about lighting in the next lecture, but for
today, we will still think of our vertex as containing a
normal
Models


We will extend our concept of a Model to include normals
We can do this by simply extending our vertex class:
class Vertex {
Vector3 Position;
Vector3 Color;
Vector3 Normal;
public:
void Draw() {
glColor3f(Color.x, Color.y, Color.z);
glNormal3f(Normal.x, Normal.y, Normal.z);
glVertex3f(Position.x, Position.y, Position.z);
}
}
// This has to be last
Model Data Structures



Everybody knows that a cube has 8 vertices
If we need to render a cube, however, each of
those vertices requires 3 different normals. In
other words, we might really need 3*8=24
vertices
If we render it as triangles, each 4-sided face
actually requires 6 vertices, meaning that we
might need to store and process 36 different
vertices!
Indexed Models







So far, we have simply thought of a model as an array of triangles,
each triangle storing 3 unique vertices
A more common method of storing a model is as an array of
vertices, and an array of triangles
In the second method, each triangle stores an index (or pointer) to a
vertex instead of storing the vertex data explicitly
This is called an indexed model or single indexed model
Indexing will almost always save memory, as models often have
shared vertices that are used by several triangles
Large, smooth meshes will often share a single vertex between 4-6
triangles (or more)
Indexing can also save processing time as the vertex array can first
be transformed and lit, and then the triangle array can be clipped
and scan converted…
Single Indexed Model
class Vertex {
Vector3 Position;
Vector3 Color;
Vector3 Normal;
};
class Triangle {
Vertex *Vert[3];
};
// or int Vert[3];
class Model {
int NumVerts,NumTris;
Vertex *Vert;
Triangle *Tri;
};
Index vs. Pointer



Should we store the triangle verts as integers (indexing into the array of
actual Vertex’s) ?
int Vert[3];
Or should we store them as pointers to the actual Vertex’s themselves ?
Vertex *Vert[3];
Memory:



Performance:


In most systems an int is 4 bytes and a pointer is 4 bytes, so there isn’t a big
difference in memory
However, for smaller models, you could benefit from using short ints, which are 2
bytes each. This would cut the triangle size in half, but limit you to 65536 vertices
Storing Vertex*’s gives the triangle direct access to the data so should be faster
Other Issues:


It’s definitely more convenient to store the pointers instead of integers
One important reason to consider storing integers instead of pointers, however,
is if you are using some type of dynamic array for the vertices (such as an STL
vector). Pointers to members of these arrays are considered dangerous, since
the array may have to reallocate itself if more vertices are added
Vertex Buffers






Hardware rendering API’s (like Direct3D and OpenGL) support some type of
vertex buffer system as well (but everybody has a different name for it)
This is essentially an unindexed or single indexed model format
You start by defining your specific vertex type. Verts usually have a position
and normal, and might have one or more colors, texture coordinates, or
other properties
You then request a vertex buffer of whatever memory size you want. This
memory is usually the actual video memory on the graphics board (not main
memory)
The vertex buffer can then be filled up with vertex data as a single large
array
One can then draw from the vertex buffer with a command like this:
DrawSomething(int type,int first vert,int numverts); // type: triangles, strips, lines…

The advantage is that a large number of triangles can be drawn with a
single CPU call and all of the work then takes place entirely on the graphics
board
Index Buffers





An index buffer (or whatever name one calls it)
is an array of (usually 2 byte or 4 byte) integers
It is stored in video memory like the vertex buffer
The integers index into a vertex buffer array
One can then draw triangles (or other primitives)
by specifying a range of these indexes
Using vertex/index buffers is most likely going to
be the fastest way to render on modern graphics
hardware
Triangles, Strips, Fans


Graphics hardware usually supports
slightly more elaborate primitives than
single triangles
Most common extensions are strips and
fans
v8
v6
v2
v4
v7
v3
v0
v1
v4
v5
v3
v5
v2
v6
v7
v0
v1
Materials & Grouping


Usually models are made up from several
different materials
The triangles are usually grouped and
drawn by material
Hierarchical Transformations
Hierarchical Transformations








We have seen how a matrix can be used to place an individual
object into a virtual 3D world
Sometimes, we have objects that are grouped together in some way
For example, we might have an articulated figure which contains
several rigid components connected together in some fashion
Or we might have several objects sitting on a tray that is being
carried around
Or we might have a bunch of moons and planets orbiting around in
a solar system
Or we might have a hotel with 1000 rooms, each room containing a
bed, chairs, table, etc.
In each of these cases, the placement of objects is described more
easily when one considers their locations relative to each other
We will see how hierarchical transformations can be used to
describe their placement
Scene Hierarchy

If a scene contains 1000 objects, we might
think of a simple organization like this:
Scene
Object 1
Object 2
Object 3
…
Object 1000
Scene Hierarchy

Or we could go for a more hierarchical
grouping like:
Scene
Room 1
Chair 1
Chair 2
Room 2
Room 3
etc…
Bed
Table
Book
Monitor
Dresser
Scene Hierarchy







It is very common in computer graphics to define a
complex scene in some sort of hierarchical fashion
The individual objects are grouped into a tree like
structure (upside down tree)
Each moving part is a single node in the tree
The node at the top is the root node
A node directly above another is that node’s parent
A node below another is a child and nodes with the
same parent are called siblings
Nodes at the bottom of the tree with no children are
called leaf nodes
Articulated Figures




An articulated figure is an example of a
hierarchical object
The moving parts can be arranged into a tree
data structure if we choose some particular
piece as the ‘root’
For an articulated figure (like a biped character),
we usually choose the root to be somewhere
near the center of the torso
Each joint in the figure has specific allowable
degrees of freedom (DOFs) that define the
range of possible poses for the figure
Example Articulated Figure
Root
Torso
Pelvis
Neck
ShoulderL
ShoulderR
HipL
HipR
Head
ElbowL
ElbowR
KneeL
KneeR
WristL
WristR
AnkleL
AnkleR
Hierarchical Transformations


We assume that each node in the tree graph
represents some object that has a matrix
describing its location and a model describing its
geometry
When a node up in the tree moves its matrix, it
takes its children with it (in other words, rotating
a character’s shoulder joint will cause the elbow,
wrist, and fingers to move as well)
Local Matrices



We will assume a tree structure where child
nodes inherit transformations from the parent
nodes
Each node in the tree stores a local matrix which
is its transformation relative to its parent
To compute a node’s world space matrix, we
need to concatenate its local matrix with its
parent’s world matrix:
W=Wparent·L
Recursive Traversal



To compute all of the world matrices in the
scene, we can traverse the tree in a
depth-first traversal
As each node is traversed, we compute its
world space matrix
By the time a node is traversed, we are
guaranteed that the parent’s world matrix
is available
Forward Kinematics

In the recursive tree traversal, each joint first computes
its local matrix L based on the values of its DOFs and
some formula representative of the joint type:
Local matrix L = Ljoint(φ1,φ2,…,φN)

Then, world matrix W is computed by concatenating L
with the world matrix of the parent joint
World matrix W = Wparent · L
GL Matrix Stack


The GL matrix stack is set up to facilitate
the rendering of hierarchical scenes
While traversing the tree, we can call
glPushMatrix() when going down a level
and glPopMatrix() when coming back up
Hierarchical Culling





Scene hierarchies can also assist in the culling
process
Each object has a precomputed bounding
sphere
This sphere is compared against the view
volume to determine if the object is visible
We can also do hierarchical culling where each
sphere contains all of its children as well
Culling a sphere automatically culls an entire
subtree of the scene
Project 2



In project 2, you are must create some
sort of simple articulated figure, such as a
hand
It must perform some simple animation
(such as opening/closing the fingers)
It must be object oriented and make use of
classes for key objects such as: Camera,
Light, Model, Hand…
Cameras
Camera {
float FOV, Aspect, NearClip, FarClip;
Vector3 Position, Target;
public:
Camera();
void DrawBegin();
void DrawEnd();
void SetAspect(float a);
};
Camera
void Camera::DrawBegin() {
glClear();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(FOV,Aspect,NearClip,FarClip);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(Position.x,Position,y,Position.z,
Target.x,Target.y,Target.z,0,1,0);
glPushMatrix();
}
void Camera::DrawBegin() {
glPopMatrix();
glSwapBuffers();
}