我可以使用 AR CORE 场景形式 API 在表面渲染 2D 图像或 GIF 图像吗?
Can I render 2D images or GIF images on surface using AR CORE scene-form API?
我正在尝试识别一张二维图像,一旦图像 tracking/recognition 成功完成,
我必须在表面上放置一张 2D 图片或 GIF 图片。
我正在使用场景形式API。
我可以渲染 3D 图像和视频,但我的要求是渲染 GIF 图片或 2D 图片。
求推荐!!!
代码-
片段:
package com.example.setupboxscanner;
import com.google.ar.core.Config;
import com.google.ar.core.Session;
import com.google.ar.sceneform.ux.ArFragment;
public class CustomArFragment extends ArFragment {
@Override
protected Config getSessionConfiguration(Session session) {
Config config = new Config(session);
config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE);
config.setFocusMode(Config.FocusMode.AUTO);
session.configure(config);
this.getArSceneView().setupSession(session);
((MainActivity)getActivity()).setupDatabase(config, session);
return config;
}
}
主要活动:
package com.example.setupboxscanner;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.ar.core.Anchor;
import com.google.ar.core.AugmentedImage;
import com.google.ar.core.AugmentedImageDatabase;
import com.google.ar.core.Config;
import com.google.ar.core.Frame;
import com.google.ar.core.Session;
import com.google.ar.core.TrackingState;
import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.FrameTime;
import com.google.ar.sceneform.Scene;
import com.google.ar.sceneform.rendering.ModelRenderable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import java.util.Collection;
public class MainActivity extends AppCompatActivity implements Scene.OnUpdateListener {
private CustomArFragment arFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
arFragment = (CustomArFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
arFragment.getArSceneView().getScene().addOnUpdateListener(this);
}
public void setupDatabase(Config config, Session session){
Bitmap setTopBoxImagesFront = BitmapFactory.decodeResource(getResources(), R.drawable.front);
// Bitmap setTopBoxImagesRear = BitmapFactory.decodeResource(getResources(), R.drawable.rear);
AugmentedImageDatabase aid = new AugmentedImageDatabase(session);
aid.addImage("image1", setTopBoxImagesFront);
// aid.addImage("image2", setTopBoxImagesRear);
config.setAugmentedImageDatabase(aid);
}
@Override
public void onUpdate(FrameTime frameTime) {
Frame frame = arFragment.getArSceneView().getArFrame();
Collection<AugmentedImage> images = frame.getUpdatedTrackables(AugmentedImage.class);
for (AugmentedImage image : images) {
if(image.getTrackingState() == TrackingState.TRACKING) {
if(image.getName().equals("image1")) {
Anchor anchor = image.createAnchor(image.getCenterPose());
createModel(anchor);
}
}
}
}
// @TargetApi(24)
private void createModel(Anchor anchor) {
Log.e("-----><>>",""+Uri.parse("//android_assets/front.jpg"));
ModelRenderable.builder().setSource(this, Uri.parse("model.sfb")).build()
.thenAccept(modelRenderable -> placeModel(modelRenderable, anchor));
}
private void placeModel(ModelRenderable modelRenderable, Anchor anchor) {
AnchorNode anchorNode = new AnchorNode(anchor);
anchorNode.setRenderable(modelRenderable);
arFragment.getArSceneView().getScene().addChild(anchorNode);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
场景形式资产:
sceneform.asset('sampledata/ArcticFox_Posed.obj',
'default',
'sampledata/ArcticFox_Posed.sfa',
'src/main/assets/ArcticFox_Posed')
ActivityMain.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment"
android:name="com.example.setupboxscanner.CustomArFragment"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
感谢您的提问。我在尝试通过 ARCore 渲染 gif and/or 2D 图像时遇到了类似的问题。幸运的是,有一种非常简单的方法可以做到这一点。您可以将此 gif 图像视图 Adding gif image in an ImageView in android 用于新的 XML 布局文件。然后在将布局附加到节点(可以是锚节点或只是相对于相机的节点 [我称之为浮动节点])之后,使用 ViewRenderable 在 ARcore Session 中渲染该布局。您应该可以清楚地查看 gif and/or 图片。
在将使用 ViewRenderable 呈现的新 XML 布局中,我有这个视图来加载 gif:
<pl.droidsonroids.gif.GifImageView
android:layout_width="173dp"
android:layout_height="183dp"
android:src="@drawable/loading2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
我正在尝试识别一张二维图像,一旦图像 tracking/recognition 成功完成,
我必须在表面上放置一张 2D 图片或 GIF 图片。
我正在使用场景形式API。
我可以渲染 3D 图像和视频,但我的要求是渲染 GIF 图片或 2D 图片。
求推荐!!!
代码-
片段:
package com.example.setupboxscanner;
import com.google.ar.core.Config;
import com.google.ar.core.Session;
import com.google.ar.sceneform.ux.ArFragment;
public class CustomArFragment extends ArFragment {
@Override
protected Config getSessionConfiguration(Session session) {
Config config = new Config(session);
config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE);
config.setFocusMode(Config.FocusMode.AUTO);
session.configure(config);
this.getArSceneView().setupSession(session);
((MainActivity)getActivity()).setupDatabase(config, session);
return config;
}
}
主要活动:
package com.example.setupboxscanner;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.ar.core.Anchor;
import com.google.ar.core.AugmentedImage;
import com.google.ar.core.AugmentedImageDatabase;
import com.google.ar.core.Config;
import com.google.ar.core.Frame;
import com.google.ar.core.Session;
import com.google.ar.core.TrackingState;
import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.FrameTime;
import com.google.ar.sceneform.Scene;
import com.google.ar.sceneform.rendering.ModelRenderable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import java.util.Collection;
public class MainActivity extends AppCompatActivity implements Scene.OnUpdateListener {
private CustomArFragment arFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
arFragment = (CustomArFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
arFragment.getArSceneView().getScene().addOnUpdateListener(this);
}
public void setupDatabase(Config config, Session session){
Bitmap setTopBoxImagesFront = BitmapFactory.decodeResource(getResources(), R.drawable.front);
// Bitmap setTopBoxImagesRear = BitmapFactory.decodeResource(getResources(), R.drawable.rear);
AugmentedImageDatabase aid = new AugmentedImageDatabase(session);
aid.addImage("image1", setTopBoxImagesFront);
// aid.addImage("image2", setTopBoxImagesRear);
config.setAugmentedImageDatabase(aid);
}
@Override
public void onUpdate(FrameTime frameTime) {
Frame frame = arFragment.getArSceneView().getArFrame();
Collection<AugmentedImage> images = frame.getUpdatedTrackables(AugmentedImage.class);
for (AugmentedImage image : images) {
if(image.getTrackingState() == TrackingState.TRACKING) {
if(image.getName().equals("image1")) {
Anchor anchor = image.createAnchor(image.getCenterPose());
createModel(anchor);
}
}
}
}
// @TargetApi(24)
private void createModel(Anchor anchor) {
Log.e("-----><>>",""+Uri.parse("//android_assets/front.jpg"));
ModelRenderable.builder().setSource(this, Uri.parse("model.sfb")).build()
.thenAccept(modelRenderable -> placeModel(modelRenderable, anchor));
}
private void placeModel(ModelRenderable modelRenderable, Anchor anchor) {
AnchorNode anchorNode = new AnchorNode(anchor);
anchorNode.setRenderable(modelRenderable);
arFragment.getArSceneView().getScene().addChild(anchorNode);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
场景形式资产:
sceneform.asset('sampledata/ArcticFox_Posed.obj',
'default',
'sampledata/ArcticFox_Posed.sfa',
'src/main/assets/ArcticFox_Posed')
ActivityMain.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment"
android:name="com.example.setupboxscanner.CustomArFragment"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
感谢您的提问。我在尝试通过 ARCore 渲染 gif and/or 2D 图像时遇到了类似的问题。幸运的是,有一种非常简单的方法可以做到这一点。您可以将此 gif 图像视图 Adding gif image in an ImageView in android 用于新的 XML 布局文件。然后在将布局附加到节点(可以是锚节点或只是相对于相机的节点 [我称之为浮动节点])之后,使用 ViewRenderable 在 ARcore Session 中渲染该布局。您应该可以清楚地查看 gif and/or 图片。
在将使用 ViewRenderable 呈现的新 XML 布局中,我有这个视图来加载 gif:
<pl.droidsonroids.gif.GifImageView
android:layout_width="173dp"
android:layout_height="183dp"
android:src="@drawable/loading2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />