Animation and Games Development

1 / 74

# Animation and Games Development - PowerPoint PPT Presentation

Animation and Games Development. 242-515 , Semester 1 , 2014-2015. Objective to describe how shape meshes and models can be used, with emphasis on the OBJ and MTL 3D formats. 10. Meshes and Models. Overview. Triangle Meshes Three Custom Meshes Phong and Gouraud Shading

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about 'Animation and Games Development' - deacon-young

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Animation and Games Development

242-515, Semester 1, 2014-2015

• Objective
• to describe how shape meshes and models can be used, with emphasis on the OBJ and MTL 3D formats

10. Meshes and Models

Overview
• Triangle Meshes
• Three Custom Meshes
• jME Built-in Shapes
• Using Models
• Using the Chase Camera
• The Wavefront (.obj) Format
• OBJ Cube Example
• Other Geometric Models
1. Triangle Meshes
• Modern hardware is optimized for triangle meshes:
• polygon meshes where every polygon is a triangle
• There are three basic types of information in a triangle mesh:
• Vertices
• Edges
• Faces

face

edge

vertex

Triangle Mesh Information
• Vertices. Each triangle has exactly three vertices. A vertex may be shared by many triangles.
• Edges. An edge connects two vertices. Each triangle has three edges. Usually, each edge is shared by two faces.
• Faces. The surfaces of the triangles. Usually stored as a list of three vertices, or a list of three edges.
A Pyramid

+Y

(0,2,0)

(-1,0,-1)

(1,0,-1)

+X

(-1,0,1)

(1,0,1)

+Z

Indexed Triangle Mesh
• An indexed triangle mesh consists of a list of vertices, and a list of triangles indicies.

+Y

4

(0,2,0)

3

(-1,0,-1)

(1,0,-1)

+X

2

(-1,0,1)

(1,0,1)

0

1

+Z

Index Order and Front Faces
• Each triangle is represented using three indices.
• The index order is specified in terms of the front face of the triangle.
• The index order follows the right-hand rule:
• the front faces the direction of the thumb
• the vertices indicies are listed in the counterclockwise order of the fingers
Example
• The triangle on the front of the pyramid is facing along the +z axis.
• This means that the triangle's indicies will be defined counter-clockwise as {0, 1, 4)
• {1,4,0} or (4,0,1} also okay

+Y

4

1

0

+X

jME Code Fragments

PyramidMesh.java

// Vertex positions in space

Vector3f [] verts = new Vector3f[5];

verts[0] = new Vector3f(-1, 0, 1);

verts[1] = new Vector3f(1, 0, 1);

verts[2] = new Vector3f(1, 0, -1);

verts[3] = new Vector3f(-1, 0, -1);

verts[4] = new Vector3f(0, 2, 0);

// the order in which mesh should be constructed from triangles

int [] indexes = {0,3,1, 1,3,2,

2,3,4, 4,3,0, 0,1,4, 4,1,2};

// mesh creation

Mesh mesh = new Mesh();

// Setting mesh buffers

// the 2nd parameter is the number of components in each value

mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(verts));

mesh.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes));

mesh.updateBound();

// mesh is displayed as a white wireframe

Geometry geom = new Geometry("pyramid", mesh);

Material matWF = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

matWF.setColor("Color", ColorRGBA.White);

geom.setMaterial(matWF);

rootNode.attachChild(geom);

rs.setWireframe(true); // activate wireframe view

rs.setFaceCullMode(RenderState.FaceCullMode.Off);

cam.setLocation(new Vector3f(0.5f, 3.5f, 4));

cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y); // look at the origin with +y-axis being up

2. Three Custom Meshes

CustomMeshes.java

lit with a

directional

light

solid

blue

colored

verticies

The Basic Mesh

+Y

2

3

(0,2,0)

(2,2,0)

(0,0,0)

(2,0,0)

+X

0

1

Create the Mesh

Mesh mesh = new Mesh();

// Vertex positions in space

Vector3f[] verts = new Vector3f[4];

verts[0] = new Vector3f(0,0,0); // can use any ordering

verts[1] = new Vector3f(2,0,0);

