x3dom / x3dom

X3DOM. A framework for integrating and manipulating X3D scenes as HTML5/DOM elements.
http://x3dom.org
Other
815 stars 271 forks source link

Semantics of url field #1199

Closed npolys closed 2 years ago

npolys commented 2 years ago

In X3D, it is expected that if one url is not found, try the next in the list.

X3DOM fails this if the first url is not found;
in ImageTexture for example.

andreasplesch commented 2 years ago

Confirmed, x3dom only looks at the first url and ignores subsequent ones. Is there are specific use case ? Due to cors, loading from non-origin servers is rare.

For ImageTexture loading x3dom uses the html Image element. It sets the src property to load the image.

https://developer.mozilla.org/en-US/docs/Web/API/Element/error_event maybe an option.

https://github.com/x3dom/x3dom/blob/master/src/util/Utils.js#L177 already uses onerror to try .dds texture loading.

Seems complicated to implement.

https://github.com/x3dom/x3dom/blob/83ce36310eda365a35ece8391e9a8c3f78800c38/src/Texture.js#L490 is called from Texture.update

https://github.com/x3dom/x3dom/blob/32c69a1972690140e738e037128230862dd7fb02/src/gfx_webgl.js#L306 create new Textures.

https://github.com/x3dom/x3dom/blob/32c69a1972690140e738e037128230862dd7fb02/src/gfx_webgl.js#L327 calls update()

andreasplesch commented 2 years ago

Looking at this more, the small patch for createTexture2D here

https://jsitor.com/4tCAhIRslT

may work for most situations. Trying the next url on error after dds rejection should be about right.

Only for ImageTexture and it does not do correct automatic blending for greyscale but should work for dds loading.

Needs checking for potential Background url confusion.

[Inline url needs different loading.]

andreasplesch commented 2 years ago

Could you please give this a try and report back ? It should work to just redefine the x3dom.Utils.createTexture2D function as above, after loading x3dom.js.

andreasplesch commented 2 years ago

Any luck ?

n-polys commented 2 years ago

Sorry, Been offline... Will try asap

On Sun, Apr 3, 2022, 8:58 PM Andreas Plesch @.***> wrote:

Any luck ?

— Reply to this email directly, view it on GitHub https://github.com/x3dom/x3dom/issues/1199#issuecomment-1086999635, or unsubscribe https://github.com/notifications/unsubscribe-auth/AYQT72JSX7G4AY7IQU4AMH3VDI5CBANCNFSM5R7ASQZQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

npolys commented 2 years ago

Thanks ~

I overloaded the function definition with what you supplied: x3dom.Utils.createTexture2D

I think this error is because I am looking at a path like file:///:/C: first ... and fails at that, then stops.

Console: Not allowed to load local resource: file:///C:/Users/enikoo/Desktop/MirrorWorlds/MossArtCenter/MossArtCenter_MayaProject/assets/MossArtsCenter_FromUnity_April_6_2017.fbm/MossArtsCenter_Model_trashcan_diffuse_MainTex.jpg

I have removed these addresses from my content with grep and now things are on relative paths.

npolys commented 2 years ago

also error with this patch in my case:

Uncaught RangeError: Invalid typed array length: 5 at new Uint32Array () at Object.x3dom.DDSLoader._read (x3dom.js:7:421745) at XMLHttpRequest.o.onload (x3dom.js:7:421440)

andreasplesch commented 2 years ago

file:// urls typically will not work. It looks it tries a url, tries then dds, and then errors at dds loading. Does that url exist ? Firefox ? Is it possible to reproduce ? Or share the scene ? Try x3dom.debug.js

npolys commented 2 years ago

Yes uncaught range error also happens in firefox, edge and chrome.

the scene is awkardly large but the imagetextures are like: url='"C:/Users/enikoo/Desktop/MirrorWorlds/MossArtCenter/MossArtCenter_MayaProject/assets/MossArtsCenter_FromUnity_April_6_2017.fbm/White_Wall_Texture.png" "White_Wall_Texture.png" "C:/Users/enikoo/Desktop/MirrorWorlds/MossArtCenter_November/assets/Nov_27/Nov_METER_MossArt_fbxParts_binary2014-5-Exp/../../../../MossArtCenter/MossArtCenter_MayaProject/assets/MossArtsCenter_FromUnity_April_6_2017.fbm/White_Wall_Texture.png"'

