Load external three.js script inside a main scene. Next step for metaverses.

True, I recently built a little THREE.js nft gallery like this https://planetnft.net

2 Likes

The threeml.org site is my experimental hub.

Like with AFrame and X3D my approach so far has been to use a meta language for the boiler plate setup and commonly used feature specification. But since it is experimental and the exact names and syntax is not important, I choose tags that mimics the threejs objects. So in this way it addresses 3D similar to Html, allowing commonly used things to be specified using tags, but still providing script access to the ThreeJS objects as a being the 3D ‘DOM’.

It does have have the possiblity to include 3D content from an external domain, either when loading the website, or triggered by an event. You can specify a group object to have an Url, which makes it behave like a 3D iframe, only without the sandbox security.
The loaded metadata can add new assets to the scene, still working on allowing to load modules with them.

Not sure if you guys have a similar approach in mind, I am open for suggestions and certainly would like more discussion and/or cooperation on this. My next step is to convert the server logic to be based on NodeJS (instead of IIS) and start using socket.io/web.rtc to be able to exchange state information about a scene between different visitors.

There is an older npm package ‘threeml’ which contains only client side code. I planned to update this when the nodejs server can be included.

You both seems to have more knowledge about using blockchain technolgy than I. I expect and hope it can resolve things like the ownership of an avatar, disallowing others to try to impersonate someone.

Nice nft gallery, forerunrun!

I have completed the conversion of the server from IIS to NodeJS, and it is now life. The rep can be found here: threemlorg/MetaThree (github.com)

Let me know your thoughts.

1 Like

@DanielAbalde What you want to do doesn’t make practical sense, to make a framework that can run any kind of threejs app natively(without embedding in an iframe) for the simple reason that three.js has a lot of versions and anyone can make an experience in one version which won’t be compatible in another. You would have to at least fix a version, and define compatibility on what people can make and what features that-can be used.
I guess, a good solution would be to just use all the work that has been done in standardizing gltf format. Basically, assume all the products(NFTs) would be in GLTF format, and people can use their custom extensions to add new stuff like procedural generation, interaction snippets, etc. You can have a framework where people can upload js class with specific format (to import and export the custom extensions). But you will need to design a complete sandbox environment for that to be secure. Or do something like custom scripts in playcanvas by making a complete unity-like scripting environment.

I am just thinking from the top of my head, does this makes sense?

Sorry but I don’t understand what I should see in http://www.threeml.org. I understand that it is a 3d scene where 2d iframe are loaded which load 3d scenes, right? But this doesn’t allow to integrate one model inside the other really, because they are two different renderings/lighting/etc. I tried to run it locally but I got an error of sql not found or something.

I don’t understand why these assumptions. I did not say that all three.js apps should be accepted, it is literally the opposite, since the approach I proposed forces you to write the architecture of the three.js app in a different way (as a function instead of as a standalone app). I don’t see any problem with versioning, the external scene should not load the three.js dependency because it is already contained in the main scene. Developers can know which version of three.js to use to make everything they write work.

This is interesting but I do not know what the limitations of this are. Do you have some resource/link that shows gltf with procedural/interaction extensions?

There are many aspects to a metaverse. One of them is that there should be no principle difference between the 2D and the 3D web. (we should for example be able to use virtual laptops and tablets in a metaverse, at least for browsing).

We have had a 2D distributed ‘metaverse’ for several decades now. The ThreeML project tries to make use of the concepts from the 2D web by the addition of an extended set of ‘html’ like tags, that implements for example hyperlinks and iframes for 3D (not to be confused with the 2d iframes that can be placed within the 3D space). These 3D iframes can load new 3D content within the scene. Currently only new content from the own domain is supported, but it is not that difficult to extend the concept to external domains (that allow CORS).

Server side there are currently a few API’s, for example to support a navigation structure to different in registred websites. As mentioned before one of the todo’s is to implement multy ‘player’ support.

Maybe I forgot to mention a requirement, let me check …

There will be quite a few conditions for the external assets when using something like this, For example you don’t want them to change the global light or skybox, the scale should be in line etc.
But of course when ‘teleporting’ to another scene, as obviously should also be possible, there is probably no issue when using another threejs version.