verts[2] = new Vector3f(0,2,0);

verts[3] = new Vector3f(2,2,0);

// the order in which mesh should be constructed from triangles

int[] indexes = {2,0,1, 1,3,2};

// setting the buffers

mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(verts));

mesh.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes)); mesh.updateBound();

A Solid Blue Mesh

Geometry geom = new Geometry("solid", mesh);

Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat.setColor("Color", ColorRGBA.Blue);

geom.setMaterial(mat);

geom.setLocalTranslation(-2, -3, 0);

rootNode.attachChild(geom);

Coloured Verticies

Mesh colMesh = mesh.clone();

Geometry colGeom = new Geometry ("colored", colMesh);

Material colMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

colMat.setBoolean("VertexColor", true);

// each vertex requires 4 color values (R G B A)

// in the same ordering as the vertices array, verts[]

float[] colorArray = {

1f, 0f, 0f, 1f, // red

0.8f, 0.2f, 1f, 1f, // purple

0.8f, 0.2f, 1f, 1f,

0f, 0f, 1f, 1f }; // blue

// Set the color buffer

colMesh.setBuffer(Type.Color, 4, colorArray); colGeom.setMaterial(colMat);

:

2

3

0

1

// Set the color buffer

colMesh.setBuffer(Type.Color, 4, colorArray);

colGeom.setMaterial(colMat);

// move mesh so it doesn't overlap with the first one

colGeom.setLocalTranslation(2, -3, 0);

rootNode.attachChild(colGeom);

Lit Mesh, Reflecting Orange

Mesh litMesh = mesh.clone();

Geometry litGeom = new Geometry ("lit", litMesh);

Material litMat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");

litMat.setBoolean("UseMaterialColors", true);

litMat.setColor("Diffuse", ColorRGBA.Orange); // reflection

litMat.setColor("Specular", ColorRGBA.White);

litMat.setFloat("Shininess", 12);

litGeom.setMaterial(litMat);

:

// verticies require normals for Phong lighting

float[] normals = {0,0,1, 0,0,1, 0,0,1, 0,0,1}; // all of them point along +z axis

litMesh.setBuffer(Type.Normal, 3, BufferUtils.createFloatBuffer(normals));

litGeom.setLocalTranslation(-2, 1, 0);

rootNode.attachChild(litGeom);

// add a white light to make the lit object visible

DirectionalLight dl = new DirectionalLight();

dl.setDirection(new Vector3f(1, 0, -2).normalizeLocal());

dl.setColor(ColorRGBA.White);

Vertex Normals Diagram

+Y

2

3

(2,2,0)

(0,2,0)

(2,0,0)

(0,0,0)

+X

0

1

directional

light

+Z

• Phong shading interpolates normals between all the shape verticies. It uses these normals to calculate the shading for every pixel
• many normals are generated
• this is the default shading technique in jME
• Gouraud shading calculates the shading for each vertex, and interpolates those shading values across every pixel
• this requires less computation since only vertex normals are needed
• The black arrows are the vertex normals.
• The blue arrows are the interpolated surface normals.
• These extra normals will make the hexagon look smoother on screen.
4. jME Built-in Shapes

Dome (the cone and pyramid are special cases)

Torus

PQTorus

Surface

(a NURB)

Viewing Wireframe Shapes

WireShape.java

// Sphere mesh = new Sphere(16, 16, 1.0f);

// Cylinder mesh = new Cylinder(20, 50, 1, 2, true);

:

Geometry geom = new Geometry("Shape", mesh);

Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat.setColor("Color", ColorRGBA.Blue);

geom.setMaterial(mat);

rootNode.attachChild(geom);

rs.setWireframe(true); // activate wireframe view

rs.setFaceCullMode(RenderState.FaceCullMode.Off);

Dome, Cone, Pyramid

Dome mesh = new Dome(Vector3f.ZERO, 32, 32, 1f, false);

Dome mesh = new Dome(Vector3f.ZERO, 2, 32, 1f, false);

// cone: planes == 2 and radialSamples > 4

Dome mesh = new Dome(Vector3f.ZERO, 2, 4, 1f, false);