npolys commented 2 years ago

<ImageTexture DEF="IM_file34" url='"C:/Users/enikoo/Desktop/MirrorWorlds/MossArtCenter/MossArtCenter_MayaProject/assets/MossArtsCenter_FromUnity_April_6_2017.fbm/White_Wall_Texture.png" "White_Wall_Texture.png" "C:/Users/enikoo/Desktop/MirrorWorlds/MossArtCenter_November/assets/Nov_27/Nov_METER_MossArt_fbxParts_binary2014-5-Exp/../../../../MossArtCenter/MossArtCenter_MayaProject/assets/MossArtsCenter_FromUnity_April_6_2017.fbm/White_Wall_Texture.png"' />

andreasplesch commented 2 years ago

with which url do you get the range error ?

are you using a http server for local files ?

andreasplesch commented 2 years ago

https://github.com/x3dom/x3dom/blob/53bb572735b37909f842e1f3ec3ce4c59f29f8ea/src/util/DDSLoader.js#L59

is probably where the range error occurs.

I think that means that the xmlhttprequest was successful:

https://github.com/x3dom/x3dom/blob/53bb572735b37909f842e1f3ec3ce4c59f29f8ea/src/util/DDSLoader.js#L8

while the earlier Image.onload had failed. Not sure when this occurs but perhaps Image src loading is stricter about local cors. It also means that the first UInt32Array constructor for a bufferview of 32 4 = 128 bytes was successful whereas the second one 5 4 = 20 bytes further in, from 128 to 148, fails. So the loaded buffer may be between 128 and 148 bytes long.

Is that a really small texture png ?

In any case, it would make sense to extend the check at

https://github.com/x3dom/x3dom/blob/53bb572735b37909f842e1f3ec3ce4c59f29f8ea/src/util/DDSLoader.js#L40

to 148 bytes:

if ( source === undefined || source.byteLength < 148 ) 

Could you try this by overloading the function

https://github.com/x3dom/x3dom/blob/53bb572735b37909f842e1f3ec3ce4c59f29f8ea/src/util/DDSLoader.js#L38

with one which has the extended check ?

andreasplesch commented 2 years ago

Here is the fixed function to test

x3dom.DDSLoader._read = function ( source )
{
    if ( source === undefined || source.byteLength < ( 128 + 5 * 4 ) )
    {
        return;
    }

    var dds =
    {
        isCompressed : false,
        isVolume     : false,
        isCubeMap    : false,
        targets      : [],
        data         : []
    };

    var int32Buffer = new Uint32Array( source, 0, 32 );

    //Parse DDS Header
    dds.header = x3dom.DDSLoader._readHeader( int32Buffer );

    int32Buffer = new Uint32Array( source, 128, 5 );

    //Parse DDS Header
    dds.header10 = x3dom.DDSLoader._readHeader10( dds, int32Buffer );

    //Check if the magic number is present
    if ( dds.header.dwMagic != 0x20534444 )
    {
        return;
    }

    //Check if the header size is correct
    if ( dds.header.dwSize != 0x7C )
    {
        return;
    }

    //Parse resource format
    if ( !x3dom.DDSLoader._readFormat( dds ) )
    {
        return;
    }

    x3dom.DDSLoader._readMipmapCount( dds );

    x3dom.DDSLoader._readType( dds );

    this._readData( dds, source );

    return dds;
};

Just add after loading x3dom.js .

andreasplesch commented 2 years ago

Any errors with local urls ? Relative urls with a running server should work.

andreasplesch commented 2 years ago

I tried with a local html and local urls but chrome will not allow it (unless security checks are disabled with a command line switch).

andreasplesch commented 2 years ago

https://jsitor.com/4tCAhIRslT is updated to be more robust against mixed local and remote urls. Should also now sniff number of color components for proper alpha blending in any url. Any testing would be much appreciated.

andreasplesch commented 2 years ago

Using a similar strategy, it may be possible to support multiple urls for inline as well:

https://github.com/andreasplesch/x3dom/blob/MFurl/src/nodes/Networking/Inline.js

https://www.web3d.org/x3d/content/examples/ConformanceNist/SpecialGroups/Inline/index.html

andreasplesch commented 2 years ago

See #1208, #1209, #1210 and #1211.

andreasplesch commented 2 years ago

Please reopen as desirable.