242-515 AGD: 10. Meshes11 Objective o to describe how shape meshes and models can be used, with emphasis on the OBJ and MTL 3D formats Animation and Games.

Presentation on theme: "242-515 AGD: 10. Meshes11 Objective o to describe how shape meshes and models can be used, with emphasis on the OBJ and MTL 3D formats Animation and Games."— Presentation transcript:

242-515 AGD: 10. Meshes11 Objective o to describe how shape meshes and models can be used, with emphasis on the OBJ and MTL 3D formats Animation and Games Development 242-515, Semester 1, 2014-2015 10. Meshes and Models

242-515 AGD: 10. Meshes22 1.Triangle Meshes 2.Three Custom Meshes 3.Phong and Gouraud Shading 4.jME Built-in Shapes 5.Using Models 6.Loading Models into a Grid 7.Using the Chase Camera 8.The Wavefront (.obj) Format 9.OBJ Cube Example 10.Other Geometric Models Overview

242-515 AGD: 10. Meshes33 Modern hardware is optimized for triangle meshes: o polygon meshes where every polygon is a triangle There are three basic types of information in a triangle mesh: 1.Vertices 2.Edges 3.Faces 1. Triangle Meshes vertex edge face

242-515 AGD: 10. Meshes44 1. Vertices. Each triangle has exactly three vertices. A vertex may be shared by many triangles. 2. Edges. An edge connects two vertices. Each triangle has three edges. Usually, each edge is shared by two faces. 3. Faces. The surfaces of the triangles. Usually stored as a list of three vertices, or a list of three edges. Triangle Mesh Information

242-515 AGD: 10. Meshes55 +X +Z +Y (1,0,1) (1,0,-1) (-1,0,1) (-1,0,-1) (0,2,0) A Pyramid

242-515 AGD: 10. Meshes66 An indexed triangle mesh consists of a list of vertices, and a list of triangles indicies. Indexed Triangle Mesh +X +Z +Y (1,0,1) (1,0,-1) (-1,0,1) (-1,0,-1) (0,2,0) 01 2 3 4

242-515 AGD: 10. Meshes77 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: o the front faces the direction of the thumb o the vertices indicies are listed in the counterclockwise order of the fingers Index Order and Front Faces

242-515 AGD: 10. Meshes88 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) o {1,4,0} or (4,0,1} also okayExample +X +Y 0 1 4

242-515 AGD: 10. Meshes99 jME Code Fragments // 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}; PyramidMesh.java

242-515 AGD: 10. Meshes10 // 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();

242-515 AGD: 10. Meshes11 // 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); RenderState rs = matWF.getAdditionalRenderState(); 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

242-515 AGD: 10. Meshes12 Execution

242-515 AGD: 10. Meshes13 2. Three Custom Meshes solid blue colored verticies lit with a directional light CustomMeshes.java

242-515 AGD: 10. Meshes14 The Basic Mesh +X +Y 01 23 (0,0,0)(2,0,0) (0,2,0)(2,2,0)

242-515 AGD: 10. Meshes15 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(); Create the Mesh

242-515 AGD: 10. Meshes16 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); A Solid Blue Mesh

242-515 AGD: 10. Meshes17 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); : Coloured Verticies 01 23

242-515 AGD: 10. Meshes18 // 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);

242-515 AGD: 10. Meshes19 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); : Lit Mesh, Reflecting Orange

242-515 AGD: 10. Meshes20 // 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); rootNode.addLight(dl);

242-515 AGD: 10. Meshes21 Vertex Normals Diagram +X +Z +Y 01 23 (0,0,0) (0,2,0) (2,0,0) (2,2,0) directional light

242-515 AGD: 10. Meshes22 Phong shading interpolates normals between all the shape verticies. It uses these normals to calculate the shading for every pixel o many normals are generated o this is the default shading technique in jME Gouraud shading calculates the shading for each vertex, and interpolates those shading values across every pixel o this requires less computation since only vertex normals are needed 3.3. Phong and Gouraud Shading

242-515 AGD: 10. Meshes23 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. Phong Shading in Action

242-515 AGD: 10. Meshes24 Phong shading makes polygons look smoother

242-515 AGD: 10. Meshes25 4. jME Built-in Shapes Dome (the cone and pyramid are special cases) TorusPQTorusSurface (a NURB)

242-515 AGD: 10. Meshes26 // 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); RenderState rs = mat.getAdditionalRenderState(); rs.setWireframe(true); // activate wireframe view rs.setFaceCullMode(RenderState.FaceCullMode.Off); Viewing Wireframe Shapes WireShape.java

242-515 AGD: 10. Meshes27 Dome, Cone, Pyramid Dome mesh = new Dome(Vector3f.ZERO, 32, 32, 1f, false); // center, planes, radialSamples, radius, insideView

242-515 AGD: 10. Meshes28 Dome mesh = new Dome(Vector3f.ZERO, 2, 32, 1f, false); // cone: planes == 2 and radialSamples > 4

242-515 AGD: 10. Meshes29 Dome mesh = new Dome(Vector3f.ZERO, 2, 4, 1f, false); // pyramid: planes == 2 and radialSamples == 4

242-515 AGD: 10. Meshes30 For more information see http://en.wikipedia.org/wiki/Torus_knot Knotted Doughnuts (braids) PQTorus mesh = new PQTorus(2, -3, 2, 1, 64, 64); // trefoil // (2,−3) torus knot

242-515 AGD: 10. Meshes31 PQTorus mesh = new PQTorus(3, -8, 2, 0.5f, 64, 64); // Flower torus, (3, -8) torus knot

242-515 AGD: 10. Meshes32 jME's built-in shapes come with pre-calculated normals, which can be displayed visually with the ShowNormals.j3md material definition. o a color gradient is calculated from the model's surface normals. o no need for lights in the scene Shapes and Normals

242-515 AGD: 10. Meshes33 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); } Viewing a Cylinder's Normals

242-515 AGD: 10. Meshes34 There are many free 3D models available online o e.g. at http://archive3d.net/, http://sketchup.google.com/3dwarehouse/ o see the list of websites at http://www.hongkiat.com/blog/ 60-excellent-free-3d-model-websites/ There are many 3D model formats: o e.g. 3D Studio (.3ds), Blender (.blend), Wavefront (.obj) o see the list at http://edutechwiki.unige.ch/en/3D_file_format 5. Using Models

242-515 AGD: 10. Meshes35 Blender (http://www.blender.org/) o extremely powerful, free, open source 3D modeller o a confusing GUI which keeps being changed o use it to import models, and export them in a different format 3DViewer (http://www.xs4all.nl/~karelse/3DViewer/) o very simple, free 3D viewer which is useful for checking models 3D Tools

242-515 AGD: 10. Meshes36 jME can load models in two formats: o Wavefront.obj format o Ogre XML I'll use.obj since it's a simple format, and is supported by most (all) 3D modeling tools. o 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 o details at http://jmonkeyengine.org/wiki/doku.php/ jme3:advanced:3d_models 3D Formats in jME

242-515 AGD: 10. Meshes37 jME can also save Spatial nodes as.j3o binary files, which can be loaded later. o details at http://jmonkeyengine.org/wiki/doku.php/ jme3:advanced:save_and_load.j3o files can be viewed and edited by the jME SDK

242-515 AGD: 10. Meshes38 6. Loading Models into a Grid GridZoneLoad.java

242-515 AGD: 10. Meshes39 The Grid Zone +X +Z +Y 1 unit 0.1 unit

242-515 AGD: 10. Meshes40 // 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() { addZone(1.2f,3.2f); // (Y,Z) camera position // load the model Spatial model = assetManager.loadModel( "Models/Teapot/Teapot.obj"); rootNode.attachChild(model); } // end of simpleInitApp() Partial Code GridZoneLoad.java

242-515 AGD: 10. Meshes41 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); addWireShape(new Grid(numLines, numLines, STEP), ColorRGBA.White).center(); // axes arrows addArrow(Vector3f.UNIT_X, ColorRGBA.Red); addArrow(Vector3f.UNIT_Y, ColorRGBA.Green); addArrow(Vector3f.UNIT_Z, ColorRGBA.Blue); addBox(WIDTH); // wireframe box :

