我一直在修补HelloAR Xamarin sample。目前,我正在处理某些2D形状,并且尝试将三角形绑定到锚点。 大多数情况下,当我将手机放到适当的位置时,三角形似乎固定在其锚点上,并且在来回移动时三角形会收缩并增大。但是,在移动电话时(即:使自己与三角形的侧面平行地向侧面移动),三角形沿与相机相同的方向稍微移动。同样,在来回移动时,三角形确实会在场景中上下移动。这是一些显示正在发生的事情的图片(我添加了垂直线):
从图片中可以看到,当我向左移动时,三角形正缓慢地爬到笔记本电脑的侧面,同时也逐渐从框架中消失。我觉得我的代码与原始示例中使用的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对象时我使用矩阵的方式肯定存在问题。有什么想法吗?