Я возился с HelloAR Xamarin sample .В настоящее время я работаю с некоторыми 2D-фигурами и пытаюсь привязать треугольник к якору.Это в основном работает , при включении телефона треугольник, кажется, прилипает к своему якору, а при движении вперед и назад треугольник сжимается и растет.Тем не менее, при перемещении телефона (т. Е. При перемещении себя вбок параллельно стороне треугольника) треугольник слегка перемещается в том же направлении, что и камера.Точно так же, перемещаясь назад и вперед, треугольник действительно перемещается вверх и вниз в сцене.Вот несколько рисунков, которые показывают, что происходит (добавленные мной вертикальные линии):
![enter image description here](https://i.stack.imgur.com/pOLJY.png)
Как видно из рисунков, по мере продвижения кслева треугольник медленно ползет к боковой части ноутбука, а также медленно исчезает из рамки.Я чувствую, что мой код очень похож на ObjectRenderer.cs , использованный в исходном примере.Вот мои эквиваленты updateModelMatrix
, CreateOnGlThread
и Draw
:
public void updateModelMatrix(float[] modelMatrix, float scaleFactor) {
float[] scaleMatrix = new float[16];
Android.Opengl.Matrix.SetIdentityM(scaleMatrix, 0);
scaleMatrix[0] = scaleFactor;
scaleMatrix[5] = scaleFactor;
scaleMatrix[10] = scaleFactor;
Android.Opengl.Matrix.MultiplyMM(mViewMatrix, 0, modelMatrix, 0, scaleMatrix, 0);
}
public void CreateOnGlThread(Context _context) {
vertexBuffer = ByteBuffer
.AllocateDirect(triangleCords.Length * BYTES_PER_FLOAT).Order(ByteOrder.NativeOrder())
.AsFloatBuffer();
vertexBuffer.Put(triangleCords).Position(0);
indices = ByteBuffer.AllocateDirect(BYTES_PER_SHORT * triangleIndices.Length)
.Order(ByteOrder.NativeOrder()).AsShortBuffer();
indices.Put(triangleIndices).Position(0);
int[] buffers = new int[2];
GLES20.GlGenBuffers(2, buffers, 0);
mVertexBufferId = buffers[0];
mIndexBufferId = buffers[1];
GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId);
GLES20.GlBufferData(GLES20.GlArrayBuffer, triangleCords.Length * BYTES_PER_FLOAT, vertexBuffer, GLES20.GlStaticDraw);
GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId);
GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId);
mIndexCount = triangleIndices.Length;
GLES20.GlBufferData(
GLES20.GlElementArrayBuffer, BYTES_PER_SHORT * mIndexCount, indices, GLES20.GlStaticDraw);
GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId);
int vertexShader = loadShader(GLES20.GlVertexShader, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GlFragmentShader, fragmentShaderCode);
program = GLES20.GlCreateProgram();
GLES20.GlAttachShader(program, vertexShader);
GLES20.GlAttachShader(program, fragmentShader);
GLES20.GlLinkProgram(program);
positionHandle = GLES20.GlGetAttribLocation(program, "a_Position");
colorHandle = GLES20.GlGetUniformLocation(program, "vColor");
mModerViewMatrixHandle = GLES20.GlGetUniformLocation(program, "u_ModelView");
mModelViewProjectionMatrixHandle = GLES20.GlGetUniformLocation(program, "u_ModelViewProjection");
Android.Opengl.Matrix.SetIdentityM(mViewMatrix, 0);
}
public void Draw(float[] _cameraView, float[] _cameraPerspective) {
Android.Opengl.Matrix.MultiplyMM(mModelViewMatrix, 0, _cameraView, 0, mViewMatrix, 0);
Android.Opengl.Matrix.MultiplyMM(mModelViewProjectionMatrix, 0, _cameraPerspective, 0, mModelViewMatrix, 0);
GLES20.GlUseProgram(program);
GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId);
GLES20.GlVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GlFloat, false, 0, 0);
GLES20.GlEnableVertexAttribArray(positionHandle);
GLES20.GlUniform4fv(colorHandle, 1, COLOR, 0);
GLES20.GlUniformMatrix4fv(mModerViewMatrixHandle, 1, false, mModelViewMatrix, 0);
GLES20.GlUniformMatrix4fv(mModelViewProjectionMatrixHandle, 1, false, mModelViewProjectionMatrix, 0);
GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId);
GLES20.GlDrawElements(GLES20.GlTriangles, mIndexCount, GLES20.GlUnsignedShort, 0);
GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0);
GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0);
}
Параметры, передаваемые в эти функции из GLSurfaceView.IRenderer.OnDrawFrame
, не должны отличаться от параметров исходного образца:
void GLSurfaceView.IRenderer.OnDrawFrame(IGL10 gl)
{
...
try {
Frame frame = session.Update();
Camera camera = frame.Camera;
...
if (tap != null && camera.TrackingState == TrackingState.Tracking) {
foreach (var hit in frame.HitTest(tap)) {
var trackable = hit.Trackable;
if (trackable is Plane && ((Plane)trackable).IsPoseInPolygon(hit.HitPose)) {
shapeAnchor = hit.CreateAnchor();
break;
}
}
}
backgroundRenderer.Draw(frame);
if (shapeAnchor != null && shapeAnchor.TrackingState == TrackingState.Tracking) {
float[] projmtx = new float[16];
camera.GetProjectionMatrix(projmtx, 0, 0.1f, 100.0f);
float[] viewmtx = new float[16];
camera.GetViewMatrix(viewmtx, 0);
shapeAnchor.Pose.ToMatrix(anchorMatrix, 0);
triangleRenderer.updateModelMatrix(anchorMatrix, 1);
triangleRenderer.Draw(viewmtx, projmtx);
}
} catch (Exception _ex) {
var x = true;
}
}
Кроме того, мой вершинный шейдер довольно прост:
private string vertexShaderCode =
"uniform mat4 u_ModelView;" +
"uniform mat4 u_ModelViewProjection;" +
"attribute vec4 a_Position;" +
"varying vec3 v_ViewPosition;" +
"void main() {" +
" v_ViewPosition = (u_ModelView * a_Position).xyz;" +
" gl_Position = u_ModelViewProjection * a_Position;" +
"}";
Тот факт, что в конечном итоге он выходит за рамки, немного озадачивает меня, определенно что-то не так с тем, какЯ использую матрицы при переходе на 2D-объекты.Есть идеи?