/// <summary> /// Draw a virtual object at a specific location on a specified plane. /// This method is called when WorldRenderManager's OnDrawFrame. /// </summary> /// <param name="cameraView">The viewMatrix is a 4 * 4 matrix.</param> /// <param name="cameraProjection">The ProjectionMatrix is a 4 * 4 matrix.</param> /// <param name="lightIntensity">The lighting intensity.</param> /// <param name="obj">The virtual object.</param> public void OnDrawFrame(float[] cameraView, float[] cameraProjection, float lightIntensity, VirtualObject obj) { ShaderUtil.CheckGlError(TAG, "onDrawFrame start."); mModelMatrixs = obj.GetModelAnchorMatrix(); Matrix.MultiplyMM(mModelViewMatrixs, 0, cameraView, 0, mModelMatrixs, 0); Matrix.MultiplyMM(mModelViewProjectionMatrixs, 0, cameraProjection, 0, mModelViewMatrixs, 0); GLES20.GlUseProgram(mGlProgram); Matrix.MultiplyMV(mViewLightDirections, 0, mModelViewMatrixs, 0, LIGHT_DIRECTIONS, 0); MatrixUtil.NormalizeVec3(mViewLightDirections); // Light direction. GLES20.GlUniform4f(mLightingParametersUniform, mViewLightDirections[0], mViewLightDirections[1], mViewLightDirections[2], lightIntensity); float[] objColors = obj.GetColor(); GLES20.GlUniform4fv(mColorUniform, 1, objColors, 0); GLES20.GlActiveTexture(GLES20.GlTexture0); GLES20.GlBindTexture(GLES20.GlTexture2d, mTextures[0]); GLES20.GlUniform1i(mTextureUniform, 0); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId); // The coordinate dimension of the read virtual object is 3. GLES20.GlVertexAttribPointer( mPositionAttribute, 3, GLES20.GlFloat, false, 0, 0); // The dimension of the normal vector is 3. GLES20.GlVertexAttribPointer( mNormalAttribute, 3, GLES20.GlFloat, false, 0, mNormalsBaseAddress); // The dimension of the texture coordinate is 2. GLES20.GlVertexAttribPointer( mTexCoordAttribute, 2, GLES20.GlFloat, false, 0, mTexCoordsBaseAddress); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); GLES20.GlUniformMatrix4fv( mModelViewUniform, 1, false, mModelViewMatrixs, 0); GLES20.GlUniformMatrix4fv( mModelViewProjectionUniform, 1, false, mModelViewProjectionMatrixs, 0); GLES20.GlEnableVertexAttribArray(mPositionAttribute); GLES20.GlEnableVertexAttribArray(mNormalAttribute); GLES20.GlEnableVertexAttribArray(mTexCoordAttribute); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId); GLES20.GlDrawElements(GLES20.GlTriangles, mIndexCount, GLES20.GlUnsignedShort, 0); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0); GLES20.GlDisableVertexAttribArray(mPositionAttribute); GLES20.GlDisableVertexAttribArray(mNormalAttribute); GLES20.GlDisableVertexAttribArray(mTexCoordAttribute); GLES20.GlBindTexture(GLES20.GlTexture2d, 0); ShaderUtil.CheckGlError(TAG, "onDrawFrame end."); }
// Convert the input coordinates to the plane coordinate system. private float[] CalculateScreenPos(float coordinateX, float coordinateY, float coordinateZ) { // The coordinates of the point are four-dimensional (x, y, z, w). float[] vecs = new float[4]; vecs[0] = coordinateX; vecs[1] = coordinateY; vecs[2] = coordinateZ; vecs[3] = 1.0f; // Store the coordinate values in the clip coordinate system. float[] rets = new float[4]; Matrix.MultiplyMV(rets, 0, mModelViewProjectionMatrixs, 0, vecs, 0); // Divide by the w component of the coordinates. rets[0] /= rets[3]; rets[1] /= rets[3]; rets[2] /= rets[3]; // In the current coordinate system, left is negative, right is positive, downward // is positive, and upward is negative.Adding 1 to the left of the X coordinate is // equivalent to moving the coordinate system leftwards. Such an operation on the Y // axis is equivalent to moving the coordinate system upwards. rets[0] += 1.0f; rets[1] = 1.0f - rets[1]; // Convert to pixel coordinates. rets[0] *= mWidth; rets[1] *= mHeight; // When the w component is set to 1, the xy component caused by coordinate system // movement is eliminated and doubled. rets[3] = 1.0f; rets[0] /= 2.0f; rets[1] /= 2.0f; return(rets); }
/** * Draws the model. * * @param cameraView A 4x4 view matrix, in column-major order. * @param cameraPerspective A 4x4 projection matrix, in column-major order. * @param lightIntensity Illumination intensity. Combined with diffuse and specular material * properties. * @see #setBlendMode(BlendMode) * @see #updateModelMatrix(float[], float) * @see #setMaterialProperties(float, float, float, float) * @see android.opengl.Matrix */ public void Draw(float[] cameraView, float[] cameraPerspective, float lightIntensity) { ShaderUtil.CheckGLError(TAG, "Before draw"); // Build the ModelView and ModelViewProjection matrices // for calculating object position and light. Matrix.MultiplyMM(mModelViewMatrix, 0, cameraView, 0, mModelMatrix, 0); Matrix.MultiplyMM(mModelViewProjectionMatrix, 0, cameraPerspective, 0, mModelViewMatrix, 0); GLES20.GlUseProgram(mProgram); // Set the lighting environment properties. Matrix.MultiplyMV(mViewLightDirection, 0, mModelViewMatrix, 0, LIGHT_DIRECTION, 0); normalizeVec3(mViewLightDirection); GLES20.GlUniform4f(mLightingParametersUniform, mViewLightDirection[0], mViewLightDirection[1], mViewLightDirection[2], lightIntensity); // Set the object material properties. GLES20.GlUniform4f(mMaterialParametersUniform, mAmbient, mDiffuse, mSpecular, mSpecularPower); // Attach the object texture. GLES20.GlActiveTexture(GLES20.GlTexture0); GLES20.GlBindTexture(GLES20.GlTexture2d, mTextures[0]); GLES20.GlUniform1i(mTextureUniform, 0); // Set the vertex attributes. GLES20.GlBindBuffer(GLES20.GlArrayBuffer, mVertexBufferId); GLES20.GlVertexAttribPointer( mPositionAttribute, COORDS_PER_VERTEX, GLES20.GlFloat, false, 0, mVerticesBaseAddress); GLES20.GlVertexAttribPointer( mNormalAttribute, 3, GLES20.GlFloat, false, 0, mNormalsBaseAddress); GLES20.GlVertexAttribPointer( mTexCoordAttribute, 2, GLES20.GlFloat, false, 0, mTexCoordsBaseAddress); GLES20.GlBindBuffer(GLES20.GlArrayBuffer, 0); // Set the ModelViewProjection matrix in the shader. GLES20.GlUniformMatrix4fv( mModelViewUniform, 1, false, mModelViewMatrix, 0); GLES20.GlUniformMatrix4fv( mModelViewProjectionUniform, 1, false, mModelViewProjectionMatrix, 0); // Enable vertex arrays GLES20.GlEnableVertexAttribArray(mPositionAttribute); GLES20.GlEnableVertexAttribArray(mNormalAttribute); GLES20.GlEnableVertexAttribArray(mTexCoordAttribute); if (mBlendMode != BlendMode.Null) { GLES20.GlDepthMask(false); GLES20.GlEnable(GLES20.GlBlend); switch (mBlendMode) { case BlendMode.Shadow: // Multiplicative blending function for Shadow. GLES20.GlBlendFunc(GLES20.GlZero, GLES20.GlOneMinusSrcAlpha); break; case BlendMode.Grid: // Grid, additive blending function. GLES20.GlBlendFunc(GLES20.GlSrcAlpha, GLES20.GlOneMinusSrcAlpha); break; } } GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, mIndexBufferId); GLES20.GlDrawElements(GLES20.GlTriangles, mIndexCount, GLES20.GlUnsignedShort, 0); GLES20.GlBindBuffer(GLES20.GlElementArrayBuffer, 0); if (mBlendMode != BlendMode.Null) { GLES20.GlDisable(GLES20.GlBlend); GLES20.GlDepthMask(true); } // Disable vertex arrays GLES20.GlDisableVertexAttribArray(mPositionAttribute); GLES20.GlDisableVertexAttribArray(mNormalAttribute); GLES20.GlDisableVertexAttribArray(mTexCoordAttribute); GLES20.GlBindTexture(GLES20.GlTexture2d, 0); ShaderUtil.CheckGLError(TAG, "After draw"); }