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."); }
/** * Creates and initializes OpenGL resources needed for rendering the model. * * @param context Context for loading the shader and below-named model and texture assets. * @param objAssetName Name of the OBJ file containing the model geometry. * @param diffuseTextureAssetName Name of the PNG file containing the diffuse texture map. */ public void CreateOnGlThread(Context context, string objAssetName, string diffuseTextureAssetName) { // Read the texture. var textureBitmap = BitmapFactory.DecodeStream(context.Assets.Open(diffuseTextureAssetName)); GLES20.GlActiveTexture(GLES20.GlTexture0); GLES20.GlGenTextures(mTextures.Length, mTextures, 0); GLES20.GlBindTexture(GLES20.GlTexture2d, mTextures[0]); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMinFilter, GLES20.GlLinearMipmapLinear); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMagFilter, GLES20.GlLinear); GLUtils.TexImage2D(GLES20.GlTexture2d, 0, textureBitmap, 0); GLES20.GlGenerateMipmap(GLES20.GlTexture2d); GLES20.GlBindTexture(GLES20.GlTexture2d, 0); textureBitmap.Recycle(); ShaderUtil.CheckGLError(TAG, "Texture loading"); // Read the obj file. var objInputStream = context.Assets.Open(objAssetName); var obj = ObjReader.Read(objInputStream); // Prepare the Obj so that its structure is suitable for // rendering with OpenGL: // 1. Triangulate it // 2. Make sure that texture coordinates are not ambiguous // 3. Make sure that normals are not ambiguous // 4. Convert it to single-indexed data obj = ObjUtils.ConvertToRenderable(obj); // OpenGL does not use Java arrays. ByteBuffers are used instead to provide data in a format // that OpenGL understands. // Obtain the data from the OBJ, as direct buffers: IntBuffer wideIndices = ObjData.GetFaceVertexIndices(obj, 3); FloatBuffer vertices = ObjData.GetVertices(obj); FloatBuffer texCoords = ObjData.GetTexCoords(obj, 2); FloatBuffer normals = ObjData.GetNormals(obj); // Convert int indices to shorts for GL ES 2.0 compatibility ShortBuffer indices = ByteBuffer.AllocateDirect(2 * wideIndices.Limit()) .Order(ByteOrder.NativeOrder()).AsShortBuffer(); while (wideIndices.HasRemaining) { indices.Put((short)wideIndices.Get()); } indices.Rewind(); var buffers = new int[2]; GLES20.GlGenBuffers(2, buffers, 0); mVertexBufferId = buffers[0]; mIndexBufferId = buffers[1]; // Load vertex buffer mVerticesBaseAddress = 0; mTexCoordsBaseAddress = mVerticesBaseAddress + 4 * vertices.Limit(); mNormalsBaseAddress = mTexCoordsBaseAddress + 4 * texCoords.Limit(); int totalBytes = mNormalsBaseAddress + 4 * normals.Limit(); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId); GLES20.GlBufferData(GLES20.GlArrayBuffer, totalBytes, null, GLES20.GlStaticDraw); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mVerticesBaseAddress, 4 * vertices.Limit(), vertices); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mTexCoordsBaseAddress, 4 * texCoords.Limit(), texCoords); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mNormalsBaseAddress, 4 * normals.Limit(), normals); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); // Load index buffer GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId); mIndexCount = indices.Limit(); GLES20.GlBufferData( GLES20.GlElementArrayBuffer, 2 * mIndexCount, indices, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0); ShaderUtil.CheckGLError(TAG, "OBJ buffer load"); int vertexShader = ShaderUtil.LoadGLShader(TAG, context, GLES20.GlVertexShader, Resource.Raw.object_vertex); int fragmentShader = ShaderUtil.LoadGLShader(TAG, context, GLES20.GlFragmentShader, Resource.Raw.object_fragment); mProgram = GLES20.GlCreateProgram(); GLES20.GlAttachShader(mProgram, vertexShader); GLES20.GlAttachShader(mProgram, fragmentShader); GLES20.GlLinkProgram(mProgram); GLES20.GlUseProgram(mProgram); ShaderUtil.CheckGLError(TAG, "Program creation"); mModelViewUniform = GLES20.GlGetUniformLocation(mProgram, "u_ModelView"); mModelViewProjectionUniform = GLES20.GlGetUniformLocation(mProgram, "u_ModelViewProjection"); mPositionAttribute = GLES20.GlGetAttribLocation(mProgram, "a_Position"); mNormalAttribute = GLES20.GlGetAttribLocation(mProgram, "a_Normal"); mTexCoordAttribute = GLES20.GlGetAttribLocation(mProgram, "a_TexCoord"); mTextureUniform = GLES20.GlGetUniformLocation(mProgram, "u_Texture"); mLightingParametersUniform = GLES20.GlGetUniformLocation(mProgram, "u_LightingParameters"); mMaterialParametersUniform = GLES20.GlGetUniformLocation(mProgram, "u_MaterialParameters"); ShaderUtil.CheckGLError(TAG, "Program parameters"); Android.Opengl.Matrix.SetIdentityM(mModelMatrix, 0); }
/** * 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)); } }
public void CreateOnGlThread(Context context, string objAssetName, string diffuseTextureAssetName) { // Read the texture. var textureBitmap = BitmapFactory.DecodeStream(context.Assets.Open(diffuseTextureAssetName)); GLES20.GlActiveTexture(GLES20.GlTexture0); GLES20.GlGenTextures(mTextures.Length, mTextures, 0); GLES20.GlBindTexture(GLES20.GlTexture2d, mTextures[0]); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMinFilter, GLES20.GlLinearMipmapLinear); GLES20.GlTexParameteri(GLES20.GlTexture2d, GLES20.GlTextureMagFilter, GLES20.GlLinear); GLUtils.TexImage2D(GLES20.GlTexture2d, 0, textureBitmap, 0); GLES20.GlGenerateMipmap(GLES20.GlTexture2d); GLES20.GlBindTexture(GLES20.GlTexture2d, 0); textureBitmap.Recycle(); ShaderUtil.CheckGLError(TAG, "Texture loading"); // Read the obj file. var objInputStream = context.Assets.Open(objAssetName); var obj = JavaGl.Obj.ObjReader.Read(objInputStream); obj = JavaGl.Obj.ObjUtils.ConvertToRenderable(obj); IntBuffer wideIndices = JavaGl.Obj.ObjData.GetFaceVertexIndices(obj, 3); FloatBuffer vertices = JavaGl.Obj.ObjData.GetVertices(obj); FloatBuffer texCoords = JavaGl.Obj.ObjData.GetTexCoords(obj, 2); FloatBuffer normals = JavaGl.Obj.ObjData.GetNormals(obj); ShortBuffer indices = ByteBuffer.AllocateDirect(2 * wideIndices.Limit()) .Order(ByteOrder.NativeOrder()).AsShortBuffer(); while (wideIndices.HasRemaining) { indices.Put((short)wideIndices.Get()); } indices.Rewind(); var buffers = new int[2]; GLES20.GlGenBuffers(2, buffers, 0); mVertexBufferId = buffers[0]; mIndexBufferId = buffers[1]; mVerticesBaseAddress = 0; mTexCoordsBaseAddress = mVerticesBaseAddress + 4 * vertices.Limit(); mNormalsBaseAddress = mTexCoordsBaseAddress + 4 * texCoords.Limit(); int totalBytes = mNormalsBaseAddress + 4 * normals.Limit(); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId); GLES20.GlBufferData(GLES20.GlArrayBuffer, totalBytes, null, GLES20.GlStaticDraw); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mVerticesBaseAddress, 4 * vertices.Limit(), vertices); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mTexCoordsBaseAddress, 4 * texCoords.Limit(), texCoords); GLES20.GlBufferSubData( GLES20.GlArrayBuffer, mNormalsBaseAddress, 4 * normals.Limit(), normals); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId); mIndexCount = indices.Limit(); GLES20.GlBufferData( GLES20.GlElementArrayBuffer, 2 * mIndexCount, indices, GLES20.GlStaticDraw); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0); ShaderUtil.CheckGLError(TAG, "OBJ buffer load"); int vertexShader = ShaderUtil.LoadGLShader(TAG, context, GLES20.GlVertexShader, Resource.Raw.object_vertex); int fragmentShader = ShaderUtil.LoadGLShader(TAG, context, GLES20.GlFragmentShader, Resource.Raw.object_fragment); mProgram = GLES20.GlCreateProgram(); GLES20.GlAttachShader(mProgram, vertexShader); GLES20.GlAttachShader(mProgram, fragmentShader); GLES20.GlLinkProgram(mProgram); GLES20.GlUseProgram(mProgram); ShaderUtil.CheckGLError(TAG, "Program creation"); mModelViewUniform = GLES20.GlGetUniformLocation(mProgram, "u_ModelView"); mModelViewProjectionUniform = GLES20.GlGetUniformLocation(mProgram, "u_ModelViewProjection"); mPositionAttribute = GLES20.GlGetAttribLocation(mProgram, "a_Position"); mNormalAttribute = GLES20.GlGetAttribLocation(mProgram, "a_Normal"); mTexCoordAttribute = GLES20.GlGetAttribLocation(mProgram, "a_TexCoord"); mTextureUniform = GLES20.GlGetUniformLocation(mProgram, "u_Texture"); mLightingParametersUniform = GLES20.GlGetUniformLocation(mProgram, "u_LightingParameters"); mMaterialParametersUniform = GLES20.GlGetUniformLocation(mProgram, "u_MaterialParameters"); ShaderUtil.CheckGLError(TAG, "Program parameters"); Android.Opengl.Matrix.SetIdentityM(mModelMatrix, 0); }