I forgot to mention that the dependencies should be installed:

  • One time install the dependencies (specified in package.json): npm i

Or did you allready do that?

Where I can see examples of 3D iframes? :heart_eyes:

But you don’t need a server to support a navigation structure… what do you mean with server side?

I did all steps and it does not load on http://localhost:8080/sub/search/ and I have this error on Chrome console:
threeml.js:1 Failed to load resource: the server responded with a status of 404 (Not Found).
It is hosted somewhere to avoid to use a local copy?

The Motas example makes heavily use of this, although mainly for small objects and their behaviours. The logic in this game is almost completely created using declaritive code. For example, the first key that you can find has the link specified:

<link url="./three/keyincorner.html" target="cornergroup1" replace="true" />

‘cornergroup1’ is the name of a group object, that is used as 3D iframe. The ‘keyincorner.html’ contains:

<gltfLoader position="0 0 0" rotation="0 0 30" scale="4" name="key2" url="./models/key.glb">
    <hover action="tooltip" text="I found a key!" atmouse="true"></hover>
    <link url="./three/keyincenter.html" target="centergroup" replace="true" />
</gltfLoader>

Thus a new key model is loaded as child in the ‘cornergroup1’ group. A tooltip is added and its own link that, when clicked, loads another file.

It can be seen as a sort of privately managed ‘Google’. The SqLite db keeps the entries. For local sites it can also be used to track visits Eventually I would think that in a none propriety system there could be a mechanism to exchange sites that want to be part of the ThreeJs metaverse, maybe a bit similar to how domains are propagated.

No, NodeJS is the server when working locally. But for some reason the folder with the most important client scripst (threeml) was not included in the GitHub repo. It is now.

I found the key (below the pilow). That’s interesting @awonnink but looks like simply loading a gltf inside a known group, although in React-style declaration. Maybe that’s enough? I’m not sure, I don’t know if it is possible to do procedural geometry; or interact with a controller in a hardware agnostic way; or to use shaders with a gltf extension; or if it will run on VR/XR devices.

Well, that’s where I can help you to understand how if you want to make a dApp on web3 instead. This assets (scenes/objects/scripts/extensions) should run as NFTs on the blockchain but I am not sure if a slower and censorship resistant decentralized database as IPFS can be used instead of a less secure and centralized database.

But for NFT contracts, basically it is associating the url where to access the asset with a tokenID within your contract in the blockchain (it’s a bit more complicated but well). Your contract also binds this ID token to an owner, which is a blockchain address (a public key). This allows your app to grant user permissions based on possessions, and allows any other app to validate that a certain user has a certain asset. The geometry or the image or the script does not matter here, what matters here is the tokenID and to whom it belongs and what use cases can be given to the user so your project can have a marketplace or new monetization systems or new utilities. The more you decentralize it and the more you distribute value to creators (they should be able to sell their own assets), the more prosperous and metaverse-ready it will be.

Maybe the example is a bit confusing, because there the used html file is quite small, and only used to load one new model and to set its behaviour, But similar to a 2D iframe, where a complete htmp page with all its functionality can be loaded, the ‘3D iframe’ can load a complete scene within the the current scene, be it currently only by using meta tags. The possibility to add new modules still has to be investigated, but I think it is feasable.

It would be interesting if one day we could combine our efforts to make a proof of concept: A remotely stored ThreeJS asset that only can be used in a 3D website if ownership is proven (if I understand you correctly).

I agree, this would have to somewhat be accepted and developed at a browser level, creating 3D script tags, I’m wondering if it’s possible to create some sort of request response where code has to be formatted, tagged and varified as a safe module to be able to run functions client side, this way, if the core is built to meet moz browser specific requirements, cors and executing scripts could be done safely?

I have been able to create a demo for loading remote ThreeJS modules at runtime. Here the module for water is loaded from another domain when clicking the box, and then the water is displayed:

Remote module **

There are some conditions for these external modules:

  • The website where they are hosted should have CORS allowed
  • All links to other resources used in the module should be absolute. This also means that it is probably best for them to use a CDN for their reference to the ThreeJS module.
  • They need a mechanism to register themselves to the main code

** You might need to clear your browser cache to get the latest scripts

