ホームページ  >  記事  >  ウェブフロントエンド  >  HTML5とWebGLをベースにしたコリジョンエフェクトの実装

HTML5とWebGLをベースにしたコリジョンエフェクトの実装

一个新手
一个新手オリジナル
2017-10-20 10:44:211426ブラウズ

これは、会社のマスターによって作成され、ユーザーが学習できるように公式 Web サイトに掲載された例です。最初は、3 つの形状プリミティブを組み合わせただけで、回転したり、拡大したりできます。 3 つのグラフィックを同時に出力し、「アニメーション」をクリックして、中央のグラフィック要素を単独で回転させます。フォームの上部にある「軸」が何に使われるのかわかりません。非常に面倒で、公式サイトのデモには説明がありません。 。 。したがって、今日の私の課題は、この例を完全に分析することです。

まず、このケースを見てみましょう:

この 3D インタラクティブ モデルの操作方法を見てみましょう。「回転」スライダーを直接スライドすると、下部に 3D および 2D 画像が表示されます。左隅の要素が回転し、「軸」の任意の値をクリックしてから「アニメーション」をクリックすると、中央の要素が回転し、同時に「範囲」スライダーをスライドさせることがわかります。 「0」にすると回転はなくなり、「30」にすると 30 度回転します。次に「リセット」を調整すると、インターフェースを完全にリフレッシュするのではなく、両側のシリンダーが部分的にリフレッシュされ、2 つのシリンダーと中央のノードとの関係に基づいてリセットされることがわかります。

左下隅は 3D シーン全体の上面図であり、グラフィックス要素の移動方向と位置を非常に直観的に明確に確認できます。

この上面図がどのように配置されているか興味があるかもしれません? 3D のプリミティブが変更されると、この上面図のプリミティブも変更されますか?フォームを右上隅に、ビューを左下隅に配置するにはどうすればよいですか? 3D の 2 つだけを移動して、この 2 つをここで固定するにはどうすればよいですか?または、他の質問があるかもしれません。ここで明確に回答できるよう最善を尽くします。答えが見つからない場合は、公式 Web サイト HT にアクセスして質問を見つけることができます。

基本は、最初に 3D シーンをレイアウトすることです。HT は、通常、グリッドを生成するのに時間がかかることがあります。そのため、初心者の開発者でもすぐに始めることができます。そうですね〜、わずか数行のコードで 3D シーンを作成できます。とても速いです。 。 。

dm = new ht.DataModel();
g3d = new ht.graph3d.Graph3dView(dm);
g3d.setGridVisible(true);//设置网格可视g3d.setGridSize(m);//设置网格大小g3d.setGridGap(w);//设置网格间距g3d.setEye([-200, 150, 200]);//设置camera位置g3d.getView().className = 'main';
document.body.appendChild(g3d.getView());

HT はデフォルトですべてのコンポーネントにスタイル「position:absolute」を設定するため、このコンポーネントを初期化した後、スタイルに位置を記述し、この例では、このコンポーネントを追加するタグに追加する必要があります。フォームフォーム、2D コンポーネント、および 3D コンポーネントは相互に依存していないため、これら 3 つを直接本体に追加できます。もう 1 つの注目すべき点は、すべての HT コンポーネントのルート層がコンポーネントの getView( を通じて取得される 1 つであることです。 ) 関数。したがって、これを HTML タグに追加する場合は、HTML タグである必要があります。

次に、インターフェイスの右上隅にフォームフォームを配置し、スタイルで「上」、「下」、「左」、「右」を直接設定します。 2D 画像:

formPane = new ht.widget.FormPane();
formPane.setLabelAlign('right');
formPane.getView().className = 'formpane';
document.body.appendChild(formPane.getView());
formPane.addRow(['Rotation:', {
    id: 'rotation',
    slider: {
        min: -180,
        max: 180,
        value: 0,
        step: 1,
        onValueChanged: function(e){
            node.setRotation(this.getValue() * Math.PI / 180);
        }
    }
}], [60, 0.1]);

この例のため、フォームには多くの行とコンテンツがあるため、フォーム内のカスタム行の例のみを取り上げました。ここでの「id」は、この要素をすばやく見つけるためのものです。Slider は HT フォームのカスタマイズのメソッドであり、この属性を設定すると、HT は、具体的には属性値に基づいて ht.widger.Slider オブジェクトを構築します。 HT for Web フォームのマニュアルを参照してください。

左下隅の 2D 上面ビューに関しては、グラフィックスを描画してデータモデルに追加する限り、それがどのようなコンポーネントであるかに関係なく、同じデータモデルを共有することによって行われます。このデータモデルが呼び出されると、データモデルを持つことができます:

g2d = new ht.graph.GraphView(dm);
g2d.getView().className = 'g2d';
g2d.setEditable(true);
document.body.appendChild(g2d.getView());
ht.Default.callLater(g2d.fitContent, g2d, [true, 50, true]);

ht.Default.callLater(func,scope,args,lay) 内のすべてのデータは、グローバルな次の番号を取得します。ここで、func はコールバック関数を指し、スコープはコールバック関数を指します。 function ドメイン、args は関数パラメータリストを指します。lay は遅延時間 (ミリ秒) です。この関数は、ページを開いたときに g2d.fitContent 関数をコールバックできます。スコープは g2d 内のみです。この関数のパラメータ リストは、fitContent(anim、padding、notZoomIn) 関数のパラメータです。これら 3 つのパラメータはそれぞれを表します。 「アニメーションを使用するかどうか」、「ズームされたプリミティブ領域とトポロジーエッジの間の距離」、および「最小スケーリング値を 1 に制限するかどうか」。

次に、3D でグラフィック要素を追加します。ここではすべてのコードをインターセプトするのではなく、特別で興味深い画像要素 (中央の外側のレイヤーにある透明な画像要素) のみを取り上げます。

shape = new ht.Shape();
shape.s({
    'all.reverse.cull': true,
    'all.color': 'rgba(0, 255, 0, 0.5)',
    'all.transparent': true
});
shape.setThickness(2);
dm.add(shape);
var resetShape = function() {
    var cs = node.getCorners(10, 10);
    cs.push(cs[0]);
    shape.setPoints(cs);
    g3d.setBoundaries(ht.Default.toBoundaries(cs));
};
resetShape();

ここにはいくつかの興味深い点があります。 :

1. ここでは、node.getCorners() メソッドを使用して、2D の場合は左上、右下、左下の 4 つの点を取得します。底面の「左上、右上、右下、左下」の4点 これに気づくまでに時間がかかりました。 。 。そしてこの4点を図形の点として使います。

2. ここでも setBoundaries(boundaries) 関数が使用されており、ht.Default.toBoundaries 関数は setBoundaries 関数のパラメーターに準拠しない形式を必要なパラメーター形式に変換するために使用されます。この例ではこの行は何の効果もないと思いますが、それでも衝突テストにおいて良い教訓を得ることができました。

我们在碰撞测试的时候经常要设置g3d.setNear函数,我实在没搞懂这个函数是拿来干嘛的,结果这个例子让我注意到,如果“我”的视线的近端截面位置也就是setNear(1),那么我能看到的就是比表面跟进1的距离,这个函数默认设置为10,就算我们不设置这个值我们也能在3d中看到图元的内部去,刚刚我们介绍的getCorners()函数,其实它还有两个参数xpadding和ypadding,分别代表“水平方向padding”“垂直方向padding”,也就是说,在我们获取四个角的同时,我们还能设置这四个角和边之间的padding。只要将这个值设置得比setNear设置的大,我们就不会看到3d图元的内部中去了。

我们还注意到似乎是“废代码”的一行: cs.push(cs[0])。这个完全不是废代码啊,帮了很大忙呢!在HT中,用ht.Shape创建的图元,只要你不手动设置绘制关闭,那么就会停留在你最终绘制的位置,所以我把最后的一个点又和第一个点连起来,那么就是一个封闭的图形了,否则你会看到后面缺了一部分,像这样:

我在其他文章中也提到过HT封装了一些很方便的方法和事件,比如datamodel#md,监听数据的属性的变化,这边我们用了md方法来判断只有中间这个node能够绕着一个点旋转,具体参考HT for Web数据模型手册:

dm.md(function(e){
    if(e.data === node){
        if(e.property === 'rotation'){
            formPane.v('rotation', 180 / Math.PI * e.newValue);
        }
        resetShape();
    }
});

这边我想要说一下“绕着一个点旋转”的功能,这边没有用我们自定义的anchor锚点,但是功能类似,通过获取我form表单上选择的“left、right、front、back”来设置旋转中心点,HT中form表单通过getValue(id)简写成v(id)根据id获取对应item元素值:

formPane.addRow([
    {
         button: {
             label: 'Animate',
             onClicked: function(){
                 var dx = 0,
                 dy = 0,
                 range = formPane.v('range') * Math.PI / 180;
                 if(formPane.v('left')){
                     dx = -node.getWidth()/2;
                 }
                 if(formPane.v('right')){
                     dx = node.getWidth()/2;
                 }
                 if(formPane.v('back')){
                     dy = -node.getHeight()/2;
                 }
                 if(formPane.v('front')){
                     dy = node.getHeight()/2;
                 }
                 animate(node, range, dx, dy);
             }
         }
     },
     {
         button: {
             label: 'Reset',
             onClicked: function(){
                 node.setRotation(0);
             }
         }
     }
], [0.1, 0.1]);

以上がHTML5とWebGLをベースにしたコリジョンエフェクトの実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。