felixmariotto / three-mesh-ui Goto Github PK
View Code? Open in Web Editor NEW⏹ Make VR user interfaces for Three.js
Home Page: https://felixmariotto.github.io/three-mesh-ui/#basic_setup
License: MIT License
⏹ Make VR user interfaces for Three.js
Home Page: https://felixmariotto.github.io/three-mesh-ui/#basic_setup
License: MIT License
It seems font sizing is off by (approximately, based on my eye) a factor of two 1.5.
I made an example here:
https://codepen.io/trusktr/pen/44f06fe6d8ef732770643b5707b7bd1a
In that example, see how the numbers (BOX_SIZE
, FONT_SIZE
, etc) map to both CSS and WebGL. Everything matches up, except the WebGL font looks about twice as big.
Question: can a font have its own intrinsic size, which would cause the font to look bigger than another font even if they have the same specified font size?
I ran into a problem with ios running, I added vconsole to previous demos:
https://raw.githack.com/gonnavis/three.js/three-mesh-ui/examples/three-mesh-ui_hellospaceworld.html
https://raw.githack.com/gonnavis/three.js/three-mesh-ui/examples/three-mesh-ui.html
on my iphone6sp safari ios13.6.1 can see these errors:
colleague's iphoneXR safari ios14.2 see these errors too:
pc and android work OK.
I made this interesting example:
https://codepen.io/trusktr/pen/11105a14a0707cc73a67ac62ca5ea6e9
It updates the font size and font content every frame. I found that on my Nvidia Quadro P2000, each frame takes about 27ms.
Looking forward to trying the InstancedMesh concept.
Sidenote, It is interesting that in the demo, the WebGL font stays perfectly in position while resizing (the math works out well), while the DOM font jumps up and down while it resizes. It seems the native browser font rendering rounds the font positioning to the nearest pixel (aliasing).
Hello,
What is the advised way of removing a component? Like the inverse of component.add()?
I have good hopes that this technic can help getting rid of most of the three.js library when bundling.
Three.js is the cause for the bundle being so large, because it's not tree-shaked and everything gets added, including the renderer, a lot of materials not used in the libs with shaders etc...
I think three.js part can be reduced from ~700kb to ~100kb, which would be a huge leap forward
It is an annoyance for most people to have to see diffs that also include the dist/
folder. Three.js includes the build/
folder, but the vast majority of all JavaScript project don't do it.
We can build dist/
for when we publish to NPM (or GitHub releases). People can get the built files from unpkg.com
.
Very simple demo only contain character "Hello world" will fail:
three-mesh-ui.js:1 TypeError: Cannot read property 'width' of undefined
at Object.getGlyphDimensions (three-mesh-ui.js:1)
at f.getGlyphDimensions (three-mesh-ui.js:1)
at three-mesh-ui.js:1
at Array.map (<anonymous>)
at f.parseParams (three-mesh-ui.js:1)
at three-mesh-ui.js:1
at new Promise (<anonymous>)
at three-mesh-ui.js:1
at new Promise (<anonymous>)
at Function.callParsingUpdateOf (three-mesh-ui.js:1)
I found that the space in it caused this error.
A complex demo without spaces works well.
Hello.
I wanted to display text with some blank lines, but Text object with Content is ignoring more new-lines in a row.
For example text "Hello\n\nThis is example text\n\nBye" should have 3 text lines and 2 blank lines between them, but it only displays 3 text lines, each in a new line.
Is there a way to display blank lines using Text.content?
Thanks,
Martin
Might it be possible to use the hidden overflow feature (or some other means) to mask an image?
The keyboard currently does not support enough layouts.
The most interesting additions would be Chinese, Arabic, Japanese and Korean, as these languages use completely different set of glyphs from what the current layouts can offer.
Keymaps are stored here, although for Chinese and Arabic I doubt that simply adding a keymap would be enough.
In any event, if layouts are added, the keyboard live demo must be updated to showcase them.
Some glyphs like period and comma produce characters too small, so when a line is created with only these characters, the line is too small.
Fix : minimal line height
Suppose I want to change the font size, or adjust the box size (imagine the user is dragging the edge of the box using a hande, and can resize the box). What's the recommended way to update the UI?
It would be nice to be able to add fonts manually instead of loading when requested. Some apps prefer loading all assets prior to starting expirience (this is my case), and yet this is not possible with three-mesh-ui.
It seems like easy-to implement feature to me, so I could make a pull request with it, but i'm new to this library, and not sure which api would be the best choice. My current suggestion is to add some method like addFont(json, texture)
to FontLibrary and expose FontLibrary to ThreeMeshUI object.
Hey! Awesome work. Glad to see someone working on nice 3d text layout!
One thing I noticed in the package.json is that express should probably be a dev dependency rather than a regular dependency, right?
Thanks again!
Currently, either a Block has a width, either its width can be computed from its children width (same for height).
It would be a great addition to support width/height: 'auto'
, so that a component takes all the width (or height) it can in its parent component.
It should be done by BoxComponent.
First of all, great work! The library looks very useful and hopefully it will keep growing!
Just wanted to report a crash when running the interactive button example:
VM420:1284 TypeError: Cannot read property 'point' of null
at updateButtons (interactive_button.js?21ac:342)
at loop (interactive_button.js?21ac:322)
at onAnimationFrame (VM170 three.module.js:24520)
at Object.onAnimationFrame [as callback] (VM170 three.module.js:15008)
at XRSession$1..onDeviceFrame (:1281:42)
Which is:
vrControl.setPointerAt( 0, intersect.point );
I'm running this in Chrome using the WebXR API Emulator, and the crash seems to be happening when the pointer is hitting the button, although its not consistent, i.e sometimes the button will highlight properly, sometimes it will crash.
Hello once again, firstly nice job on pushing this project along! It's progressed quite a ways
I noticed in my chess game that you can see the menu text in front of the chess pieces, even though the chess pieces are closer to the camera. I've linked to my app below, and you can recreate what I'm talking about on desktop by just dragging the orbit controls down so that the chess pieces are between the camera and menu text
https://halfbaked.city/apps/chess-xr/app
I'm assuming this is not expected behavior? And from what I could tell it's not due to the renderOrder as I tried commenting those lines out and still had the same result
First, nice project!
I know this may be a ways off, but text selection with copy/paste would be awesome!
Hello,
So I was trying to display some text using THREE.OrthographicCamera
, but only the background is displayed and no text can be seen.
Reproducible example : https://jsfiddle.net/ds16nbgu/
I tried to play around with text shaders (vertex + fragment) : disabling clipping, setting gl_FragColor
to vec3(1.0)
but doesn't seem to help. I also tried to set ThreeMeshUI.Text.frustumCulled
to false
and THREE.MeshBasicMaterial.depthTest
to false
, without success.
I searched for a while and this doesn't seem to be a known issue. What might be the cause of that ?
Thanks by advance.
The thought here is that the text layout/rendering engine (all stuff that happens within one rectangle area) could be its own standalone thing. Then the UI layout (ability to lay out boxes within boxes) could be a separate thing, and not only limited to boxes (imagine any 3D objects in a horizontal or vertical layout).
Actually, it could even be three things! three-layout-engine, three-text-engine, and three-mesh-ui. All three of them would be decoupled:
Block
mechanism, but does not specifically render anything in the layout, it's just virtual spaces.Any other library could, for example, use just three-layout-engine to lay any objects out. F.e. imagine a row of spheres, with no planes.
The decoupling of the layout from what will be rendered within the layout would be very nice.
Of course, maybe this doesn't need to be three separate libs, and it can be one lib with all three parts within the lib. But thinking about the three separate parts is the main idea.
If I want to, for example, use the layout system with the current Block
s, how may I skip using the planes and instead put my own objects in there? I think currently I would have to traverse block.threeOBJ
and manually remove what I don't want then stick in what I want.
With a layout decoupled, I could just use the layout API if I need to.
Instead of having three libraries, we could start by arranging src
into three folders:
src/
layout/
text/
ui/
index.js
where ui/
would import from both layout
and text
, and index.js
would re-export everything including the existing Block
class, etc, but would also export new underlying layout and text classes.
So far manually adding a font for three-mesh-ui to create text is mandatory.
It must be defined this way :
ThreeMeshUI.Block({
fontFamily: './assets/Roboto-msdf.json',
fontTexture: './assets/Roboto-msdf.png'
});
It is not very user-friendly, as the user must download the fonts from the repo or take the time to create their own, find a place to store it in their app file system, etc...
I think it would be best to have at least the Roboto font (open source) as the default font, so these two parameters can be skipped, and Text will fallback to Roboto if the user defined no font.
The font files should be placed in ./src/assets
How to set double-sided display?
It would be great if the library supported optional alternative text types for alternative use-cases.
For instance, one can imagine an instancedText based on THREE.InstancedMesh, to support fast-changing text.
One can also imagine a vectorText to support complex font that cannot be well rendered with MSDF, or that must be rendered very large with exactitude.
The architecture to support alternative text types is ready in TextManager
related : #11
The keyboard example has 'Z' become 'w' as lowercase, instead of 'z'.
I believe it's from this line: https://github.com/felixmariotto/three-mesh-ui/blob/master/src/utils/Keymaps.js#L148
Tests would be a great way to ensure nothing breaks. How do you feel about adding unit testing infrastructure?
OK, so we talked about a lot of possibilities, I would like to sum things up and organise to draw a practical roadmap.
These are points to work on, roughly in order :
As outlined in #12, three-mesh-ui needs a bit of refactoring, for a better separation of concerns.
As outlined in #3, three-mesh-ui components should inherit from THREE.Object3D, for a more convenient raycasting and transforming of the root component.
The refactoring should help with the bug you mentioned in #7, since we will have a module that will position glyphs in a container, whatever their type (SDF, geometry, vector, etc..). It should also provide a standard object to raycast to, whatever the text type, as requested in #1
As outlined in #11, it needs new text classes, including InstancedText, VectorText, and CanvasText. One of the classes must be aliased to Text, which should be the most versatile, a good default for beginners.
As outlined in #9 and #5, it needs some updates related to bundling, in order to:
@trusktr as you seem interested in the project, do you want to collaborate with some of these points ? If so which ones ?
I'm planning on dropping what I was doing with InstancedMesh for the moment, which was mostly getting nowhere. In my opinion the first two points should be addressed first, as it is the foundation for everything else.
Edit -- Some addition :
component.fontColor
and component.fontOpacity
Hello! I've used this library for some time now, but still I didn't find a way to implement layout like one on this screenshot:
The problem is, there's no way to set vertical spacing between paragraphs, like margin-top or something similar. There is interLine, but it affects every individual line. Adding several line breaks to text also has no effect, library treats them as single one. I could go with a separate block for every paragraph, but then I need to calculate size or bounds of generated text and modify block height to avoid overlapping. But for me, trying to compute it via bounding box gives wrong results. Of course, It could all be placed manually, but I need to create a lot of such screens with different text, and I can't define it in advance. So is there a way to do it, or am I missing something?
On iPhone Safari, three-mesh-ui only seems to work when Web GL 2.0 is disabled. I am on iOS 14.0.1. I will update to 14.2 and try again. If this issue persists, how can I go about making three-mesh-ui compatible with Web GL 2.0 in my project?
So I understand from this that the layout to aim for is the JCUKEN layout.
As english is very common on the internet, I suppose that you guys need to switch from time to time to access "missing" letters like N.
How do you do with the physical keyboard ? What would be a convenient way of doing it with this virtual keyboard ?
my english is poor,so i try my best to describe the problem i meet. i hope you can get it.
i download the 'three-mesh-ui' code on github, and i create a three-mesh-ui panel in my html file by the guide, and there is no wrong in console.but the panel is invisible,only 'room' is visible. i don't know how to solve it, could you have any advise?thank you so much
there is my initContainer code
var container;
function initContainer() {
container = new ThreeMeshUI.Block({
height: 1.5,
width:1
});
container.position.set( 0, 1, -1.8);
container.rotation.x = - 0.55;
scene.add( container );
}
here is my init code
function init() {
initScene();
initLight();
initCamera();
initRender();
initControls();
initContainer(); //here i init container
const room = new THREE.LineSegments(
new BoxLineGeometry( 6, 6, 6, 10, 10, 10 ).translate( 0, 3, 0 ),
new THREE.LineBasicMaterial( { color: 0x808080 } )
);
scene.add(room);
renderer.setAnimationLoop( loop );
}
I need to scroll text when overflow. Is it possible ?
Thanks Mehmet
Set up two-sided display
Now that hidden overflow is available, it should be possible to scroll the content of a Block if it's overflowing.
This must be done while keeping the library controller-agnostic. Some API can be added to components if necessary to help with positioning a Block inside a Block, or getting a X / Y offset, but no mention to controllers must be done in the core.
I just noticed this when clicking around the examples:
This happens when trying to switch back to any layout that's already been selected.
I'm using mouse and keyboard on Windows in latest Chrome.
Trying to get things installed and running but having issues. I am using the latest create-react-app and three.js via yarn.
From yarn I get this error:
error [email protected]: The engine "node" is incompatible with this module. Expected version "12.x". Got "14.2.0"
error Found incompatible module.
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.
I can install with npm but the the dependency tree is broken.
I know you mentioned here that you didn't want to add another dependency it might be worth considering support for custom or external text rendering systems. This might just mean documenting the text mesh interface that a class has to adhere to already and how fill it in but you'd know better!
My use case is to enable users to use a custom font from the web which would mean being able to parse a font and generate an SDF texture on the client. And unfortunately I'm not aware of any multi channel SDF texture generators in javascript. Troika text would be an option to embed for this but using something like Typr.js or Opentype.js to parse fonts and generate an SDF for a custom solution would work too.
It should be possible to position Blocks similarly to CSS justify-content space-between
and space-evenly
.
It should be done by BoxComponent
I thought to share this neat project: http://makepad.nl/
It is written in Rust, and compiled to WebAssembly. But the neat part is it ultimately renders all the UI (tree view, scrollable views, editable text, etc) with WebGL.
It would slightly improve the text look to support kerning.
The recommended MSDF text files generator produces fonts that follow this standard. Enough information is embedded with each character to support kerning.
If supported, this should be handled by TextManager.
Related : #17
In the example for buttons there is some custom code in VRControl to handle Raycasting. I think it might make sense to make a utility function for raycasting the UI as part of this project's source code. That or restructure some things to make it easier to use THREE.Raycaster. Thoughts?
Hi,
I just update the three-mesh-ui in my project, and the background texture doesn't change color then i set the background color attribute. Insted it change the over part of the background.
this.background.set({
backgroundColor: new THREE.Color('#FF0000'),
backgroundTexture: this.textureBack,
opacity: 1,
});
this.object.set({
backgroundColor: new THREE.Color('#00FF00'),
backgroundTexture: this.texture,
opacity: 1,
})
The spacing between the UI planes?
That creates the method anew for each instance. Example: if there's 5 methods in a class, and 5 instances, that'll create 5x5 function instances.
It's nothing big to worry about, just sticking this here so we can check it out later. (But you are in quite the envious hack mode 😄 so I wouldn't be surprised if you got to it before I could swing back!)
Side question: have you considered using class
? If you decided not to, is it for old browser support?
The build folder should contain a development bundle with not minification for debugging, and a minified and uglyfied bundled for production.
Alternatively, we can update the webpack build to output a single ESM file like build/three-mesh-ui.esm.js
, and also publish that to NPM.
Alternatively I think we could add .js
to all the module identifiers inside of src/
.
Then we could import from src directly:
import('https://unpkg.com/[email protected]/src/three-mesh-ui.js').then(console.log)
In Chrome you should currently get an error like
Uncaught (in promise) TypeError: Failed to resolve module specifier "three". Relative references must start with either "/", "./", or "../".
Besides changing import specifiers to use .js
, we would also need to release an importmap so that it knows how to resolve three (we can have it point to https://unpkg.com/[email protected]
).
Maybe the first option is easier, but requires a build step.
I've noticed that neither of the text implementations honor kerning offsets for glyph pairs. I'm not sure if the current font encoding carries kerning information, but if it does then honoring that would be a significant improvement.
Hi,
When adding containers as child to the camera rather than the scene i get the following errors (I want some of the ui oriented realtive to the view instead of stationariy in the word)
4three-mesh-ui:1` Block got no dimension from its parameters or from children parameters
updateLayout @ three-mesh-ui:1
8three-mesh-ui:1 'undefined' is an unknown value for the backgroundSize attribute
updateUVs @ three-mesh-ui:1
The gist of the code
scene.add(camera)
camera.add(container);
container.position.set(0,-0.35,-1);
container.lookAt( camera.position );
Adding directly to scene works as expected
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.