Heim  >  Artikel  >  Web-Frontend  >  Implementierung des Kollisionseffekts basierend auf HTML5 und WebGL

Implementierung des Kollisionseffekts basierend auf HTML5 und WebGL

一个新手
一个新手Original
2017-10-20 10:44:211439Durchsuche

Dies ist ein Beispiel, das vom Meister des Unternehmens geschrieben und auf der offiziellen Website veröffentlicht wurde, damit Benutzer es zunächst lernen können. Es wurden nur drei Formprimitive kombiniert, und dann können sie gedreht werden Verkleinern Sie diese drei Grafiken und klicken Sie auf „Animieren“, um nur das mittlere Grafikelement um einen bestimmten Punkt drehen zu lassen. Ich weiß wirklich nicht, wofür die „Achse“ oben im Formular verwendet wird. und ich finde es sehr umständlich. Außerdem ist es eine Demo auf der offiziellen Website und es gibt keine Erklärung. . . Meine heutige Aufgabe besteht also darin, dieses Beispiel vollständig zu analysieren!

Schauen wir uns zunächst diesen Fall an:

Sehen wir uns an, wie dieses interaktive 3D-Modell bedient wird. Sie können die „Rotation“ direkt verschieben „Schieberegler, Sie werden sehen, dass sich die Grundelemente in 3D und 2D in der unteren linken Ecke drehen. Klicken Sie dann auf einen beliebigen Wert in „Achse“ und dann auf „Animieren“. Sie werden sehen, dass sich das Grundelement in der Mitte dreht. und schieben Sie den „Bereich“ „Der Schieberegler steuert das Ausmaß Ihrer Drehung. Wenn Sie ihn auf „0“ einstellen, dreht er sich nicht. Wenn Sie ihn auf „30“ einstellen, dreht er sich um 30 Grad und so weiter. Passen Sie dann „Zurücksetzen“ an und Sie werden feststellen, dass die Zylinder auf beiden Seiten nicht vollständig aktualisiert werden, sondern basierend auf der Beziehung zwischen den beiden Zylindern und dem mittleren Knoten teilweise aktualisiert und zurückgesetzt werden.

Die untere linke Ecke ist eine Draufsicht der gesamten 3D-Szene, sodass wir die Bewegungsrichtung und Position der Grundelemente sehr intuitiv erkennen können.

Vielleicht sind Sie neugierig, wie diese Draufsicht platziert ist? Wenn sich die Grundelemente in 3D ändern, ändern sich dann auch die Grundelemente in dieser Draufsicht? Wie platziere ich das Formular in der oberen rechten Ecke und die Ansicht in der unteren linken Ecke? Wie kann man nur zwei 3D verschieben und diese beiden hier reparieren? Oder Sie haben andere Fragen, ich werde mein Bestes geben, diese hier klar zu beantworten. Wenn Sie die Antwort wirklich nicht finden, können Sie Ihre Frage auf unserer offiziellen Website HT for Web finden.

Okay, das Grundprinzip besteht darin, zuerst die 3D-Szene zu entwerfen. Normalerweise kann es eine Weile dauern, bis wir das Raster erstellen, und es handelt sich um einfachen Code, den Sie erhalten können Schnell gestartet ~ Sie können eine 3D-Szene in nur wenigen Codezeilen erstellen, was sehr schnell geht. . .

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

Da HT standardmäßig den Stil „position:absolute“ für alle Komponenten festlegt, müssen wir beim Initialisieren dieser Komponente die Position im Stil schreiben und diese Komponente zum In-Tag hinzufügen In diesem Beispiel sind die Formularform, die 2D-Komponente und die 3D-Komponente nicht voneinander abhängig, sodass wir diese drei direkt zum Körper hinzufügen können. Eine weitere erwähnenswerte Sache ist, dass alle HT-Komponenten alle ein p sind wird über die Funktion getView() der Komponente abgerufen. Wenn wir es also zu einem HTML-Tag hinzufügen möchten, muss es ein HTML-Tag sein.

Platzieren Sie dann das Formular in der oberen rechten Ecke der Benutzeroberfläche und legen Sie direkt „oben“, „unten“, „links“ und „rechts“ im Stil fest. Das Gleiche gilt für 2D-Bilder:

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

Da das Formular in diesem Beispiel eine große Anzahl von Zeilen und Inhalten hat, habe ich nur ein Beispiel einer benutzerdefinierten Zeile im Formular genommen. Die „id“ dient hier nur dazu, dieses Element schnell zu finden. Die Slider-Funktion erstellt automatisch das ht.widger.Slider-Objekt basierend auf dem Attributwert Parameter finden Sie im HT for Web-Formularhandbuch.

Was die 2D-Draufsicht in der unteren linken Ecke betrifft, erfolgt dies durch die gemeinsame Nutzung desselben Datenmodells mit 3D, solange wir die Grafiken zeichnen und sie dann dem Datenmodell hinzufügen, unabhängig von der Komponente , solange dieses Datenmodell aufgerufen wird. Sie können alle Daten im Datenmodell haben:

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) ruft die globale nächste Nummer ab, auf die sich func bezieht bezieht sich auf die Rückruffunktion und der Gültigkeitsbereich bezieht sich auf die Funktionsdomäne, args bezieht sich auf die Funktionsparameterliste und Verzögerung ist die Verzögerungszeit (Millisekunden). Diese Funktion kann die Funktion g2d.fitContent zurückrufen, wenn die Seite geöffnet wird, und der Umfang liegt nur in g2d. Die Parameterliste dieser Funktion besteht aus den Parametern der Funktion fitContent(anim, padding, notZoomIn). „Ob Animation verwendet werden soll.“ „Der Abstand zwischen dem vergrößerten Grundelementbereich und der topologischen Kante“ und „Ob der minimale Skalierungswert auf 1 begrenzt werden soll“.

Dann füge ich die Grafikelemente in 3D hinzu. Ich werde hier nicht alle Codes abfangen, sondern nur ein spezielles und interessantes Grafikelement nehmen, das transparente Grafikelement in der mittleren Außenschicht:

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

Hier gibt es einige interessante Punkte:

1. Die Methode node.getCorners() dient dazu, vier Punkte zu erhalten: oben links, oben rechts, unten rechts. und unten links. Bei 3D geht es darum, die vier Punkte „oben links, oben rechts, unten rechts, unten links“ direkt zu erhalten. . . Und basierend auf diesen vier Punkten als Punkten der Form.

2. Die Funktion setBoundaries(boundaries) wird auch hier verwendet, und die Funktion ht.Default.toBoundaries wird verwendet, um das Format, das nicht den Parametern der setBoundaries-Funktion entspricht, in das erforderliche Parameterformat zu konvertieren. Obwohl ich denke, dass diese Zeile in diesem Beispiel keine Auswirkung hat, hat sie mir dennoch eine gute Lektion in Sachen Kollisionstests erteilt.

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

Das obige ist der detaillierte Inhalt vonImplementierung des Kollisionseffekts basierend auf HTML5 und WebGL. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn