Home > OS >  Three.js Cordova - How to load textures without the use of a server/http?
Three.js Cordova - How to load textures without the use of a server/http?

Time:12-13

I'm trying to make a Cordova game using Three.js where it could be playable Offline, but it seems Three.js is very keen on making it mandatory to serve texture files via http. Is there a way around this? I'm desperately trying to avoid using a Node.js server for my game, if possible

Before you mention it can't be done, there are plenty of games on Google Play/App Store that are 3D and work offline, e.g Temple Run, Match 3D, ect. How do these work?

Since trying to load GLB/GLTF models, have to use import {GLTF} method in my index.js file, which my index.html file needs index.js to be declared as a module, which in turn gets hit with a CORS

I've tried converting my .glb files to .json and using Three.js's built-in ObjectLoader, but I get an error THREE.ObjectLoader: Can't load resources/models/test.json

index.html

 <html>
     <head>
        <title>Test</title>
        <meta charset="utf-8">
        <meta http-equiv="Content-Security-Policy" content="default-src * self blob: data: gap:; style-src * self 'unsafe-inline' blob: data: gap:; script-src * 'self' 'unsafe-eval' 'unsafe-inline' blob: data: gap:; object-src * 'self' blob: data: gap:; img-src * self 'unsafe-inline' blob: data: gap:; connect-src self * 'unsafe-inline' blob: data: gap:; frame-src * self blob: data: gap:;">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
        <meta name="color-scheme" content="light dark">
        <link rel="stylesheet" href="css/styles.css">
    
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/three.min.js"></script>
        <script type="text/javascript" src="js/jquery-3.5.1.min.js">     </script>
    
        <script type="text/javascript" src="js/OrbitControls.js"></script>
        <script type="module" src="loaders/GLTFLoader.js"></script>
        <script type="module" src="js/index.js"></script>
     </head>
     <body>
        <div id="screen-gameplay" ></div>
     </body>
 </html>

index.js

//When I remove this `import`, and change the `type = "module"` to
//`type="text/javascript" from `<script type="module" src="js/index.js"></script>`,
//it works fine
import { GLTFLoader } from '../loaders/GLTFLoader.js';

const loader = new THREE.ObjectLoader();

function loadModel(path){
    loader.load(
        // resource URL
        path,

        // onl oad callback
        // Here the loaded data is assumed to be an object
        function ( obj ) {
            // Add the loaded object to the scene
            scene.add( obj );
        },

        // onProgress callback
        function ( xhr ) {
            console.log( (xhr.loaded / xhr.total * 100)   '% loaded' );
        },

        // one rror callback
        function ( err ) {
            console.error( 'An error happened' );
        }
    );
}

loadModel('resources/models/test.json');

config.xml

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.example.test" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>Test</name>
    <description>
        Test
    </description>
    <author email="[email protected]" href="http://cordova.io">
        Test
    </author>
    <content src="index.html" />
    <access origin="*" />
    <allow-navigation href="*"/>
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <preference name="AndroidXEnabled" value="true" />
    <preference name="android-minSdkVersion" value="22" />
    <preference name="AndroidInsecureFileModeEnabled" value="true" />
    <platform name="android">
        <preference name="AndroidBlacklistSecureSocketProtocols" value="SSLv3,TLSv1" />
        <resource-file src="www/audio/zombie.wav" target="app/src/main/res/raw/zombie.wav" />
        <allow-intent href="market:*" />
        <preference name="Orientation" value="landscape" /> 
        <preference name="Fullscreen" value="true" />
        <preference name="AndroidXEnabled" value="true" />
        <preference name="StatusBarOverlaysWebView" value="false" />
        <preference name="AndroidInsecureFileModeEnabled" value="true" />
    </platform>
    <platform name="ios">
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
    </platform>
    <platform name="browser">
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
    </platform>
</widget>

Plugin List

