google-ar / sceneform-android-sdk

Sceneform SDK for Android
https://developers.google.com/sceneform/develop/
Apache License 2.0
1.23k stars 603 forks source link

Load .sfb file from Device Storage #64

Closed ltthuc1989 closed 6 years ago

ltthuc1989 commented 6 years ago

Hi develop team! I can create .sfb file by using "com.google.ar.sceneform.plugin".So I want to copy these file into my android storage folder.These code is for rendering 3D model from assets folder. CompletableFuture sunStage = ModelRenderable.builder().setSource(this, Uri.parse("Sol.sfb")).build(); How can i load 3D file from my own folder and render them in my app?.Thanks

tpsiaki commented 6 years ago

Hi @ltthuc1989 - thanks for the question!

To load from external storage, you'll want to use a file URI. You can build one of these from any java.io.File using the Uri.fromFile() api. Finally, in order to get a file that references your Android storage folder, you'll want to use one of the related external storage Android apis such as [Environment.getExternalStorageDirectory()](https://developer.android.com/reference/android/os/Environment#getExternalStorageDirectory())

ldima commented 6 years ago

@tpsiaki Hi. I created File, check file - it exist. But I get all time Unable to load Renderable registryId='file:///storage/emulated/0/Download/lion3.sfb' java.util.concurrent.CompletionException: java.io.FileNotFoundException: /storage/emulated/0/Download/lion3.sfb

String strSfb = "/storage/emulated/0/Download/lion3.sfb"; File file = new File(strSfb); file .exists() //=true {addObject(Uri.fromFile(file));}

ltthuc1989 commented 6 years ago

Hi @tpsiaki ! When i create 3D model with material file by using "com.google.ar.sceneform.plugin". It will automatic read material file from "sampledata" folder data then write these material path into .sfb file .these meterial path like this: samplers: [ { file: "sampledata/models/Sol/Sol_Transparent_Mat_baseColor.png", name: "Sol_Transparent_Mat_baseColor", pipeline_name: "Sol_Transparent_Mat_baseColor.png", }, { file: "sampledata/models/Sol/SolarFlare_Transparent_Mat_baseColor.png", name: "SolarFlare_Transparent_Mat_baseColor", pipeline_name: "SolarFlare_Transparent_Mat_baseColor.png", }, { file: "sampledata/models/Sol/SolarFlare_Transparent_Mat_emissive.png", name: "SolarFlare_Transparent_Mat_emissive", pipeline_name: "SolarFlare_Transparent_Mat_emissive.png", }, { file: "sampledata/models/Sol/Sol_Opaque_Mat_baseColor.png", name: "Sol_Opaque_Mat_baseColor", pipeline_name: "Sol_Opaque_Mat_baseColor.png", }, { file: "sampledata/models/Sol/Sol_Transparent_Mat_emissive.png", name: "Sol_Transparent_Mat_emissive", pipeline_name: "Sol_Transparent_Mat_emissive.png", }, { file: "sampledata/models/Sol/Sol_Opaque_Mat_emissive.png", name: "Sol_Opaque_Mat_emissive", pipeline_name: "Sol_Opaque_Mat_emissive.png", }, ], .I mean that if i put these material file into my Device Storage (storage/emuated/0/Download/app_folder/model/Sol/....) and .sfb file (....../Download/app_folder/sfb/...) .So i have to using text editor to edit sfb file one by one to change material file path(file: "sampledata/models/Sol/Sol_Opaque_Mat_baseColor.png )to (file:storage/emuated/0/Download/app_folder/model/Sol/..) is that right?thanks

tpsiaki commented 6 years ago

@ltthuc1989 - the file paths referenced in the .sfa file are only used to build the .sfb file on your development machine. The content in these files is bundled into the .sfb file, and the .sfb file is the only artifact used at runtime. This is why we recommend that you place models in the sampledata folder since that folder is not bundled into your apk.

So, you should leave the file paths in the .sfa pointing at the locations of the corresponding files on your development machine, and then build the .sfb. Then place the .sfb in your device storage, and you should be able to load the .sfb directly from there.

ltthuc1989 commented 6 years ago

Hi @tpsiaki ! i have got it.Thank so much :-)

malik-at-work commented 6 years ago

@ldima The URI based file loading isn't looking at external storage. Right now it's only looking for application assets using file:// and remote uris starting with http://

We will track this issue at https://github.com/google-ar/sceneform-android-sdk/issues/79

scolar commented 6 years ago

you can load .sfb file from sdcard like this: // sdcard File file = new File("/storage/emulated/0/ar/model.sfb"); Callable callable = new Callable() { @Override public InputStream call() throws Exception { InputStream inputStream = new FileInputStream(file); return inputStream; } }; FutureTask task = new FutureTask<>(callable); new Thread(task).start();

    ModelRenderable.builder()
            .setSource(this, callable)
            .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;
                    });
ishaang10 commented 5 years ago

@scolar can you please update it.... i tried this but my app is crashing. i have checked for file.exists() and it returned true so the file is there.

thanks

chnouman commented 5 years ago

I'm downloading my models this way:

fun downloadFile(downloadSFB: String) {
        var downloadManager: DownloadManager

        downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
        val uri = Uri.parse(downloadSFB)
        val request = DownloadManager.Request(uri)
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
        request.setDestinationInExternalFilesDir(this,Environment.DIRECTORY_DOWNLOADS, "andy.sfb")
        val reference = downloadManager.enqueue(request)
    }

after downloading I'm showing it as:

var fileX = File("storage/emulated/0/Android/data/com.gathergood.calum.ardemo/files/Download/andy.sfb");

        var callable: Callable<InputStream> = Callable<InputStream> {
            FileInputStream(fileX);
        }
        ModelRenderable.builder()
                .setSource(applicationContext, callable)
                .build()
                .thenAccept {
                    currentModelRenderable = it
                }
                .exceptionally {
                            Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG).show();
                            return@exceptionally null

                }
iShelar commented 4 years ago

I'm downloading my models this way:

fun downloadFile(downloadSFB: String) {
     var downloadManager: DownloadManager

     downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
     val uri = Uri.parse(downloadSFB)
     val request = DownloadManager.Request(uri)
     request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
     request.setDestinationInExternalFilesDir(this,Environment.DIRECTORY_DOWNLOADS, "andy.sfb")
     val reference = downloadManager.enqueue(request)
 }

after downloading I'm showing it as:

var fileX = File("storage/emulated/0/Android/data/com.gathergood.calum.ardemo/files/Download/andy.sfb");

        var callable: Callable<InputStream> = Callable<InputStream> {
            FileInputStream(fileX);
        }
        ModelRenderable.builder()
                .setSource(applicationContext, callable)
                .build()
                .thenAccept {
                    currentModelRenderable = it
                }
                .exceptionally {
                            Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG).show();
                            return@exceptionally null

                }

I tried all this...But it cant render the model...app is working fine...but It cant load the model from local storage.

chnouman commented 4 years ago

@iShelar make sure you are using correct permissions.