Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

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:

1 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 , Semester 1, Meshes and Models

2 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

3 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

4 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

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

6 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)

7 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

8 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

9 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};

10 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();

11 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

12 AGD: 10. Meshes12 Execution

13 AGD: 10. Meshes13 2. Three Custom Meshes solid blue colored verticies lit with a directional light

14 AGD: 10. Meshes14 The Basic Mesh +X +Y (0,0,0)(2,0,0) (0,2,0)(2,2,0)

15 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

16 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

17 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

18 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);

19 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

20 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);

21 AGD: 10. Meshes21 Vertex Normals Diagram +X +Z +Y (0,0,0) (0,2,0) (2,0,0) (2,2,0) directional light

22 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

23 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

24 AGD: 10. Meshes24 Phong shading makes polygons look smoother

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

26 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

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

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

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

30 AGD: 10. Meshes30 For more information see Knotted Doughnuts (braids) PQTorus mesh = new PQTorus(2, -3, 2, 1, 64, 64); // trefoil // (2,−3) torus knot

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

32 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

33 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

34 AGD: 10. Meshes34 There are many free 3D models available online o e.g. at o see the list of websites at 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 5. Using Models

35 AGD: 10. Meshes35 Blender ( 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 ( o very simple, free 3D viewer which is useful for checking models 3D Tools

36 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 jme3:advanced:3d_models 3D Formats in jME

37 AGD: 10. Meshes37 jME can also save Spatial nodes as.j3o binary files, which can be loaded later. o details at jme3:advanced:save_and_load.j3o files can be viewed and edited by the jME SDK

38 AGD: 10. Meshes38 6. Loading Models into a Grid

39 AGD: 10. Meshes39 The Grid Zone +X +Z +Y 1 unit 0.1 unit

40 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

41 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 :

42 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

43 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)); }

44 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()

45 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

46 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

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

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

49 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:

50 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:

51 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

52 AGD: 10. Meshes52 Rotating Around the HoverTank rotate left and up by dragging the mouse

53 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

54 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()

55 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

56 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)

57 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

58 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

59 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

60 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

61 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

62 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

63 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

64 AGD: 10. Meshes64 # Blender v2.62 (sub 0) OBJ File: '' # mtllib blenderCube.mtl o Cube v // 1 v // 2 v // 3 v // 4 v // 5 v // 6 v // 7 v // 8 vn // 1 vn // 2 vn // 3 vn // 4 vn // 5 vn // 6 g Cube_Cube_Material usemtl Material : The OBJ file only 6 normals (1 per face) blenderCube.obj

65 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)

66 AGD: 10. Meshes66 4 OBJ Cube Diagram +X +Z +Y (1,-1,1) (1,-1,-1) (-1,1,1) (-1,-1,1) (1,1,-1) 6 7 (-1,1,-1)

67 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) f 2//4 6//4 7//4 f 2//4 7//4 3//4 uses the right hand rule to define the front face

68 AGD: 10. Meshes68 # Blender MTL File: '' # Material Count: 1 newmtl Material Ns Ka // no ambient Kd // gray Ks Ni // no refraction d // no transparency illum 2 // use Ks for highlights The MTL File blenderCube.mtl

69 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

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

71 AGD: 10. Meshes71 The OBJ format is fully explained at: o The MTL format: o Full OBJ and MTL Details

72 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

73 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

74 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

Ads by Google