cordova-custom-config 5.1.0 "cordova-custom-config"
cordova-plugin-androidx-adapter 1.1.3 "cordova-plugin-androidx-adapter"
cordova-plugin-badge 0.8.8 "Badge"
cordova-plugin-cors 1.3.0 "CORS"
cordova-plugin-device-motion 2.0.1 "Device Motion"
cordova-plugin-device-orientation 2.0.1 "Device Orientation"
cordova-plugin-device 2.0.3 "Device"
cordova-plugin-fullscreen 1.3.0 "cordova-plugin-fullscreen"
cordova-plugin-local-notification 0.9.3 "LocalNotification"
cordova-plugin-screen-orientation 3.0.2 "Screen Orientation"
cordova-plugin-vibration 3.1.1 "Vibration"
cordova-plugin-whitelist 1.3.5 "Whitelist"
cordova-plugin-wkwebview-engine 1.2.2 "Cordova WKWebView Engine"
cordova-plugin-wkwebviewxhrfix 0.1.0 "WKWebView XHR Fix"
es6-promise-plugin 4.2.2 "Promise"

Folders & Files Structure (Omitted most irrelevant files)

www
|_ audio
|_ build
|___ three.js
|___ three.module.js
|___ three.min.js
|_ css
|___ styles.css
|_ img
|_ js
|___ index.js
|___ jquery.js
|___ three.js
|___ orbitControls.js
|_ loaders
|___ GLTFLoader.js
|_ resources
|___ skybox
|___ models
|_____ test.json
|_____ test.glb
|_ index.html

Android Studio Logcat (Debug)

2021-12-12 18:29:20.264 10578-10578/? I/om.example.enz: Late-enabling -Xcheck:jni
2021-12-12 18:29:20.264 10578-10578/? I/om.example.enz: Late-enabling -Xcheck:jni
2021-12-12 18:29:20.279 10578-10578/? E/USNET: USNET: appName: com.example.enzy
2021-12-12 18:29:20.276 1360-2387/? W/System.err:     at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30)
2021-12-12 18:29:20.264 10578-10578/? I/om.example.enz: Late-enabling -Xcheck:jni
2021-12-12 18:29:20.280 10578-10578/? D/ProcessState: Binder ioctl to enable oneway spam detection failed: Invalid argument
2021-12-12 18:29:20.279 10578-10578/? E/USNET: USNET: appName: com.example.enzy
2021-12-12 18:29:20.282 10578-10578/? D/ActivityThread: setConscryptValidator
2021-12-12 18:29:20.282 10578-10578/? D/ActivityThread: setConscryptValidator - put
2021-12-12 18:29:20.280 10578-10578/? D/ProcessState: Binder ioctl to enable oneway spam detection failed: Invalid argument
2021-12-12 18:29:20.282 10578-10578/? D/ActivityThread: setConscryptValidator
2021-12-12 18:29:20.282 10578-10578/? D/ActivityThread: setConscryptValidator - put
2021-12-12 18:29:20.279 10578-10578/? E/USNET: USNET: appName: com.example.enzy
2021-12-12 18:29:20.280 10578-10578/? D/ProcessState: Binder ioctl to enable oneway spam detection failed: Invalid argument
2021-12-12 18:29:20.282 10578-10578/? D/ActivityThread: setConscryptValidator
2021-12-12 18:29:20.282 10578-10578/? D/ActivityThread: setConscryptValidator - put
2021-12-12 18:29:20.293 10578-10578/com.example.enzy D/ActivityThread: handleBindApplication()   app=com.example.enzy
2021-12-12 18:29:20.293 10578-10578/com.example.enzy D/CompatibilityChangeReporter: Compat change id reported: 171979766; UID 10413; state: DISABLED
2021-12-12 18:29:20.298 10578-10578/com.example.enzy D/ApplicationLoaders: Returning zygote-cached class loader: /system/framework/android.test.base.jar
2021-12-12 18:29:20.330 10578-10578/com.example.enzy D/LoadedApk: LoadedApk::makeApplication() appContext.mOpPackageName=com.example.enzy appContext.mBasePackageName=com.example.enzy
2021-12-12 18:29:20.330 10578-10578/com.example.enzy D/NetworkSecurityConfig: No Network Security Config specified, using platform default
2021-12-12 18:29:20.338 10578-10578/com.example.enzy D/NetworkSecurityConfig: No Network Security Config specified, using platform default
2021-12-12 18:29:20.343 10578-10578/com.example.enzy D/ActivityThread: handleBindApplication() --
2021-12-12 18:29:20.347 10578-10602/com.example.enzy I/AdrenoGLES-0: QUALCOMM build                   : b25f720, I2fb6e682e6
Build Date                       : 09/14/21
OpenGL ES Shader Compiler Version: EV031.35.01.09
Local Branch                     : CLDebug0914
Remote Branch                    : 
Remote Branch                    : 
Reconstruct Branch               : 
2021-12-12 18:29:20.347 10578-10602/com.example.enzy I/AdrenoGLES-0: Build Config                     : S P 10.0.7 AArch64
2021-12-12 18:29:20.347 10578-10602/com.example.enzy I/AdrenoGLES-0: Driver Path                      : /vendor/lib64/egl/libGLESv2_adreno.so
2021-12-12 18:29:20.349 10578-10602/com.example.enzy I/AdrenoGLES-0: PFP: 0x016dc094, ME: 0x00000000
2021-12-12 18:29:20.367 10578-10578/com.example.enzy I/CordovaLog: Changing log level to DEBUG(3)
2021-12-12 18:29:20.367 10578-10578/com.example.enzy I/CordovaActivity: Apache Cordova native platform version 10.1.1 is starting
2021-12-12 18:29:20.367 10578-10578/com.example.enzy D/CordovaActivity: CordovaActivity.onCreate()
2021-12-12 18:29:20.372 10578-10578/com.example.enzy I/DecorView: [INFO] isPopOver=false, config=true
2021-12-12 18:29:20.372 10578-10578/com.example.enzy I/DecorView: updateCaptionType >> DecorView@554fcad[], isFloating=false, isApplication=true, hasWindowControllerCallback=true, hasWindowDecorCaption=false
2021-12-12 18:29:20.372 10578-10578/com.example.enzy D/DecorView: setCaptionType = 0, this = DecorView@554fcad[]
2021-12-12 18:29:20.387 10578-10578/com.example.enzy I/WebViewFactory: Loading com.google.android.webview version 96.0.4664.92 (code 466409234)
2021-12-12 18:29:20.397 10578-10578/com.example.enzy W/om.example.enz: Accessing hidden method Landroid/os/Trace;->isTagEnabled(J)Z (unsupported, reflection, allowed)
2021-12-12 18:29:20.397 10578-10578/com.example.enzy W/om.example.enz: Accessing hidden method Landroid/os/Trace;->traceBegin(JLjava/lang/String;)V (unsupported, reflection, allowed)
2021-12-12 18:29:20.397 10578-10578/com.example.enzy W/om.example.enz: Accessing hidden method Landroid/os/Trace;->traceEnd(J)V (unsupported, reflection, allowed)
2021-12-12 18:29:20.397 10578-10578/com.example.enzy W/om.example.enz: Accessing hidden method Landroid/os/Trace;->asyncTraceBegin(JLjava/lang/String;I)V (unsupported, reflection, allowed)
2021-12-12 18:29:20.397 10578-10578/com.example.enzy W/om.example.enz: Accessing hidden method Landroid/os/Trace;->asyncTraceEnd(JLjava/lang/String;I)V (unsupported, reflection, allowed)
2021-12-12 18:29:20.398 10578-10578/com.example.enzy I/cr_WVCFactoryProvider: Loaded version=96.0.4664.92 minSdkVersion=29 isBundle=true multiprocess=true packageId=2
2021-12-12 18:29:20.409 10578-10578/com.example.enzy I/cr_LibraryLoader: Successfully loaded native library
2021-12-12 18:29:20.409 10578-10578/com.example.enzy I/cr_CachingUmaRecorder: Flushed 8 samples from 8 histograms.
2021-12-12 18:29:20.414 10578-10611/com.example.enzy E/SchedPolicy: Failed to find cgroup for tid 10578
2021-12-12 18:29:20.429 10578-10615/com.example.enzy W/chromium: [WARNING:dns_config_service_android.cc(153)] Failed to read DnsConfig.
2021-12-12 18:29:20.439 10578-10578/com.example.enzy D/CompatibilityChangeReporter: Compat change id reported: 171228096; UID 10413; state: ENABLED
2021-12-12 18:29:20.458 10578-10578/com.example.enzy W/om.example.enz: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (unsupported, reflection, allowed)
2021-12-12 18:29:20.458 10578-10578/com.example.enzy W/om.example.enz: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (unsupported, reflection, allowed)
2021-12-12 18:29:20.462 10578-10578/com.example.enzy D/SystemWebViewEngine: CordovaWebView is running on device made by: samsung
2021-12-12 18:29:20.462 10578-10578/com.example.enzy D/SystemWebViewEngine: Enabled insecure file access
2021-12-12 18:29:20.463 10578-10578/com.example.enzy D/PluginManager: init()
2021-12-12 18:29:20.465 10578-10578/com.example.enzy D/PluginManager: getPlugin - put: CordovaAllowListPlugin
2021-12-12 18:29:20.465 10578-10578/com.example.enzy D/PluginManager: startupPlugins: put - Badge
2021-12-12 18:29:20.465 10578-10578/com.example.enzy D/PluginManager: startupPlugins: put - Device
2021-12-12 18:29:20.465 10578-10578/com.example.enzy D/PluginManager: startupPlugins: put - Accelerometer
2021-12-12 18:29:20.465 10578-10578/com.example.enzy D/PluginManager: startupPlugins: put - Compass
2021-12-12 18:29:20.465 10578-10578/com.example.enzy D/PluginManager: startupPlugins: put - AndroidFullScreen
2021-12-12 18:29:20.465 10578-10578/com.example.enzy D/PluginManager: startupPlugins: put - LocalNotification
2021-12-12 18:29:20.465 10578-10578/com.example.enzy D/PluginManager: startupPlugins: put - CDVOrientation
2021-12-12 18:29:20.465 10578-10578/com.example.enzy D/PluginManager: startupPlugins: put - CoreAndroid
2021-12-12 18:29:20.465 10578-10578/com.example.enzy D/CordovaWebViewImpl: >>> loadUrl(file:///android_asset/www/index.html)
2021-12-12 18:29:20.467 10578-10621/com.example.enzy W/om.example.enz: Accessing hidden method Landroid/media/AudioManager;->getOutputLatency(I)I (unsupported, reflection, allowed)
2021-12-12 18:29:20.472 10578-10621/com.example.enzy W/cr_media: Requires BLUETOOTH permission
2021-12-12 18:29:20.472 10578-10578/com.example.enzy D/CordovaActivity: Started the activity.
2021-12-12 18:29:20.475 10578-10578/com.example.enzy D/CordovaActivity: Resumed the activity.
2021-12-12 18:29:20.476 10578-10578/com.example.enzy I/MSHandlerLifeCycle: isMultiSplitHandlerRequested: ignored. pkg=com.example.enzy parent=null callers=com.android.internal.policy.DecorView.setVisibility:4216 android.app.ActivityThread.handleResumeActivity:5285 android.app.servertransaction.ResumeActivityItem.execute:54 android.app.servertransaction.ActivityTransactionItem.execute:45 android.app.servertransaction.TransactionExecutor.executeLifecycleState:176 
2021-12-12 18:29:20.476 10578-10578/com.example.enzy I/MSHandlerLifeCycle: removeMultiSplitHandler: no exist. decor=DecorView@554fcad[]
2021-12-12 18:29:20.479 10578-10602/com.example.enzy D/NativeCustomFrequencyManager: [NativeCFMS] BpCustomFrequencyManager::BpCustomFrequencyManager()
2021-12-12 18:29:20.480 10578-10578/com.example.enzy D/InsetsSourceConsumer: setRequestedVisible: visible=false, type=21, host=com.example.enzy/com.example.enzy.MainActivity, from=android.view.InsetsSourceConsumer.hide:242 android.view.InsetsController.collectSourceControls:1214 android.view.InsetsController.controlAnimationUnchecked:1076 android.view.InsetsController.applyAnimation:1455 android.view.InsetsController.applyAnimation:1436 android.view.InsetsController.hide:1005 android.view.InsetsController.hide:980 android.view.ViewRootImpl.controlInsetsForCompatibility:3037 android.view.ViewRootImpl.setView:1504 android.view.WindowManagerGlobal.addView:488 
2021-12-12 18:29:20.481 10578-10578/com.example.enzy D/InsetsSourceConsumer: setRequestedVisible: visible=false, type=20, host=com.example.enzy/com.example.enzy.MainActivity, from=android.view.InsetsSourceConsumer.hide:242 android.view.InsetsController.collectSourceControls:1214 android.view.InsetsController.controlAnimationUnchecked:1076 android.view.InsetsController.applyAnimation:1455 android.view.InsetsController.applyAnimation:1436 android.view.InsetsController.hide:1005 android.view.InsetsController.hide:980 android.view.ViewRootImpl.controlInsetsForCompatibility:3037 android.view.ViewRootImpl.setView:1504 android.view.WindowManagerGlobal.addView:488 
2021-12-12 18:29:20.481 10578-10578/com.example.enzy D/InsetsSourceConsumer: setRequestedVisible: visible=false, type=1, host=com.example.enzy/com.example.enzy.MainActivity, from=android.view.InsetsSourceConsumer.hide:242 android.view.InsetsController.collectSourceControls:1214 android.view.InsetsController.controlAnimationUnchecked:1076 android.view.InsetsController.applyAnimation:1455 android.view.InsetsController.applyAnimation:1436 android.view.InsetsController.hide:1005 android.view.InsetsController.hide:980 android.view.ViewRootImpl.controlInsetsForCompatibility:3037 android.view.ViewRootImpl.setView:1504 android.view.WindowManagerGlobal.addView:488 
2021-12-12 18:29:20.481 10578-10578/com.example.enzy D/InsetsSourceConsumer: setRequestedVisible: visible=false, type=0, host=com.example.enzy/com.example.enzy.MainActivity, from=android.view.InsetsSourceConsumer.hide:242 android.view.InsetsController.collectSourceControls:1214 android.view.InsetsController.controlAnimationUnchecked:1076 android.view.InsetsController.applyAnimation:1455 android.view.InsetsController.applyAnimation:1436 android.view.InsetsController.hide:1005 android.view.InsetsController.hide:980 android.view.ViewRootImpl.controlInsetsForCompatibility:3037 android.view.ViewRootImpl.setView:1504 android.view.WindowManagerGlobal.addView:488 
2021-12-12 18:29:20.484 10578-10578/com.example.enzy I/ViewRootImpl@3068e7c[MainActivity]: setView = com.android.internal.policy.DecorView@554fcad TM=true
2021-12-12 18:29:20.484 10578-10578/com.example.enzy I/MSHandlerLifeCycle: isMultiSplitHandlerRequested: windowingMode=1 isFullscreen=true isPopOver=false isHidden=false skipActivityType=false isHandlerType=true this: DecorView@554fcad[MainActivity]
2021-12-12 18:29:20.484 10578-10578/com.example.enzy I/MSHandlerLifeCycle: removeMultiSplitHandler: no exist. decor=DecorView@554fcad[MainActivity]
2021-12-12 18:29:20.509 10578-10578/com.example.enzy I/ViewRootImpl@3068e7c[MainActivity]: Relayout returned: old=(0,0,3200,1440) new=(100,0,3200,1440) req=(3200,1440)0 dur=6 res=0x7 s={true 508994645632} ch=true fn=-1
2021-12-12 18:29:20.512 10578-10602/com.example.enzy D/hw-ProcessState: Binder ioctl to enable oneway spam detection failed: Invalid argument
2021-12-12 18:29:20.537 10578-10602/com.example.enzy I/BufferQueueProducer: [ViewRootImpl@3068e7c[MainActivity]#0(BLAST Consumer)0](id:295200000000,api:1,p:10578,c:10578) queueBuffer: queued for the first time.
2021-12-12 18:29:20.539 10578-10602/com.example.enzy D/OpenGLRenderer: GPIS:: SetUp Pid : 10578    Tid : 10602
2021-12-12 18:29:20.558 10578-10578/com.example.enzy I/View: draw TL bounds[ Rect(0, 0 - 101, 101) ] color[ ff000000 ] this - DecorView@554fcad[MainActivity]
2021-12-12 18:29:20.558 10578-10578/com.example.enzy I/View: draw BL bounds[ Rect(0, 1339 - 101, 1440) ] color[ ff000000 ] this - DecorView@554fcad[MainActivity]
2021-12-12 18:29:20.558 10578-10578/com.example.enzy D/CordovaWebViewImpl: onPageDidNavigate(file:///android_asset/www/index.html)
2021-12-12 18:29:20.558 10578-10578/com.example.enzy D/PluginManager: postMessage: onPageStarted
2021-12-12 18:29:20.558 10578-10578/com.example.enzy I/ViewRootImpl@3068e7c[MainActivity]: MSG_WINDOW_FOCUS_CHANGED 1 1
2021-12-12 18:29:20.559 10578-10578/com.example.enzy D/InputMethodManager: startInputInner - Id : 0
2021-12-12 18:29:20.559 10578-10578/com.example.enzy I/InputMethodManager: startInputInner - mService.startInputOrWindowGainedFocus
2021-12-12 18:29:20.563 10578-10578/com.example.enzy D/InputMethodManager: startInputInner - Id : 0
2021-12-12 18:29:20.583 10578-10578/com.example.enzy D/JsMessageQueue: Set native->JS mode to EvalBridgeMode
2021-12-12 18:29:20.674 10578-10685/com.example.enzy D/PluginManager: getPlugin - put: CoreAndroid
2021-12-12 18:29:20.675 10578-10578/com.example.enzy D/PluginManager: postMessage: spinner
2021-12-12 18:29:20.681 10578-10685/com.example.enzy I/ShortcutBadger: Checking if platform supports badge counters, attempt 1/3.
2021-12-12 18:29:20.686 10578-10685/com.example.enzy I/ShortcutBadger: Badge counter is supported in this platform.
2021-12-12 18:29:20.692 10578-10685/com.example.enzy D/PluginManager: getPlugin - put: Badge
2021-12-12 18:29:20.695 10578-10685/com.example.enzy D/PluginManager: getPlugin - put: Device
2021-12-12 18:29:20.698 10578-10685/com.example.enzy D/PluginManager: getPlugin - put: LocalNotification
2021-12-12 18:29:20.703 10578-10578/com.example.enzy D/CordovaWebViewImpl: onPageFinished(file:///android_asset/www/index.html)
2021-12-12 18:29:20.703 10578-10578/com.example.enzy D/PluginManager: postMessage: onPageFinished

CodePudding user response:

It is just doing a XHR request via a XMLHttpRequest, so there shouldn't be any issue loading local files, it all depends how you're set. If you are using cordova-android 10, you can try setting in your config.xml

 <preference name="AndroidInsecureFileModeEnabled" value="true" />

For iOS, try using cordova-plugin-ios-xhr and set your preferences to

 <preference name="allowFileAccessFromFileURLs" value="true" />
 <preference name="allowUniversalAccessFromFileURLs" value="true" />

 
  • Related