2 Likes

Great to hear, good work! Can’t wait to test!

Well done! Start to see the potential!

What are your next steps?

I see the need of an optional clipping bounding box, and a way to transform the external scene or at least be able to match the scale. Imagine including an external scene in a gallery display, it should not exceed the limits of the display and therefore should be scalable to fit.

What about interaction? How do you plan to include it? as a parameter of the mod.handle function?

Can that way the main scene send data to the external scene? I think this is fundamental, for example the external scene may need to know the bounding box where it is going to be drawn to adapt its content to it, or send it the user’s position or anything.

In the current implementation the loaded module is not isolated from the main scene. The module can have access to the complete parent scene, so in it could for example implement special mouse handling for its own meshes.

Not sure whether clipping bounding boxes will be the most common usecase (open question), and or whether that should be provided by the parent, or implemented by the module itself. In the implemented example you will want the water to be an integral part of the main scene.

When registring the module can make use of a parent object, which is the scene or, in this case, a group object. This means that the parent can effect position, rotation and scale properties of the child objects exposed by the module.

In the example the external module is referenced using:

<module url="http://v-slam.org/clearwater/myscript.js">
    <group rotation="10 0 0">
        <clearwater></clearwater>
    </group>
</module>

(this meta language code is loaded and evaluated when clicking the box).

The definitions within the ‘module’ are evaluated after the module has finished loading. The ‘clearwater’ tag is defined and handled by the module. As can be seen the ‘group’ tag is normal ThreeML code and can be used to modify transformations for the ‘clearwater’.

Would it make sense to setup interactive events such as mousemove, pointer down etc as global publicly accessible functions that take external objects as a callback? This way would prevent multiple event handlers being added if one or more modules are imported right?

Same, not sure there’s need for clipping but any model imports can be averaged in scale, by finding the bounding box of the original mesh and calculating it’s units decimal places, the scale can be determined by scaling the models size to 1 unit ( meter) times by the models original scale relative to its decimal unit, eg if the model is 35 units, it could be reduced to 3.5 units by dividing by its decimal place, this case 1,a model of 355 units would be divided by 2 decimal places or ‘100’ yielding 3.55 units. If that makes sense?

Imagine an art gallery (as your planetnft.net), any external scene with a lot of extension and a lot of small scale detail, the viewer will need to zoom in/out and this should not affect the rest of the main scene, but be clipped on its display region.

Without a bounding box the parent scene cannot control which part of the child scene to show (to let user navigate for example), or make it responsive, and also it makes impossible to use an environment on the child scene (I imagine this as a mask aligned with the camera direction and allowing to render the scene background but clipping the sides). But thinking more use cases to visualize it… if you have an architecture studio or a real estate agency (in the metaverse) you want to be able to show building models and when scaling them, you don’t want them to occupy all the space but the same region in which you visualize, this is, a bounding box. To me is quite obvious that the main scene should be able to clip (if needed) a child scene and that this bounds should be accessible from the child scene.

So that means that main scene can set up extra data that the child scene can read, right?

Not sure about events, but quite a few functions, like for raycasting etc could be made public.

I understand. In fact in the code snippets there is an example that shows how gttf models can be normalized ( ThreeML documentation), search for ‘normalize’

However, I think there should be a ‘default’ scale that developers for a metaversie should aim for, and the most obvious one is to use 1 unit = 1m, (and then have their models comparable to their real size). An owner of the parent site can always decide to divert from the given scall by scaling its parent group

Yes. By convention ThreeML exposes the global object ‘threeml’. This object has multiple public methods, like getScene() to get the scene object, registerModule() to register a module etc.

It would be nice if we could setup a small metaverse from different domains, just to see what issues will arise.

I agree, we did this with Planetnft, the dinominator was 1 unit, as suggested, to fit the size of the plinth top surface area, the problem was that the largest x y z dimension becomes 1 meter (unit) meaning theres no effort or convention to meet a real world scale, ideally, all models would meet a global conventional scale, however, this is not a method that’s followed by new modelers, my suggestion is finding out the decimal unit, divide or times to find its relative unit size and maintaining a global scale by reducing each model to 1 unit times it’s original decimal unit