UNPKG

@adhiban/three-mesh-ui

Version:

a library on top of three.js to help in creating 3D user interfaces, with minor changes ;)

129 lines (81 loc) 2.73 kB
import { PlaneGeometry } from 'three'; /** * Job: create a plane geometry with the right UVs to map the MSDF texture on the wanted glyph. * * Knows: dimension of the plane to create, specs of the font used, glyph requireed */ export default class MSDFGlyph extends PlaneGeometry { constructor( inline, font ) { const char = inline.glyph; const fontSize = inline.fontSize; super( fontSize, fontSize ); // Misc glyphs if ( char.match( /\s/g ) === null ) { if ( font.info.charset.indexOf( char ) === -1 ) console.error( `The character '${char}' is not included in the font characters set.` ); this.mapUVs( font, char ); this.transformGeometry( font, fontSize, char, inline ); // White spaces (we don't want our plane geometry to have a visual width nor a height) } else { this.nullifyUVs(); this.scale( 0, 0, 1 ); this.translate( 0, fontSize / 2, 0 ); } } /** * Compute the right UVs that will map the MSDF texture so that the passed character * will appear centered in full size * @private */ mapUVs( font, char ) { const charOBJ = font.chars.find( charOBJ => charOBJ.char === char ); const common = font.common; const xMin = charOBJ.x / common.scaleW; const xMax = ( charOBJ.x + charOBJ.width ) / common.scaleW; const yMin = 1 - ( ( charOBJ.y + charOBJ.height ) / common.scaleH ); const yMax = 1 - ( charOBJ.y / common.scaleH ); // const uvAttribute = this.attributes.uv; for ( let i = 0; i < uvAttribute.count; i++ ) { let u = uvAttribute.getX( i ); let v = uvAttribute.getY( i ); [ u, v ] = ( () => { switch ( i ) { case 0 : return [ xMin, yMax ]; case 1 : return [ xMax, yMax ]; case 2 : return [ xMin, yMin ]; case 3 : return [ xMax, yMin ]; } } )(); uvAttribute.setXY( i, u, v ); } } /** Set all UVs to 0, so that none of the glyphs on the texture will appear */ nullifyUVs() { const uvAttribute = this.attributes.uv; for ( let i = 0; i < uvAttribute.count; i++ ) { uvAttribute.setXY( i, 0, 0 ); } } /** Gives the previously computed scale and offset to the geometry */ transformGeometry( font, fontSize, char, inline ) { const charOBJ = font.chars.find( charOBJ => charOBJ.char === char ); const common = font.common; const newHeight = charOBJ.height / common.lineHeight; const newWidth = ( charOBJ.width * newHeight ) / charOBJ.height; this.scale( newWidth, newHeight, 1 ); // this.translate( inline.width / 2, ( inline.height / 2 ) - inline.anchor, 0 ); } }