Anonymous
При преобразовании из android.graphics.Matrix в android.opengl.Matrix возникли некоторые проблемы
Сообщение
Anonymous » 15 июл 2024, 09:01
Когда я пытаюсь масштабировать, изображение сразу перемещается в верхний левый угол, а затем увеличивается и панорамируется. Это мой код.
Ссылка для снимка
Код: Выделить всё
import android.content.Context;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.Matrix;
import android.util.Log;
import android.view.MotionEvent;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
public class NewOneCylinder180Image extends ObjectInterface {
private final String vertexShaderCode =
"attribute vec4 v_Position;" +
"attribute vec2 a_TexCoord;" +
"uniform mat4 u_TransformMatrix;"+
"varying vec2 vTexCoord;" +
"void main() {" +
" vec4 zoomedPos = u_TransformMatrix * v_Position;\n" +
" gl_Position = zoomedPos;" +
" vTexCoord = a_TexCoord;" +
"}";
private final String fragmentShaderCode =
"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;" +
"varying vec2 vTexCoord;"+
"uniform float u_Offset;"+
"uniform samplerExternalOES uTexture;" +
"void main()" +
"{" +
"highp vec4 texel0;" +
"vec2 uv = vTexCoord;" +
"uv.x = mod(uv.x + u_Offset, 1.0);" +
"float r = 0.1 + uv.y * 0.79;" +
"float theta = 2.0 * 3.14159265 * (uv.x - 0.5);" +
"vec2 newCoord = vec2(0.5, 0.5) + r * vec2(cos(theta), sin(theta));" +
"texel0 = texture2D(uTexture, newCoord);" +
"gl_FragColor = texel0;" +
"}";
private int mProgram;
private FloatBuffer vertexBuffer;
private FloatBuffer texCoordBuffer;
private ShortBuffer indexBuffer;
private int textureId;
private int viewWidth = 0, viewHeight = 0;
private int[] viewport;
float[] transformMatrix = new float[16];
private float offset = 0.0f;
private float[] vertices = {
-1f, -1f,
1f, -1f,
-1f, 1f,
1f, 1f
};
private float[] texCoords = {
0.5f, 0f,
1.0f, 0f,
0.5f, 0.51f,
1.0f, 0.51f
};
private short[] indices = {
0, 1, 2,
1, 3, 2
};
public void setViewport(int[] viewport) {
this.viewport = viewport;
}
public void setWidthHeight(int width, int height) {
this.viewWidth = width;
this.viewHeight = height;
}
public void setImageId(int id) {
this.textureId = id;
}
public NewOneCylinder180Image(Context context) {
this.mContext = context;
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertices);
vertexBuffer.position(0);
texCoordBuffer = ByteBuffer.allocateDirect(texCoords.length * 4)
.order(ByteOrder.nativeOrder()).asFloatBuffer().put(texCoords);
texCoordBuffer.position(0);
indexBuffer = ByteBuffer.allocateDirect(indices.length * 2)
.order(ByteOrder.nativeOrder()).asShortBuffer().put(indices);
indexBuffer.position(0);
Matrix.setIdentityM(transformMatrix, 0);
}
public void draw() {
GLES20.glUseProgram(mProgram);
GLES20.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
// Bind texture
int textureHandle = GLES20.glGetUniformLocation(mProgram, "uTexture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
GLES20.glUniform1i(textureHandle, 0);
// Setup vertex and texture coordinates
int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "v_Position");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer);
int mTextureHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoord");
GLES20.glEnableVertexAttribArray(mTextureHandle);
GLES20.glVertexAttribPointer(mTextureHandle, 2, GLES20.GL_FLOAT, false, 0, texCoordBuffer);
int uOffsetLocation = GLES20.glGetUniformLocation(mProgram, "u_Offset");
GLES20.glUniform1f(uOffsetLocation, offset);
int uTransformMatrixLocation = GLES20.glGetUniformLocation(mProgram, "u_TransformMatrix");
GLES20.glUniformMatrix4fv(uTransformMatrixLocation, 1, false, transformMatrix, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTextureHandle);
}
private android.graphics.Matrix matrix = new android.graphics.Matrix();
private float mScaleFactorHeight = 1.f;
private float mScaleFactorWidth = 1.f;
private float windowFocusX = 0.f;
private float windowFocusY = 0.f;
private float translateX = 0f;
private float translateY = 0f;
private float textureViewRatioX = 0f;
private float textureViewRatioY = 0f;
private float getTranslateX(float scaledTextureViewFocusX) {
translateX = windowFocusX - scaledTextureViewFocusX;
float minTranslateX = (1f - mScaleFactorWidth) * viewWidth;
if (translateX < minTranslateX) {
translateX = minTranslateX;
windowFocusX = translateX + scaledTextureViewFocusX;
}
if (translateX > 0) {
translateX = 0;
windowFocusX = translateX + scaledTextureViewFocusX;
}
return translateX;
}
private float getTranslateY(float scaledTextureViewFocusY) {
translateY = windowFocusY - scaledTextureViewFocusY;
float minTranslateY = (1f - mScaleFactorHeight) * viewHeight;
if (translateY < minTranslateY) {
translateY = minTranslateY;
windowFocusY = translateY + scaledTextureViewFocusY;
}
if (translateY > 0) {
translateY = 0;
windowFocusY = translateY + scaledTextureViewFocusY;
}
return translateY;
}
private float normalizeTranslateX(float x) {
float translateX = (x - (viewWidth / 2f)) / (viewWidth / 2f);
if (x < viewWidth / 2f) {
translateX = -1f + (x / (viewWidth / 2f));
}
return translateX;
}
private float normalizeTranslateY(float y) {
float translateY = -(y - (viewHeight / 2f)) / (viewHeight / 2f);
if (y < viewHeight / 2f) {
translateY = 1f - (y / (viewHeight / 2f));
}
return translateY;
}
private void setTransformations() {
float scaledTextureViewFocusX = (viewWidth * mScaleFactorWidth * textureViewRatioX) ;
float scaledTextureViewFocusY = (viewHeight * mScaleFactorHeight * textureViewRatioY) ;
matrix.reset();
matrix.setScale(mScaleFactorWidth, mScaleFactorHeight);
multiRatio = 1f;
matrix.postTranslate(getTranslateX(scaledTextureViewFocusX), getTranslateY(scaledTextureViewFocusY));
float[] androidMatrixValues = new float[9];
matrix.getValues(androidMatrixValues);
float scaleX = androidMatrixValues[android.graphics.Matrix.MSCALE_X];
float scaleY = androidMatrixValues[android.graphics.Matrix.MSCALE_Y];
float translateX1 = normalizeTranslateX(androidMatrixValues[2]); // have issues.
float translateY1 = normalizeTranslateY(androidMatrixValues[5]); // have issues.
float[] openGLMatrix = new float[] {
scaleX, 0f, 0f, 0f,
0f, scaleY, 0f, 0f,
0f, 0f, 1f, 0f,
translateX1, translateY1, 0f, 1f
};
Matrix.setIdentityM(transformMatrix, 0);
Matrix.multiplyMM(transformMatrix, 0, transformMatrix, 0, openGLMatrix, 0);
}
private int count = 0;
private int pointerIndex = 0;
private float lastDis = 0f;
private boolean isScaleBegin = false;
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
@Override
public void onTouchEvent(MotionEvent event) {
int touchCount = event.getPointerCount();
int index = event.getActionIndex();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
if (touchCount >= 2 && !isScaleBegin) {
isScaleBegin = true;
lastDis = spacing(event);
windowFocusX = (event.getX(1) + event.getX(0)) / 2;
windowFocusY = (event.getY(1) + event.getY(0)) / 2;
textureViewRatioX = (windowFocusX - translateX) / (viewWidth * mScaleFactorWidth);
textureViewRatioY = (windowFocusY - translateY) / (viewHeight * mScaleFactorHeight);
}
case MotionEvent.ACTION_MOVE:
if (touchCount >= 2 && isScaleBegin) {
float dist = spacing(event);
float scale = dist / lastDis;
float tempWidth = mScaleFactorWidth * scale;
lastDis = dist;
if(tempWidth > 30f) {
return;
}
mScaleFactorWidth = tempWidth;
mScaleFactorWidth = Math.max(1.f, Math.min(mScaleFactorWidth, 30f));
mScaleFactorHeight *= scale;
mScaleFactorHeight = Math.max(1.f, Math.min(mScaleFactorHeight, 30f));
setTransformations();
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
isScaleBegin = false;
lastDis = 0f;
break;
}
}
}
Я надеюсь добиться тех же функций масштабирования и панорамирования с помощью android.graphics.Matrix, что и при непосредственном использовании TextView. В настоящее время использование TextureView с android.graphics.Matrix работает должным образом, но я столкнулся с этой проблемой при преобразовании в координаты OpenGL. Поэтому я ищу здесь помощь в виде предложений или идей.
Подробнее здесь:
https://stackoverflow.com/questions/787 ... ome-issues
1721023287
Anonymous
Когда я пытаюсь масштабировать, изображение сразу перемещается в верхний левый угол, а затем увеличивается и панорамируется. Это мой код. Ссылка для снимка [code]import android.content.Context; import android.opengl.GLES11Ext; import android.opengl.GLES20; import android.opengl.Matrix; import android.util.Log; import android.view.MotionEvent; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; public class NewOneCylinder180Image extends ObjectInterface { private final String vertexShaderCode = "attribute vec4 v_Position;" + "attribute vec2 a_TexCoord;" + "uniform mat4 u_TransformMatrix;"+ "varying vec2 vTexCoord;" + "void main() {" + " vec4 zoomedPos = u_TransformMatrix * v_Position;\n" + " gl_Position = zoomedPos;" + " vTexCoord = a_TexCoord;" + "}"; private final String fragmentShaderCode = "#extension GL_OES_EGL_image_external : require\n" + "precision mediump float;" + "varying vec2 vTexCoord;"+ "uniform float u_Offset;"+ "uniform samplerExternalOES uTexture;" + "void main()" + "{" + "highp vec4 texel0;" + "vec2 uv = vTexCoord;" + "uv.x = mod(uv.x + u_Offset, 1.0);" + "float r = 0.1 + uv.y * 0.79;" + "float theta = 2.0 * 3.14159265 * (uv.x - 0.5);" + "vec2 newCoord = vec2(0.5, 0.5) + r * vec2(cos(theta), sin(theta));" + "texel0 = texture2D(uTexture, newCoord);" + "gl_FragColor = texel0;" + "}"; private int mProgram; private FloatBuffer vertexBuffer; private FloatBuffer texCoordBuffer; private ShortBuffer indexBuffer; private int textureId; private int viewWidth = 0, viewHeight = 0; private int[] viewport; float[] transformMatrix = new float[16]; private float offset = 0.0f; private float[] vertices = { -1f, -1f, 1f, -1f, -1f, 1f, 1f, 1f }; private float[] texCoords = { 0.5f, 0f, 1.0f, 0f, 0.5f, 0.51f, 1.0f, 0.51f }; private short[] indices = { 0, 1, 2, 1, 3, 2 }; public void setViewport(int[] viewport) { this.viewport = viewport; } public void setWidthHeight(int width, int height) { this.viewWidth = width; this.viewHeight = height; } public void setImageId(int id) { this.textureId = id; } public NewOneCylinder180Image(Context context) { this.mContext = context; int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); mProgram = GLES20.glCreateProgram(); GLES20.glAttachShader(mProgram, vertexShader); GLES20.glAttachShader(mProgram, fragmentShader); GLES20.glLinkProgram(mProgram); vertexBuffer = ByteBuffer.allocateDirect(vertices.length * 4) .order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertices); vertexBuffer.position(0); texCoordBuffer = ByteBuffer.allocateDirect(texCoords.length * 4) .order(ByteOrder.nativeOrder()).asFloatBuffer().put(texCoords); texCoordBuffer.position(0); indexBuffer = ByteBuffer.allocateDirect(indices.length * 2) .order(ByteOrder.nativeOrder()).asShortBuffer().put(indices); indexBuffer.position(0); Matrix.setIdentityM(transformMatrix, 0); } public void draw() { GLES20.glUseProgram(mProgram); GLES20.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); // Bind texture int textureHandle = GLES20.glGetUniformLocation(mProgram, "uTexture"); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId); GLES20.glUniform1i(textureHandle, 0); // Setup vertex and texture coordinates int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "v_Position"); GLES20.glEnableVertexAttribArray(mPositionHandle); GLES20.glVertexAttribPointer(mPositionHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer); int mTextureHandle = GLES20.glGetAttribLocation(mProgram, "a_TexCoord"); GLES20.glEnableVertexAttribArray(mTextureHandle); GLES20.glVertexAttribPointer(mTextureHandle, 2, GLES20.GL_FLOAT, false, 0, texCoordBuffer); int uOffsetLocation = GLES20.glGetUniformLocation(mProgram, "u_Offset"); GLES20.glUniform1f(uOffsetLocation, offset); int uTransformMatrixLocation = GLES20.glGetUniformLocation(mProgram, "u_TransformMatrix"); GLES20.glUniformMatrix4fv(uTransformMatrixLocation, 1, false, transformMatrix, 0); GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer); GLES20.glDisableVertexAttribArray(mPositionHandle); GLES20.glDisableVertexAttribArray(mTextureHandle); } private android.graphics.Matrix matrix = new android.graphics.Matrix(); private float mScaleFactorHeight = 1.f; private float mScaleFactorWidth = 1.f; private float windowFocusX = 0.f; private float windowFocusY = 0.f; private float translateX = 0f; private float translateY = 0f; private float textureViewRatioX = 0f; private float textureViewRatioY = 0f; private float getTranslateX(float scaledTextureViewFocusX) { translateX = windowFocusX - scaledTextureViewFocusX; float minTranslateX = (1f - mScaleFactorWidth) * viewWidth; if (translateX < minTranslateX) { translateX = minTranslateX; windowFocusX = translateX + scaledTextureViewFocusX; } if (translateX > 0) { translateX = 0; windowFocusX = translateX + scaledTextureViewFocusX; } return translateX; } private float getTranslateY(float scaledTextureViewFocusY) { translateY = windowFocusY - scaledTextureViewFocusY; float minTranslateY = (1f - mScaleFactorHeight) * viewHeight; if (translateY < minTranslateY) { translateY = minTranslateY; windowFocusY = translateY + scaledTextureViewFocusY; } if (translateY > 0) { translateY = 0; windowFocusY = translateY + scaledTextureViewFocusY; } return translateY; } private float normalizeTranslateX(float x) { float translateX = (x - (viewWidth / 2f)) / (viewWidth / 2f); if (x < viewWidth / 2f) { translateX = -1f + (x / (viewWidth / 2f)); } return translateX; } private float normalizeTranslateY(float y) { float translateY = -(y - (viewHeight / 2f)) / (viewHeight / 2f); if (y < viewHeight / 2f) { translateY = 1f - (y / (viewHeight / 2f)); } return translateY; } private void setTransformations() { float scaledTextureViewFocusX = (viewWidth * mScaleFactorWidth * textureViewRatioX) ; float scaledTextureViewFocusY = (viewHeight * mScaleFactorHeight * textureViewRatioY) ; matrix.reset(); matrix.setScale(mScaleFactorWidth, mScaleFactorHeight); multiRatio = 1f; matrix.postTranslate(getTranslateX(scaledTextureViewFocusX), getTranslateY(scaledTextureViewFocusY)); float[] androidMatrixValues = new float[9]; matrix.getValues(androidMatrixValues); float scaleX = androidMatrixValues[android.graphics.Matrix.MSCALE_X]; float scaleY = androidMatrixValues[android.graphics.Matrix.MSCALE_Y]; float translateX1 = normalizeTranslateX(androidMatrixValues[2]); // have issues. float translateY1 = normalizeTranslateY(androidMatrixValues[5]); // have issues. float[] openGLMatrix = new float[] { scaleX, 0f, 0f, 0f, 0f, scaleY, 0f, 0f, 0f, 0f, 1f, 0f, translateX1, translateY1, 0f, 1f }; Matrix.setIdentityM(transformMatrix, 0); Matrix.multiplyMM(transformMatrix, 0, transformMatrix, 0, openGLMatrix, 0); } private int count = 0; private int pointerIndex = 0; private float lastDis = 0f; private boolean isScaleBegin = false; private float spacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(x * x + y * y); } @Override public void onTouchEvent(MotionEvent event) { int touchCount = event.getPointerCount(); int index = event.getActionIndex(); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: if (touchCount >= 2 && !isScaleBegin) { isScaleBegin = true; lastDis = spacing(event); windowFocusX = (event.getX(1) + event.getX(0)) / 2; windowFocusY = (event.getY(1) + event.getY(0)) / 2; textureViewRatioX = (windowFocusX - translateX) / (viewWidth * mScaleFactorWidth); textureViewRatioY = (windowFocusY - translateY) / (viewHeight * mScaleFactorHeight); } case MotionEvent.ACTION_MOVE: if (touchCount >= 2 && isScaleBegin) { float dist = spacing(event); float scale = dist / lastDis; float tempWidth = mScaleFactorWidth * scale; lastDis = dist; if(tempWidth > 30f) { return; } mScaleFactorWidth = tempWidth; mScaleFactorWidth = Math.max(1.f, Math.min(mScaleFactorWidth, 30f)); mScaleFactorHeight *= scale; mScaleFactorHeight = Math.max(1.f, Math.min(mScaleFactorHeight, 30f)); setTransformations(); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: isScaleBegin = false; lastDis = 0f; break; } } } [/code] Я надеюсь добиться тех же функций масштабирования и панорамирования с помощью android.graphics.Matrix, что и при непосредственном использовании TextView. В настоящее время использование TextureView с android.graphics.Matrix работает должным образом, но я столкнулся с этой проблемой при преобразовании в координаты OpenGL. Поэтому я ищу здесь помощь в виде предложений или идей. Подробнее здесь: [url]https://stackoverflow.com/questions/78748166/convert-from-android-graphics-matrix-to-android-opengl-matrix-have-some-issues[/url]