在 android 帮助上在 opengl 中移动立方体
经过大量的试验和错误,我能够绘制一个立方体和一个立方体前面的瓷砖地图。我添加了输入,这样当您移动手指时,相机就会移动。但现在我想在我的游戏进程中添加下一步。我希望它让我的立方体移动到我在 3d 空间中按手指的位置。听起来有点困难。我想做的是让你用一根手指在地图上滑动相机,用另一根手指双击并移动。到目前为止,我的立方体在原地抖动和摇摆,但没有移动到我想要的位置。当然,我的代码都不是完美的,而且我对 gluunproject 的关注可能远远不正确。这是到目前为止我的代码
立方体创建者和更新代码//其简短
public shapemaker(int x, int y, int z,int width)
{
centerx =x;
centery =y;
centerz =z;
mysquare1= new square(centerx,centery,centerz-5,1,.0f,.0f,1f,"vert");
mysquare2= new square(centerx-1,centery,centerz-6f,1,.0f,1.0f,.0f,"side");
mysquare3= new square(centerx,centery,centerz-7,1,1.0f,.0f,.0f,"vert");
mysquare4= new square(centerx+1,centery,centerz-6f,1,.0f,.5f,.5f,"side");
mysquare5= new square(centerx,centery-1,centerz-6f,1,.5f,.5f,.0f,"horiz");
mysquare6= new square(centerx,centery+1,centerz-6f,1,.5f,.0f,.5f,"horiz");
}
public void updatecube(float x, float y, float z)
{
centerx =x;
centery =y;
centerz =z;
mysquare1= new square(centerx,centery,centerz-5,1,.0f,.0f,1f,"vert");
mysquare2= new square(centerx-1,centery,centerz-6f,1,.0f,1.0f,.0f,"side");
mysquare3= new square(centerx,centery,centerz-7,1,1.0f,.0f,.0f,"vert");
mysquare4= new square(centerx+1,centery,centerz-6f,1,.0f,.5f,.5f,"side");
mysquare5= new square(centerx,centery-1,centerz-6f,1,.5f,.5f,.0f,"horiz");
mysquare6= new square(centerx,centery+1,centerz-6f,1,.5f,.0f,.5f,"horiz");
}
public void drawcube(GL10 gl)
{
mysquare1.draw(gl);
mysquare2.draw(gl);
mysquare3.draw(gl);
mysquare4.draw(gl);
mysquare5.draw(gl);
mysquare6.draw(gl);
}
public float getcenterx()
{
return centerx;
}
public float getcentery()
{
return centery;
}
public float getcenterz()
{
return centerz;
}
这是实际的实现代码,它基于谷歌对 opengl 的介绍
class ClearGLSurfaceView extends GLSurfaceView {
private static final String BufferUtils = null;
float x =0;
float y =0;
float z =0f;
float prevx=0;
float prevy=0;
GL10 mygl;
// GL gl;
float mywidth;
float myheight;
public ClearGLSurfaceView(Context context,float width, float height) {
super(context);
mRenderer = new ClearRenderer();
setRenderer(mRenderer);
mywidth = width;
myheight = height;
}
@Override
public boolean onTouchEvent(final MotionEvent event)
{
queueEvent(new Runnable() {
// Find the index of the active pointer and fetch its position
public void run()
{
float curx = event.getX();
float cury = event.getY();
final int action = event.getAction();
if(action == MotionEvent.ACTION_MOVE)
{
if(curx>prevx)
{
x-=.1f;
}
if(curx<prevx)
{
x+=.1f;
}
if(cury>prevy)
{
y+=.1f;
}
if(cury<prevy)
{
y-=.1f;
}
}
if(action == MotionEvent.ACTION_DOWN)
{
// GLU.gluUnProject(winX, winY, winZ, model,
// modelOffset, project, projectOffset, view, viewOffset, obj, objOffset)
vector2d moveto = new vector2d(0,0);
moveto = mRenderer.getworkcoords(curx,cury);
Log.i("move to ", "x "+moveto.x+" y "+ moveto.y+" z " + moveto.z);
mRenderer.updatemoveto(moveto.x, moveto.y);
}
prevx= curx;
prevy = cury;
mRenderer.updatecamera(x, y, z);
}
});
return true;
}
ClearRenderer mRenderer;
}
class ClearRenderer Implements GLSurfaceView.Renderer {
GL10 mygl;
GL11 mygl11;
int viewport[] = new int[4];
float modelview[] = new float[16];
float projection[] = new float[16];
float wcoord[] = new float[4];
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // OpenGL docs.
gl.glShadeModel(GL10.GL_SMOOTH);// OpenGL docs.
gl.glClearDepthf(1.0f);// OpenGL docs.
gl.glEnable(GL10.GL_DEPTH_TEST);// OpenGL docs.
gl.glDepthFunc(GL10.GL_LEQUAL);// OpenGL docs.
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, // OpenGL docs.
GL10.GL_NICEST);
mygl = gl;
mygl11 = (GL11) gl;
int index;
int counter = 0;
float zcoord = -7.0f;
mygl11.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, modelview, 0);
mygl11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, projection, 0);
mygl11.glGetIntegerv(GL11.GL_VIEWPORT, viewport, 0);
for(int x=0;x<11;x++)
{
for(int y =0;y<10;y++)
{
index = tilemap1[y][x];
if(index==0)
{
tiles[counter]=new square(x,y,zcoord,0.5f,1.0f,0.0f,0f,"vert");
}
if(index==1)
{
tiles[counter]=new square(x,y,zcoord,0.5f,0f,1.0f,0f,"vert");
}
if(index==2)
{
tiles[counter]=new square(x,y,zcoord,0.5f,0.0f,0.0f,1f,"vert");
}
counter++;
}
}
}
public vector2d getworkcoords(float width,float height)
{
float[] depth = new float[1];
float winx = width;
float winy =viewport[3]-height;
//vector2d position = new vector2d(0,0);
int test = GLU.gluUnProject(winx, winy,0.0f, modelview, 0, projection,
0, viewport, 0, wcoord, 0);
vector2d v = new vector2d(0,0);
v.x = wcoord[0];
v.y = wcoord[1];
v.z = wcoord[2];
return v ;
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, w, h);
gl.glMatrixMode(GL10.GL_PROJECTION);// OpenGL docs.
gl.glLoadIdentity();// OpenGL docs.
GLU.gluPerspective(gl, 45.0f,
(float) w / (float) h,
0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);// OpenGL docs.
gl.glLoadIdentity();// OpenGL docs.
}
public float movetox;
public float movetoy;
float currentposx;
float currentposy;
public void updatemoveto(float x , float y) { 移动毒素=x; 移动玩具 = y; } public void onDrawFrame(GL10 gl) {
gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
currentposx = mycube.getcenterx();
currentposy = mycube.getcentery();
float x = movetox -currentposx;
float y = movetoy - currentposy;
double angle = Math.atan2(y, x);
double mx =.5f* Math.cos(angle);
double my = .5f* Math.sin(angle);
double mmx = mx+ currentposx;
double mmy = my+ currentposy;
mycube.updatecube((float)(mmx), (float)(mmy),0);
mycube.drawcube(gl);
for(int i = 0;i<110;i++)
{
tiles[i].draw(gl);
}
}
public void setColor(float r, float g, float b) {
mRed = r;
mGreen = g;
mBlue = b;
}
public void updatecamera(float myx, float myy, float myz)
{
mygl.glLoadIdentity();// OpenGL docs.
GLU.gluLookAt(mygl, myx, myy, myz, myx, myy, myz-10, 0, 1, 0);
}
private float mRed;
private float mGreen;
private float mBlue;
int tilemap1[][] = {
{0,0,0,0,0,0,0,0,0,0,0},
{0,1,2,1,1,1,1,1,1,1,0},
{0,1,2,1,1,1,1,1,1,1,0},
{0,1,2,1,1,1,1,1,1,1,0},
{0,1,2,2,2,1,1,1,1,1,0},
{0,1,1,1,2,1,1,1,1,1,0},
{0,1,1,1,2,1,1,1,1,1,0},
{0,1,1,1,2,1,1,1,1,1,0},
{0,1,1,1,2,2,1,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0},
};
square[] tiles = new square[110];
shapemaker mycube = new shapemaker(0,0,0,1);
}
我没有包含创建方法和暂停方法。我还想获得有关设计代码结构的建议,因为我的实现还远远不够完美。
简而言之。我希望帮助弄清楚如何修改我编写的代码,以使立方体移动到我按下的位置。以及如何改进代码
谢谢
After a lot of trial and error I was able to draw a cube and a tile map for the cube to be infront of. I added input so that when you move your finger, the camera moves. But now I want to add the next step in my games progression. I want it to have my cube move to where i pressed my finger in 3d space. It sounds a bit difficult. What I wanted to do is have you use one finger to slide the camera around the map and the other to double tap and move. So far my cube jitters and wobbles in place but doesn't move to where I want it to go. Of course none of my code is perfect and my following of gluunproject might be far from correct. Here is my code so far
The cube creator and update code//its short
public shapemaker(int x, int y, int z,int width)
{
centerx =x;
centery =y;
centerz =z;
mysquare1= new square(centerx,centery,centerz-5,1,.0f,.0f,1f,"vert");
mysquare2= new square(centerx-1,centery,centerz-6f,1,.0f,1.0f,.0f,"side");
mysquare3= new square(centerx,centery,centerz-7,1,1.0f,.0f,.0f,"vert");
mysquare4= new square(centerx+1,centery,centerz-6f,1,.0f,.5f,.5f,"side");
mysquare5= new square(centerx,centery-1,centerz-6f,1,.5f,.5f,.0f,"horiz");
mysquare6= new square(centerx,centery+1,centerz-6f,1,.5f,.0f,.5f,"horiz");
}
public void updatecube(float x, float y, float z)
{
centerx =x;
centery =y;
centerz =z;
mysquare1= new square(centerx,centery,centerz-5,1,.0f,.0f,1f,"vert");
mysquare2= new square(centerx-1,centery,centerz-6f,1,.0f,1.0f,.0f,"side");
mysquare3= new square(centerx,centery,centerz-7,1,1.0f,.0f,.0f,"vert");
mysquare4= new square(centerx+1,centery,centerz-6f,1,.0f,.5f,.5f,"side");
mysquare5= new square(centerx,centery-1,centerz-6f,1,.5f,.5f,.0f,"horiz");
mysquare6= new square(centerx,centery+1,centerz-6f,1,.5f,.0f,.5f,"horiz");
}
public void drawcube(GL10 gl)
{
mysquare1.draw(gl);
mysquare2.draw(gl);
mysquare3.draw(gl);
mysquare4.draw(gl);
mysquare5.draw(gl);
mysquare6.draw(gl);
}
public float getcenterx()
{
return centerx;
}
public float getcentery()
{
return centery;
}
public float getcenterz()
{
return centerz;
}
Here is the actual implementation code , it is based off of googles intro to opengl
class ClearGLSurfaceView extends GLSurfaceView {
private static final String BufferUtils = null;
float x =0;
float y =0;
float z =0f;
float prevx=0;
float prevy=0;
GL10 mygl;
// GL gl;
float mywidth;
float myheight;
public ClearGLSurfaceView(Context context,float width, float height) {
super(context);
mRenderer = new ClearRenderer();
setRenderer(mRenderer);
mywidth = width;
myheight = height;
}
@Override
public boolean onTouchEvent(final MotionEvent event)
{
queueEvent(new Runnable() {
// Find the index of the active pointer and fetch its position
public void run()
{
float curx = event.getX();
float cury = event.getY();
final int action = event.getAction();
if(action == MotionEvent.ACTION_MOVE)
{
if(curx>prevx)
{
x-=.1f;
}
if(curx<prevx)
{
x+=.1f;
}
if(cury>prevy)
{
y+=.1f;
}
if(cury<prevy)
{
y-=.1f;
}
}
if(action == MotionEvent.ACTION_DOWN)
{
// GLU.gluUnProject(winX, winY, winZ, model,
// modelOffset, project, projectOffset, view, viewOffset, obj, objOffset)
vector2d moveto = new vector2d(0,0);
moveto = mRenderer.getworkcoords(curx,cury);
Log.i("move to ", "x "+moveto.x+" y "+ moveto.y+" z " + moveto.z);
mRenderer.updatemoveto(moveto.x, moveto.y);
}
prevx= curx;
prevy = cury;
mRenderer.updatecamera(x, y, z);
}
});
return true;
}
ClearRenderer mRenderer;
}
class ClearRenderer implements GLSurfaceView.Renderer {
GL10 mygl;
GL11 mygl11;
int viewport[] = new int[4];
float modelview[] = new float[16];
float projection[] = new float[16];
float wcoord[] = new float[4];
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // OpenGL docs.
gl.glShadeModel(GL10.GL_SMOOTH);// OpenGL docs.
gl.glClearDepthf(1.0f);// OpenGL docs.
gl.glEnable(GL10.GL_DEPTH_TEST);// OpenGL docs.
gl.glDepthFunc(GL10.GL_LEQUAL);// OpenGL docs.
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, // OpenGL docs.
GL10.GL_NICEST);
mygl = gl;
mygl11 = (GL11) gl;
int index;
int counter = 0;
float zcoord = -7.0f;
mygl11.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, modelview, 0);
mygl11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, projection, 0);
mygl11.glGetIntegerv(GL11.GL_VIEWPORT, viewport, 0);
for(int x=0;x<11;x++)
{
for(int y =0;y<10;y++)
{
index = tilemap1[y][x];
if(index==0)
{
tiles[counter]=new square(x,y,zcoord,0.5f,1.0f,0.0f,0f,"vert");
}
if(index==1)
{
tiles[counter]=new square(x,y,zcoord,0.5f,0f,1.0f,0f,"vert");
}
if(index==2)
{
tiles[counter]=new square(x,y,zcoord,0.5f,0.0f,0.0f,1f,"vert");
}
counter++;
}
}
}
public vector2d getworkcoords(float width,float height)
{
float[] depth = new float[1];
float winx = width;
float winy =viewport[3]-height;
//vector2d position = new vector2d(0,0);
int test = GLU.gluUnProject(winx, winy,0.0f, modelview, 0, projection,
0, viewport, 0, wcoord, 0);
vector2d v = new vector2d(0,0);
v.x = wcoord[0];
v.y = wcoord[1];
v.z = wcoord[2];
return v ;
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, w, h);
gl.glMatrixMode(GL10.GL_PROJECTION);// OpenGL docs.
gl.glLoadIdentity();// OpenGL docs.
GLU.gluPerspective(gl, 45.0f,
(float) w / (float) h,
0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);// OpenGL docs.
gl.glLoadIdentity();// OpenGL docs.
}
public float movetox;
public float movetoy;
float currentposx;
float currentposy;
public void updatemoveto(float x , float y)
{
movetox = x;
movetoy = y;
}
public void onDrawFrame(GL10 gl) {
gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
currentposx = mycube.getcenterx();
currentposy = mycube.getcentery();
float x = movetox -currentposx;
float y = movetoy - currentposy;
double angle = Math.atan2(y, x);
double mx =.5f* Math.cos(angle);
double my = .5f* Math.sin(angle);
double mmx = mx+ currentposx;
double mmy = my+ currentposy;
mycube.updatecube((float)(mmx), (float)(mmy),0);
mycube.drawcube(gl);
for(int i = 0;i<110;i++)
{
tiles[i].draw(gl);
}
}
public void setColor(float r, float g, float b) {
mRed = r;
mGreen = g;
mBlue = b;
}
public void updatecamera(float myx, float myy, float myz)
{
mygl.glLoadIdentity();// OpenGL docs.
GLU.gluLookAt(mygl, myx, myy, myz, myx, myy, myz-10, 0, 1, 0);
}
private float mRed;
private float mGreen;
private float mBlue;
int tilemap1[][] = {
{0,0,0,0,0,0,0,0,0,0,0},
{0,1,2,1,1,1,1,1,1,1,0},
{0,1,2,1,1,1,1,1,1,1,0},
{0,1,2,1,1,1,1,1,1,1,0},
{0,1,2,2,2,1,1,1,1,1,0},
{0,1,1,1,2,1,1,1,1,1,0},
{0,1,1,1,2,1,1,1,1,1,0},
{0,1,1,1,2,1,1,1,1,1,0},
{0,1,1,1,2,2,1,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0},
};
square[] tiles = new square[110];
shapemaker mycube = new shapemaker(0,0,0,1);
}
I did not include the on create method and the on pause ones. I would also like advice on designing the code structure because my implementation is far from perfect.
So in short. I would like help figuring out how to modify the code I made to have a cube move to where i press. And how you would improve the code
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,
您不需要在每次移动时重新创建顶点。这是非常复杂的任务,并且会降低帧速率(FPS)。在您的代码中您有模型矩阵。通常它负责模型的平移、缩放旋转(示例中的网格、立方体)。在常见情况下,您必须转换模型矩阵,然后转换多个模型、投影和视图矩阵,您将获得设备屏幕的矩阵。然后通过顶点位置与该矩阵相乘,您将得到顶点的正确位置。
你可以看看这个问题/答案
First of all,
you don't need to recreate vertices on every moving. It is very complex task and it will low the framerate (FPS). In you code you have model matrix. Usually it is responsible for translating, scaling rotating of your model(mesh, cube in your example). In common case you have to translate the model matrix and then multiple model, projection and view matrixes, you will get the matrix for your device screen. Then by multiplication of vertex postion and this matrix you'll get the right position of vertex.
you can look at this question/answer