242-515 AGD: 10. Meshes42 // white light aimed down in front-left quadrant DirectionalLight dl1 = new DirectionalLight(); dl1.setDirection(new Vector3f(-1, -1, 1).normalizeLocal()); dl1.setColor( ColorRGBA.White); rootNode.addLight(dl1); // white light aimed down in back-right quadrant DirectionalLight dl2 = new DirectionalLight(); dl2.setDirection(new Vector3f(1, -1, -1).normalizeLocal()); dl2.setColor( ColorRGBA.White); rootNode.addLight(dl2); } // end of addZone() x z y x z y

242-515 AGD: 10. Meshes43 private void addArrow(Vector3f dir, ColorRGBA color) { Arrow arrow = new Arrow(dir); arrow.setLineWidth(3); // make arrow thicker addWireShape(arrow, color); } // end of addArrow() private void addBox(float size) // a wireframe box { Geometry g = addWireShape( new WireBox(size, size/2, size), ColorRGBA.Yellow); g.setLocalTranslation( new Vector3f(0, size/2, 0)); }

242-515 AGD: 10. Meshes44 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.getAdditionalRenderState().setWireframe(true); mat.setColor("Color", color); g.setMaterial(mat); rootNode.attachChild(g); return g; } // end of addWireShape()

242-515 AGD: 10. Meshes45 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: omodel.scale(0.01f); // 100 times smaller omodel.rotate(0, (float)Math.toRadians(90), 0); // rotate 90 degrees around the y-axis omodel.setLocalTranslation( new Vector3f(-2, 0, 0)); // move 2 units left along the x-axis Adjusting the Model

242-515 AGD: 10. Meshes46 The loaded bus.obj model is too large: oSpatial model = assetManager.loadModel( "models/bus.obj"); o bus.obj is in the local models/ directory I worked out the size problem by using the camera keys and mouse to move about: o the WASDQZ keys to zoom in/out and translate left/right/up/down. o the mouse to rotate left/right/up/down Bus Example

242-515 AGD: 10. Meshes47 Original view of the bus: After zooming out a lot (it's a seat inside the bus):

242-515 AGD: 10. Meshes48 bus.obj in 3DViewer (to check the model):

242-515 AGD: 10. Meshes49 Modified jME code: Spatial model = assetManager.loadModel("models/bus.obj"); model.scale(0.005f); model.setLocalTranslation( new Vector3f(0, 0.2f, 0)); 200x smaller then moved up 0.2f units:

242-515 AGD: 10. Meshes50 Spatial model = assetManager.loadModel( "Models/HoverTank/Tank2.mesh.xml"); model.scale(0.1f); model.rotate(0, -(float)Math.toRadians(90), 0);HoverTank 10x smaller then rotated -90 degrees around the y-axis:

242-515 AGD: 10. Meshes51 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 o this kind of camera can rotate around a specified Spatial o it will also automatically follow the Spatal if it moves (i.e. it chases the model) 7. Using the Chase Camera

242-515 AGD: 10. Meshes52 Rotating Around the HoverTank ViewHoverTank.java rotate left and up by dragging the mouse

242-515 AGD: 10. Meshes53 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); : Partial Code

