实际上,我有一个适用于 Android 1.5 的应用程序,其中包含一个 GLSurfaceView 类,它在屏幕上显示一个简单的方形多边形。
我想学习如何添加一个新功能,即移动用手指触摸的方 block 的功能。我的意思是当用户触摸方 block 并移动手指时,方 block 应该粘在手指上,直到手指松开屏幕。
我们将不胜感激任何教程/代码示例/帮助。
我的代码:
public class MySurfaceView extends GLSurfaceView implements Renderer {
private Context context;
private Square square;
private float xrot; //X Rotation
private float yrot; //Y Rotation
private float zrot; //Z Rotation
private float xspeed; //X Rotation Speed
private float yspeed; //Y Rotation Speed
private float z = -1.15f; //Profundidad en el eje Z
private float oldX; //valor anterior de X, para rotación
private float oldY; //valor anterior de Y, para rotación
private final float TOUCH_SCALE = 0.2f; //necesario para la rotación
//create the matrix grabber object in your initialization code
private MatrixGrabber mg = new MatrixGrabber();
private boolean firstTimeDone=false; //true si la aplicación ya ha sido inicializada.
public MySurfaceView(Context context, Bitmap image) {
super(context);
this.context = context;
setEGLConfigChooser(8, 8, 8, 8, 16, 0); //fondo transparente
getHolder().setFormat(PixelFormat.TRANSLUCENT); //fondo transparente
//Transformamos esta clase en renderizadora
this.setRenderer(this);
//Request focus, para que los botones reaccionen
this.requestFocus();
this.setFocusableInTouchMode(true);
square = new Square(image);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glDisable(GL10.GL_DITHER); //dithering OFF
gl.glEnable(GL10.GL_TEXTURE_2D); //Texture Mapping ON
gl.glShadeModel(GL10.GL_SMOOTH); //Smooth Shading
gl.glClearDepthf(1.0f); //Depth Buffer Setup
gl.glEnable(GL10.GL_DEPTH_TEST); //Depth Testing ON
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glClearColor(0,0,0,0); //fondo transparente
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
//Cargamos la textura del cubo.
square.loadGLTexture(gl, this.context);
}
public void onDrawFrame(GL10 gl) {
//Limpiamos pantalla y Depth Buffer
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
//Dibujado
gl.glTranslatef(0.0f, 0.0f, z); //Move z units into the screen
gl.glScalef(0.8f, 0.8f, 0.8f); //Escalamos para que quepa en la pantalla
//Rotamos sobre los ejes.
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f); //X
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f); //Y
gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f); //Z
//Dibujamos el cuadrado
square.draw(gl);
//Factores de rotación.
xrot += xspeed;
yrot += yspeed;
if (!firstTimeDone)
{
/////////////// NEW CODE FOR SCALING THE AR IMAGE TO THE DESIRED WIDTH /////////////////
mg.getCurrentProjection(gl);
mg.getCurrentModelView(gl);
float [] modelMatrix = new float[16];
float [] projMatrix = new float[16];
modelMatrix=mg.mModelView;
projMatrix=mg.mProjection;
int [] mView = new int[4];
mView[0] = 0;
mView[1] = 0;
mView[2] = 800; //width
mView[3] = 480; //height
float [] outputCoords = new float[3];
GLU.gluProject(-1.0f, -1.0f, z, modelMatrix, 0, projMatrix, 0, mView, 0, outputCoords, 0);
int i=0;
System.out.print(i);
// firstTimeDone=true;
}
}
//si el surface cambia, resetea la vista, imagino que esto pasa cuando cambias de modo portrait/landscape o sacas el teclado físico en móviles tipo Droid.
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height == 0) {
height = 1;
}
gl.glViewport(0, 0, width, height); //Reset Viewport
gl.glMatrixMode(GL10.GL_PROJECTION); //Select Projection Matrix
gl.glLoadIdentity(); //Reset Projection Matrix
//Aspect Ratio de la ventana
GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select Modelview Matrix
gl.glLoadIdentity(); //Reset Modelview Matrix
}
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_MOVE:
//Calculamos el cambio
float dx = x - oldX;
float dy = y - oldY;
xrot += dy * TOUCH_SCALE;
yrot += dx * TOUCH_SCALE;
//Log.w("XXXXXX", "ACTION_MOVE_NO_ZOOM");
break;
}
oldX = x;
oldY = y;
return true; //El evento ha sido manejado
}
public void zoomIn(){
z=z+0.2f;
if (z>-1.0f)
z=-1.0f;
}
public void zoomOut(){
z=z-0.2f;
if (z<-20.0f)
z=-20.0f;
}
public void rotateL(){
zrot=zrot+3.0f;
}
public void rotateR(){
zrot=zrot-3.0f;
}
public void reset()
{
xrot=0;
yrot=0;
zrot=0;
xspeed=0;
yspeed=0;
z = -5.0f;
}
}
这是我的方形类:
public class Square {
//Buffer de vertices
private FloatBuffer vertexBuffer;
//Buffer de coordenadas de texturas
private FloatBuffer textureBuffer;
//Puntero de texturas
private int[] textures = new int[3];
//El item a representar
private Bitmap image;
//Definición de vertices
private float vertices[] =
{
-1.0f, -1.0f, 0.0f, //Bottom Left
1.0f, -1.0f, 0.0f, //Bottom Right
-1.0f, 1.0f, 0.0f, //Top Left
1.0f, 1.0f, 0.0f //Top Right
};
/*
private float vertices[] =
{
-0.8f, -0.8f, 0.0f, //Bottom Left
0.8f, -0.8f, 0.0f, //Bottom Right
-0.8f, 0.8f, 0.0f, //Top Left
0.8f, 0.8f, 0.0f
};
*/
//Coordenadas (u, v) de las texturas
/*
private float texture[] =
{
//Mapping coordinates for the vertices
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
*/
private float texture[] =
{
//Mapping coordinates for the vertices
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
//Inicializamos los buffers
public Square(Bitmap image) {
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
this.image=image;
}
//Funcion de dibujado
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CCW);
//gl.glEnable(GL10.GL_BLEND);
//Bind our only previously generated texture in this case
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
//Enable vertex buffer
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//gl.glDisable(GL10.GL_BLEND);
}
//Carga de texturas
public void loadGLTexture(GL10 gl, Context context) {
//Generamos un puntero de texturas
gl.glGenTextures(1, textures, 0);
//y se lo asignamos a nuestro array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//Creamos filtros de texturas
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
//Diferentes parametros de textura posibles GL10.GL_CLAMP_TO_EDGE
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
/*
String imagePath = "radiocd5.png";
AssetManager mngr = context.getAssets();
InputStream is=null;
try {
is = mngr.open(imagePath);
} catch (IOException e1) { e1.printStackTrace(); }
*/
//Get the texture from the Android resource directory
InputStream is=null;
/*
if (item.equals("rim"))
is = context.getResources().openRawResource(R.drawable.rueda);
else if (item.equals("selector"))
is = context.getResources().openRawResource(R.drawable.selector);
*/
/*
is = context.getResources().openRawResource(resourceId);
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
is = null;
} catch (IOException e) {
}
}
*/
Bitmap bitmap =image;
//con el siguiente código redimensionamos las imágenes que sean mas grandes de 256x256.
int newW=bitmap.getWidth();
int newH=bitmap.getHeight();
float fact;
if (newH>256 || newW>256)
{
if (newH>256)
{
fact=(float)255/(float)newH; //porcentaje por el que multiplicar para ser tamaño 256
newH=(int)(newH*fact); //altura reducida al porcentaje necesario
newW=(int)(newW*fact); //anchura reducida al porcentaje necesario
}
if (newW>256)
{
fact=(float)255/(float)newW; //porcentaje por el que multiplicar para ser tamaño 256
newH=(int)(newH*fact); //altura reducida al porcentaje necesario
newW=(int)(newW*fact); //anchura reducida al porcentaje necesario
}
bitmap=Bitmap.createScaledBitmap(bitmap, newW, newH, true);
}
//con el siguiente código transformamos imágenes no potencia de 2 en imágenes potencia de 2 (pot)
//meto el bitmap NOPOT en un bitmap POT para que no aparezcan texturas blancas.
int nextPot=256;
int h = bitmap.getHeight();
int w = bitmap.getWidth();
int offx=(nextPot-w)/2; //distancia respecto a la izquierda, para que la imagen quede centrada en la nueva imagen POT
int offy=(nextPot-h)/2; //distancia respecto a arriba, para que la imagen quede centrada en la nueva imagen POT
Bitmap bitmap2 = Bitmap.createBitmap(nextPot, nextPot, Bitmap.Config.ARGB_8888); //crea un bitmap transparente gracias al ARGB_8888
Canvas comboImage = new Canvas(bitmap2);
comboImage.drawBitmap(bitmap, offx, offy, null);
comboImage.save();
//Usamos Android GLUtils para espcificar una textura de 2 dimensiones para nuestro bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap2, 0);
//Checkeamos si el GL context es versión 1.1 y generamos los Mipmaps por Flag. Si no, llamamos a nuestra propia implementación
if(gl instanceof GL11) {
gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap2, 0);
} else {
buildMipmap(gl, bitmap2);
}
//Limpiamos los bitmaps
bitmap.recycle();
bitmap2.recycle();
}
//Nuestra implementación de MipMap. Escalamos el bitmap original hacia abajo por factor de 2 y lo asignamos como nuevo nivel de mipmap
private void buildMipmap(GL10 gl, Bitmap bitmap) {
int level = 0;
int height = bitmap.getHeight();
int width = bitmap.getWidth();
while(height >= 1 || width >= 1) {
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bitmap, 0);
if(height == 1 || width == 1) {
break;
}
level++;
height /= 2;
width /= 2;
Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
bitmap.recycle();
bitmap = bitmap2;
}
}
}
最佳答案
你看过Android教程代码了吗?他们在 OpenGL ES 1 和 2 中有一些与此非常相似的示例。
在 OpenGL ES 1 教程中,有一节专门用于处理触摸事件。 http://developer.android.com/resources/tutorials/opengl/opengl-es10.html#touch
所以你想将 AddMotion 部分从 glrotatef 命令修改为 gltranslatef;
编辑
看起来您对坐标转换比对象选择更感兴趣。因此,无论您在屏幕上触摸何处,图像都会到达那里(与触摸和拖动图像相反,这意味着选择)。 你关于 winZ 的问题让我觉得你正在尝试 gluunproject。 如果是这种情况,您已经知道您的 winZ,因为您通过“z”变量将相机从对象平移回来。既然你的 z 是负数,为什么不试试这个呢?
假设您已经在 Activity 中为 GLSurfaceView 设置了 GLWrapper:
mGLView.setGLWrapper(new GLWrapper() {
public GL wrap(GL gl) {
return new MatrixTrackingGL(gl);
}
});
然后,在您的 GLSurfaceView/Renderer 子类中...
public float[] unproject(GL10 gl, float x, float y) {
mMatrixGrabber.getCurrentState(gl);
int[] view = {0,0,this.getWidth(), this.getHeight()};
float[] pos = new float[4];
float[] result = null;
int retval = GLU.gluUnProject(x, y, -z,
mMatrixGrabber.mModelView, 0,
mMatrixGrabber.mProjection, 0,
view, 0,
pos, 0);
if (retval != GL10.GL_TRUE) {
Log.e("unproject", GLU.gluErrorString(retval));
} else {
result = new float[3];
result[0] = pos[0] / pos[3];
result[1] = pos[1] / pos[3];
result[2] = pos[2] / pos[3];
result = pos;
}
return result;
}
然后您可以修改您的 TouchEvent 处理程序以包含
switch (event.getAction())
{
case MotionEvent.ACTION_MOVE:
//Calculamos el cambio
float dx = x - oldX;
float dy = y - oldY;
xrot += dy * TOUCH_SCALE;
yrot += dx * TOUCH_SCALE;
//Log.w("XXXXXX", "ACTION_MOVE_NO_ZOOM");
touching = true;
break;
case MotionEvent.ACTION_UP:
xrot = 0;
yrot = 0;
zrot = 0;
touching = false;
break;
}
并在其他平移/缩放/旋转调用之前将下一部分放在绘制方法中:
if (touching) {
float[] point = unproject(gl, oldX, (this.getHeight() - oldY));
if (point == null) {
Log.e("Draw", "No Point");
} else {
gl.glTranslatef(point[0], point[1], 0);
}
}
希望这能给您带来您想要的结果。
关于android - 如何用手指移动 OpenGL 正方形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8010971/
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?
我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
A/ctohttp://wiki.nginx.org/CoreModule#usermaster进程曾经以root用户运行,是否可以以不同的用户运行nginxmaster进程? 最佳答案 只需以非root身份运行init脚本(即/etc/init.d/nginxstart),就可以用不同的用户运行nginxmaster进程。如果这真的是你想要做的,你将需要确保日志和pid目录(通常是/var/log/nginx&/var/run/nginx.pid)对该用户是可写的,并且您所有的listen调用都是针对大于1024的端口(因为绑定(
我正在尝试解决http://projecteuler.net/problem=1.我想创建一个方法,它接受一个整数,然后创建一个包含它前面的所有整数的数组,并将整数本身作为数组中的值。以下是我目前所拥有的。代码不起作用。defmake_array(num)numbers=Array.newnumcount=1numbers.eachdo|number|numbers 最佳答案 (1..num).to_a是您在Ruby中需要做的全部。1..num将创建一个Range对象,以1开始并以任意值num结束是。Range对象有to_a方法通过
我有这样的HTML代码:Label1Value1Label2Value2...我的代码不起作用。doc.css("first").eachdo|item|label=item.css("dt")value=item.css("dd")end显示所有首先标记,然后标记标签,我需要“标签:值” 最佳答案 首先,您的HTML应该有和中的元素:Label1Value1Label2Value2...但这不会改变您解析它的方式。你想找到s并遍历它们,然后在每个你可以使用next_element得到;像这样:doc=Nokogiri::HTML(
我在游戏和帐户模型之间存在多对多关系,如下所示:classAccount:destroyhas_many:games,:through=>:account_gamesendclassGame:destroyhas_many:accounts,:through=>:account_gamesendclassAccountGame现在我知道让我们说我想创建一个类似这样的记录:@account=Account.new(params[:user])@account.games但是我应该如何在执行此操作时更新AccountGame中的某些属性?假设AccountGame有一些名为score的字段
我正在尝试使用Ruby中的SeleniumWebDriver2.4模拟鼠标移动如果我运行测试,是否应该看到鼠标在我的屏幕上移动?我很困惑。我试过很多不同的方法示例代码:require'selenium-webdriver'driver=Selenium::WebDriver.for:firefoxdriver.navigate.to'http://www.google.com'element=driver.find_element(:id,'gbqfba')那我试过了driver.action.move_to(element).performdriver.mouse.move_to(e
我正在寻找一个好的图形框架来用Ruby制作一个漂亮的2D游戏。我做了3个非常简单的测试,看看哪个图形Ruby框架在Gosu之间更快。和Rubygame.该测试创建了1000个“Square”类的实例,这些实例使用框架的方法以最简单的方式移动和绘制一个红色方block。第三个测试是同一件事,但在纯OpenGL实现中(没有任何框架)。这是结果:纯OPENGL(使用ruby-opengl)80Fps:alttexthttp://grab.by/JTMGOSU(使用ruby-opengl+gosu)46Fps:alttexthttp://grab.by/JTCRUBYGAME(使用ru