Replace 3D object in google arcore

1

I am new to OpenGL and ARCore and I am using GoogleArCore Sample as a base to create my application. I am able to scale and zoom the 3D object but I am not able to replace the current 3D object with another 3D object. I am already detecting the shadders before loading of a new object.

Basically, I want to reload onSurfaceCreated(GL10 gl, EGLConfig config) but I do not know how to do it.

Here is my code

public class MyARActivity extends BaseActivity<MyActivityArBinding> implements GLSurfaceView.Renderer {
    private static final String TAG = DashboardActivity.class.getSimpleName();

    //AR Variables
    private int mWidth;
    private int mHeight;
    private boolean capturePicture = false;
    private boolean installRequested;
    private boolean moving;
    float[] projmtx = new float[16];
    float[] viewmtx = new float[16];
    private Session session;
    private GestureDetector gestureDetector;
    private Snackbar messageSnackbar;
    private DisplayRotationHelper displayRotationHelper;
    private final BackgroundRenderer backgroundRenderer = new BackgroundRenderer();
    private ObjectRenderer virtualObject;// = new ObjectRenderer();
    private ObjectRenderer virtualObjectShadow;// = new ObjectRenderer();
    private final PlaneRenderer planeRenderer = new PlaneRenderer();
    private PointCloudRenderer pointCloud = new PointCloudRenderer();
    private ScaleGestureDetector scaleGestureDetector;
    private MyScaleGestureDetector_1 myScaleGestureDetector;
    // Temporary matrix allocated here to reduce number of allocations for each frame.
    private float[] anchorMatrix = new float[16];
    // Tap handling and UI.
    private ArrayBlockingQueue<MotionEvent> queuedSingleTaps = new ArrayBlockingQueue<>(16);
    private ArrayList<Anchor> anchors = new ArrayList<>();
    private int[] m3DCharacters = new int[]{R.drawable.cat, R.drawable.old_man, R.drawable.bat};
    private SQLiteHelper sqlHelper;
    private boolean isUpdate;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHeaderVisible(false);
        doDefaults();
    }

    private void doDefaults() {
        binding.setPresenter(this);
        sqlHelper = SQLiteHelper.getInstance(this);
        initAR();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void initAR() {
        displayRotationHelper = new DisplayRotationHelper(this);
        myScaleGestureDetector = new MyScaleGestureDetector_1();
        scaleGestureDetector = new ScaleGestureDetector(this, myScaleGestureDetector);

        // Set up tap listener.
        gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                if (anchors.size() <= 0) {
                    onSingleTap(e);
                }
                return true;
            }

            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }
        });

        binding.surfaceView.setOnTouchListener(
                new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {

                        switch (event.getAction()) {
                            case MotionEvent.ACTION_DOWN:
                                moving = true;
                                DebugHelper.log("ACTION_DOWN");
                                break;

                            case MotionEvent.ACTION_UP:
                                DebugHelper.log("ACTION_UP");
                                moving = false;
                                DebugHelper.log("SF at ACTION_UP::::", String.valueOf(myScaleGestureDetector.getScaleFactor()));
                                break;
                            case MotionEvent.ACTION_MOVE:
                                if (anchors.size() > 0) {
                                    onSecondTouch(event);
                                }
                                break;
                        }
                        return gestureDetector.onTouchEvent(event);

                    }
                });

        // Set up renderer.
        binding.surfaceView.setPreserveEGLContextOnPause(true);
        binding.surfaceView.setEGLContextClientVersion(2);
        binding.surfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); // Alpha used for plane blending.
        binding.surfaceView.setRenderer(this);
        binding.surfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
        installRequested = false;
    }

    private void onSavePicture() {
        setLoading(true, "Capturing image...");
        Log.e("SavePicture Called", "Yes");
        int pixelData[] = new int[mWidth * mHeight];
        // Read the pixels from the current GL frame.
        IntBuffer buf = IntBuffer.wrap(pixelData);
        buf.position(0);
        GLES20.glReadPixels(0, 0, mWidth, mHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);

        // Convert the pixel data from RGBA to what Android wants, ARGB.
        int bitmapData[] = new int[pixelData.length];
        for (int i = 0; i < mHeight; i++) {
            for (int j = 0; j < mWidth; j++) {
                int p = pixelData[i * mWidth + j];
                int b = (p & 0x00ff0000) >> 16;
                int r = (p & 0x000000ff) << 16;
                int ga = p & 0xff00ff00;
                bitmapData[(mHeight - i - 1) * mWidth + j] = ga | r | b;
            }
        }
        // Create a bitmap.
        Bitmap capturedBitmap = Bitmap.createBitmap(bitmapData, mWidth, mHeight, Bitmap.Config.ARGB_8888);
        Bitmap waterBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.watermark_camar);
        Bitmap waterMarkBitmap = ImageUtil.getInstance().createWaterMaskRightBottom(this, capturedBitmap, waterBitmap, 10, 5);
        sqlHelper.saveToInternalStorage(this, waterMarkBitmap);
        setLoading(false, "");
    }

    /**
     * To capture the current AR Frame
     */
    public void onCaptureClick() {
        if (!ExternalPermissionHelper.hasExtStoragePermission(MyARActivity.this)) {
            ExternalPermissionHelper.requestExtStoragePermission(MyARActivity.this);
            return;
        }
        capturePicture = true;
    }

    /**
     * To open and close the character selection horizontal list
     */
    public void onCharClick() {
        createCharacterScrollView();
    }

    /**
     * To close the entire AR view
     */
    public void closeScreen() {
        finish();
    }

    private void createCharacterScrollView() {
        try {
            binding.LinearTopSlider.setVisibility(View.VISIBLE);
            LayoutInflater inflater = LayoutInflater.from(this);
            binding.charContainer.removeAllViews();
            binding.horizontalChar.scrollTo(0, 0);
            for (int i = 0; i < m3DCharacters.length; i++) {
                View cell = inflater.inflate(R.layout.item_character, null);
                ImageView imgGroup = cell.findViewById(R.id.imgChar);
                View view = cell.findViewById(R.id.view);
                //String name = "cartoon" + (i + 1);
                imgGroup.setImageResource(m3DCharacters[i]); //getResourceId(name)
                view.setVisibility(i < m3DCharacters.length - 1 ? View.VISIBLE : View.GONE);
                binding.charContainer.addView(cell);
                cell.setTag(i);
                cell.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        final int position = (int) view.getTag();
                        switch (position) {
                            case 0:
                                loadObject(0.28f, 3.5f, 0.28f, "cat/cat.obj");
                                break;
                            case 1:
                                loadObject(0.0085f, 5f, 1f, "man/muro.obj");
                                break;
                            case 2:
                                loadObject(0.0009f, 2.75f, 0.25f, "bloodwing/bloodwing.obj");
                                break;
                        }
                    }
                });
            }
            binding.charContainer.setVisibility(View.VISIBLE);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private int getResourceId(String drawableName) {
        return getResources().getIdentifier(drawableName, "drawable", getPackageName());
    }

    private void onSecondTouch(MotionEvent e) {
        Log.e("Second Touch", "Executed");
        if (e.getPointerCount() > 1) {
            scaleGestureDetector.onTouchEvent(e);
        } else {
            queuedSingleTaps.offer(e);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (session == null) {
            Exception exception = null;
            String message = null;
            try {
                switch (ArCoreApk.getInstance().requestInstall(this, !installRequested)) {
                    case INSTALL_REQUESTED:
                        installRequested = true;
                        return;
                    case INSTALLED:
                        break;
                }

                // ARCore requires camera permissions to operate. If we did not yet obtain runtime
                // permission on Android M and above, now is a good time to ask the user for it.
                if (!CameraPermissionHelper.hasCameraPermission(this)) {
                    CameraPermissionHelper.requestCameraPermission(this);
                    return;
                }

                session = new Session(/* context= */ this);
            } catch (UnavailableArcoreNotInstalledException
                    | UnavailableUserDeclinedInstallationException e) {
                message = "Please install ARCore";
                exception = e;
            } catch (UnavailableApkTooOldException e) {
                message = "Please update ARCore";
                exception = e;
            } catch (UnavailableSdkTooOldException e) {
                message = "Please update this app";
                exception = e;
            } catch (Exception e) {
                message = "This device does not support AR";
                exception = e;
            }

            if (message != null) {
                showMsg(message);
                Log.e(TAG, "Exception creating session", exception);
                return;
            }

            // Create default config and check if supported.
            Config config = new Config(session);
            if (!session.isSupported(config)) {
                showMsg("This device does not support AR");
            }
            session.configure(config);
        }

        showLoadingMessage();
        // Note that order matters - see the note in onPause(), the reverse applies here.
        session.resume();
        binding.surfaceView.onResume();
        displayRotationHelper.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        if (session != null) {
            // Note that the order matters - GLSurfaceView is paused first so that it does not try
            // to query the session. If Session is paused before GLSurfaceView, GLSurfaceView may
            // still call session.update() and get a SessionPausedException.
            displayRotationHelper.onPause();
            binding.surfaceView.onPause();
            session.pause();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
        switch (requestCode) {
            case CameraPermissionHelper.CAMERA_PERMISSION_CODE:
                if (!CameraPermissionHelper.hasCameraPermission(this)) {
                    showMsg("Camera permission is needed to run this application");
                    if (!CameraPermissionHelper.shouldShowRequestPermissionRationale(this)) {
                        // Permission denied with checking "Do not ask again".
                        CameraPermissionHelper.launchPermissionSettings(this);
                    }
                    finish();
                }
                break;

            case ExternalPermissionHelper.EXT_STORAGE_PERMISSION_CODE:
                if (!ExternalPermissionHelper.hasExtStoragePermission(this)) {
                    showMsg("External storage permission is needed to capture the photo");
                    if (!ExternalPermissionHelper.shouldShowRequestPermissionRationale(this)) {
                        // Permission denied with checking "Do not ask again".
                        ExternalPermissionHelper.launchPermissionSettings(this);
                    }
                    finish();
                }
                break;
        }
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            // Standard Android full-screen functionality.
            getWindow()
                    .getDecorView()
                    .setSystemUiVisibility(
                            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        }
    }

    private void onSingleTap(MotionEvent e) {
        // Queue tap if there is space. Tap is lost if queue is full.
        DebugHelper.log("onSingleTap()");
        queuedSingleTaps.offer(e);
    }

    private void loadCatObject() {
        try {
            myScaleGestureDetector.setScaleFactor(0.25f);
            myScaleGestureDetector.setMinValue(3.5f);
            myScaleGestureDetector.setMaxValue(0.25f);
            virtualObject = new ObjectRenderer("cat/cat.obj");
            //virtualObject.createOnGlThread(this, "cat/cat.obj", "cat/cat.png");
            virtualObject.createOnGlThread(this);
            virtualObject.setMaterialProperties(0.0f, 1.0f, 1.0f, 6.0f);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void loadBloodwingObject() {
        try {
            myScaleGestureDetector.setScaleFactor(0.0009f);
            myScaleGestureDetector.setMinValue(2.75f);
            myScaleGestureDetector.setMaxValue(0.25f);
            virtualObject = new ObjectRenderer("bloodwing/bloodwing.obj");
            virtualObject.createOnGlThread(this);
            //virtualObject.createOnGlThread(this, "bloodwing/bloodwing.obj", "bloodwing/bloodwing.jpg");
            virtualObject.setMaterialProperties(0.0f, 1.0f, 1.0f, 6.0f);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void loadMan() {
        try {
            myScaleGestureDetector.setScaleFactor(0.0085f);
            myScaleGestureDetector.setMinValue(5f);
            myScaleGestureDetector.setMaxValue(1f);
            virtualObject = new ObjectRenderer("man/muro.obj");
            virtualObject.createOnGlThread(this);
            virtualObject.setMaterialProperties(0.0f, 1.0f, 1.0f, 6.0f);
        } catch (Exception ex) {
            ex.printStackTrace();
            finish();
        }
    }

    private void loadObject(float scaleFactor, float minValue, float maxValue, String objectPath) {
        try {
            myScaleGestureDetector.setScaleFactor(scaleFactor);
            myScaleGestureDetector.setMinValue(minValue);
            myScaleGestureDetector.setMaxValue(maxValue);
            if (virtualObject == null) {
                virtualObject = new ObjectRenderer(objectPath);
                virtualObject.createOnGlThread(this);
                virtualObject.setMaterialProperties(0.0f, 1.0f, 1.0f, 6.0f);
            } else {
                isUpdate = true;
                GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
                virtualObject.updateObjectPath(objectPath);
                virtualObject.createOnGlThread(this);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        // Create the texture and pass it to ARCore session to be filled during update().
        backgroundRenderer.createOnGlThread(/*context=*/ this);
        // Prepare the other rendering objects.
        loadObject(0.40f, 3.5f, 0.28f, "cat/cat.obj");
        try {
            planeRenderer.createOnGlThread(/*context=*/ this, "trigrid.png");
        } catch (IOException e) {
            Log.e(TAG, "Failed to read plane texture");
        }
        pointCloud.createOnGlThread(/*context=*/ this);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        displayRotationHelper.onSurfaceChanged(width, height);
        GLES20.glViewport(0, 0, width, height);
        mWidth = width;
        mHeight = height;
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        // Clear screen to notify driver it should not load any pixels from previous frame.
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

        if (session == null) {
            return;
        }
        // Notify ARCore session that the view size changed so that the perspective matrix and
        // the video background can be properly adjusted.
        displayRotationHelper.updateSessionIfNeeded(session);

        try {
            session.setCameraTextureName(backgroundRenderer.getTextureId());

            // Obtain the current frame from ARSession. When the configuration is set to
            // UpdateMode.BLOCKING (it is by default), this will throttle the rendering to the
            // camera framerate.
            Frame frame = session.update();
            Camera camera = frame.getCamera();

            // Handle taps. Handling only one tap per frame, as taps are usually low frequency
            // compared to frame rate.
            MotionEvent tap = queuedSingleTaps.poll();
            if (tap != null && camera.getTrackingState() == TrackingState.TRACKING) {
                for (HitResult hit : frame.hitTest(tap)) {
                    // Check if any plane was hit, and if it was hit inside the plane polygon
                    Trackable trackable = hit.getTrackable();
                    // Creates an anchor if a plane or an oriented point was hit.
                    if ((trackable instanceof Plane && ((Plane) trackable).isPoseInPolygon(hit.getHitPose()))
                            || (trackable instanceof Point
                            && ((Point) trackable).getOrientationMode()
                            == Point.OrientationMode.ESTIMATED_SURFACE_NORMAL)) {
                        // Hits are sorted by depth. Consider only closest hit on a plane or oriented point.
                        // Cap the number of objects created. This avoids overloading both the
                        // rendering system and ARCore.
                        //if (!isUpdate) {
                        DebugHelper.log("Anchor size = " + anchors.size());
                        if (anchors.size() >= 1) {
                            anchors.get(0).detach();
                            anchors.remove(0);
                        }
                        // Adding an Anchor tells ARCore that it should track this position in
                        // space. This anchor is created on the Plane to place the 3D model
                        // in the correct position relative both to the world and to the plane.
                        if (isUpdate) {
                            if (anchors.size() > 0) {
                                DebugHelper.log("anchor list has data");
                                for (Anchor anchor : anchors) {
                                    anchor.detach();
                                    anchors.remove(anchor);
                                }
                            }
                        }
                        Anchor anchor = hit.createAnchor();
                        if (anchor != null)
                            anchors.add(anchor);
                        else
                            DebugHelper.log("anchor is null");
                        //}
                        break;
                    }
                }
            }

            // Draw background.
            backgroundRenderer.draw(frame);

            // If not tracking, don't draw 3d objects.
            if (camera.getTrackingState() == TrackingState.PAUSED) {
                return;
            }

            // Get projection matrix.
            camera.getProjectionMatrix(projmtx, 0, 0.1f, 100.0f);

            // Get camera matrix and draw.
            camera.getViewMatrix(viewmtx, 0);

            // Compute lighting from average intensity of the image.
            final float lightIntensity = frame.getLightEstimate().getPixelIntensity();

            // Visualize tracked points.
            PointCloud pointCloud = frame.acquirePointCloud();
            this.pointCloud.update(pointCloud);
            if (!capturePicture)
                this.pointCloud.draw(viewmtx, projmtx);

            // Application is responsible for releasing the point cloud resources after
            // using it.
            pointCloud.release();

            // Check if we detected at least one plane. If so, hide the loading message.
            if (messageSnackbar != null) {
                {
                    for (Plane plane : session.getAllTrackables(Plane.class)) {
                        if (plane.getType() == Plane.Type.HORIZONTAL_UPWARD_FACING
                                && plane.getTrackingState() == TrackingState.TRACKING) {
                            hideLoadingMessage();
                            break;
                        }
                        //xgfgdfgfgd
                        //binding.setCharClick(true);
                    }
                }
                for (Plane plane : session.getAllTrackables(Plane.class)) {
                    if (plane.getType() == Plane.Type.HORIZONTAL_UPWARD_FACING && plane.getTrackingState() == TrackingState.TRACKING) {
                        hideLoadingMessage();
                        break;
                    }
                    //dfgdfgdfgdf
                    //binding.setCharClick(true);
                }
            }


            // Visualize planes.
            if (!capturePicture)
                planeRenderer.drawPlanes(session.getAllTrackables(Plane.class), camera.getDisplayOrientedPose(), projmtx);

            // Visualize anchors created by touch.
            for (Anchor anchor : anchors) {
                if (anchor.getTrackingState() != TrackingState.TRACKING) {
                    continue;
                }
                // Get the current pose of an Anchor in world space. The Anchor pose is updated
                // during calls to session.update() as ARCore refines its estimate of the world.
                anchor.getPose().toMatrix(anchorMatrix, 0);

                // Update and draw the model and its shadow.
                if (virtualObject != null) {
                    virtualObject.updateModelMatrix(anchorMatrix, myScaleGestureDetector.getScaleFactor());
                    if (viewmtx != null && projmtx != null) {
                        virtualObject.draw(viewmtx, projmtx, lightIntensity);
                    }
                }
                if (virtualObjectShadow != null) {
                    virtualObjectShadow.updateModelMatrix(anchorMatrix, myScaleGestureDetector.getScaleFactor());
                    if (viewmtx != null && projmtx != null)
                        virtualObjectShadow.draw(viewmtx, projmtx, lightIntensity);
                }
            }

            if (capturePicture) {
                capturePicture = false;
                onSavePicture();
            }

        } catch (Throwable t) {
            // Avoid crashing the application due to unhandled exceptions.
            Log.e(TAG, "Exception on the OpenGL thread", t);
        }
    }

    private void setLoading(boolean isLoading, String message) {
        binding.setLoading(isLoading);
        binding.setLoadingMessage(message);
    }

    private void showSnackbarMessage(String message, boolean finishOnDismiss) {
        messageSnackbar =
                Snackbar.make(
                        MyARActivity.this.findViewById(android.R.id.content),
                        message,
                        Snackbar.LENGTH_INDEFINITE);
        messageSnackbar.getView().setBackgroundColor(0xbf323232);
        if (finishOnDismiss) {
            messageSnackbar.setAction(
                    "Dismiss",
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            messageSnackbar.dismiss();
                        }
                    });
            messageSnackbar.addCallback(
                    new BaseTransientBottomBar.BaseCallback<Snackbar>() {
                        @Override
                        public void onDismissed(Snackbar transientBottomBar, int event) {
                            super.onDismissed(transientBottomBar, event);
                            finish();
                        }
                    });
        }
        messageSnackbar.show();
    }

    private void showLoadingMessage() {
        runOnUiThread(
                new Runnable() {
                    @Override
                    public void run() {
                        showSnackbarMessage("Searching for surfaces...", false);
                    }
                });
    }

    private void hideLoadingMessage() {
        runOnUiThread(
                new Runnable() {
                    @Override
                    public void run() {
                        if (messageSnackbar != null) {
                            messageSnackbar.dismiss();
                        }
                        messageSnackbar = null;
                    }
                });
    }
}

In my ObjectRenderer and BackgroundRenderer is reset my code.

Hee is my reset code

BackgroundRenderer.java

public void resetData() {
    GLES20.glDeleteShader(vertexShader);
    GLES20.glDeleteShader(fragmentShader);
    GLES20.glDeleteProgram(quadProgram);
    textureId = -1;
}

ObjectRenderer.java

Public void updateObjectPath(String objectPath) {
    try {
        GLES20.glDeleteShader(vertexShader);
        GLES20.glDeleteShader(fragmentShader);
        GLES20.glDeleteProgram(mProgram);
        reset();
        this.OBJ_PATH = objectPath;
        } 
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void reset() {
        this.OBJ_PATH = null;
        this.mObj = null;
        this.mModelMatrix = null;
        this.mModelViewMatrix = null;
        this.mModelViewProjectionMatrix = null;
        this.mViewLightDirection = null;
        this.mTextures = null;
        this.vectorArrayObjectIds = null;
        this.mMaterialParametersUniform = -1;
        this.mModelViewProjectionUniform = -1;
        this.mVerticesBaseAddress = -1;
        this.mTexCoordsBaseAddress = -1;
        this.mNormalAttribute = -1;
        this.mNormalsBaseAddress = -1;
        this.mIndexBufferId = -1;
        this.mVertexBufferId = -1;
        this.mBlendMode = null;
        this.mProgram = -1;
        this.mLightingParametersUniform = -1;
        this.mIndexCount = -1;
        this.mModelViewUniform = -1;
        this.mPositionAttribute = -1;
        this.mTexCoordAttribute = -1;
        this.vertexShader = -1;
        this.fragmentShader = -1;
        this.mAmbient = 0.3f;
        this.mDiffuse = 1.0f;
        this.mSpecular = 1.0f;
        this.mSpecularPower = 6.0f;
        this.mModelMatrix = new float[16];
        this.mModelViewMatrix = new float[16];
        this.mModelViewProjectionMatrix = new float[16];
        this.mViewLightDirection = new float[4];
    }

Can anyone guide me to same?

Thanks in advance.

android
opengl-es-2.0
arcore
asked on Stack Overflow Apr 4, 2018 by Riddhi Shah • edited Apr 4, 2018 by Riddhi Shah

2 Answers

3

You need to pass new object name and its texture to onDrawFrame method this is because of its work only on GL thread. Also, note that you're using GL version 2.

glSurfaceView.setEGLContextClientVersion(2);

    @Override
    public void onDrawFrame(GL10 gl) {

        if (isObjChanged) {
            isObjChanged = false;
            try {
                virtualObject.createOnGlThread(getContext(), objName, textureName);
                virtualObject.setMaterialProperties(0.0f, 2.0f, 0.5f, 6.0f);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }

        // Clear screen to notify driver it should not load any pixels from previous frame.
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        if (session == null) {
            return;
        }
        // Notify ARCore session that the view size changed so that the perspective matrix and
        // the video background can be properly adjusted.
        displayRotationHelper.updateSessionIfNeeded(session);

        try {
            session.setCameraTextureName(backgroundRenderer.getTextureId());

            // Obtain the current frame from ARSession. When the configuration is set to
            // UpdateMode.BLOCKING (it is by default), this will throttle the rendering to the
            // camera framerate.
            Frame frame = session.update();
            Camera camera = frame.getCamera();

            // Handle taps. Handling only one tap per frame, as taps are usually low frequency
            // compared to frame rate.

            MotionEvent tap = tapHelper.poll();
            if (tap != null && camera.getTrackingState() == TrackingState.TRACKING) {
                for (HitResult hit : frame.hitTest(tap)) {
                    // Check if any plane was hit, and if it was hit inside the plane polygon
                    Trackable trackable = hit.getTrackable();
                    // Creates an anchor if a plane or an oriented point was hit.
                    if ((trackable instanceof Plane && ((Plane) trackable).isPoseInPolygon(hit.getHitPose()))
                            || (trackable instanceof Point
                            && ((Point) trackable).getOrientationMode()
                            == Point.OrientationMode.ESTIMATED_SURFACE_NORMAL)) {
                        // Hits are sorted by depth. Consider only closest hit on a plane or oriented point.
                        // Cap the number of objects created. This avoids overloading both the
                        // rendering system and ARCore.
                        if (anchors.size() >= 1) {
                            anchors.get(0).detach();
                            anchors.remove(0);
                        }
                        // Adding an Anchor tells ARCore that it should track this position in
                        // space. This anchor is created on the Plane to place the 3D model
                        // in the correct position relative both to the world and to the plane.
                        anchors.add(hit.createAnchor());
                        break;
                    }
                }
            }

            // Draw background.
            backgroundRenderer.draw(frame);

            // If not tracking, don't draw 3d objects.
            if (camera.getTrackingState() == TrackingState.PAUSED) {
                return;
            }

            // Get projection matrix.
            float[] projmtx = new float[16];
            camera.getProjectionMatrix(projmtx, 0, 0.1f, 100.0f);

            // Get camera matrix and draw.
            float[] viewmtx = new float[16];
            camera.getViewMatrix(viewmtx, 0);

            // Compute lighting from average intensity of the image.
            // The first three components are color scaling factors.
            // The last one is the average pixel intensity in gamma space.
            final float[] colorCorrectionRgba = new float[4];
            frame.getLightEstimate().getColorCorrection(colorCorrectionRgba, 0);

            // Visualize tracked points.
            PointCloud pointCloud = frame.acquirePointCloud();
            pointCloudRenderer.update(pointCloud);
            pointCloudRenderer.draw(viewmtx, projmtx);

            // Application is responsible for releasing the point cloud resources after
            // using it.
            pointCloud.release();

            // Check if we detected at least one plane. If so, hide the loading message.
            if (messageSnackbarHelper.isShowing()) {
                for (Plane plane : session.getAllTrackables(Plane.class)) {
                    if (plane.getType() == com.google.ar.core.Plane.Type.HORIZONTAL_UPWARD_FACING
                            && plane.getTrackingState() == TrackingState.TRACKING) {
                        messageSnackbarHelper.hide(getActivity());
                        break;
                    }
                }
            }

            // Visualize planes.
            planeRenderer.drawPlanes(
                    session.getAllTrackables(Plane.class), camera.getDisplayOrientedPose(), projmtx);

            // Visualize anchors created by touch.

            for (Anchor anchor : anchors) {
                if (anchor.getTrackingState() != TrackingState.TRACKING) {
                    continue;
                }
                // Get the current pose of an Anchor in world space. The Anchor pose is updated
                // during calls to session.update() as ARCore refines its estimate of the world.
                anchor.getPose().toMatrix(anchorMatrix, 0);

                // Update and draw the model and its shadow.
                virtualObject.updateModelMatrix(anchorMatrix, scaleFactor);
                virtualObject.draw(viewmtx, projmtx, colorCorrectionRgba);
            }

        } catch (Throwable t) {
            // Avoid crashing the application due to unhandled exceptions.
            Log.e(TAG, "Exception on the OpenGL thread", t);
        }
    }
answered on Stack Overflow Apr 11, 2018 by Sanju Rajpal • edited Apr 11, 2018 by Shubham Sejpal
0

In OpenGL ES defines the following 6 error values Code:

1280 GL_INVALID_ENUM      
1281 GL_INVALID_VALUE     
1282 GL_INVALID_OPERATION 
1283 GL_STACK_OVERFLOW    
1284 GL_STACK_UNDERFLOW   
1285 GL_OUT_OF_MEMORY

You got a GL_INVALID_ENUM error, which means you passed an unsupported enum value to a GL function.

answered on Stack Overflow Apr 4, 2018 by Amjad Khan

User contributions licensed under CC BY-SA 3.0