Created
August 31, 2020 14:08
-
-
Save chydee/8e11e8c87e930136af19db46dda83f5b to your computer and use it in GitHub Desktop.
Render 3D Objects or Scene in android without ARCore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<com.google.ar.sceneform.SceneView | |
android:id="@+id/scene_view" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:background="@color/deep_teal"/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dependencies{ | |
... | |
//sceneform | |
implementation 'com.google.ar.sceneform:core:1.17.1' | |
implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.17.1' | |
implementation 'com.google.ar.sceneform:assets:1.17.1' | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dependencies { | |
... | |
//To connect to firebase | |
classpath 'com.google.gms:google-services:4.3.3' | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
References: | |
//ARCore Cupcakes #1 — Render a Scene without AR for phones without ARCore | |
https://medium.com/@harivigneshjayapalan/arcore-cupcakes-1-render-a-scene-without-ar-for-phones-without-arcore-27d61a43a130 | |
//Build and interact with a scene | |
https://developers.google.com/sceneform/develop/build-scene | |
//Getting started with firebase storage | |
https://firebase.google.com/docs/storage/android/start |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Classes declaration | |
private Node sketchNode; | |
private Scene scene; | |
private SceneView sceneView; | |
private StorageReference modelRef; | |
private FirebaseStorage storage; | |
private RelativeLayout sceneContainer; | |
private ModelRenderable renderable; | |
//End of Classes declaration | |
//Initialize FireBase App | |
FirebaseApp.initializeApp(this); | |
//TODO: Assign values or initialize the variables created above | |
//Get Scene | |
scene = sceneView.getScene(); | |
// The scene's Camera node is placed at the origin (position 0,0,0) and facing forward (direction 0,0,-1). | |
// Because the camera's position and rotation is not tied to AR motion tracking, you can reposition or animate it like any other node. | |
Camera camera = sceneView.getScene().getCamera(); | |
camera.setLocalRotation(Quaternion.axisAngle(Vector3.right(), -30.0f)); | |
/** | |
* Downloads file from FirebaseStorage and pass it to the method that handles | |
* the rendering | |
*/ | |
private void setUpRenderer(){String fileName){ | |
//Get the storage refernce with the fileName | |
modelRef = storage.getReference().child(fileName.toLowerCase() + ".glb"); | |
try { | |
//Create a Temporary File | |
File file = File.createTempFile("objects", "glb"); | |
modelRef.getFile(file).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() { | |
@Override | |
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) { | |
sceneContainer.setVisibility(View.VISIBLE); //Sets the container visible to Visible | |
buildModel(file); //Handle the rendering | |
} | |
}); | |
} catch (IOException e) { | |
e.printStackTrace(); //catch the exception when something goes wrong | |
} | |
} | |
/** | |
* load the 3D model in the space | |
* | |
* @param uri - URI of the model, imported using Sceneform plugin | |
*/ | |
private void buildModel(File uri) { | |
RenderableSource source = RenderableSource.builder() | |
.setSource(this, Uri.parse(uri.getPath()), RenderableSource.SourceType.GLB) // Does the conversion | |
.setRecenterMode(RenderableSource.RecenterMode.ROOT) | |
.build(); | |
ModelRenderable.builder() | |
.setSource(this, source) | |
.build() | |
.thenAccept(modelRenderable -> { | |
Toast.makeText(getApplicationContext(), "Model Built", Toast.LENGTH_SHORT).show(); | |
renderable = modelRenderable; | |
addToNode(renderable); | |
}) | |
.exceptionally(exception -> { | |
new AlertDialog.Builder(this.getApplicationContext()) | |
.setMessage(exception.getMessage()) | |
.setTitle("Error!") | |
.create().show(); | |
return null; | |
}); | |
} | |
private void addToNode(ModelRenderable modelRenderable) { | |
sketchNode = new Node(); | |
sketchNode.setParent(scene); | |
sketchNode.setLocalPosition(new Vector3(0f, -3f, -5f)); //Sets Object postion on the screen | |
sketchNode.setLocalScale(new Vector3(3f, 3f, 3f)); //Sets objects scale | |
sketchNode.setName("bucket"); | |
sketchNode.setRenderable(modelRenderable); | |
scene.addChild(sketchNode); | |
} | |
//Then call setUpRenderer inside the onDetectClick() method | |
// This block checks for the probability with the highest value and then pass the label to | |
// the setUp Renderer as the fileName | |
if ((classifier.getProbability(index) * 100) > 50) { | |
//Toast.makeText(this, classifier.getLabel(index), Toast.LENGTH_SHORT).show(); | |
setUpRenderer(classifier.getLabel(index)); | |
} | |
//This method handles the release of resources and resetting everything to the default state | |
private void clear() { | |
if (sketchNode != null) { | |
sketchNode.setParent(null); | |
sketchNode.setRenderable(null); | |
sceneView.getScene().removeChild(sketchNode); | |
} | |
resetView(); // Refer to resetView(); in your code | |
} | |
//Close the modal and reset the resources | |
public void onCloseClick(View view) { | |
sceneContainer.setVisibility(View.GONE); | |
if (sketchNode != null) { | |
sketchNode.setParent(null); | |
sketchNode.setRenderable(null); | |
sceneView.getScene().removeChild(sketchNode); | |
} | |
} | |
//Override the following | |
@Override | |
public void onPause() { | |
super.onPause(); | |
sceneView.pause(); | |
} | |
@Override | |
public void onResume() { | |
super.onResume(); | |
try { | |
sceneView.resume(); | |
} catch (CameraNotAvailableException e) { | |
e.printStackTrace(); | |
} | |
} | |
@Override | |
public void onDestroy() { | |
super.onDestroy(); | |
sceneView.destroy(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment