public Square ()
		{
			// initialize vertex byte buffer for shape coordinates
			ByteBuffer bb = ByteBuffer.AllocateDirect (
			// (# of coordinate values * 4 bytes per float)
			        squareCoords.Length * 4);
			bb.Order (ByteOrder.NativeOrder ());
			vertexBuffer = bb.AsFloatBuffer ();
			vertexBuffer.Put (squareCoords);
			vertexBuffer.Position (0);

			// initialize byte buffer for the draw list
			ByteBuffer dlb = ByteBuffer.AllocateDirect (
			// (# of coordinate values * 2 bytes per short)
			        drawOrder.Length * 2);
			dlb.Order (ByteOrder.NativeOrder ());
			drawListBuffer = dlb.AsShortBuffer ();
			drawListBuffer.Put (drawOrder);
			drawListBuffer.Position (0);

			// prepare shaders and OpenGL program
			int vertexShader = MyGLRenderer.LoadShader (GLES20.GlVertexShader,
			                                           vertexShaderCode);
			int fragmentShader = MyGLRenderer.LoadShader (GLES20.GlFragmentShader,
			                                             fragmentShaderCode);

			mProgram = GLES20.GlCreateProgram ();             // create empty OpenGL Program
			GLES20.GlAttachShader (mProgram, vertexShader);   // add the vertex shader to program
			GLES20.GlAttachShader (mProgram, fragmentShader); // add the fragment shader to program
			GLES20.GlLinkProgram (mProgram);                  // create OpenGL program executables
		}
Example #2
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));
            }
        }
Example #3
0
        /**
         * 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);
        }
Example #4
0
 public void SetIndices(short[] indices, int offset, int length)
 {
     _indices.Clear();
     _indices.Put(indices, offset, length);
     _indices.Flip();
 }