I don’t think a 2d projection of a VR space has the same mental weight as being able to re-create a real snapshot. For example, if I create an art gallery and impart my creative energy into it, I may not care about someone posting photos of the time they spent there in VR, but may care a lot about how the app encourges and enables the “export” of the entire gallery, as-is, for reproduction in VR.
But I can grab copies of everything; it’s a web browser and it’s downloading stuff from the internet. Right?
Right, so we should be careful about encouraging people to share information they don’t want others to be able to copy. We can design hubs such that information you share is encrypted and only decipherable by the person you want to share that information with, but each user still has to trust the people they’re sharing the information with.
When you say “low stakes” I’m reminded of these articles.
Are the “practice spaces” in these articles what you have in mind? Preventing copies is not the only way to encourage “low stakes” exchange.
(As an aside while there are interesting thoughts in these articles, I don’t believe/agree with the conclusions/recommendations.)
I like this. It’s the same as the snapshot model except that Mozilla doesn’t store the snapshots for you and you can edit/store/author however you want.
Yes we’ll want some story around keeping artifacts compatible with future versions of hubs (or hoping there exists mirrors of older versions). A formal schema seems like a good way to tackle this, although an informal schema and manual upgrade process may be tractable for some small number of simple changes. (We add a field to a component, then upgrade the text-based snapshots by running them thru sed to add a default value for that field.)
I admit this gets my spidey-sense tingling, but perhaps just because of context. Is this important for … what long term trajectory/use-case?
One read on this says we absolutely MUST store content because most people don’t have web-accessible storage, so requiring a URL is too high a barrier. But this feels wrong to me; we’re creating yet-another closed system the minute content is put in it and saved in our servers. Sure, it’s built on the web, and sure it’s open and has nice properties. But, the content is now hidden and saved and “OMG I have no idea where it lives and how to get rid of it”
Another read on this say we absolutely MUST NOT store content and must insist that anyone who wants to share personal stuff must first upload it somewhere. Perhaps we give them links; perhaps we build on services like Firefox snapshots to provide storage. BUT, that storage is outside of hubs and controllable and manageable independently.
Me, I would likely create directories in dropbox for certain uses: drop copies of things there so I can find them, use dropbox finder integration on my mac to get a copy of the url, paste it. If I decide I regret sharing a picture or video, I delete it from dropbox. And that link breaks. Easy-peasy.
The web is full of places and services for storing and sharing content; it seems like we’re being more webby if all the content that you can share and view and create in hubs ends up in those, and we reference it by URL.
I would like to suggest a hybrid of:
Room Snapshot Model (RS)
“Opt-in Pinned Objects” (ORO) model
Essentially, functions like RS but only for opted-in objects.
Let’s call it:
“Opt-in Snapshot Model” (ORS) model
The reason for this is that as I want to be able to save state of a room at will, but trust that I have control over who sees it and when. I also expect that other users in that room have a say in what content they share can be saved or not. At the same time, I understand that anyone can save the state of the room. This would be like several people taking a photo of a whiteboard after a meeting, but then being able to restore that whiteboard in any other meeting in the future (with the caveat that anyone can erase their contribution to that whiteboard before the photo is taken, if desired).
I believe that we also want ORO in addition to this, but as far as order of operations go, ORS should come first. This also potentially avoids the concerns about us storing data, at least for now.
I’ll add that if we’re only saving links to external content, it also means that I can pull access to my contributions at any time afterwards, as well. (or change it, by updating the files … which is a whole other interesting “feature”).
I can empathize with this – the CCK model kind of blurs the lines a bit though. The CCK model is kind of “local storage security semantics, but we push things to our servers to help reduce loading times.” If you’re not logged in, the data is effectively deleted. We will TTL it away as well, even though the bits are useless. Also, the mental model for the creator is “hit the delete button on the object in 3D” to delete the data, if they want to do it “manually.”
Perhaps the answer for v1 is CCK but use remotestorage.io as the underlying storage medium, with a “happy path” to use our provider. Helps with the privacy and centralization concerns, but could be a real nightmare UX-wise though. (typing in VR = awful, etc)
Yeah I think a “pinning” model (where, in the abstract sense, objects have a 0/1 state on them) and snapshotting may go hand in hand. If the object has a 0, it is ephemeral, exists only when the owner is connected, and can’t be easily exported. If it’s a 1, it will exist no matter who is in there (unless someone deletes it) and will be included in exports.
It makes sense to me that a single logical bit drives both, since its kind of a bit on “readability” of the internal bits of the object. It isn’t a system-enforced readability constraint (since its the web) but an application-enforced (or at least, encouraged) one.
The fact that it enables persistence decoupled from the creator is just inductive from the fact that the object’s guts are “readable” by other participants – eg if the creator left, everyone can see its state anyway and so could just replicate it, so having it be “automatically” kept in the room regardless of who is in there is just a convenience to prevent the need to “hand it off” between people. (the “room is empty” case is also inductive since theoretically you could build a bot to just do this work for you :))
Yes the “low-stakes” term is stolen from there
I wonder if “low” vs “high” stakes in communications tools is something like “colored functions” (http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/) – as soon as you have one “high stakes” element (like, for example, the expectation that personal photos you share will appear in another person’s “stash” for their own use however they please) then suddenly the whole medium inherits it and becomes “high stakes.”
Ok so here’s a concrete proposal of a plan. I think based on the feedback in the thread we can pitch the CCK concept, and implement a 2-phased build out of ORO which then leads naturally to an RS model that dovetails with the editor tooling. (Doing it in the opposite order seems hard to wrap my head around.) The net effect on the other side is we have most of the use-cases covered, privacy seems good, and there’s minimal UX complexity.
First, we should just ensure that content created by a user (drawings, etc) does not get lost due to a reconnect. This is basically unrelated to persistence but I think is worth mentioning as something worth verifying and enabling if it doesn’t work.
I think the main mechanic we should introduce first is the “pin” concept. Every object in the room is by-default “un-pinned” and will be erased when the owner leaves. However, the creator (and only the creator) has the ability to pin the object. The UX probably looks something like “hit pause, and pinned objects look more ‘permanent’ in the scene, and you have a one-click to pin action you can perform.” A v2 could introduce a “pin lock” concept so all objects created are pinned by default for that session.
Under the hood, pinning will store the state of the object in a durable way (mechanism TBD) and also move uploaded content into permanent storage.
In order to pin something, the person must create an account. This is necessary because we need a way for that person to audit and delete the objects they have stored on our servers. The pin action can be visible at all times but clicking it will pop a sign in/sign up gate.
On the other side of this, users have a mental model that they must opt in to any long term persistence. This model is very privacy preserving since only the creator can pin, and it’s always clear to the creator when their objects are being made permanent. The downside is there may be unintentional loss of work if you forget to pin something important, but if we introduce the “auto-pin” functionality in a nice way, that could close the gap.
Once pinning is implemented, the next phase will be to allow users to take a room with pinned objects and remix it in various ways. At this point, we can probably align this with our UX and model for scene creators using the Spoke editor. At this point it seems likely that scene creators will have two options for managing their scenes:
- Full export to GLTF, do what you wish and host where you want. Does not require an account.
- Hosted solution, scenes are stored on our servers, with various pages to support their use and discovery. Requires an account.
These two methods would then become available to users in-room as well but the context would be the set of pinned objects in the room.
At any time, users would have the option to export the current scene as a GLTF – that GLTF will include a reference to the scene GLTF and have internal nodes for each of the pinned objects. When that GLTF is used as the scene for a new Hubs room, it should effectively behave as a snapshot: the pinned objects will be in the room, but are dynamic and can be deleted, etc, as they are at export time. This export option will be available without an account, but will only export pinned objects, so those objects will have had to be created by people who have an account.
In addition to that, there will be an option to “Create a Scene” from the current room, which will tie into the same flow that is used in the Spoke editor. This will require an account, and will export and host the scene (which includes the pinned objects) in an identical fashion to the flow in the editor, but would be in game. This new scene would then be available on hubs.mozilla.com for sharing, feedback, etc.
One big downside to this model is that there’s an account gate to enable any form of persistence, since someone needs to pin an object for it to become persistent and exportable. It seems difficult to resolve this without adding at bunch of conceptual complexity: users should control what data can be exported, which implies they should have an opt-in mechanism to allow export/persistence of that data.
If we wanted to avoid the account creation step, we could have two attributes object creators can set (“pin this object” which would require an account, and “allow this object to be exported” which wouldn’t) but that seems super confusing and weird. The model outlined above is pretty natural: an object can be in two states – the initial state is the object is ephemeral and hard to export by others, and once it goes into the “pinned” state, it is permanent and conceptually exposes its data to everyone in the room, both in the form of being exportable but also because the object will always be in that room for them to see even if the creator leaves.
Overall, this seems worth the tradeoff, but if there’s a way to introduce the use case of “a bunch of people can create a room, intentionally create exportable objects, and export it as a GLTF without anyone signing in” I’d support it if it doesn’t result in a bunch of UX complexity or change the “my object are private and temporary by default” mental model users will have if we implement the above.
Also worth mentioning: what is covered here is largely about UX and not fundamental security when it comes to others in the room – since others in the room download your data to see it, of course they have everything they need to copy all of your objects, regardless of if you have pinned them.
Regardless of technical capabilities, encouraging certain behaviors and models for how people should interact with one another in the space is our job as social system designers, and the UX we design is our best way to communicate this. The model above encourages opt-in-to-expose content as the model, but leaves open the possibility for alternatives to be created by 3rd parties. For example, one could imagine a browser plugin that enables “export to GLTF” for all scenes you are in while in Hubs.
With this in mind, we shouldn’t be too fearful around our built-in UX being too restricting if the restrictions are there to foster certain cultural norms and increase user trust. If these are too limiting for certain users the possibility will exist for 3rd parties to help get around them. Much better for us to be adding these kinds of features with care, than potentially making things too open in a way that is hard to reverse – particularly because in most contexts where this is problematic for people, the web makes it possible for them to find a non-sanctioned mechanism to get past any model we’ve burned in. And of course, we’ll learn and potentially can refine these models over time as we determine if any of our decisions were overly cautious.
Also worth mentioning that the term “pin” here is probably a placeholder – it’s not a great metaphor, since it might imply that you can’t move the object around anymore when it’s pinned. I’m having trouble coming up with a better one though. (Stick, save, lock come to mind too but seem worse than pin.)
A question I have when reading this:
How are these exported GLTF’s used as scenes for a new hubs room?
The reason I am asking is this implies (to me) that you will support the use case I’ve been pushing for: creating GLTF’s externally. If I can point hubs at a GLTF, I should be able to create those GLTF’s any way I want.
Am I reading it too much? I really want to be able to create rooms externally, and automatically. A room with images on the walls for all my recent blog posts and projects; a room with the slides from a lecture; a room with the most recent video for a class.
Hey thanks Blair, we already support the case you are asking for. If you go to hubs.mozilla.com and click “options” in the top corner of the room creation box, you can enter a custom GLTF URL. So anyone who has the chops to get a GLTF scene on the web (probably with the help of our Spoke editor to add behaviors and test it) will be able to use it without storing anything on our servers. We’ll always support people bringing their own assets and hosting, and our initial roll-out of Spoke is not coupled with hosting but will be directing users to use their own hosting.
The hosting proposal is separated into two separate features: hosted scenes and stored room objects. Both of these will deliver a lot of user value beyond what we have already:
If you upload and let us host your scene:
- You obviously don’t need to worry about where to save it
- We will offer some UX around sharing and using it for room creation. (like a landing page to see it and create new rooms with it, or a profile page for you to show people all of your uploaded scenes.)
- It will allow other users to remix your scene easily, right in the browser ,if you’ve CC licensed it (this could be critically important to growing the ecosystem)
- We’ll be able to promote your scene in our newsletters, the home page carousel, etc.
- Probably more stuff down the line
So hosting scenes is pretty huge if we expect there to be creators out there who want to create scenes for others to see, remix, or use. If we don’t build this stuff ourselves, its unlikely to get built anytime soon by the community, if ever, for a whole variety of reasons, not the least of which that there currently is no community and these tools may actually help create the community!
The other part of hosted state is persistent room objects. This need has just become really obvious now that the media tools work has come together. I want to be able to go into Hubs, create a room, spawn some photos, save them in the room, and then leave so I can come back later and look at them, for example, with the same link. I don’t want to have to worry about hosting, GLTF files, or any of that incidental complexity, I just want to spawn my photos and not have them disappear when I disconnect by clicking a save button or something. This seems like a pretty obvious thing for us to build, and is something I selfishly want for myself
Is there a URL option for this? I suppose I always need to create the room manually, though; is the GLTF grabbed directly each time? So, I could point it at blairmacintyre.me/hubhub.gltf (which I create somehow), and then create a room that uses that, and whenever I go to the resulting room URL, it will pull that model?
Where does the “pathing” data live? Custom data in the GLTF?
Oh, cool. That will be interesting to try.
There are good reasons for hosting, I’m not disputing that! Even if only because “normal people don’t manage their own domains” …
Yes, I can see that. I assume these things will mix … or will they? If I host my own GLTF for the room, and then persist stuff, can my GLTF still live on my server, and the hosted content still be hosted by you?
Oh, one more thing that occurred to me as I thought about this, to clarify my thinking about externally created rooms.
I want to be able to create a room and pre-populate it with media elements (e.g., videos that are ready to be played, images and other content around the space). Not things that are part of the GLTF.
That’s what I need to do many things I imagine doing.
Essentially, it boils down to: everything I can do manually in the room (add media, select what is persistent, etc), I want to be able to do ahead of time via a program.
Yep, so there are a few paths that are going to materialize:
First path is going to be to add these items as objects to the scene via Spoke, export it, host the exported GLTF on GitHub pages (or wherever you want) and then create a room pointing there.
Second path will be you won’t have to worry about hosting it yourself, and you’ll get a landing page to send people to in order to create rooms with it, if you hit “Upload scene to Hubs” from within Spoke. (Don’t want to post roadmap targets here but obv this is in the works.)
Third path (which may materialize before second path, not sure) will be you create a room in Hubs, spawn all the stuff you want using the tools we have now, and then on each object you’ll have a button you can hit to “keep” it in the room. (You’ll need to sign into an account.) Once you do that the objects will stick around in the room after you leave so you can share that room link with others.
Fourth path (which is dependent upon everything above) is that you will arrange objects in the room in-game as in the third path, but have export options to export the arranged scene to GLTF or as a hosted scene.
Hopefully we will get these things built quickly!
How will things like youtube videos be expressed in a GLTF?
I would add that I’d like to see a variation here which is
- I write my own tools that generate a GLTF (and associated data, like where people can walk, what the “objects” like video are, etc) and host it myself, and point hubs at it when I create the room. Since the URL is visited whenever the room is opened, I can update it over time. Or it can be generated on-the-fly.
This will require some way to ensure that all current visitors see the same content. For example, perhaps rooms have version numbers; when a room has been shut down because nobody is there, and the URL is visited again, the version increments, so the host of the GLTF is responsible for sending the same vision of the room for each given version number. Dunno … I assume this is obvious to you folks.
Yeah it should be pretty simple to enable this. The GLTF spec extensions we’re proposing should encapsulate most of what you’re talking about here.
Right now we’re setting things up so we’re just going to be able to serialize most scene state into GLTF. We’re already using this to deal with collision, navmesh, and animations. One of these will (theoretically) include the content metadata for a spawned media object like a video URL. So the GLTF will just mark a node in the scene with a “media” behavior and a URL, much like we do now directly in Networked-AFrame. The Hubs client will be the de-facto reference implementation of how to “interpret” these behaviors, but the long winding road to standardization certainly exists. (For example, a URL pointing to a Giphy landing page requires different resolution rules than one pointing to a PDF.)
The sync state will be ephemeral state on the object’s network state, handed off between connected users, but not burned into the GLTF. If everyone leaves the video is implicitly reset and the first person to wander in starts it from t=0.
With regards to versioning, it’d probably be something to build if/when the demand is there. In practice, especially since we’re on the web, I think the odds of this being a pain point are pretty low for a while. For example, if someone wanders in “late” and the scene has been updated with some new object, in practice the people in the room will realize and just refresh to get the latest version. (The odds of this happening for most use-cases I can imagine are quite low since it requires concurrent co-presence, a mutated scene, and the change mattering, but maybe I’m not being imaginative enough :))