我想旋转对象z轴,所以我使用下面的代码,但它不在特定位置旋转,它的旋转只是返回并出现在附近。我认为GLU.gluLookAt(gl, 0, 0, 10, 0, 0, 0, 0, 1, 0);
中的值存在问题。请帮我设置正确的值,以便旋转效果良好。
gl.glTranslatef(mOrigin.x, mOrigin.y, mOrigin.z);
gl.glRotatef(mRotate.x, 1f, 0f, 0f);
gl.glRotatef(mRotate.y, 0f, 1f, 0f);
gl.glRotatef(mRotate.z, 0f, 0f, 1f);
private class Renderer implements GLSurfaceView.Renderer {
public Renderer() {
setEGLConfigChooser(8, 8, 8, 8, 16, 0);
getHolder().setFormat(PixelFormat.TRANSLUCENT);
setZOrderOnTop(true);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f,0.0f,0.0f, 0.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glShadeModel(GL10.GL_SMOOTH);
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
mViewWidth = (float)w;
mViewHeight = (float)h;
gl.glViewport(0,0,w,h);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 45, mViewWidth/mViewHeight, 0.1f, 100f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glPushMatrix();
gl.glDisable(GL10.GL_DITHER);
GLU.gluLookAt(gl, 0, 0, 10, 0, 0, 0, 0, 1, 0);
//draw_model
gl.glPushMatrix();
if(mOrigin != null && mRotate != null) {
gl.glTranslatef(mOrigin.x, mOrigin.y, mOrigin.z);
gl.glRotatef(mRotate.x, 1f, 0f, 0f);
gl.glRotatef(mRotate.y, 0f, 1f, 0f);
gl.glRotatef(mRotate.z, 0f, 0f, 1f);
}
if(mModel != null) {
mModel.draw(gl, mContext);
if(!RendererView.textureFileName.equals(""))
mModel.bindTextures(mContext, gl);
}
gl.glPopMatrix();
gl.glPopMatrix();
if(isPictureTake) {
w = getWidth();
h = getHeight();
b = new int[w*(y+h)];
bt = new int[w*h];
IntBuffer ib = IntBuffer.wrap(b);
ib.position(0);
gl.glReadPixels(0, 0, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, ib);
createBitmapFromGLSurface(mContext);
isPictureTake = false;
}
}
}
ObjLoader.java
package com.amplimesh.models;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.StringTokenizer;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import com.amplimesh.renderer.RendererView;
import com.amplimesh.util.Point3;
/**
* Object Loader and draw the texture and object.
* @author Ajay
*/
public class ObjModel {
/**
* It fill the texture into the mesh
* @param context
* @param gl
*/
public void bindTextures(Context context, GL10 gl) {
Bitmap bitmap;
try {
InputStream is = context.getAssets().open("textures/"+RendererView.textureFileName);
bitmap = BitmapFactory.decodeStream(is);
if(bitmap != null) {
// generate one texture pointer
gl.glGenTextures(1, mTextures, 0);
// ...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[0]);
// create nearest filtered texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
//Different possible texture parameters, e.g. 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);
// Use Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
// Clean up
bitmap.recycle();
}
} catch (java.io.IOException e) {
return;
}
}
/**
* It draw the object.
* @param gl
*/
public void draw(GL10 gl, Context mContext) {
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
for (Model model : mModels) {
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, model.v);
if (model.vt != null && mTextures != null) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[0]);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, model.vt);
}
if (model.vn != null) {
gl.glNormalPointer(GL10.GL_FLOAT, 0, model.vn);
}
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, model.v_size);
}
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
/**
* It Load the object from stream.
* @param is
* @param texture_name
* @return
* @throws IOException
*/
public static ObjModel loadFromStream(InputStream is, String texture_name) throws IOException {
ObjModel obj = ObjLoader.loadFromStream(is);
return obj;
}
private Model mModels[];
private int mTextures[] = new int[1];;
/**
* It read the the obj file.
* @author Ajay
*/
private static class ObjLoader {
public static ObjModel loadFromStream(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
ObjModel obj = new ObjModel();
ArrayList<Point3> v = new ArrayList<Point3>();
ArrayList<Point3> vt = new ArrayList<Point3>();
ArrayList<Point3> vn = new ArrayList<Point3>();
ArrayList<Face> f = new ArrayList<Face>();
ArrayList<Model> o = new ArrayList<Model>();
boolean o_pending=false;
while(reader.ready()) {
String line = reader.readLine();
if (line == null)
break;
StringTokenizer tok = new StringTokenizer(line);
String cmd = tok.nextToken();
if (cmd.equals("o")) {
if (o_pending) {
Model model = new Model();
model.fill(f, vt.size() > 0, vn.size() > 0);
o.add(model);
}
else {
o_pending=true;
}
}
else
if (cmd.equals("v")) {
v.add(read_point(tok));
}
else
if (cmd.equals("vn")) {
vn.add(read_point(tok));
}
else
if (cmd.equals("vt")) {
vt.add(read_point(tok));
}
else
if (cmd.equals("f")) {
if (tok.countTokens() != 3)
continue;
Face face = new Face(3);
while (tok.hasMoreTokens()) {
StringTokenizer face_tok = new StringTokenizer(tok.nextToken(), "/");
int v_idx = -1;
int vt_idx = -1;
int vn_idx = -1;
v_idx = Integer.parseInt(face_tok.nextToken());
if (face_tok.hasMoreTokens()) vt_idx = Integer.parseInt(face_tok.nextToken());
if (face_tok.hasMoreTokens()) vn_idx = Integer.parseInt(face_tok.nextToken());
//Log.v("objmodel", "face: "+v_idx+"/"+vt_idx+"/"+vn_idx);
face.addVertex(
v.get(v_idx-1),
vt_idx == -1 ? null : vt.get(vt_idx-1),
vn_idx == -1 ? null : vn.get(vn_idx-1)
);
}
f.add(face);
}
}
if (o_pending) {
Model model = new Model();
model.fill(f, vt.size() > 0, vn.size() > 0);
o.add(model);
}
obj.mModels = new Model[o.size()];
o.toArray(obj.mModels);
return obj;
}
private static Point3 read_point(StringTokenizer tok) {
Point3 ret = new Point3();
if (tok.hasMoreTokens()) {
ret.x = Float.parseFloat(tok.nextToken());
if (tok.hasMoreTokens()) {
ret.y = Float.parseFloat(tok.nextToken());
if (tok.hasMoreTokens()) {
ret.z = Float.parseFloat(tok.nextToken());
}
}
}
return ret;
}
}
private static class Face {
Point3 v[];
Point3 vt[];
Point3 vn[];
int size;
int count;
public Face(int size) {
this.size = size;
this.count = 0;
this.v = new Point3[size];
this.vt = new Point3[size];
this.vn = new Point3[size];
}
public boolean addVertex(Point3 v, Point3 vt, Point3 vn) {
if (count >= size)
return false;
this.v[count] = v;
this.vt[count] = vt;
this.vn[count] = vn;
count++;
return true;
}
public void pushOnto(FloatBuffer v_buffer, FloatBuffer vt_buffer, FloatBuffer vn_buffer) {
int i;
for (i=0; i<size; i++) {
v_buffer.put(v[i].x); v_buffer.put(v[i].y); v_buffer.put(v[i].z);
if (vt_buffer != null && vt[i] != null) {
vt_buffer.put(vt[i].x); vt_buffer.put(vt[i].y);
}
if (vn_buffer != null && vn[i] != null) {
vn_buffer.put(vn[i].x); vn_buffer.put(vn[i].y); vn_buffer.put(vn[i].z);
}
}
}
}
/**
* It hold the vertex buffer, vertex normal and texture.
* @author Ajay
*/
private static class Model {
public FloatBuffer v;
public FloatBuffer vt;
public FloatBuffer vn;
public int v_size;
public void fill(ArrayList<Face> faces, boolean has_tex, boolean has_normals) {
int f_len = faces.size();
this.v_size = f_len * 3;
ByteBuffer tBuf = ByteBuffer.allocateDirect(this.v_size*3 * 4);
tBuf.order(ByteOrder.nativeOrder());
this.v = tBuf.asFloatBuffer();
if (has_tex) {
ByteBuffer vtBuf = ByteBuffer.allocateDirect(this.v_size*3 * 4);
vtBuf.order(ByteOrder.nativeOrder());
this.vt = vtBuf.asFloatBuffer();
}
if (has_normals) {
ByteBuffer vnBuf = ByteBuffer.allocateDirect(this.v_size*3 * 4);
vnBuf.order(ByteOrder.nativeOrder());
this.vn = vnBuf.asFloatBuffer();
}
int i;
for (i=0; i < f_len; i++) {
Face face = faces.get(i);
face.pushOnto(this.v, this.vt, this.vn);
}
this.v.rewind();
if (this.vt != null)
this.vt.rewind();
if (this.vn != null)
this.vn.rewind();
}
}
}
答案 0 :(得分:0)
要围绕轴旋转特定位置的对象,首先需要将对象的中心转换为原点。在您的示例中,您在(mOrigin)处有一个对象,可能相对于另一个翻译(您的相机的位置)。
不是将对象平移到最终位置然后旋转,而是需要将其转换为(0,0,0),旋转然后转换到最终位置。
在最简单的情况下,这将是:
gl.glRotatef (mRotate.x, 1f, 0f, 0f);
gl.glRotatef (mRotate.y, 0f, 1f, 0f);
gl.glRotatef (mRotate.z, 0f, 0f, 1f);
gl.glTranslatef (mOrigin.x, mOrigin.y, mOrigin.z);
在更复杂的情况下,你的对象相对于相机,你必须做这样的事情:
gl.glTranslatef (-Camera.x, -Camera.y, -Camera.z);
gl.glRotatef (mRotate.x, 1f, 0f, 0f);
gl.glRotatef (mRotate.y, 0f, 1f, 0f);
gl.glRotatef (mRotate.z, 0f, 0f, 1f);
gl.glTranslatef (Camera.x + mOrigin.x, Camera.y + mOrigin.y, Camera.z + mOrigin.z);
答案 1 :(得分:0)
Glulookat的旋转组件看起来很好,所以我没有看到任何可能导致问题的问题。
首先,根据您提供的链接,在我看来,您想围绕Y轴旋转,尽管您提到了围绕Z轴的旋转,这可能会产生不同的结果。 https://www.dropbox.com/s/ozt7beo4gz5q293/demo2__A.avi
其次,您在m_Rotate向量中使用的值是多少?他们是度数还是弧度?
第三,你是推动还是弹出矩阵堆栈?如果是这样的话?或者您是否将自己的矩阵数据输入OpenGL?您是否确保在绘制调用期间调用glLoadIdentity()将视图矩阵设置回单位矩阵?
TBH可能存在许多可能导致问题的领域。要缩小可能的问题区域,请在绘图功能中执行以下操作;
首先请务必致电
glLoadIdentity();
将您的相机翻译在对象后面(在您的GLuLookAt中设置为0,0,10)。
glTranslatef(0.0f,0.0f,-10.0f);
然后绕Z轴进行简单的旋转;
glRotatef(mRotate.z, 0.0f, 0.0f, 1.0f);
编辑:就我所知,你调用onDrawFrame来绘制场景中的东西。 。在此调用中,您需要执行这些更改以确定问题所在。
而不是这个;
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glPushMatrix();
gl.glDisable(GL10.GL_DITHER);
GLU.gluLookAt(gl, 0, 0, 10, 0, 0, 0, 0, 1, 0);
//draw_model
gl.glPushMatrix();
if(mOrigin != null && mRotate != null) {
gl.glTranslatef(mOrigin.x, mOrigin.y, mOrigin.z);
gl.glRotatef(mRotate.x, 1f, 0f, 0f);
gl.glRotatef(mRotate.y, 0f, 1f, 0f);
gl.glRotatef(mRotate.z, 0f, 0f, 1f);
}
...
gl.glPopMatrix();
gl.glPopMatrix();
}
尝试更简单的事情。
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glDisable(GL10.GL_DITHER);
gl.glMatrixMode(GL10.GL_MODELVIEW); //making sure OpenGL currently in model view
gl.glLoadIdentity(); //clear the model view matrix to identity matrix
gl.glTranslatef(0.0f, 0.0f, -10.0f); //move 10 unit backwards so as if camera moves backwards.
gl.glRotatef(90.0f,0.0f,0.0f,1.0f) //rotate 90 degree around the z axis.
//draw_model
...
//gl.glPopMatrix();
//gl.glPopMatrix();
}
通过这样做你可能的问题区域减少了很多。你可以开始搞清楚问题了。如果上面的代码有效,那么可能的错误会减少很多。
可能是那样;
BTW:我不是java的专家,但在c ++和Objective c中,我们不能将1f设置为浮点值。我们必须使用1.0f否则编译器会抱怨。