Maison  >  Article  >  interface Web  >  Implémentation d'un effet de collision basé sur HTML5 et WebGL

Implémentation d'un effet de collision basé sur HTML5 et WebGL

一个新手
一个新手original
2017-10-20 10:44:211421parcourir

Il s'agit d'un exemple écrit par le maître de l'entreprise et publié sur le site officiel pour que les utilisateurs puissent l'apprendre. Au début, je ne savais vraiment pas ce qu'il faisait. Il combinait simplement trois primitives de forme, puis elles pouvaient être pivotées. et agrandi en même temps. Réduisez ces trois graphiques et cliquez sur "Animer" pour faire pivoter l'élément graphique du milieu autour d'un certain point seul. Je ne sais vraiment pas à quoi sert "l'Axe" en haut du formulaire, et je trouve ça très fastidieux. De plus, c'est une démo sur le site officiel, et il n'y a aucune explication. . . Ma tâche aujourd'hui est donc d'analyser complètement cet exemple !

Regardons d'abord ce cas :

Voyons comment faire fonctionner ce modèle interactif 3D. Vous pouvez directement faire glisser la "Rotation". " curseur, vous verrez que les primitives en 3D et 2D dans le coin inférieur gauche vont pivoter, puis cliquez sur n'importe quelle valeur dans "Axe", puis cliquez sur "Animer", vous verrez que la primitive du milieu va pivoter, et faites glisser le "Plage" "Le curseur contrôle l'étendue de votre rotation. Si vous l'ajustez à "0", il ne tournera pas. Si vous l'ajustez à "30", il pivotera de 30 degrés, et ainsi de suite. Ajustez ensuite « Réinitialiser » et vous constaterez qu'au lieu de rafraîchir complètement l'interface, les cylindres des deux côtés sont partiellement rafraîchis et réinitialisés en fonction de la relation entre les deux cylindres et le nœud central.

Le coin inférieur gauche est une vue de dessus de toute la scène 3D, afin que nous puissions voir clairement la direction de déplacement et la position des primitives de manière très intuitive.

Peut-être êtes-vous curieux de savoir comment cette vue de dessus est placée ? Si les primitives en 3D changent, les primitives de cette vue de dessus changeront-elles également ? Comment placer le formulaire dans le coin supérieur droit et la vue dans le coin inférieur gauche ? Comment déplacer seulement deux 3D et réparer ces deux-là ici ? Ou vous avez peut-être d'autres questions. Je ferai de mon mieux pour y répondre clairement ici. Si vous ne trouvez vraiment pas la réponse, vous pouvez vous rendre sur notre site officiel HT for Web pour trouver votre question.

D'accord, la base est de présenter d'abord la scène 3D. HT est très détaillé dans la fourniture de méthodes. Habituellement, la génération de la grille peut prendre un certain temps. C'est également du code de base, donc vous êtes des développeurs novices. peut démarrer rapidement ~ Vous pouvez créer une scène 3D en seulement quelques lignes de code, ce qui est si rapide. . .

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());

Puisque HT définit le style "position:absolute" pour tous les composants par défaut, lorsque nous initialisons ce composant, nous devons écrire la position dans le style et ajouter ce composant au Dans la balise pour être ajouté, dans cet exemple, le formulaire, le composant 2D et le composant 3D ne dépendent pas les uns des autres, nous pouvons donc ajouter directement ces trois au corps. Une autre chose à noter est que tous les composants HT La couche racine est entièrement un p, ce qui. est obtenu via la fonction getView() du composant. Donc si nous voulons l'ajouter à une balise HTML, il doit s'agir d'une balise HTML.

Placez ensuite le formulaire dans le coin supérieur droit de l'interface. Placez-le dans le coin supérieur droit et définissez directement le "haut", "le bas", "la gauche" et la "droite" dans le style. Il en va de même pour les images 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]);

Étant donné que le formulaire de cet exemple comporte un grand nombre de lignes et de contenu, je n'ai pris qu'un exemple de ligne personnalisée dans le formulaire. Le "id" ici sert simplement à trouver rapidement cet élément. Slider est une méthode pour personnaliser le formulaire HT, la fonction slider après avoir défini cet attribut, HT construira automatiquement l'objet ht.widger.Slider en fonction de la valeur de l'attribut. Pour les paramètres, veuillez vous référer au manuel du formulaire HT for Web.

Quant à la vue de dessus 2D dans le coin inférieur gauche, cela se fait en partageant le même modèle de données avec la 3D tant que nous dessinons les graphiques puis les ajoutons au modèle de données, quel que soit le composant dont il s'agit. , tant que ce modèle de données est appelé Vous pouvez avoir toutes les données dans le modèle de données :

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, delay) obtient le numéro global suivant, où func fait référence à la fonction de rappel et scope fait référence au domaine de fonction, args fait référence à la liste des paramètres de fonction et delay est le temps de retard (millisecondes). Cette fonction peut rappeler la fonction g2d.fitContent lorsque la page est ouverte, et la portée est uniquement dans g2d. La liste des paramètres de cette fonction est constituée des paramètres de la fonction fitContent(anim, padding, notZoomIn) qui représentent respectivement ces trois paramètres. "s'il faut utiliser l'animation". "La distance entre la zone primitive zoomée et le bord topologique", et "s'il faut limiter la valeur de mise à l'échelle minimale à 1".

Ajoutez ensuite les éléments graphiques en 3D. Je n'intercepterai pas tous les codes ici, mais je prendrai seulement un élément graphique spécial et intéressant, l'élément graphique transparent dans la couche externe intermédiaire :

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();

Il y a quelques points intéressants ici :

1. La méthode node.getCorners() est utilisée ici pour obtenir quatre points. Pour la 2D, ils sont en haut à gauche, en haut à droite, en bas à droite. et en bas à gauche Quatre points ; pour la 3D, il s'agit d'obtenir directement les quatre points « supérieur gauche, supérieur droit, inférieur droit, inférieur gauche » sur la surface inférieure. Il m'a fallu du temps pour réagir à cela. . . Et utilisez ces quatre points comme points de la forme.

2. La fonction setBoundaries(boundaries) est également utilisée ici, et la fonction ht.Default.toBoundaries est utilisée pour convertir le format qui n'est pas conforme aux paramètres de la fonction setBoundaries dans le format de paramètre requis. Même si je pense que cette ligne n'a aucun effet dans cet exemple, elle m'a quand même appris une bonne leçon en matière de tests de collision.

我们在碰撞测试的时候经常要设置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]);

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn