华为AR-Engine集成设置手势放大缩小旋转

前段时间项目中想要实现AR功能,用于室内物品摆放,看了几个第三方sdk发现回复的都非常慢,所以就想自己试下水,特此记录一下。
自己分别集成了谷歌ARCore和华为的AR-Engine,不过发现都没有特定的手势判断,就自己在原有的demo基础上加了一丢丢代码,demo具体的集成步骤就不写了,官方全有,直接上代码
demo链接:hms-AREngine-demo: 华为AREngine示例代码用于展示如何使用华为AR提供的基础能力,具体能力包括运动跟踪、平面检测、人脸识别与手势识别等。 (gitee.com)https://gitee.com/hms-core/hms-AREngine-demoGitHub - HMS-Core/hms-AREngine-demo: Huawei AREngine kit sample code demonstrates how to use Huawei AR functions, including motion tracking, plane detection, face recognition and gesture recognition, etc.Huawei AREngine kit sample code demonstrates how to use Huawei AR functions, including motion tracking, plane detection, face recognition and gesture recognition, etc. - GitHub - HMS-Core/hms-AREngine-demo: Huawei AREngine kit sample code demonstrates how to use Huawei AR functions, including motion tracking, plane detection, face recognition and gesture recognition, etc.https://github.com/HMS-Core/hms-AREngine-demo集成后会发现项目总只有拖拽的手势,放大缩小及旋转的手势没有。

华为项目只加了seekbar控制放大缩小及旋转,公司想要直接通过手势去做处理所以就有了下面的代码:
在GestureEventFactory 类里面加入

/**
 * 放大缩小手势
 */
const val GESTURE_EVENT_TYPE_MAX_AND_MIN = 4

/**
 * 旋转
 */
const val GESTURE_EVENT_TYPE_ROTATE = 5

fun createMaxAndMinEvent(scale:Float):GestureEvent=
    GestureEvent(GESTURE_EVENT_TYPE_MAX_AND_MIN, scaleFactor = scale)

fun createRotate(angle: Float): GestureEvent=GestureEvent(GESTURE_EVENT_TYPE_ROTATE, angle = angle)
放大缩小及旋转判断是使用ScaleGestureDetector通过手势去判断用户具体操作,代码写在GestureController类里
 val scaleGestureDetector by lazy {
        //是否在放大缩小中 0初始状态 1放大缩小 2旋转
        var progressType = "0"
        //记录上次缩放比例
        var preScale = 1f
        //记录当前缩放比例
        var curScale=1f
        ScaleGestureDetector(mainApp?.get(), object : ScaleGestureDetector.OnScaleGestureListener {
            override fun onScale(detector: ScaleGestureDetector?): Boolean {
                detector?.run {
                 val absX=   abs(currentSpanX - previousSpanX)
                 val absY=   abs(currentSpanY - previousSpanY)
                    if (progressType == "0" && (absX != 0f && absY != 0f)) {
                        progressType = if (progressType=="1"||(absX <50&&absY<150)) {
                                //放大缩小
                                "1"
                            } else {
                                //旋转
                                "2"
                            }
                    }
                    when (progressType) {
                        "1" -> {
                            curScale = if (preScale == 1f) {
                                scaleFactor
                            } else {
                                //当前的伸缩值*之前的伸缩值 保持连续性
                                scaleFactor * preScale
                            }
                            //当放大倍数大于2或者缩小倍数小于0.1倍 就不伸缩图片 返回true取消处理伸缩手势事件
                            if (curScale > 2 || curScale < 0.1) {
                                preScale = curScale
                            }
                            tapQueue.offer(GestureEventFactory.createMaxAndMinEvent(scaleFactor))

                        }
                        "2" -> {
                            //获取两指间的角度                           tapQueue.offer(GestureEventFactory.createRotate(currentSpan))

                        }
                        else -> Unit
                    }
                }
                return false
            }

            override fun onScaleBegin(detector: ScaleGestureDetector?): Boolean=true

            override fun onScaleEnd(detector: ScaleGestureDetector?) {
                //保存上一次伸缩值
                progressType = "0"
                preScale = curScale
            }

        })
    }
WorldActivity内initUI方法内添加调用
private fun initUi() {
        surfaceview.apply {
            setOnTouchListener { v, event ->
                v.performClick()
             gestureController.eventType =when(event.action){
                 MotionEvent.ACTION_MOVE->{
                     if (gestureController.eventType!=2){ 1
                     }else gestureController.eventType
                 }
                 ACTION_POINTER_2_DOWN,
                 ACTION_POINTER_2_UP->{
                     2
                 }
                 else->0
             }
                //在这里调用
                gestureController.scaleGestureDetector.onTouchEvent(event)
                gestureController.gestureDetector.onTouchEvent(event)

            }
            preserveEGLContextOnPause = true
            setEGLContextClientVersion(2)
            setEGLConfigChooser(8, 8, 8, 8, 16, 0)
            setRenderer(worldRenderController)
            renderMode = GLSurfaceView.RENDERMODE_CONTINUOUSLY
        }
    }

 然后HitTestService 类里面加入下面代码,重复的自行去掉

when (event.type) {
            //双击选中
            GestureEventFactory.GESTURE_EVENT_TYPE_DOUBLE_TAP -> {
                handleDoubleTapEvent(viewMatrix, projectionMatrix, event)
            }
            //选中后按住移动
            GestureEventFactory.GESTURE_EVENT_TYPE_SCROLL -> {
                selectedObject?.run {
                    setArAnchor(hitTest4Result(arFrame, arCamera, event.eventSecond).createAnchor())
                }
            }
            //单击
            GestureEventFactory.GESTURE_EVENT_TYPE_SINGLE_TAP_CONFIRMED -> {
                // Do not perform anything when an object is selected.
                selectedObject?.isSelected=false
                selectedObject = null
                handleSingleTapEvent(hitTest4Result(arFrame, arCamera, event.eventFirst))
            }
            //放大缩小
            GestureEventFactory.GESTURE_EVENT_TYPE_MAX_AND_MIN->{
                virtualObjects.forEach {
                    if (it.isSelected){
                            it.updateScaleFactor(event.scaleFactor)
                    }
                }
            }
            //旋转
            GestureEventFactory.GESTURE_EVENT_TYPE_ROTATE->{
                virtualObjects.forEach {
                    if (it.isSelected){
                        it.updateRotation(event.angle)
                    }
                }
            }
            else -> {
                LogUtil.error(TAG, "未知的运动事件类型,什么都不做.")
            }
        }

自此就完成了,下面贴上 放大缩小及旋转的方法其实官方有。

在VirtualObject 类里面加入

 private var mRotationAngle: Float=0f
    private var mScaleFactor: Float=0f
 /**
     * Obtain the anchor matrix data of the current virtual object.
     *
     * @return Anchor matrix data of the current virtual object.
     */
//    fun getModelAnchorMatrix(): FloatArray {
//        val modelMatrix = FloatArray(Constants.MATRIX_SIZE)
//        arAnchor.pose.toMatrix(modelMatrix, 0)
//        return FloatArray(Constants.MATRIX_SIZE).also {
//            Matrix.multiplyMM(it, 0, modelMatrix, 0, Constants.FACTOR_MODEL_MATRIX, 0)
//        }
//    }
    /**
     * 设置物体放大缩小
     */
    fun updateScaleFactor(scaleFactor: Float) {
        // 由外部设置缩放系数,在0.15f的缩放的基础上进行再次缩放
        mScaleFactor = 1f * scaleFactor
    }

    /**
     * 设置物体旋转
     */
    fun updateRotation(angle: Float) {
        // 由外部设置旋转角度
        mRotationAngle = angle
    }

    fun getModelAnchorMatrix(): FloatArray? {

        val modelMatrix = FloatArray(Constants.MATRIX_SIZE)
        arAnchor.pose.toMatrix(modelMatrix, 0)
        return FloatArray(Constants.MATRIX_SIZE).also {
            Matrix.multiplyMM(it, 0, modelMatrix, 0, Constants.FACTOR_MODEL_MATRIX, 0)
            // 将模型绕y轴旋转指定角度
            Matrix.rotateM(it, 0, mRotationAngle, 0f, 1f, 0f)
            // 将模型的x,y,z尺寸缩放指定的系数
            if (mScaleFactor != 0f) {
                Matrix.scaleM(it, 0, mScaleFactor, mScaleFactor, mScaleFactor)
            }
        }
    }

全部搞定,时间紧迫,写的不好将就看吧,因为公司网没法上github,只能后期再补传代码及实现效果了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值