private void DrawLabel(float[] cameraViews, float[] cameraProjection) { ShaderUtil.CheckGlError(TAG, "Draw label start."); Matrix.MultiplyMM(modelViewMatrix, 0, cameraViews, 0, modelMatrix, 0); Matrix.MultiplyMM(modelViewProjectionMatrix, 0, cameraProjection, 0, modelViewMatrix, 0); float halfWidth = LABEL_WIDTH / 2.0f; float halfHeight = LABEL_HEIGHT / 2.0f; float[] vertices = { -halfWidth, -halfHeight, 1, -halfWidth, halfHeight, 1, halfWidth, halfHeight, 1, halfWidth, -halfHeight, 1, }; // The size of each floating point is 4 bits. FloatBuffer vetBuffer = ByteBuffer.AllocateDirect(4 * vertices.Length) .Order(ByteOrder.NativeOrder()).AsFloatBuffer(); vetBuffer.Rewind(); for (int i = 0; i < vertices.Length; ++i) { vetBuffer.Put(vertices[i]); } vetBuffer.Rewind(); // The size of each floating point is 4 bits. GLES20.GlVertexAttribPointer(glPositionParameter, COORDS_PER_VERTEX, GLES20.GlFloat, false, 4 * COORDS_PER_VERTEX, vetBuffer); // Set the sequence of OpenGL drawing points to generate two triangles that form a plane. short[] indices = { 0, 1, 2, 0, 2, 3 }; // Size of the allocated buffer. ShortBuffer idxBuffer = ByteBuffer.AllocateDirect(2 * indices.Length) .Order(ByteOrder.NativeOrder()).AsShortBuffer(); idxBuffer.Rewind(); for (int i = 0; i < indices.Length; ++i) { idxBuffer.Put(indices[i]); } idxBuffer.Rewind(); GLES20.GlUniformMatrix4fv(glModelViewProjectionMatrix, 1, false, modelViewProjectionMatrix, 0); GLES20.GlDrawElements(GLES20.GlTriangleStrip, idxBuffer.Limit(), GLES20.GlUnsignedShort, idxBuffer); ShaderUtil.CheckGlError(TAG, "Draw label end."); }
/// <summary> /// Converts a plane polygon from ARCore into a <see cref="Vector3"/> array. /// </summary> /// <param name="buffer">The float buffer containing 2D vertices of the polygon</param> /// <param name="waveVectorArray">The <see cref="Vector3"/> array with the 3D vertices of the polygon</param> public static void ToWave(this FloatBuffer buffer, ref Vector3[] waveVectorArray) { buffer.Rewind(); var boundaryVertices = buffer.Limit() / 2; if (waveVectorArray == null) { waveVectorArray = new Vector3[boundaryVertices]; } else if (waveVectorArray.Length != boundaryVertices) { Array.Resize(ref waveVectorArray, boundaryVertices); } for (int i = 0; i < boundaryVertices; i++) { waveVectorArray[i].X = buffer.Get(); waveVectorArray[i].Z = buffer.Get(); } }
/** * Updates the plane model transform matrix and extents. */ private void updatePlaneParameters(float[] planeMatrix, float extentX, float extentZ, FloatBuffer boundary) { Array.Copy(planeMatrix, 0, mModelMatrix, 0, 16); if (boundary == null) { mVertexBuffer.Limit(0); mIndexBuffer.Limit(0); return; } // Generate a new set of vertices and a corresponding triangle strip index set so that // the plane boundary polygon has a fading edge. This is done by making a copy of the // boundary polygon vertices and scaling it down around center to push it inwards. Then // the index buffer is setup accordingly. boundary.Rewind(); int boundaryVertices = boundary.Limit() / 2; int numVertices; int numIndices; numVertices = boundaryVertices * VERTS_PER_BOUNDARY_VERT; // drawn as GL_TRIANGLE_STRIP with 3n-2 triangles (n-2 for fill, 2n for perimeter). numIndices = boundaryVertices * INDICES_PER_BOUNDARY_VERT; if (mVertexBuffer.Capacity() < numVertices * COORDS_PER_VERTEX) { int size = mVertexBuffer.Capacity(); while (size < numVertices * COORDS_PER_VERTEX) { size *= 2; } mVertexBuffer = ByteBuffer.AllocateDirect(BYTES_PER_FLOAT * size) .Order(ByteOrder.NativeOrder()).AsFloatBuffer(); } mVertexBuffer.Rewind(); mVertexBuffer.Limit(numVertices * COORDS_PER_VERTEX); if (mIndexBuffer.Capacity() < numIndices) { int size = mIndexBuffer.Capacity(); while (size < numIndices) { size *= 2; } mIndexBuffer = ByteBuffer.AllocateDirect(BYTES_PER_SHORT * size) .Order(ByteOrder.NativeOrder()).AsShortBuffer(); } mIndexBuffer.Rewind(); mIndexBuffer.Limit(numIndices); // Note: when either dimension of the bounding box is smaller than 2*FADE_RADIUS_M we // generate a bunch of 0-area triangles. These don't get rendered though so it works // out ok. float xScale = Math.Max((extentX - 2 * FADE_RADIUS_M) / extentX, 0.0f); float zScale = Math.Max((extentZ - 2 * FADE_RADIUS_M) / extentZ, 0.0f); while (boundary.HasRemaining) { float x = boundary.Get(); float z = boundary.Get(); mVertexBuffer.Put(x); mVertexBuffer.Put(z); mVertexBuffer.Put(0.0f); mVertexBuffer.Put(x * xScale); mVertexBuffer.Put(z * zScale); mVertexBuffer.Put(1.0f); } // step 1, perimeter mIndexBuffer.Put((short)((boundaryVertices - 1) * 2)); for (int i = 0; i < boundaryVertices; ++i) { mIndexBuffer.Put((short)(i * 2)); mIndexBuffer.Put((short)(i * 2 + 1)); } mIndexBuffer.Put((short)1); // This leaves us on the interior edge of the perimeter between the inset vertices // for boundary verts n-1 and 0. // step 2, interior: for (int i = 1; i < boundaryVertices / 2; ++i) { mIndexBuffer.Put((short)((boundaryVertices - 1 - i) * 2 + 1)); mIndexBuffer.Put((short)(i * 2 + 1)); } if (boundaryVertices % 2 != 0) { mIndexBuffer.Put((short)((boundaryVertices / 2) * 2 + 1)); } }