- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用用于 Android 应用程序的 OpenGL ES 2.0 实现了彩色 3D 立方体的可视化。我的目标:立方体应该对滑动事件(左、右、上、下)使用react,然后立方体应该在相应的方向旋转。
旋转:
我的代码:
public class Cube20 {
private volatile int angleX;
private volatile int angleY;
private volatile Cube.RotateDirection rotateDirection;
public Cube.RotateDirection getRotateDirection() {
return rotateDirection;
}
public void setRotation(Cube.RotateDirection rotateDirection) {
this.rotateDirection = Cube.RotateDirection.getDirectionForID(rotateDirection.getId());
}
public int getAngleX() {
return angleX;
}
public void setAngleX(int angleX) {
this.angleX = angleX;
}
public int getAngleY() {
return angleY;
}
public void setAngleY(int angleY) {
this.angleY = angleY;
}
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// The matrix must be included as a modifier of gl_Position.
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private final FloatBuffer vertexBuffer;
//private final ShortBuffer drawListBuffer;
private final int mProgram;
private final ShortBuffer indexBuffer;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
private float[] vertices = { // Vertices of the 6 faces
// FRONT
-1.0f, -1.0f, 1.0f, // 0. left-bottom-front (0)
1.0f, -1.0f, 1.0f, // 1. right-bottom-front
-1.0f, 1.0f, 1.0f, // 2. left-top-front
1.0f, 1.0f, 1.0f, // 3. right-top-front
// BACK
1.0f, -1.0f, -1.0f, // 6. right-bottom-back (4)
-1.0f, -1.0f, -1.0f, // 4. left-bottom-back
1.0f, 1.0f, -1.0f, // 7. right-top-back
-1.0f, 1.0f, -1.0f, // 5. left-top-back
// LEFT
-1.0f, -1.0f, -1.0f, // 4. left-bottom-back (8)
-1.0f, -1.0f, 1.0f, // 0. left-bottom-front
-1.0f, 1.0f, -1.0f, // 5. left-top-back
-1.0f, 1.0f, 1.0f, // 2. left-top-front
// RIGHT
1.0f, -1.0f, 1.0f, // 1. right-bottom-front (12)
1.0f, -1.0f, -1.0f, // 6. right-bottom-back
1.0f, 1.0f, 1.0f, // 3. right-top-front
1.0f, 1.0f, -1.0f, // 7. right-top-back
// TOP
-1.0f, 1.0f, 1.0f, // 2. left-top-front
1.0f, 1.0f, 1.0f, // 3. right-top-front
-1.0f, 1.0f, -1.0f, // 5. left-top-back
1.0f, 1.0f, -1.0f, // 7. right-top-back
// BOTTOM
-1.0f, -1.0f, -1.0f, // 4. left-bottom-back
1.0f, -1.0f, -1.0f, // 6. right-bottom-back
-1.0f, -1.0f, 1.0f, // 0. left-bottom-front
1.0f, -1.0f, 1.0f // 1. right-bottom-front
};
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
private float[][] colors = { // Colors of the 6 faces
{1.0f, 0.5f, 0.0f, 1.0f}, // 0. orange
{1.0f, 0.0f, 1.0f, 1.0f}, // 1. violet
{0.0f, 1.0f, 0.0f, 1.0f}, // 2. green
{0.0f, 0.0f, 1.0f, 1.0f}, // 3. blue
{1.0f, 0.0f, 0.0f, 1.0f}, // 4. red
{1.0f, 1.0f, 0.0f, 1.0f} // 5. yellow
};
short[] indices = {
0, 1, 2, 2, 1, 3, // FRONT
4, 5, 6, 6, 5, 7, // BACK
8, 9, 10, 10, 9, 11, // LEFT
12, 13, 14, 14, 13, 15, // RIGHT
16, 17, 18, 18, 17, 19, // TOP
20, 21, 22, 22, 21, 23, // BOTTOM
};
private int numFaces = 6;
/**
* Sets up the drawing object data for use in an OpenGL ES context.
*/
public Cube20() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
vertices.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
// initialize byte buffer for the draw list
indexBuffer = ByteBuffer.allocateDirect(indices.length * 2).order(ByteOrder.nativeOrder()).asShortBuffer();
indexBuffer.put(indices).position(0);
// prepare shaders and OpenGL program
int vertexShader = RenderUtils.loadShader(
GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = RenderUtils.loadShader(
GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // create OpenGL program executables
this.rotateDirection = Cube.RotateDirection.NONE;
}
/**
* Encapsulates the OpenGL ES instructions for drawing this shape.
*
* @param mvpMatrix - The Model View Project matrix in which to draw
* this shape.
*/
public void draw(float[] mvpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
GLES20.glFrontFace(GLES20.GL_CCW);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glCullFace(GLES20.GL_BACK);
// scale
float scale_matrix[] = new float[16];
Matrix.setIdentityM(scale_matrix, 0);
Matrix.scaleM(scale_matrix, 0, 0.5f, 0.5f, 1);
Matrix.multiplyMM(mvpMatrix, 0, scale_matrix, 0, mvpMatrix, 0);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
//GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
RenderUtils.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
RenderUtils.checkGlError("glUniformMatrix4fv");
// Render all the faces
for (int face = 0; face < numFaces; face++) {
// Set the color for each of the faces
GLES20.glUniform4fv(mColorHandle, 1, colors[face], 0);
indexBuffer.position(face * 6);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
}
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisable(GLES20.GL_CULL_FACE);
}
}
public class MyGLSurfaceView extends GLSurfaceView {
private volatile MyGLRenderer myGLRenderer;
public MyGLSurfaceView(Context context) {
super(context);
// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2);
myGLRenderer = new MyGLRenderer(context);
setRenderer(myGLRenderer); // Use a custom renderer
setOnTouchListener(new OnSwipeListener(context));
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
}
class OnSwipeListener implements View.OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeListener(Context context) {
this.gestureDetector = new GestureDetector(context, new OnFlingListener());
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return this.gestureDetector.onTouchEvent(event);
}
private class OnFlingListener extends GestureDetector.SimpleOnGestureListener {
private final Object LOCK = new Object();
@Override
public boolean onDown(MotionEvent e) {
return true;
}
/**
* @return true if the event is consumed, else false
*/
@Override
public boolean onFling(MotionEvent down, MotionEvent up, float velocityX, float velocityY) {
//super.onFling(down, up, velocityX, velocityY);
float distanceX = up.getX() - down.getX();
float distanceY = up.getY() - down.getY();
final Cube20 cube = myGLRenderer.getCube();
if (!cube.getRotateDirection().equals(Cube.RotateDirection.NONE)) {
return false;
}
if (Math.abs(distanceX) > Math.abs(distanceY)) {
if (distanceX > 0) {
// RIGHT
cube.setRotation(Cube.RotateDirection.RIGHT);
} else {
// LEFT
cube.setRotation(Cube.RotateDirection.LEFT);
}
} else {
if (distanceY < 0) {
// TOP
cube.setRotation(Cube.RotateDirection.UP);
} else {
// DOWN
cube.setRotation(Cube.RotateDirection.DOWN);
}
}
//requestRender();
return true;
}
}
}
}
public class MyGLRenderer implements GLSurfaceView.Renderer {
Context context; // Application's context
private volatile int rotationAngle;
private volatile float rotateX;
private volatile float rotateY;
private boolean firstRotation = true;
private Cube20 cube;
// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
// Constructor with global application context
public MyGLRenderer(Context context) {
this.context = context;
}
public float getRotateX() {
return rotateX;
}
public void setRotateX(float rotateX) {
this.rotateX = rotateX;
}
public float getRotateY() {
return rotateY;
}
public void setRotateY(float rotateY) {
this.rotateY = rotateY;
}
public float getAngle() {
return rotationAngle;
}
public void setAngle(int angle) {
rotationAngle = angle;
}
// Call back when the surface is first created or re-created
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
this.cube = new Cube20();
}
// Call back to draw the current frame.
@Override
public void onDrawFrame(GL10 gl) {
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -1, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// zoom out a bit
Matrix.translateM(mMVPMatrix, 0, 0, 0, 4.5f);
int angleOffset = 5;
// update the angles for the x and y rotation
if (cube.getRotateDirection().equals(Cube.RotateDirection.LEFT)) {
cube.setAngleY(cube.getAngleY() - angleOffset);
} else if (cube.getRotateDirection().equals(Cube.RotateDirection.RIGHT)) {
cube.setAngleY(cube.getAngleY() + angleOffset);
} else if (cube.getRotateDirection().equals(Cube.RotateDirection.UP)) {
cube.setAngleX(cube.getAngleX() + angleOffset);
} else if (cube.getRotateDirection().equals(Cube.RotateDirection.DOWN)) {
cube.setAngleX(cube.getAngleX() - angleOffset);
}
firstRotation = false;
// rotate and draw
rotate();
cube.draw(mMVPMatrix);
// test if rotation should be stopped (lock in each 90° step)
if (cube.getRotateDirection().equals(Cube.RotateDirection.LEFT) ||
cube.getRotateDirection().equals(Cube.RotateDirection.RIGHT)) {
if (!firstRotation && cube.getAngleY() % 90 == 0) {
cube.setRotation(Cube.RotateDirection.NONE);
}
}
if (cube.getRotateDirection().equals(Cube.RotateDirection.UP) ||
cube.getRotateDirection().equals(Cube.RotateDirection.DOWN)) {
if (!firstRotation && cube.getAngleX() % 90 == 0) {
cube.setRotation(Cube.RotateDirection.NONE);
}
}
Log.i("MyGLRENDER~ ", cube.getRotateDirection().toString());
}
private void rotate() {
float[] rotationMatrix = new float[16];
Matrix.setIdentityM(rotationMatrix, 0);
// rotate in x and y direction, apply that to the intermediate matrix
Matrix.rotateM(rotationMatrix, 0, cube.getAngleX(), 1, 0, 0);
Matrix.rotateM(rotationMatrix, 0, cube.getAngleY(), 0, 1, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mMVPMatrix, 0, rotationMatrix, 0);
}
// Call back after onSurfaceCreated() or whenever the window's size changes
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
public Cube20 getCube() {
return cube;
}
}
public class MyGLActivity extends Activity {
private GLSurfaceView glView; // Use GLSurfaceView
// Call back when the activity is started, to initialize the view
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glView = new MyGLSurfaceView(this); // Allocate a GLSurfaceView
this.setContentView(glView); // This activity sets to GLSurfaceView
}
// Call back when the activity is going into the background
@Override
protected void onPause() {
super.onPause();
glView.onPause();
}
// Call back after onPause()
@Override
protected void onResume() {
super.onResume();
glView.onResume();
}
}
我期望的行为:
使用此设置我遇到以下问题:
MyGLSurfaceView
处的滑动监听器之间可能存在线程问题。和MyGLRenderer
(它保存对立方体的引用)。轮换在 MyGLRenderer.rotate
处完成。立方体使用单独的角度 (x/y),并且还有一个当前已完成旋转的属性(左、右、上、下、无),该属性在 OnSwipeListener
中更新.
我的猜测是角度或 RotateDirection
未正确更新。该应用程序在 OnePlus 3T @ Android 8.0 上进行测试,IDE 为 Android Studio 3.2.1。
最佳答案
如果您将立方体绕 X 轴旋转了 90°,那么绕立方体 Y 轴的旋转当然就是绕世界中的 Z 轴旋转。您必须围绕世界的 Y 轴旋转,而不是围绕立方体的 Y 轴。
为此,您必须将立方体的串联旋转存储在旋转矩阵中,并将新的旋转应用于该矩阵。
创建旋转矩阵的成员:
private final float[] mRotationMatrix = new float[16];
通过单位矩阵初始化:
Matrix.setIdentityM(mRotationMatrix, 0);
在方法rotate
中,您必须将当前动画应用到旋转矩阵。顺序必须是animationMatrix * mRotationMatrix
。矩阵乘法不是commutative 。如果您不遵守乘法的顺序,您将得到与以前相同的结果,并且旋转将围绕立方体的轴而不是围绕世界的轴。
private void rotate() {
float[] animationMatrix = new float[16];
Matrix.setIdentityM(animationMatrix, 0);
// rotate in x and y direction, apply that to the intermediate matrix
Matrix.rotateM(animationMatrix, 0, cube.getAngleX(), 1, 0, 0);
Matrix.rotateM(animationMatrix, 0, cube.getAngleY(), 0, 1, 0);
// concatenate the animation and the rotation matrix; the order is important
Matrix.multiplyMM(animationMatrix, 0, animationMatrix, 0, mRotationMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mMVPMatrix, 0, animationMatrix, 0);
}
当动画达到 90° 时,您必须更改旋转矩阵并重置旋转角度:
if (cube.getRotateDirection().equals(Cube.RotateDirection.LEFT) ||
cube.getRotateDirection().equals(Cube.RotateDirection.RIGHT)) {
if (!firstRotation && cube.getAngleY() % 90 == 0) {
float[] newRotationMatrix = new float[16];
Matrix.setIdentityM(newRotationMatrix, 0);
Matrix.rotateM(newRotationMatrix, 0, cube.getAngleY(), 0, 1, 0);
// concatenate the new 90 rotation to the rotation matrix
Matrix.multiplyMM(mRotationMatrix, 0, newRotationMatrix, 0, mRotationMatrix, 0);
// reset the angle
cube.setAngleY(0);
cube.setRotation(Cube.RotateDirection.NONE);
}
}
if (cube.getRotateDirection().equals(Cube.RotateDirection.UP) ||
cube.getRotateDirection().equals(Cube.RotateDirection.DOWN)) {
if (!firstRotation && cube.getAngleX() % 90 == 0) {
float[] newRotationMatrix = new float[16];
Matrix.setIdentityM(newRotationMatrix, 0);
Matrix.rotateM(newRotationMatrix, 0, cube.getAngleX(), 1, 0, 0);
// concatenate the new 90 rotation to the rotation matrix
Matrix.multiplyMM(mRotationMatrix, 0, newRotationMatrix, 0, mRotationMatrix, 0);
// reset the angle
cube.setAngleX(0);
cube.setRotation(Cube.RotateDirection.NONE);
}
}
关于java - OpenGL ES 2.0 Android - 立方体旋转错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53349892/
在 settings.py LANGUAGE_CODE = 'es-mx'或 LANGUAGE_CODE = 'es-ar'不起作用,但是 LANGUAGE_CODE = 'es'或 LANGUAGE
我想知道OpenGL ES 2.0和OpenGL ES 3.0之间有什么区别。 OpenGL ES 3.0的主要优点是什么? 最佳答案 总体而言,这些变化通过更大的缓冲区、更多的格式、更多的统一等提高
这是我为此端点使用 Postman localhost:9201/response_v2_862875ee3a88a6d09c95bdbda029ce2b/_search 的请求正文 { "_sour
OpenGL ES 2.0 没有 ES 1.0 那样的 GL_POINT_SMOOTH 定义。这意味着我用来绘制圆圈的代码不再有效: glEnable(GL_POINT_SMOOTH); glPoin
我尝试编译这个着色器: varying vec2 TexCoords; varying vec4 color; uniform sampler2D text; uniform vec3 textCol
我是 OpenGL ES 的新手,我使用的是 OpenGL ES 2.0 版本。我可以在片段着色器中使用按位操作(右移、左移)吗? 最佳答案 OpenGL ES 2.0 没有按位运算符。 ES 3.0
有没有办法只用线画一个三角形? 我认为GL_TRIANGLES选项可使三角形充满颜色。 最佳答案 使用glPolygonMode(face, model)设置填充模式: glPolygonMode(G
我想用一个包含 yuv 数据的采样器在 opengl es 着色器中将 yuv 转换为 rgb。我的代码如下: 1)我将 yuv 数据发送到纹理: GLES20.glTexImage2D(GLES20
我正在使用这样的域: http://www.domain.com/es/blabla.html 我想更改 .es 的/es 部分并将 URLS 转换为类似以下内容: http://www.domain
有谁知道OpenGL ES是否支持GL_TEXTURE_RECTANGLE?我计划将它用于 2D 图形以支持非二次幂图像。我当前的实现使用 alpha=0 填充的 POT 纹理,对于拉伸(stretc
我需要在具有 PowerVR SGX 硬件的 ARM 设备上实现离屏纹理渲染。 一切都完成了(使用了像素缓冲区和 OpenGL ES 2.0 API)。唯一 Unresolved 问题是速度很慢glR
这是一个奇怪的事情。我有一个片段着色器,据我所知只能返回黑色或红色,但它将像素渲染为白色。如果我删除一根特定的线,它会返回我期望的颜色。它适用于 WebGL,但不适用于 Raspberry Pi 上的
我正在考虑将一些 OpenGL 代码移植到 OpenGL ES 并且想知道这段代码到底做了什么: glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT) 因为 g
我正在考虑将一些 OpenGL 代码移植到 OpenGL ES 并且想知道这段代码到底做了什么: glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT) 因为 g
GLSL ES最多可以编译多少个程序?所以假设我创建了 100 个片段着色器,每个都有不同的效果。所以在运行时我编译所有这些并动态地我用 glUseProgram 交换它们。我假设每次我编译一个新的
我正在尝试使用顶点缓冲区对象来绘制圆,并在 iPhone 上的 OpenGL ES 2.0 中启用 GL_POINT_SMOOTH 来绘制点。 我使用以下 ES 1.0 渲染代码在 iPhone 4
为什么在 OpenGL ES 1.x 中缩放(均匀)对象会导致对象变轻? 更有意义的是它会更暗,因为法线被缩小是否也会使对象更暗?但由于某种原因,物体变轻了。当我放大时,对象变得更暗。在我看来,这应该
我正在尝试通过移植 some code 在 iOS 上的 OpenGL ES 2.0 中获得一些阴影效果。来自标准 GL。部分示例涉及将深度缓冲区复制到纹理: glBindTexture(GL_TEX
所以我正在使用 2D 骨骼动画系统。 有 X 个骨骼,每个骨骼至少有 1 个部分(一个四边形,两个三角形)。平均而言,我可能有 20 块骨头和 30 个部分。大多数骨骼都依赖于父骨骼,骨骼会每帧移动。
我在使用 ES 着色器时遇到了一些晦涩难懂的问题,而且我现在几乎没有想法了。 这是一些代码: .. precision mediump float; .. #define STEP (1f/6f) 5
我是一名优秀的程序员,十分优秀!