この記事では、主に、基本的なモデル リング、トーラス ノット、パイプラインとモデル生成、モデルの読み込み、アニメーションの追加、クリック イベントの追加、マテリアルの変更など、Three.js + Blender テクノロジー スタックを使用して Meta のクールな 3D ダイナミック ロゴを実現する方法について説明します。 背景
メタバースとは何ですか?メタバースという用語は、 メタバースの内包は、情報革命 成果を達成する早速本題に入り、この記事の例の実装効果を見てみましょう。 開発と実装
開発の前に、 トライアル 1: THREE.TorusGeometry
構文例:
トライアル 2: THREE.TorusKnotGeometry
構文例:
トライアル3: THREE.TubeGeometry
コードサンプル // ... var controls = 新しい関数 () { //ポイント座標 this.deafultpoints = [ [0, 0.4, -0.4], [0.4, 0, 0], [0.4, 0.8, 0.4], [0, 0.4, 0.4], [-0.4, 0, 0], [-0.4, 0.8, -0.4], [0, 0.4, -0.4] ] this.セグメント = 64; this.radius = 1; this.radiusSegments = 8; this.closed = true; ポイントは[]です。 this.newPoints = 関数 () { var ポイント = []; (var i = 0; i < controls.deafultpoints.length; i++) { var _x = controls.defaultpoints[i][0] * 22; var _y = controls.defaultpoints[i][1] * 22; var _z = controls.defaultpoints[i][2] * 22; points.push(新しいTHREE.Vector3(_x, _y, _z)); } controls.points = ポイント; コントロールを再度描画します。 }; this.redraw = 関数 () { redrawGeometryAndUpdateUI(gui、シーン、コントロール、関数() { generatePoints(controls.points, controls.segments, controls.radius, controls.radiusSegments, を返します。 コントロールを閉じます); }); }; }; コントロール。新しいポイント(); 関数 generatePoints(ポイント、セグメント、半径、半径セグメント、閉じた) { if (spGroup) scene.remove(spGroup); spGroup = 新しい THREE.Object3D(); var material = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: false }); points.forEach(関数(ポイント) { var spGeom = new THREE.SphereGeometry(0.1); var spMesh = new THREE.Mesh(spGeom, マテリアル); spMesh.position.copy(ポイント); spGroup を追加します。 }); シーンを追加します(spGroup); 新しい THREE.TubeGeometry(新しい THREE.CatmullRomCurve3(points), segments, radius, radiusSegments, closed) を返します。 } // ... トライアル4: Blender + Three.jsこれは
モデリングチュートリアル
Blenderを使ったモデリングモデリングには 依存関係の読み込み <script src="./assets/libs/three.js"></script> <script src="./assets/libs/loaders/FBXLoader.js"></script> <script src="./assets/libs/inflate.min.js"></script> <script src="./assets/libs/OrbitControls.js"></script> <script src="./assets/libs/stats.js"></script> シーンの初期化 var container、stats、controls、compose、camera、scene、renderer、light、clickableObjects = []、mixer、mixerArr = []、manMixer; var clock = new THREE.Clock(); 初期化(); アニメーション化(); 関数init() { コンテナ = document.createElement('div'); document.body.appendChild(コンテナ); // シーン scene = new THREE.Scene(); シーンを透明にする scene.fog = 新しい THREE.Fog(0xa0a0a0, 200, 1000); // パースペクティブ カメラ: 視野、アスペクト比、近い平面、遠い平面 camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000); カメラの位置を設定します(0, 4, 16); カメラ.lookAt(新しいTHREE.Vector3(0, 0, 0)); // 半球光源: 屋外効果のためのより自然な光源を作成します。light = new THREE.HemisphereLight(0xefefef); ライトの位置を設定します(0, 20, 0); シーンにライトを追加します。 // 指向性ライト light = new THREE.DirectionalLight(0x2d2d2d); ライトの位置を設定します(0, 20, 10); ライトをキャストします。 シーンにライトを追加します。 // アンビエントライト var ambientLight = new THREE.AmbientLight(0xffffff, .5); シーンにアンビエントライトを追加します。 // グリッド var grid = new THREE.GridHelper(100, 100, 0xffffff, 0xffffff); グリッドの位置を設定します(0, -10, 0); グリッドの不透明度 = 0.3; グリッドのマテリアルを透明にする シーンにグリッドを追加します。 レンダラー = 新しい THREE.WebGLRenderer({ アンチエイリアス: true、アルファ: true }); レンダラーのピクセル比を設定します。 レンダラーの出力エンコーディング = THREE.sRGBEncoding; レンダラーのサイズを設定します。 //背景色を透明に設定しますrenderer.setClearAlpha(0); // 有効にする shadowrenderer.shadowMap.enabled = true; コンテナに子要素を追加します。 // レンズ コントローラーを追加します。controls = new THREE.OrbitControls(camera, renderer.domElement); コントロールのターゲットを設定します(0, 0, 0); コントロールを更新します。 window.addEventListener('resize', onWindowResize, false); // パフォーマンスプラグインを初期化します。stats = new Stats(); コンテナに子要素を追加します。 } // 画面ズーム関数 onWindowResize() { カメラのアスペクト比は window.innerWidth または window.innerHeight です。 カメラの投影マトリックスを更新します。 レンダラーのサイズを設定します。 }
ロゴモデルを読み込んでいます
var ローダー = new THREE.FBXLoader(); loader.load('assets/models/meta.fbx', 関数(メッシュ) { mesh.traverse(関数(子) { 子がメッシュである場合 子.castShadow = true; 子.receiveShadow = true; } }); メッシュの回転y = Math.PI / 2; メッシュの位置を設定します(0, 1, 0); メッシュスケールを0.05に設定します。 シーンを追加します(メッシュ); }); 材料の追加この記事の var texLoader = new THREE.TextureLoader(); loader.load('assets/models/meta.fbx', 関数(メッシュ) { mesh.traverse(関数(子) { 子がメッシュである場合 if (child.name === 'ベジェ円') { child.material = 新しい THREE.MeshPhysicalMaterial({ マップ: texLoader.load("./assets/images/metal.png"), 金属度: .2, 粗さ: 0.1、 露出: 0.4 }); } } }); }) アニメーションを追加
loader.load('assets/models/meta.fbx', 関数(メッシュ) { メッシュ.アニメーション.マップ(アイテム => { メッシュ.traverse(子 => { // モデルには複数のオブジェクトがあり、それぞれに異なるアニメーションがあるため、この例ではベジェ円メッシュにのみアニメーションを追加します if (child.name === 'Bezier circle') { ミキサーを新しい THREE.AnimationMixer(child); にします。 ミキサーArr.push(ミキサー); アニメーションクリップを item にします。 アニメーションクリップの継続時間 = 8; clipAction を mixer.clipAction(animationClip).play() にします。 アニメーションクリップ = clipAction.getClip(); } }) }) }); アニメーションを追加した後は、 関数アニメーション() { レンダラー.レンダリング(シーン、カメラ); // このメソッドの 2 回の実行間の時間間隔を取得します。let time = clock.getDelta(); // ロゴアニメーションを更新 mixerArr.map(mixer => { ミキサー && mixer.update(時間); }); // キャラクターアニメーションを更新 manMixer && manMixer.update(time); 統計情報を更新します。 アニメーションフレームをリクエストします(アニメーション化します); } 読み込みの進行状況を表示
<div class="読み込み中" id="読み込み中"> <p class="text">読み込みの進行状況<span id="progress">0%</span></p> <div> var ローダー = new THREE.FBXLoader(); loader.load('assets/models/meta.fbx', メッシュ => { }, 解像度 => { // 読み込みの進行状況 let progress = (res.loaded / res.total * 100).toFixed(0); document.getElementById('progress').innerText = progress; (進捗状況 === 100)の場合{ document.getElementById('loading').style.display = 'なし'; } }, エラー => { // ロード失敗 console.log(err) }); 成果を達成する クリックして素材を変更ページのクリック イベントをリッスンし、 // raycaster とマウス変数を宣言します var raycaster = new THREE.Raycaster(); var マウス = new THREE.Vector2(); 関数 onMouseClick(イベント) { // マウスのクリック位置に基づいて、レイキャスターが必要とするポイントの位置を計算します。画面の中心を原点とし、値の範囲は -1 ~ 1 です。 マウスのx = (イベントのクライアントX / ウィンドウのインナー幅) * 2 - 1; mouse.y = - (event.clientY / window.innerHeight) * 2 + 1; // マウスポイントの位置と現在のカメラマトリックスに基づいてレイキャスターを計算します raycaster.setFromCamera(マウス、カメラ); // レイキャスターのラインがすべてのモデルと交差する配列コレクションを取得します。let intersects = raycaster.intersectObjects(clickableObjects); 交差する長さが0より大きい場合 console.log(交差[0].オブジェクト) selectedObj = intersects[0].objectとします。 selectedObj.material = 新しい THREE.MeshStandardMaterial({ 色: `#${Math.random().toString(16).slice(-6)}`, 金属性: Math.random(), 粗さ: Math.random() }) } } window.addEventListener('click', onMouseClick, false); キャラクターモデルを読み込んでいますキャラクターモデルの読み込みプロセスは、 loader.load('assets/models/man.fbx', 関数(メッシュ) { mesh.traverse(関数(子) { 子がメッシュである場合 子.castShadow = true; 子.receiveShadow = true; } }); メッシュの回転y = Math.PI / 2; メッシュの位置を設定します(-14, -8.4, -3); メッシュスケールを設定します(0.085, 0.085, 0.085); シーンを追加します(メッシュ); manMixer = 新しい THREE.AnimationMixer(メッシュ); animationClip = mesh.animations[0] とします。 clipAction を manMixer.clipAction(animationClip).play() にします。 アニメーションクリップ = clipAction.getClip(); }, 解像度 => { 進捗状況を (res.loaded / res.total * 100).toFixed(0) とします。 document.getElementById('progress').innerText = progress + '%'; if (数値(進捗) === 100) { document.getElementById('loading').style.display = 'なし'; } }, エラー => { コンソール.log(エラー) }); この記事のサンプルキャラクターモデルは mixamo.com から取得したもので、何百ものキャラクターと何千ものアクションを自由に組み合わせて 要約するこの記事に含まれる主な知識ポイントは次のとおりです。
参考文献[1] three.jsを使用してクールなアシッドスタイルの3Dページを作成する [2] ThreeJsにおけるマテリアルの理解 [3] スリーのアニメーションの第一印象 [4] メタバースとは何ですか? 著者: dragonir 記事URL: https://www.cnblogs.com/dragonir/p/15574412.html Three.js で Facebook Metaverse 3D ダイナミック ロゴを実装する方法についての記事はこれで終わりです。Three.js 3D ダイナミック ロゴに関するその他の関連コンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: UTF-8 ファイルの Unicode 署名 BOM (バイト オーダー マーク) の問題
/******************** * カーネルにおけるリンクリストの応用********...
ここでは、PHP、JSP、または .NET 環境については説明しません。アーキテクチャの観点から問題...
この記事の例では、カレンダーウィジェットを実装するためのjsの具体的なコードを参考までに共有していま...
何人かのブロガーが私の記事を評価してくれたのは嬉しいです。マークと知り合ってからは、私は彼をフォロー...
プロジェクトの要件は、日付と時刻を選択し、現在の時刻以降の時刻のみを選択し、最小レベルを分単位で無効...
この記事は、CentOS 7の詳細なインストールチュートリアルを参考のために記録します。具体的な内容...
基礎位置の一致順序は、「最初に正規表現に一致し、次に共通表現に一致」です。実際のロケーションの一致順...
HTML タグには、インライン要素とブロックレベル要素の 2 種類があります。まず、インライン要素と...
仮想化とコンテナ化は、クラウドベースのプロジェクトでは避けられない 2 つの問題です。仮想化は純粋な...
Centos7 上で openresty 用の Dockerfile を作成し、ビルドしました。 d...
覗き見の問題サーバーでは、IIS サービスが複数のサイトを展開していると仮定すると、サイトの 1 つ...
この記事では、Harbor アーキテクチャの構成と、実行時に各コンポーネントを使用する方法について説...
コンテナデータボリュームとはデータがコンテナ内にある場合、コンテナを削除するとデータは失われます。例...
1. 必要なカーネルバージョンをダウンロードする2. オペレーティングシステムにアップロードする3....
序文データベースの応用において、プログラマーは継続的な実践を通じて多くの経験を積んできました。これら...