Closed kirankaushal closed 6 years ago
@kirankaushal
It works for me:
node.getScene().onRemoveChild(node.getParent())
node.setRenderable(null)
session.update()
But I'm not sure that it's correct way to remove model from screen
It's working for rendering.But I want to remove rendered Anchor node too.
I have removed added Achor until it's not rendered created node but I was not able to remove rendered node too.
Calling parent.removeChild(child) or node.setParent(null) is the correct way to remove a Node from the scene. You can do the same thing with an AnchorNode. Additionally, you can call anchorNode.getAnchor().detach to access the ARCore anchor and tell ARCore to stop tracking that anchor.
I tried to ditach anchorNode but it's not working
Can you please share your code with us? Thanks!
package com.example.nandakiran.sceneformoverview;
import android.content.Intent; import android.graphics.Bitmap; import android.icu.text.SimpleDateFormat; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.support.annotation.GuardedBy; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.support.design.widget.Snackbar; import android.support.v4.content.FileProvider; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.view.PixelCopy; import android.view.View; import android.widget.Button; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast;
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.Point; import com.google.ar.core.Trackable; import com.google.ar.core.TrackingState; import com.google.ar.sceneform.AnchorNode; import com.google.ar.sceneform.ArSceneView; import com.google.ar.sceneform.rendering.ModelRenderable; import com.google.ar.sceneform.rendering.Renderable; import com.google.ar.sceneform.rendering.ViewRenderable; import com.google.ar.sceneform.ux.ArFragment; import com.google.ar.sceneform.ux.TransformableNode;
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; import java.util.List; import java.util.concurrent.CompletableFuture;
public class SceneFormActivity extends AppCompatActivity { private ArFragment arFragment; private ModelRenderable andyRenderable; private PointerDrawable pointer = new PointerDrawable(); private boolean isTracking; private boolean isHitting; private ArSceneView arSceneView; private String TAG="SceneFormActivity"; @Nullable @GuardedBy("singleTapAnchorLock") private Anchor anchor; private Anchor anchor1; ImageButton imageButton; AnchorNode anchorNode;
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment);
imageButton=findViewById(R.id.ImageButtonClick);
imageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
takePhoto();
}
});
// When you build a Renderable, Sceneform loads its resources in the background while returning
// a CompletableFuture. Call thenAccept(), handle(), or check isDone() before calling get().
/* if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
ModelRenderable.builder()
.setSource(this, R.raw.andy)
.build()
.thenAccept(renderable -> andyRenderable = renderable)
.exceptionally(
throwable -> {
Toast toast =
Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
return null;
});
}
/ / arFragment.setOnTapArPlaneListener( (HitResult hitResult, Plane plane, MotionEvent motionEvent) -> { if (andyRenderable == null) { return; }
if (plane.getType() != Plane.Type.HORIZONTAL_UPWARD_FACING) {
return;
}
// Create the Anchor.
Anchor anchor = hitResult.createAnchor();
AnchorNode anchorNode = new AnchorNode(anchor);
anchorNode.setParent(arFragment.getArSceneView().getScene());
// Create the transformable andy and add it to the anchor.
TransformableNode andy = new TransformableNode(arFragment.getTransformationSystem());
andy.setParent(anchorNode);
andy.setRenderable(andyRenderable);
andy.select();
});*/
/* arFragment.getArSceneView().getScene().setOnUpdateListener(frameTime -> {
arFragment.onUpdate(frameTime);
onUpdate();
});*/
initializeGallery();
}
//
private void initializeGallery() {
LinearLayout gallery = findViewById(R.id.gallery_layout);
ImageView andy = new ImageView(this);
andy.setImageResource(R.drawable.droid_thumb);
andy.setPadding(10,10,10,10);
andy.setContentDescription("andy");
andy.setOnClickListener(view ->{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// Log.d(TAG, String.valueOf(arFragment.getArSceneView().getArFrame().getUpdatedAnchors()));
addObject(Uri.parse("andy.sfb"));
}
});
gallery.addView(andy);
ImageView cabin = new ImageView(this);
cabin.setImageResource(R.drawable.cabin_thumb);
cabin.setContentDescription("cabin");
cabin.setPadding(10,10,10,10);
cabin.setOnClickListener(view ->{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
addObject(Uri.parse("Cabin.sfb"));
}
});
gallery.addView(cabin);
ImageView house = new ImageView(this);
house.setImageResource(R.drawable.house_thumb);
house.setContentDescription("house");
house.setPadding(10,10,10,10);
house.setOnClickListener(view ->{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
addObject(Uri.parse("House.sfb"));
}
});
gallery.addView(house);
/*ImageView igloo = new ImageView(this);
igloo.setImageResource(R.drawable.igloo_thumb);
igloo.setContentDescription("igloo");
igloo.setPadding(10,10,10,10);
igloo.setOnClickListener(view ->{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
addObject(Uri.parse("igloo.sfb"));
}
});
gallery.addView(igloo);*/
Button button=new Button(this);
button.setText("Clear Anchor");
button.setPadding(15,15,15,15);
button.setOnClickListener(view ->{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setNewAnchor(null);
setNewAnchor1(null);
}
});
gallery.addView(button);
}
private void addObject(Uri model) {
Frame frame = arFragment.getArSceneView().getArFrame();
android.graphics.Point pt = getScreenCenter();
List<HitResult> hits;
if (frame != null ) {
hits = frame.hitTest(pt.x, pt.y);
for (HitResult hit : hits) {
Trackable trackable = hit.getTrackable();
if ((trackable instanceof Plane &&
((Plane) trackable).isPoseInPolygon(hit.getHitPose()))) {
placeObject(arFragment, hit.createAnchor(), model);
break;
}
}
}
}
private void placeObject(ArFragment arFragment, Anchor anchor, Uri model) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
CompletableFuture<Void> renderableFuture =
ModelRenderable.builder()
.setSource(arFragment.getContext(), model)
.build()
.thenAccept(renderable -> addNodeToScene(arFragment, anchor, renderable))
.exceptionally((throwable -> {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(throwable.getMessage())
.setTitle("Codelab error!");
AlertDialog dialog = builder.create();
dialog.show();
return null;
}));
}
}
private void addNodeToScene(ArFragment arFragment, Anchor anchor, Renderable renderable) {
AnchorNode anchorNode = new AnchorNode(anchor);
setNewAnchor(anchor);
TransformableNode node = new TransformableNode(arFragment.getTransformationSystem());
node.setRenderable(renderable);
node.setParent(anchorNode);
Log.d(TAG,"anchor: "+anchor);
Log.d(TAG,"anchor node: "+anchorNode.getAnchor());
arFragment.getArSceneView().getScene().addChild(anchorNode);
//setNewAnchor1(anchorNode.getAnchor());
node.select();
}
//code to create pointer
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void onUpdate() {
boolean trackingChanged = updateTracking();
View contentView = findViewById(android.R.id.content);
if (trackingChanged) {
if (isTracking) {
contentView.getOverlay().add(pointer);
} else {
contentView.getOverlay().remove(pointer);
}
contentView.invalidate();
}
if (isTracking) {
boolean hitTestChanged = updateHitTest();
if (hitTestChanged) {
pointer.setEnabled(isHitting);
contentView.invalidate();
}
}
}
private boolean updateTracking() {
Frame frame = arFragment.getArSceneView().getArFrame();
boolean wasTracking = isTracking;
isTracking = frame.getCamera().getTrackingState() == TrackingState.TRACKING;
return isTracking != wasTracking;
}
private boolean updateHitTest() {
Frame frame = arFragment.getArSceneView().getArFrame();
android.graphics.Point pt = getScreenCenter();
List<HitResult> hits;
boolean wasHitting = isHitting;
isHitting = false;
if (frame != null) {
hits = frame.hitTest(pt.x, pt.y);
for (HitResult hit : hits) {
Trackable trackable = hit.getTrackable();
if ((trackable instanceof Plane &&
((Plane) trackable).isPoseInPolygon(hit.getHitPose()))) {
isHitting = true;
break;
}
}
}
return wasHitting != isHitting;
}
private android.graphics.Point getScreenCenter() {
View vw = findViewById(android.R.id.content);
return new android.graphics.Point(vw.getWidth()/2, vw.getHeight()/2);
}
@GuardedBy("singleTapAnchorLock")
private void setNewAnchor(@Nullable Anchor newAnchor) {
if (anchor != null) {
anchor.detach();
}
anchor = newAnchor;
}
@GuardedBy("singleTapAnchorLock")
private void setNewAnchor1(AnchorNode anchorNode1) {
if(anchorNode!=null){
anchorNode.setParent(null);
}
anchorNode = anchorNode1;
}
private void takePhoto() {
final String filename = generateFilename();
ArSceneView view = arFragment.getArSceneView();
// Create a bitmap the size of the scene view.
final Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
Bitmap.Config.ARGB_8888);
// Create a handler thread to offload the processing of the image.
final HandlerThread handlerThread = new HandlerThread("PixelCopier");
handlerThread.start();
// Make the request to copy.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
PixelCopy.request(view, bitmap, (copyResult) -> {
if (copyResult == PixelCopy.SUCCESS) {
try {
saveBitmapToDisk(bitmap, filename);
} catch (IOException e) {
Toast toast = Toast.makeText(SceneFormActivity.this, e.toString(),
Toast.LENGTH_LONG);
toast.show();
return;
}
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content),
"Photo saved", Snackbar.LENGTH_LONG);
snackbar.setAction("Open in Photos", v -> {
File photoFile = new File(filename);
Uri photoURI = FileProvider.getUriForFile(SceneFormActivity.this,
SceneFormActivity.this.getPackageName() + ".ar.name.provider",
photoFile);
Intent intent = new Intent(Intent.ACTION_VIEW, photoURI);
intent.setDataAndType(photoURI, "image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
});
snackbar.show();
} else {
Toast toast = Toast.makeText(SceneFormActivity.this,
"Failed to copyPixels: " + copyResult, Toast.LENGTH_LONG);
toast.show();
}
handlerThread.quitSafely();
}, new Handler(handlerThread.getLooper()));
}
}
private void saveBitmapToDisk(Bitmap bitmap, String filename) throws IOException {
File out = new File(filename);
if (!out.getParentFile().exists()) {
out.getParentFile().mkdirs();
}
try (FileOutputStream outputStream = new FileOutputStream(filename);
ByteArrayOutputStream outputData = new ByteArrayOutputStream()) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputData);
outputData.writeTo(outputStream);
outputStream.flush();
outputStream.close();
} catch (IOException ex) {
throw new IOException("Failed to save bitmap to disk", ex);
}
}
private String generateFilename() {
String date =
null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
date = new SimpleDateFormat("yyyyMMddHHmmss", java.util.Locale.getDefault()).format(new Date());
}
return Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES) + File.separator + "Sceneform/" + date + "_screenshot.jpg";
}
}
I have made a setNewAnchor() method and called that method while A anchor hit on screen and also when I want to clear Anchor on Clear button click.
I had made changes in CodeLab SceneForm Project by Google
If I understand you correctly, you want to clear the anchor if an existing anchor is already in the scene? I do this here. This also moves the renderable nodes to be children of the new anchor.
It is good practice to not have a renderable set on the anchor node, but rather add a child node of the anchor node which has the renderable set.
/** Sets the new value of the current anchor. Detaches the old anchor, if it was non-null. */
private void setNewAnchor(Anchor newAnchor) {
AnchorNode newAnchorNode = null;
if (anchorNode != null && newAnchor != null) {
// Create a new anchor node and move the children over.
newAnchorNode = new AnchorNode(newAnchor);
newAnchorNode.setParent(arFragment.getArSceneView().getScene());
List<Node> children = new ArrayList<>(anchorNode.getChildren());
for (Node child : children) {
child.setParent(newAnchorNode);
}
} else if (anchorNode == null && newAnchor != null) {
// First anchor node created, add Andy as a child.
newAnchorNode = new AnchorNode(newAnchor);
newAnchorNode.setParent(arFragment.getArSceneView().getScene());
Node andy = new Node();
andy.setRenderable(andyRenderable);
andy.setParent(newAnchorNode);
} else {
// Just clean up the anchor node.
if (anchorNode != null && anchorNode.getAnchor() != null) {
anchorNode.getAnchor().detach();
anchorNode.setParent(null);
anchorNode = null;
}
}
anchorNode = newAnchorNode;
}
If you simply want to clear the scene you can do this by:
private void onClear() {
List<Node> children = new ArrayList<>(fragment.getArSceneView().getScene().getChildren());
for (Node node : children) {
if (node instanceof AnchorNode) {
if (((AnchorNode) node).getAnchor() != null) {
((AnchorNode) node).getAnchor().detach();
}
}
if (!(node instanceof Camera) && !(node instanceof Sun)) {
node.setParent(null);
}
}
}
Closing due to inactivity
this works for me
private void removePreviousAnchors() { List<Node> nodeList = new ArrayList<>(arFragment.getArSceneView().getScene().getChildren()); for (Node childNode : nodeList) { if (childNode instanceof AnchorNode) { if (((AnchorNode) childNode).getAnchor() != null) { ((AnchorNode) childNode).getAnchor().detach(); ((AnchorNode) childNode).setParent(null); } } } }
andyRenderable = finalAndy.get(); node= new Node(); node.setRenderable(andyRenderable);
node.setOnTapListener((v, event) -> { Toast.makeText( c, "I want to remove node from scene", Toast.LENGTH_LONG) .show(); });
i want to remove node from scene on tap of node
It clearly tells that,you miss a '{' . Close the parentheses wherever you are missing it.
On Tue, Apr 30, 2019, 10:47 PM Nana-asiamah98 notifications@github.com wrote:
@SheikhZayed https://github.com/SheikhZayed I'm getting an error with your code. '}' expected How do I resolve it?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google-ar/sceneform-android-sdk/issues/135#issuecomment-488069639, or mute the thread https://github.com/notifications/unsubscribe-auth/ACC6FFPBKSRIDWBNI73H5MTPTCH23ANCNFSM4FGHMEKA .
@SheikhZayed I fixed it but it deletes all the nodes created. I want to delete a single node. Please,help me out.
I want to clear the node without any button click , I want to stop rendering a video when image has been removed from the place while we are rendering the video on that image. The problem is I still see the video rendering on that part even the image has been removed.
When sceneform render anchor with TransformableNode node = new TransformableNode(arFragment.getTransformationSystem()); node.setRenderable(renderable); node.setParent(anchorNode); arFragment.getArSceneView().getScene().addChild(anchorNode); node.select();
then how to detect and ditach() Anchor from sceneform in android. I have ditached() an Anchor on clear button but after rendering its not ditaching .How to do it?