要在不使用TransformableNode的情况下旋转模型,可以使用AR Session的onUpdate方法来手动更新模型的旋转。
以下是一个使用ARcore和Sceneform的代码示例,展示了如何通过手势旋转模型:
import android.content.Context;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.ar.core.Anchor;
import com.google.ar.core.Frame;
import com.google.ar.core.HitResult;
import com.google.ar.core.Plane;
import com.google.ar.core.Pose;
import com.google.ar.core.Session;
import com.google.ar.core.Trackable;
import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.ArSceneView;
import com.google.ar.sceneform.HitTestResult;
import com.google.ar.sceneform.Node;
import com.google.ar.sceneform.math.Quaternion;
import com.google.ar.sceneform.math.Vector3;
import com.google.ar.sceneform.rendering.ModelRenderable;
import com.google.ar.sceneform.ux.ArFragment;
import com.google.ar.sceneform.ux.BaseArFragment;
import com.google.ar.sceneform.ux.TransformableNode;
public class MainActivity extends AppCompatActivity {
private ArFragment arFragment;
private ModelRenderable modelRenderable;
private GestureDetector gestureDetector;
private Node modelNode;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.arFragment);
// 创建手势检测器
gestureDetector = new GestureDetector(this, new GestureListener());
// 点击屏幕时加载模型
arFragment.setOnTapArPlaneListener((hitResult, plane, motionEvent) -> {
if (modelRenderable == null) {
ModelRenderable.builder()
.setSource(this, Uri.parse("model.sfb"))
.build()
.thenAccept(renderable -> {
modelRenderable = renderable;
addModel(hitResult);
})
.exceptionally(throwable -> {
Toast.makeText(this, "无法加载模型", Toast.LENGTH_SHORT).show();
return null;
});
} else {
addModel(hitResult);
}
});
// 设置ArSceneView的触摸监听器
arFragment.getArSceneView().setOnTouchListener((view, motionEvent) -> {
return gestureDetector.onTouchEvent(motionEvent);
});
}
private void addModel(HitResult hitResult) {
Anchor anchor = hitResult.createAnchor();
AnchorNode anchorNode = new AnchorNode(anchor);
anchorNode.setParent(arFragment.getArSceneView().getScene());
modelNode = new Node();
modelNode.setParent(anchorNode);
modelNode.setRenderable(modelRenderable);
// 在指定位置缩放模型
modelNode.setLocalScale(new Vector3(0.2f, 0.2f, 0.2f));
}
private class GestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (modelNode != null) {
// 计算旋转角度
float deltaX = e2.getX() - e1.getX();
float deltaY = e2.getY() - e1.getY();
float rotation = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY) * 0.5f;
// 根据旋转角度旋转模型
Quaternion deltaRotationQuaternion = Quaternion.axisAngle(new Vector3(deltaY, deltaX, 0f), rotation);
Quaternion modelRotation = modelNode.getLocalRotation();
Quaternion newModelRotation = Quaternion.multiply(modelRotation, deltaRotationQuaternion);
modelNode.setLocalRotation(newModelRotation);
}
return true;
}
}
}
上述代码中,我们在onCreate方法中创建了一个ArFragment,并设置了点击屏幕时加载模型的监听器。当模型加载完成后,我们将其添加到AnchorNode中,并设置了其初始缩放比例。
在ArSceneView的触摸监听器中,我们使用GestureDetector来监听手势,在滑动屏幕时计算旋转角度,并根据旋转角度旋转模型。这样就能够实现在不使用TransformableNode的情况