Creating a 3D road in Android OpenGL ES -
i'm trying create simple game in android. road meant games temple run
or subway surf
simpler , abstract opengl es without other libraries. i've read lot of basic tutorials explains 3d construction logic , used basic sample of creating 3d cube rotates.
i trying use sample create game road. made square more rectangle , duplicate 30x5 square road. i've tried many combinations , internet find solution , yet have problems\questions:
- how set 30x5 squares 1 next another? i'm getting squares unwanted gap
- i want set vieweye point (the "camera") 45 degrees middle of first row, player see road upon him
- next, want move along road. iv'e seen rotate , how works. there way same viewpoint or need change squares drawing z's?
- i see ondrawframe() calling on , on many times. control fps, i've seen on internet people have used there own fps calculation sleep(). isn't there built 1 already?
glrenderer code:
import javax.microedition.khronos.egl.eglconfig; import javax.microedition.khronos.opengles.gl10; import android.content.context; import android.opengl.glsurfaceview; import android.opengl.glu; import android.util.log; class glrenderer implements glsurfaceview.renderer { private static final string tag = "glrenderer" ; private final context context; private float mcuberotation = 70.0f; private triangle triangle; private cube[][] cube; glrenderer(context context) { this.context = context; } public void onsurfacecreated(gl10 gl, eglconfig config) { gl.glclearcolor(0.0f, 0.0f, 0.0f, 0.5f); gl.glcleardepthf(1.0f); gl.glenable(gl10.gl_depth_test); gl.gldepthfunc(gl10.gl_lequal); gl.glhint(gl10.gl_perspective_correction_hint,gl10.gl_nicest); } public void onsurfacechanged(gl10 gl, int width, int height) { log.d("myopenglrenderer", "surface changed. width=" + width + " height=" + height); system.out.println("arg"); //get map cube = new cube[30][5]; for(int = 0; < cube.length; i++) for(int j = 0; j < cube[i].length; j++) cube[i][j] = new cube(); //draw triangle triangle = new triangle(0.5f, 1, 0, 0); // define view frustum gl.glviewport(0, 0, width, height); gl.glmatrixmode(gl10.gl_projection); gl.glloadidentity(); float ratio = (float) width / height; glu.gluperspective(gl, 45.0f, ratio, 0.1f, 100.0f); gl.glmatrixmode(gl10.gl_modelview); gl.glloadidentity(); } public void ondrawframe(gl10 gl) { // clear screen black gl.glclear(gl10.gl_color_buffer_bit | gl10.gl_depth_buffer_bit); //translate(dx, dy, dz) // position model can see //gl.glmatrixmode(gl10.gl_modelview); gl.glloadidentity(); gl.gltranslatef(0.0f, 0.0f, -10.0f); gl.glrotatef(mcuberotation, 1.0f, 1.0f, 1.0f); gl.gltranslatef(0.0f, 0.0f, -10.0f); cube[0][0].draw(gl); gl.gltranslatef(0.0f, 0.0f, -10.0f); cube[0][1].draw(gl); gl.gltranslatef(0.0f, 0.0f, -10.0f); cube[0][2].draw(gl); gl.glloadidentity(); //set rotation mcuberotation -= 0.15f; system.out.println("mcuberotation: "+mcuberotation); } }
cube code:
import java.nio.bytebuffer; import java.nio.byteorder; import java.nio.floatbuffer; import javax.microedition.khronos.opengles.gl10; class cube { private floatbuffer mvertexbuffer; //vertex private floatbuffer mcolorbuffer; //color private bytebuffer mindexbuffer; //face indices float width = 1.0f; float height = 0.5f; float depth = 1.0f; private float vertices[] = { -width, -height, -depth, // 0 width, -height, -depth, // 1 width, height, -depth, // 2 -width, height, -depth, // 3 -width, -height, depth, // 4 width, -height, depth, // 5 width, height, depth, // 6 -width, height, depth, // 7 }; private float colors[] = { 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.5f, 0.0f, 1.0f, 1.0f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; private byte indices[] = { 0, 4, 5, 0, 5, 1, 1, 5, 6, 1, 6, 2, 2, 6, 7, 2, 7, 3, 3, 7, 4, 3, 4, 0, 4, 7, 6, 4, 6, 5, 3, 0, 1, 3, 1, 2 }; public cube() { bytebuffer bytebuf = bytebuffer.allocatedirect(vertices.length * 4); bytebuf.order(byteorder.nativeorder()); mvertexbuffer = bytebuf.asfloatbuffer(); mvertexbuffer.put(vertices); mvertexbuffer.position(0); bytebuf = bytebuffer.allocatedirect(colors.length * 4); bytebuf.order(byteorder.nativeorder()); mcolorbuffer = bytebuf.asfloatbuffer(); mcolorbuffer.put(colors); mcolorbuffer.position(0); mindexbuffer = bytebuffer.allocatedirect(indices.length); mindexbuffer.put(indices); mindexbuffer.position(0); } public void draw(gl10 gl) { gl.glfrontface(gl10.gl_cw); gl.glvertexpointer(3, gl10.gl_float, 0, mvertexbuffer); gl.glcolorpointer(4, gl10.gl_float, 0, mcolorbuffer); gl.glenableclientstate(gl10.gl_vertex_array); gl.glenableclientstate(gl10.gl_color_array); gl.gldrawelements(gl10.gl_triangles, 36, gl10.gl_unsigned_byte, mindexbuffer); gl.gldisableclientstate(gl10.gl_vertex_array); gl.gldisableclientstate(gl10.gl_color_array); } }
eventually i'll draw square array using gldrawarrays() or gldrawelements() i've used 3 objects.
there's lot of questions here. can't cover in detail, can give pointers steer in right direction.
to draw 150 squares, have number of options:
- create vertex buffer single square, , draw 150 times, translations applied. easiest off ground, recommend getting working first. it's reasonable approach if squares same.
- create 150 vertex buffers, different coordinates. wouldn't recommend because it's least efficient, , doesn't have benefits on other approaches.
- store vertices 150 squares in single vertex buffer. efficient of first 3 options, works long relative orientation of squares remains same. may want try once have basics working.
- use instanced rendering. more advanced feature, , available in es 3.0. mentioning future reference.
what attempted sort of hybrid between option 1 , 2. if want go option 1, need 1 instance of cube
class. if @ did, makes sense. created 150 objects same, not useful.
now, on questions:
- to draw squares without gaps between them, amount of translations needs same size of each square. squares 2 units wide, translate each 1 10 units. translate them in z-direction, don't quite understand.
- if want stick kind of functionality have been using, check out
glu.glulookat()
. allows place camera want it, , point in direction. - same 2. call
glu.glulookat()
every time want move viewpoint. - android caps frame rate @ 60 frames per second. that's should shooting anyway, imho. if want limit 30 fps later save power, think can cross bridge when there. based on researched recently, there's no clean , portable way on android. proposed solutions have seen kind of hacky me.
a couple more things on code:
- your color definitions odd. specify colors in 4 components, , size of array correct that. write array 3 values per line, makes want 3 component colors. either 1 can done, need make sure you're consistent. 3 components enough, unless need transparency.
- you using es 1.0. that's valid, , might easier started with. should aware many of features considered obsolete, , using es 2.0 let learn more modern , current opengl features. initial hurdle higher, there's tradeoff here.
Comments
Post a Comment