// pyramid: planes == 2 and radialSamples == 4

Knotted Doughnuts (braids)

PQTorus mesh = new PQTorus(2, -3, 2, 1, 64, 64); // trefoil// (2,−3) torus knot

PQTorus mesh = new PQTorus(3, -8, 2, 0.5f, 64, 64);

// Flower torus, (3, -8) torus knot

Shapes and Normals
• jME's built-in shapes come with pre-calculated normals, which can be displayed visually with the ShowNormals.j3md material definition.
• a color gradient is calculated from the model's surface normals.
• no need for lights in the scene
Viewing a Cylinder's Normals

public void simpleInitApp()

{ Cylinder mesh = new Cylinder(20, 50, 1, 2, true);

Geometry geom = new Geometry("Shape", mesh);

Material mat = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");

geom.setMaterial(mat);

geom.rotate(FastMath.HALF_PI, 0, 0);

rootNode.attachChild(geom);

}

5. Using Models
• There are many free 3D models available online
• see the list of websites athttp://www.hongkiat.com/blog/ 60-excellent-free-3d-model-websites/
• There are many 3D model formats:
• e.g. 3D Studio (.3ds), Blender (.blend), Wavefront (.obj)
• see the list at http://edutechwiki.unige.ch/en/3D_file_format
3D Tools
• Blender (http://www.blender.org/)
• extremely powerful, free, open source 3D modeller
• a confusing GUI which keeps being changed
• use it to import models, and export them in a different format
• 3DViewer (http://www.xs4all.nl/~karelse/3DViewer/)
• very simple, free 3D viewer which is useful for checking models
3D Formats in jME
• jME can load models in two formats:
• Wavefront .obj format
• Ogre XML
• I'll use .obj since it's a simple format, and is supported by most (all) 3D modeling tools.
• the format is text-based, and is easy to edit manually (see later)
• Blender can export Ogre XML files, but it requires the installation of a plugin

jME can also save Spatial nodes as .j3o binary files, which can be loaded later.

• .j3o files can be viewed and edited by the jME SDK
The Grid Zone

+Y

1 unit

+X

1 unit

0.1 unit

1 unit

+Z

Partial Code

// globals private static final float STEP = 0.1f; // space between grid lines

private static final float WIDTH = 1.0f; // extent along +axis of grid and box

public void simpleInitApp()

{

rootNode.attachChild(model);

} // end of simpleInitApp()

private void addZone(float y, float z)

{

viewPort.setBackgroundColor(ColorRGBA.DarkGray);

cam.setLocation(new Vector3f(0,y,z));

cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y); // look at the origin with +y-axis being up

// grid-based floor

int numLines = (int)((WIDTH/STEP)*2 + 1);

// axes arrows

// white light aimed down in front-left quadrant

DirectionalLight dl1 = new DirectionalLight();

dl1.setDirection(new Vector3f(-1, -1, 1).normalizeLocal());

dl1.setColor( ColorRGBA.White);

// white light aimed down in back-right quadrant

DirectionalLight dl2 = new DirectionalLight();

dl2.setDirection(new Vector3f(1, -1, -1).normalizeLocal());

dl2.setColor( ColorRGBA.White);

y

y

x

x

z

z

private void addArrow(Vector3f dir, ColorRGBA color)

{

Arrow arrow = new Arrow(dir);

arrow.setLineWidth(3); // make arrow thicker

// a wireframe box

{ Geometry g = addWireShape( new WireBox(size, size/2, size), ColorRGBA.Yellow);

g.setLocalTranslation( new Vector3f(0, size/2, 0));

}

private Geometry addWireShape(Mesh shape, ColorRGBA color)

// add a colored wireframe version of shape to the scene

{

Geometry g = new Geometry("shape", shape);

Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

mat.setColor("Color", color);

g.setMaterial(mat);

rootNode.attachChild(g);

return g;

• The imported shape may be too large, translated a long way from the origin, or rotated incorrectly.
• In that case, add code to simpleInitApp() like:
• model.scale(0.01f); // 100 times smaller
• model.rotate(0, (float)Math.toRadians(90), 0); // rotate 90 degrees around the y-axis
• model.setLocalTranslation( new Vector3f(-2, 0, 0)); // move 2 units left along the x-axis
Bus Example
• The loaded bus.obj model is too large:
• Spatial model = assetManager.loadModel( "models/bus.obj");
• bus.obj is in the local models/ directory
• I worked out the size problem by using the camera keys and mouse to move about:
• the WASDQZ keys to zoom in/out and translate left/right/up/down.
• the mouse to rotate left/right/up/down

Original viewof the bus:

• After zooming out a lot (it's a seat inside thebus):

Modified jME code:

model.scale(0.005f);

model.setLocalTranslation( new Vector3f(0, 0.2f, 0));

200x smaller

then moved

up 0.2f units:

HoverTank

model.scale(0.1f);

10x smaller

then rotated

-90 degrees

around the

y-axis:

7. Using the Chase Camera
• A drawback of the default camera (a FlyByCamera object) is that rotation is around the camera's position.
• For model viewing, it is often better to rotate around the model.
• This is possible by using a ChaseCamera object instead
• this kind of camera can rotate around a specified Spatial
• it will also automatically follow the Spatal if it moves (i.e. it chasesthe model)
Rotating Around the HoverTank

ViewHoverTank.java

rotate left and up by

dragging the mouse

Partial Code

public void simpleInitApp()

{

Node tank = (Node) assetManager.loadModel( "Models/HoverTank/Tank2.mesh.xml");

rootNode.attachChild(tank);

// replace FlyByCamera by ChaseCamera

flyCam.setEnabled(false);

ChaseCamera chaseCam = new ChaseCamera(cam, tank, inputManager);

// camera follows the tank and // can turn around it by dragging the mouse

chaseCam.setSmoothMotion(true);

chaseCam.setMaxDistance(100000);

chaseCam.setMinVerticalRotation(-FastMath.PI / 2);

:

// white light from above

Vector3f lightDir = new Vector3f(-1, -1, 1).normalize();

DirectionalLight dl1 = new DirectionalLight();

dl1.setColor(ColorRGBA.White);

dl1.setDirection(lightDir);

// orange light from below

Vector3f lightDir2 = new Vector3f(1, 1, -1).normalize();

DirectionalLight dl2 = new DirectionalLight();

dl2.setColor(ColorRGBA.Orange);

dl2.setDirection(lightDir2);

} // end of simpleInitApp()

8. The Wavefront (.obj) Format
• Most models are made up of triangles.
• Each triangle is called a face.
• Each face is defined using vertices
• a face may also have normals and texture coordinates
• Faces can be grouped together, and different groups can be assigned materials made from ambient, diffuse, and specular colors, and textures.
• The material information is stored in a separate MTL text file.

There are three types of basic OBJ statements:

• for defining shape
• for grouping
• for materials (most of these operations are located in the separate .mtl file)
Defining Shape
• Vertex position:

v float float float

• each "v" line has an index, starting from 1
• A normal:

vn float float float

• each "vn" line has an index, starting from 1
• 2D or 3D texture coordinate:

vt float float [float]

• each "vt" line has an index, startiong from 1

A face (in terms of vertex indicies)

f int int int

• A face (uses vertex and texture indicies)

f int/int int/int int/int

• A face (uses vertex, texture and normal indicies):

f int/int/int int/int/int int/int/int

Grouping
• g name
• Faces ("f" lines) defined after a "g" line will belong to the group called “name”.
• Named groups are a useful way of referring to a collection of faces for assigning materials or textures.
Material Use Statements
• mltlib filename
• The MTL file named in the “mltlib” statement will contain material definitions used in the rest of the OBJ file.
• usemtl name
• All subsequent faces after this line will be rendered with the named material, until the next “usemtl” line.
The MTL File Format
• Ambient RGB color:

Ka r g b

• Diffuse RGB:

Kd r g b

• Specular color:

Ks r g b

• Transparency:

d alpha

Tr alpha

Shininess:

Ns s

• Illumination mode:

illum n

• If n == 1 then no specular highlights are used
• If n == 2 then use “Ks” value for the highlights
• if n == 0 then all lighting is disabled
• Texture filename:

map_Ka filename

9. OBJ Cube Example
• A cube was exported from Blender as the OBJ file blenderCube.obj
• a MTL file was created automatically, called blenderCube.mtl

in Blender

The OBJ file

blenderCube.obj

# Blender v2.62 (sub 0) OBJ File: ''

# www.blender.org

mtllib blenderCube.mtl

o Cube

v 1.000000 -1.000000 -1.000000 // 1

v 1.000000 -1.000000 1.000000 // 2

v -1.000000 -1.000000 1.000000 // 3

v -1.000000 -1.000000 -1.000000 // 4

v 1.000000 1.000000 -0.999999 // 5

v 0.999999 1.000000 1.000001 // 6

v -1.000000 1.000000 1.000000 // 7

v -1.000000 1.000000 -1.000000 // 8

vn 0.000000 -1.000000 0.000000 // 1

vn 0.000000 1.000000 0.000000 // 2

vn 1.000000 0.000000 0.000000 // 3

vn -0.000000 -0.000000 1.000000 // 4

vn -1.000000 -0.000000 -0.000000 // 5

vn 0.000000 0.000000 -1.000000 // 6

g Cube_Cube_Material

usemtl Material

:

only 6 normals

(1 per face)

each face is defined using

3 vertices and 1 normal;

no tex coords used

s off

f 1//1 2//1 3//1

f 1//1 3//1 4//1

f 5//2 8//2 7//2

f 5//2 7//2 6//2

f 1//3 5//3 6//3

f 1//3 6//3 2//3

f 2//4 6//4 7//4

f 2//4 7//4 3//4

f 3//5 7//5 8//5

f 3//5 8//5 4//5

f 5//6 1//6 4//6

f 5//6 4//6 8//6

12 faces (even though the

cube only has 6 sides)

OBJ Cube Diagram

+Y

2

(-1,1,-1)

(1,1,-1)

8

5

6

6

7

(-1,1,1)

3

+X

5

4

1

(1,-1,-1)

4

3

(1,-1,1)

2

+Z

(-1,-1,1)

1

A Cube Side Has 2 Faces

f 2//4 6//4 7//4

f 2//4 7//4 3//4

+Y

(-1,1,1)

(1,1,1)

6

7

+X

4

3

(1,-1,1)

2

(-1,-1,1)

+Z

uses the right hand rule

to define the front face

The MTL File

blenderCube.mtl

# Blender MTL File: ''

# Material Count: 1

newmtl Material

Ns 96.078431

Ka 0.000000 0.000000 0.000000 // no ambient

Kd 0.640000 0.640000 0.640000 // gray

Ks 0.500000 0.500000 0.500000

Ni 1.000000 // no refraction

d 1.000000 // no transparency

illum 2 // use Ks for highlights

model.scale(0.5f);

Cube's sides

are scaled to

0.5 units

Modifying the Material
• It's easy to modify the MTL file:

Kd 0.54 0.89 0.63 // jade (see Part 9, sec 6.1)

Cube's diffuse

reflection is

Full OBJ and MTL Details
• The OBJ format is fully explained at:
• http://local.wasp.uwa.edu.au/~pbourke/dataformats/obj/
• The MTL format:
• http://local.wasp.uwa.edu.au/~pbourke/dataformats/mtl/
10. Other Geometric Models
• The use of meshes composed of verticies, faces, edges, and normals is the standard way of creating models in computer graphics.
• There are other approaches, such as:
• Constructive Solid Geometry (CSG)
• Metaballs
Constructive Solid Geometry (CSG)
• CSG builds a shape using Boolean operators (union, difference, intersection) on primitive shapes (cubes, spheres, etc)
• available in the Unreal engine

union:

cube + sphere

intersection:

cube ∩ sphere

difference:

cube - sphere

Metaballs
• Used to model organic shapes and fluids.
• A ball has a fuzzy region around it.
• When two ball come near to each other, their fuzzy regions start merging.

the red and blue metaballs come together