Chapter 21

3-03: 車のマテリアル (Car Material)

ちょまど (千代田まどか)
ちょまど (千代田まどか)
2022.03.30に更新

このページの原文: https://doc.babylonjs.com/start/chap3/carmat

🚙 3-03: 車のマテリアル (Car Material)

ボックスのそれぞれの面にそれぞれの画像を使用したのと同じように、押し出された (extruded) ポリゴンと円柱にもそれぞれの画像を使います。

画像

車体にはこの画像を使います。

これは車輪用です。

🚙 車体に画像を張っていく

面に画像を設定していきます。

2-06 で解説した通りボックスに使う FaceUV 配列には面ごとに以下のインデックスが振られています:

番号 面 (原文)
0 背面 (back)
1 前面 (front)
2 右面 (right)
3 左面 (left)
4 上部 (top)
5 底 (bottom)

車体が現在横になっていることを考慮しながら、それぞれの面の番号(インデックス)を考えていきます。
車体の上下部分は、画像の (ほぼ) 四分の一 (左上部分) を使用しています。

車体の底部(車体を立たせたら側面)の座標指定は、左下 (0, 0.5) から右上(0.38, 1) です。

faceUV[0] = new BABYLON.Vector4(0, 0.5, 0.38, 1);

車体の上部は同じ画像を使用していますが、車の反対側に合わせるには裏返す必要があります。

faceUV[2] = new BABYLON.Vector4(0.38, 1, 0, 0.5);

車体のエッジ部は (0, 0) から (1, 0.5) まで伸びています。

faceUV[1] = new BABYLON.Vector4(0, 0, 1, 0.5);

サンプル「車体にマテリアルを追加」

https://playground.babylonjs.com/#KDPAQ9#12
createScene 関数内の車体構築部分
// ベース
const outline = [
    new BABYLON.Vector3(-0.3, 0, -0.1),
    new BABYLON.Vector3(0.2, 0, -0.1),
]

// カーブした前面
for (let i = 0; i < 20; i++) {
    outline.push(new BABYLON.Vector3(0.2 * Math.cos(i * Math.PI / 40), 0, 0.2 * Math.sin(i * Math.PI / 40) - 0.1));
}

// 上部
outline.push(new BABYLON.Vector3(0, 0, 0.1));
outline.push(new BABYLON.Vector3(-0.3, 0, 0.1));

// 背面は自動で描画される

// 面の UV
const faceUV = [];
faceUV[0] = new BABYLON.Vector4(0, 0.5, 0.38, 1);
faceUV[1] = new BABYLON.Vector4(0, 0, 1, 0.5);
faceUV[2] = new BABYLON.Vector4(0.38, 1, 0, 0.5);

// マテリアル
const carMat = new BABYLON.StandardMaterial("carMat");
carMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/car.png");

const car = BABYLON.MeshBuilder.ExtrudePolygon(
    "car", 
    {
        shape: outline, 
        depth: 0.2, 
        faceUV: faceUV, 
        wrap: true
    }
);
car.material = carMat;

🚙 車輪に画像を張っていく

車輪 (wheel) は対称性があるため、より単純で、画像全体を上下に使用し、エッジに黒いピクセルをピックアップするだけです。

// ↓ (0, 0) から (1, 1) なので画像全体を面に反映している
wheelUV[0] = new BABYLON.Vector4(0, 0, 1, 1);
// ↓ 画像の (0, 0.5) 部分の 1点 (黒) だけ面に反映している
wheelUV[1] = new BABYLON.Vector4(0, 0.5, 0, 0.5);
// ↓ (0, 0) から (1, 1) なので画像全体を面に反映している
wheelUV[2] = new BABYLON.Vector4(0, 0, 1, 1);

https://playground.babylonjs.com/#KDPAQ9#13

車(車体 + 車輪)を描画するコードは、最終的にこうなります。

const buildCar = () => {
    // ベース
    const outline = [
        new BABYLON.Vector3(-0.3, 0, -0.1),
        new BABYLON.Vector3(0.2, 0, -0.1),
    ]

    // カーブした前面
    for (let i = 0; i < 20; i++) {
        outline.push(new BABYLON.Vector3(0.2 * Math.cos(i * Math.PI / 40), 0, 0.2 * Math.sin(i * Math.PI / 40) - 0.1));
    }

    // 上部
    outline.push(new BABYLON.Vector3(0, 0, 0.1));
    outline.push(new BABYLON.Vector3(-0.3, 0, 0.1));

    // 背面は自動で描画される

    // 面の UV
    const faceUV = [];
    faceUV[0] = new BABYLON.Vector4(0, 0.5, 0.38, 1);
    faceUV[1] = new BABYLON.Vector4(0, 0, 1, 0.5);
    faceUV[2] = new BABYLON.Vector4(0.38, 1, 0, 0.5);

    // マテリアル
    const carMat = new BABYLON.StandardMaterial("carMat");
    carMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/car.png");

    const car = BABYLON.MeshBuilder.ExtrudePolygon(
        "car", 
        {
            shape: outline, 
            depth: 0.2, 
            faceUV: faceUV, 
            wrap: true
        }
    );
    car.material = carMat;

    // 車輪用の UV
    const wheelUV = [];
    wheelUV[0] = new BABYLON.Vector4(0, 0, 1, 1);
    wheelUV[1] = new BABYLON.Vector4(0, 0.5, 0, 0.5);
    wheelUV[2] = new BABYLON.Vector4(0, 0, 1, 1);
    
    // 車輪用のマテリアル
    const wheelMat = new BABYLON.StandardMaterial("wheelMat");
    wheelMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/wheel.png");

    const wheelRB = BABYLON.MeshBuilder.CreateCylinder(
        "wheelRB", 
        {
            diameter: 0.125, 
            height: 0.05, 
            faceUV: wheelUV
        }
    );
    wheelRB.material = wheelMat;
    wheelRB.parent = car;
    wheelRB.position.z = -0.1;
    wheelRB.position.x = -0.2;
    wheelRB.position.y = 0.035;

    wheelRF = wheelRB.clone("wheelRF");
    wheelRF.position.x = 0.1;

    wheelLB = wheelRB.clone("wheelLB");
    wheelLB.position.y = -0.2 - 0.035;

    wheelLF = wheelRF.clone("wheelLF");
    wheelLF.position.y = -0.2 - 0.035;

    return car;
}

☞ 次

次は車輪にアニメーションをつけてみましょう。