[UIデザイナーが学ぶ]Three.jsの3Dテキストの基本的な話
普段はメーカーで地味なおじさんUIデザイナーとして勤務しております。
あまり業務では利用しませんが、Three.jsの3Dテキストについて学び直しているので、備忘録的にまとめています。
3Dテキストの表示方法
利用するフォントはなんでも良いのですが、GoogleFontなどを利用する場合はFacetype.jsなどでコンバートした後読み込んでください。
...中略...
import { FontLoader } from "three/examples/jsm/loaders/FontLoader.js";
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js";
...中略...
const fontLoader = new FontLoader();
fontLoader.load("/fonts/helvetiker_regular.typeface.json", (font) => {
const textGeometry = new TextGeometry("Hello World", {
font: font, // THREE.Font のインスタンス
size: 0.5, // テキストのサイズ。デフォルトは 100 です
depth: 0.2, // テキストを押し出す厚さ。デフォルトは 50 です
curveSegments: 5, // 曲線上の点の数。デフォルトは 12 です
bevelEnabled: true, // ベベルをオンにします。デフォルトは Falseです
bevelThickness: 0.03, // テキストのベベルの深さ。デフォルトは 10 です
bevelSize: 0.02, // テキストのアウトラインからベベルまでの距離。デフォルトは 8 です
bevelOffset: 0, // テキストのアウトラインからベベルが始まる距離。デフォルトは 0 です
bevelSegments: 4, // ベベル セグメントの数。デフォルトは 3 です
});
const textMaterial = new THREE.MeshBasicMaterial();
const text = new THREE.Mesh(textGeometry, textMaterial);
scene.add(text);
});
textGeometryはメッシュの数が多くなってしまうので、なるべくセグメントは小さな数になるように調整したほうが良さそうです。
ジオメトリの原点を中心に配置する
textGeometryもジオメトリの原点はテキストの先頭になっています。
回転などをする際には、先頭が原点だと不都合がある場合がありますので、ジオメトリの原点を中心を移動します。
computeBoundingBox()
computeBoundingBox()を利用することで、ジオメトリの最小および最大の頂点を計算し、それを基にバウンディングボックス(境界ボックス)を設定します。
// テキストジオメトリの作成
const textGeometry = new THREE.TextGeometry('Hello, Three.js!', {
font: font,
size: 80,
height: 5,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 10,
bevelSize: 8,
bevelOffset: 0,
bevelSegments: 5
});
// バウンディングボックスの計算
textGeometry.computeBoundingBox();
// バウンディングボックスの取得
const boundingBox = textGeometry.boundingBox;
console.log(boundingBox);
boundingBoxは以下のような値になります。
{
isBox3: true,
min: {
x: -0.019999999552965164,
y: -0.033042728900909424,
z: -0.029999999329447746,
},
max: {
x: 3.5439999103546143,
y: 0.5264999866485596,
z: 0.23000000417232513 },
}
この値を利用してジオメトリの真ん中に原点を移動します。
translateを利用してジオメトリを移動します。
const textGeometry = new TextGeometry("Hello World", {
font: font,
size: 0.5,
depth: 0.2,
curveSegments: 5,
bevelEnabled: true,
bevelThickness: 0.03,
bevelSize: 0.02,
bevelOffset: 0,
bevelSegments: 4,
});
textGeometry.computeBoundingBox();
textGeometry.translate(
-textGeometry.boundingBox.max.x * 0.5,
-textGeometry.boundingBox.max.y * 0.5,
-textGeometry.boundingBox.max.z * 0.5
);
移動後のバウンディングボックスの値はこちらです。
{
isBox3: true,
min: {
x: -1.7919999361038208,
y: -0.2962927222251892,
z: -0.14499999582767487,
},
max: {
x: 1.7719999551773071,
y: 0.2632499933242798,
z: 0.11500000208616257,
},
};
minとmaxの値が少しずれているのはbevelThickness、bevelSizeを考慮して計算する必要があるからです。
textGeometry.translate(
-(textGeometry.boundingBox.max.x - 0.02) * 0.5, // Subtract bevel size
-(textGeometry.boundingBox.max.y - 0.02) * 0.5, // Subtract bevel size
-(textGeometry.boundingBox.max.z - 0.03) * 0.5 // Subtract bevel thickness
);
バウンディングボックスの値。
だいたいですが値が揃いました。
{
isBox3: true,
min: {
x: -1.781999945640564,
y: -0.2862927317619324,
z: -0.12999999523162842,
},
max: {
x: 1.781999945640564,
y: 0.2732499837875366,
z: 0.12999999523162842 },
};
textGeometry.center()
textGeometry.center()を利用すると、簡単に中央配置ができます。
textGeometry.center()
テキストも色々な表現に利用できそうなので、今後も情報を追加しようと思います。