1 / 74

Animation and Games Development

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

Télécharger la présentation

Animation and Games Development

An Image/Link below is provided (as is) to download presentation 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. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 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

  2. Overview • Triangle Meshes • Three Custom Meshes • Phong and Gouraud Shading • jME Built-in Shapes • Using Models • Loading Models into a Grid • Using the Chase Camera • The Wavefront (.obj) Format • OBJ Cube Example • Other Geometric Models

  3. 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

  4. 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.

  5. A Pyramid +Y (0,2,0) (-1,0,-1) (1,0,-1) +X (-1,0,1) (1,0,1) +Z

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

  7. 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

  8. 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

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

  10. // 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. // 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. Execution

  13. 2. Three Custom Meshes CustomMeshes.java lit with a directional light solid blue colored verticies

  14. The Basic Mesh +Y 2 3 (0,2,0) (2,2,0) (0,0,0) (2,0,0) +X 0 1

  15. 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();

  16. 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);

  17. 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

  18. // 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. 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); :

  20. // 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. Vertex Normals Diagram +Y 2 3 (2,2,0) (0,2,0) (2,0,0) (0,0,0) +X 0 1 directional light +Z

  22. 3.3. Phong and Gouraud Shading • 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

  23. Phong Shading in Action • 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.

  24. Phong shading makes polygons look smoother

  25. 4. jME Built-in Shapes Dome (the cone and pyramid are special cases) Torus PQTorus Surface (a NURB)

  26. 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); RenderState rs = mat.getAdditionalRenderState(); rs.setWireframe(true); // activate wireframe view rs.setFaceCullMode(RenderState.FaceCullMode.Off);

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

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

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

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

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

  32. 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

  33. 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); }

  34. 5. Using Models • There are many free 3D models available online • e.g. at http://archive3d.net/, http://sketchup.google.com/3dwarehouse/ • 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

  35. 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

  36. 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 • details at http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:3d_models

  37. jME can also save Spatial nodes as .j3o binary files, which can be loaded later. • details at http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:save_and_load • .j3o files can be viewed and edited by the jME SDK

  38. 6. Loading Models into a Grid GridZoneLoad.java

  39. The Grid Zone +Y 1 unit +X 1 unit 0.1 unit 1 unit +Z

  40. Partial Code GridZoneLoad.java // 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()

  41. 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. // 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() y y x x z z

  43. 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. 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. Adjusting the Model • 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

  46. 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

  47. Original viewof the bus: • After zooming out a lot (it's a seat inside thebus):

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

  49. 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. HoverTank Spatial model = assetManager.loadModel( "Models/HoverTank/Tank2.mesh.xml"); model.scale(0.1f); model.rotate(0, -(float)Math.toRadians(90), 0); 10x smaller then rotated -90 degrees around the y-axis:

More Related