242-515 AGD: 10. Meshes54 // white light from above Vector3f lightDir = new Vector3f(-1, -1, 1).normalize(); DirectionalLight dl1 = new DirectionalLight(); dl1.setColor(ColorRGBA.White); dl1.setDirection(lightDir); rootNode.addLight(dl1); // orange light from below Vector3f lightDir2 = new Vector3f(1, 1, -1).normalize(); DirectionalLight dl2 = new DirectionalLight(); dl2.setColor(ColorRGBA.Orange); dl2.setDirection(lightDir2); rootNode.addLight(dl2); } // end of simpleInitApp()

242-515 AGD: 10. Meshes55 Most models are made up of triangles. Each triangle is called a face. Each face is defined using vertices o 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. 8. The Wavefront (.obj) Format

242-515 AGD: 10. Meshes56 There are three types of basic OBJ statements: o for defining shape o for grouping o for materials (most of these operations are located in the separate.mtl file)

242-515 AGD: 10. Meshes57 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 Defining Shape

242-515 AGD: 10. Meshes58 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

242-515 AGD: 10. Meshes59 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.Grouping

242-515 AGD: 10. Meshes60 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. Material Use Statements

242-515 AGD: 10. Meshes61 Ambient RGB color: Ka r g b Diffuse RGB: Kd r g b Specular color: Ks r g b Transparency: d alpha Tr alpha The MTL File Format

242-515 AGD: 10. Meshes62 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

242-515 AGD: 10. Meshes63 A cube was exported from Blender as the OBJ file blenderCube.obj o a MTL file was created automatically, called blenderCube.mtl 9. OBJ Cube Example in Blender

242-515 AGD: 10. Meshes64 # 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 : The OBJ file only 6 normals (1 per face) blenderCube.obj

242-515 AGD: 10. Meshes65 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 each face is defined using 3 vertices and 1 normal; no tex coords used 12 faces (even though the cube only has 6 sides)

242-515 AGD: 10. Meshes66 4 OBJ Cube Diagram +X +Z +Y (1,-1,1) (1,-1,-1) (-1,1,1) 1 2 3 5 (-1,-1,1) (1,1,-1) 6 7 (-1,1,-1) 8 5 3 2 6 4 1

242-515 AGD: 10. Meshes67 A Cube Side Has 2 Faces +X +Z +Y (1,-1,1) (1,1,1) (-1,1,1) 2 3 (-1,-1,1) 6 7 4 f 2//4 6//4 7//4 f 2//4 7//4 3//4 uses the right hand rule to define the front face

242-515 AGD: 10. Meshes68 # 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 The MTL File blenderCube.mtl

242-515 AGD: 10. Meshes69 Spatial model = assetManager.loadModel("models/blenderCube.obj"); model.scale(0.5f); Loaded by jME Cube's sides are scaled to 0.5 units GridZoneLoad.java

242-515 AGD: 10. Meshes70 It's easy to modify the MTL file: Kd 0.54 0.89 0.63 // jade (see Part 9, sec 6.1) Modifying the Material Cube's diffuse reflection is now jade

242-515 AGD: 10. Meshes71 The OBJ format is fully explained at: o http://local.wasp.uwa.edu.au/~pbourke/dataformats/obj/ The MTL format: o http://local.wasp.uwa.edu.au/~pbourke/dataformats/mtl/ Full OBJ and MTL Details

242-515 AGD: 10. Meshes72 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: o Constructive Solid Geometry (CSG) o Metaballs 10. Other Geometric Models

242-515 AGD: 10. Meshes73 CSG builds a shape using Boolean operators (union, difference, intersection) on primitive shapes (cubes, spheres, etc) o available in the Unreal engine Constructive Solid Geometry (CSG) union: cube + sphere difference: cube - sphere intersection: cube ∩ sphere

242-515 AGD: 10. Meshes74 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.Metaballs the red and blue metaballs come together

Download ppt "242-515 AGD: 10. Meshes11 Objective o to describe how shape meshes and models can be used, with emphasis on the OBJ and MTL 3D formats Animation and Games."

Similar presentations