Detaillierter Prozess zum Zeichnen dreidimensionaler Pfeillinien mit three.js

Detaillierter Prozess zum Zeichnen dreidimensionaler Pfeillinien mit three.js

Nachfrage: Diese Nachfrage ist ein dringender Bedarf! In einer U-Bahn-Szene muss ein Fluchtweg mit einem Pfeil angezeigt werden, der den Weg anzeigt. Ich habe nicht weniger als ein Dutzend Stunden gebraucht, um diesen Pfeil zu zeichnen, und ich war schließlich fertig, aber es gab noch ein Problem. Meine Anforderung an diesen Pfeil ist, dass er, egal ob in der Szene hinein- oder herausgezoomt wird, weder zu groß noch zu klein sein darf, um deutlich erkannt zu werden, und dass sich seine Form nicht ändern darf, da er sonst nicht wie ein Pfeil aussieht.

Verwendet Line2.js von three.js und eine Open-Source-Bibliothek MeshLine.js

Teil des Codes:

DrawPath.js:

/**
 * Zeichne eine Route */

importiere * als DREI aus „../build/three.module.js“;
importiere { MeshLine, MeshLineMaterial, MeshLineRaycast } aus '../js.my/MeshLine.js';

importiere { Line2 } aus '../js/lines/Line2.js';
importiere { LineMaterial } aus '../js/lines/LineMaterial.js';
importiere { LineGeometry } aus '../js/lines/LineGeometry.js';
importiere { GeometryUtils } aus '../js/utils/GeometryUtils.js';

importiere { CanvasDraw } von '../js.my/CanvasDraw.js';

importiere { Utils } von '../js.my/Utils.js';
importiere { Msg } von '../js.my/Msg.js';

let DrawPath = Funktion () {

    lass _self = dies;

    let _canvasDraw = neues CanvasDraw();
    Utils();
    let msg = neue Msg();

    dies._isDrawing = falsch;
    dieser._Pfad = [];
    diese._zeilen = [];
    diese._arrows = [];

    Lassen Sie _depthTest = true;
    lass _side = 0;

    let viewerContainerId = '#cc';
    let viewerContainer = $(viewerContainerId)[0];

    Objekte lassen;
    lass die Kamera;
    lass dich wenden;
    lass Szene;

    this.config = Funktion (Objekte_, Kamera_, Szene_, Drehung_) {
        Objekte = Objekte_;
        Kamera = Kamera_;
        drehen = drehen_;
        Szene = Szene_;

        this._oldDistance = 1;
        this._oldCameraPos = { x: Kamera.position.x, y: Kamera.position.y, z: Kamera.position.z }
    }

    dies.start = Funktion () {
        wenn (!this._isDrawing) {
            dies._isDrawing = wahr;
            viewerContainer.addEventListener('klicken', ray);
            viewerContainer.addEventListener('Maus nach unten', Maus nach unten);
            viewerContainer.addEventListener('Maus hoch', Maus hoch);
        }
        msg.show("Bitte klicken Sie auf den Boden, um die Linie zu zeichnen");
    }

    dies.stop = Funktion () {
        wenn (this._isDrawing) {
            dies._isDrawing = falsch;
            viewerContainer.removeEventListener('klicken', ray);
            viewerContainer.addEventListener('Maus nach unten', Maus nach unten);
            viewerContainer.addEventListener('Maus hoch', Maus hoch);
        }
        msg.show("Linienzeichnung beenden");
    }

    Funktion mousedown(params) {
        this._mousedownPosition = { x: Kamera.position.x, y: Kamera.position.y, z: Kamera.position.z }
    }

    Funktion mouseup(Parameter) {
        this._mouseupPosition = { x: Kamera.position.x, y: Kamera.position.y, z: Kamera.position.z }
    }

    Funktion Strahl(e) {
        schalte.unFocusButton();

        let raycaster = createRaycaster(e.clientX, e.clientY);
        lass intersects = raycaster.intersectObjects(Objekte.alle);
        wenn (Schnittpunkt.Länge > 0) {
            lass Punkt = schneidet[0].Punkt;

            lass Abstand = utils.abstand(diese._mousedownPosition.x, diese._mousedownPosition.y, diese._mousedownPosition.z, diese._mouseupPosition.x, diese._mouseupPosition.y, diese._mouseupPosition.z);

            wenn (Abstand < 5) {
                _self._path.push({ x: Punkt.x, y: Punkt.y + 50, z: Punkt.z });

                wenn (_self._path.length > 1) {
                    lass Punkt1 = _self._Pfad[_self._Pfad.Länge - 2];
                    lass Punkt2 = _self._path[_self._path.length - 1];

                    zeichneLinie(Punkt1, Punkt2);
                    zeichnePfeil(Punkt1, Punkt2);
                }
            }
        }
    }

    Funktion erstelleRaycaster(ClientX, ClientY) {
        sei x = (ClientX / $(viewerContainerId).width()) * 2 - 1;
        sei y = -(clientY / $(viewerContainerId).height()) * 2 + 1;

        sei Standardvektor = neuer DREI.Vektor3(x, y, 0,5);

        lass worldVector = standardVector.unproject(Kamera);

        lass ray = worldVector.sub(camera.position).normalize();

        lass raycaster = neu THREE.Raycaster(Kameraposition, Strahl);

        Raycaster zurückgeben;
    }

    dies.refresh = Funktion () {
        wenn (_self._path.length > 1) {
            lass Abstand = utils.abstand(diese._alteKameraPos.x, diese._alteKameraPos.y, diese._alteKameraPos.z, Kamera.position.x, Kamera.position.y, Kamera.position.z);
            sei das Verhältnis = 1;
            wenn (this._oldDistance != 0) {
                Verhältnis = Math.abs((this._oldDistance - Entfernung) / this._oldDistance)
            }

            wenn (Abstand > 5 && Verhältnis > 0,1) {
                console.log("======= DrawPath-Aktualisierung= ...
                für (lass i = 0; i < _self._path.length - 1; i++) {
                    lass Pfeil = _self._arrows[i];
                    lass Punkt1 = _self._Pfad[i];
                    lass Punkt2 = _self._Pfad[i + 1];
                    Pfeil aktualisieren(Punkt1, Punkt2, Pfeil);
                }
                this._oldDistance = Entfernung;
                this._oldCameraPos = { x: Kamera.position.x, y: Kamera.position.y, z: Kamera.position.z }
            }
        }
    }

    Funktion zeichneLinie(Punkt1, Punkt2) {
        const Positionen = [];

        Positionen.Push(Punkt1.x / 50, Punkt1.y / 50, Punkt1.z / 50);
        Positionen.Push(Punkt2.x / 50, Punkt2.y / 50, Punkt2.z / 50);

        let geometrie = neue LineGeometry();
        geometrie.setPositions(Positionen);

        let matLine = neues Linienmaterial({
            Farbe: 0x009900,
            Linienbreite: 0,003, // in Welteinheiten mit Größendämpfung, andernfalls Pixel
            gestrichelt: wahr,
            Tiefentest: _Tiefentest,
            Seite: _Seite
        });

        lass Linie = neue Linie2(Geometrie, matLine);
        line.computeLineDistances();
        Linie.Skala.Satz(50, 50, 50);

        Szene.Hinzufügen(Zeile);
        _self._lines.push(Zeile);

    }

    Funktion zeichnePfeil(Punkt1, Punkt2) {
        let arrowLine = _self.createArrowLine(punkt1, punkt2);
        var meshLine = Pfeillinie.meshLine;

        let canvasTexture = _canvasDraw.drawArrow(DREI, Renderer, 300, 100); //Pfeil var Material = neues MeshLineMaterial({
            useMap: wahr,
            Karte: CanvasTexture,
            Farbe: neue THREE.Color(0x00f300),
            Deckkraft: 1,
            Auflösung: neuer THREE.Vector2($(viewerContainerId).width(), $(viewerContainerId).height()),
            Linienbreite: Pfeillinie.Linienbreite,
            Tiefentest: _Tiefentest,
            Seite: _Seite,
            Wiederholung: new THREE.Vector2(1, 1),
            transparent: wahr,
            GrößeDämpfung: 1
        });

        var mesh = neues THREE.Mesh(meshLine.geometry, material);
        mesh.scale.set(50, 50, 50);
        Szene.Hinzufügen(Netz);
        _self._arrows.push(Netz);

    }

    Funktion RefreshArrow(Punkt1, Punkt2, Pfeil) {
        let arrowLine = _self.createArrowLine(punkt1, punkt2);
        var meshLine = Pfeillinie.meshLine;

        let canvasTexture = _canvasDraw.drawArrow(DREI, Renderer, 300, 100); //Pfeil var Material = neues MeshLineMaterial({
            useMap: wahr,
            Karte: CanvasTexture,
            Farbe: neue THREE.Color(0x00f300),
            Deckkraft: 1,
            Auflösung: neuer THREE.Vector2($(viewerContainerId).width(), $(viewerContainerId).height()),
            Linienbreite: Pfeillinie.Linienbreite,
            Tiefentest: _Tiefentest,
            Seite: _Seite,
            Wiederholung: new THREE.Vector2(1, 1),
            transparent: wahr,
            GrößeDämpfung: 1
        });

        Pfeil.Geometrie = MeshLine.Geometrie;
        Pfeil.Material = Material;

    }

    this.createArrowLine = Funktion (Punkt1, Punkt2) {
        lass centerPoint = { x: (punkt1.x + punkt2.x) / 2, y: (punkt1.y + punkt2.y) / 2, z: (punkt1.z + punkt2.z) / 2 };
        let Abstand = utils.Abstand(Punkt1.x, Punkt1.y, Punkt1.z, Punkt2.x, Punkt2.y, Punkt2.z);

        var startPos = { x: (Punkt1.x + Punkt2.x) / 2 / 50, y: (Punkt1.y + Punkt2.y) / 2 / 50, z: (Punkt1.z + Punkt2.z) / 2 / 50 }

        sei d = utils.distance(centerPoint.x, centerPoint.y, centerPoint.z, Kameraposition.x, Kameraposition.y, Kameraposition.z);
        wenn (d < 2000) d = 2000;
        wenn (d > 10000) d = 10000;
        sei Zeilenbreite = 100 * d / 4000;
        //Konsole.log("d=", d);

        sei sc = 0,035;
        var endPos = { x: startPos.x + (punkt2.x - punkt1.x) * sc * d / Abstand / 50, y: startPos.y + (punkt2.y - punkt1.y) * sc * d / Abstand / 50, z: startPos.z + (punkt2.z - punkt1.z) * sc * d / Abstand / 50 }

        var Pfeillinienpunkte = [];
        : arrowLinePoints.push(startPos.x, startPos.y, startPos.z);
        : arrowLinePoints.push(endPos.x, endPos.y, endPos.z);

        var meshLine = neue MeshLine();
        meshLine.setGeometry(arrowLinePoints);

        return { meshLine: meshLine, Linienbreite: Linienbreite };
    }

    this.setDepthTest = Funktion (bl) {
        wenn (bl) {
            _depthTest = wahr;
            this._lines.map(Zeile => {
                Linie.Material.TiefenTest = true;
                Linie.Material.Seite = 0;
            });
            diese._arrows.map(arrow => {
                Pfeil.Material.TiefenTest = true;
                Pfeil.Material.Seite = 0;
            });
        } anders {
            _depthTest = falsch;
            this._lines.map(Zeile => {
                Linie.Material.TiefenTest = falsch;
                Linie.Material.Seite = DREI.Doppelseite;
            });
            diese._arrows.map(arrow => {
                Pfeil.Material.TiefenTest = falsch;
                Pfeil.Material.Seite = DREI.Doppelseite;
            });
        }
    }

    /**
     * Stornieren */
    dies.undo = Funktion () {
        Szene.entfernen(this._lines[this._lines.length - 1]);
        Szene.entfernen(this._arrows[this._arrows.length - 1]);
        _self._path.splice(this._path.length - 1, 1);
        _self._lines.splice(this._lines.length - 1, 1);
        _self._arrows.splice(this._arrows.length - 1, 1);
    }

}

DrawPath.prototype.constructor = Zeichenpfad;

exportiere { DrawPath }

Teil des Codes in show.js:

lass drawPath;

    //Zeichnen Sie die Linie drawPath = new DrawPath();
    drawPath.config(
        Objekte,
        Kamera,
        Szene,
        drehen
    );

    $("#rightContainer").anzeigen();
    $("#line-start").on("click", Funktion (Ereignis) {
        zeichnePath.start();
    });
    $("#line-stop").on("click", Funktion (Ereignis) {
        zeichnePath.stop();
    });
    $("#line-undo").on("click", Funktion (Ereignis) {
        drawPath.undo();
    });
    $("#line-show").on("click", Funktion (Ereignis) {
        zeichnePath.refresh();
    });
    lassen Sie Tiefentest = true;
    $("#line-depthTest").on("click", Funktion (Ereignis) {
        if (Tiefentest) {
            drawPath.setDepthTest(false);
            Tiefentest = falsch;
        } anders {
            drawPath.setDepthTest(true);
            Tiefentest = wahr;
        }
    });

setzeIntervall(() => {
    Zeichenpfad und Zeichenpfad.refresh();
}, 100);

Effektbild:

Es gibt noch einige Probleme:

Obwohl die Szene vergrößert ist und der Pfeil in dieser Darstellung etwas groß ist, wird die maximale Größe immer noch kontrolliert. Es gibt nur ein Problem mit der Form, das möglicherweise ein Perspektivproblem ist.

Der von mir erwartete Effekt sollte etwa dieser sein, d. h., egal aus welchem ​​Blickwinkel man ihn betrachtet, der Pfeil sollte nicht verformt sein:

Dies ist das Ende dieses Artikels über die Verwendung von three.js zum Zeichnen dreidimensionaler Pfeillinien, der mein halbes Leben in Anspruch genommen hat. Weitere verwandte Inhalte zu dreidimensionalen Pfeillinien mit three.js finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Three.js realisiert den dynamischen 3D-Logoeffekt von Facebook Metaverse
  • Verwenden Sie three.js, um coole 3D-Seiteneffekte im Acid-Stil zu erzielen
  • So erzielen Sie mit three.js einen dynamischen 3D-Texteffekt
  • Three.js-Beispielcode zur Implementierung des Tautropfen-Animationseffekts
  • Detaillierte Erläuterung der Verwendung und Leistungstests von Multithreading in three.js
  • Erste Erfahrungen mit der Texterstellung mit Javascript Three.js

<<:  Erfahren Sie, wie Sie saubere und standardmäßige HTML-Tags schreiben

>>:  Eine kurze Diskussion des interessanten Boxmodells der CSS3-Boxgrößeneigenschaft

Artikel empfehlen

js, um den Popup-Effekt zu erzielen

In diesem Artikelbeispiel wird der spezifische Co...

Detaillierte Erläuterung der Verwendung des gcc-Befehls unter Linux

Inhaltsverzeichnis 1. Vorverarbeitung 2. Zusammen...

Vue verwendet Echart, um Beschriftungen und Farben anzupassen

In diesem Artikelbeispiel wird der spezifische Co...

Verwenden von Apache ab zum Durchführen von HTTP-Leistungstests

Mac wird mit Apache-Umgebung geliefert Öffnen Sie...

So weisen Sie Feldern bei der MySQL-Abfrage Standardwerte zu

brauchen Wenn Sie ein Feld abfragen, müssen Sie e...

Lösung für die Inkonsistenz zwischen Crontab-Ausführungszeit und Systemzeit

Vorwort Unter LINUX werden periodische Aufgaben n...

Detaillierte Erklärung des Sticky Position-Attributs in CSS

Beim Entwickeln mobiler Apps stoßen Sie häufig au...

Detaillierte Erläuterung der gespeicherten Prozeduren und Funktionen von MySQL

1 Gespeicherte Prozedur 1.1 Was ist eine gespeich...

MySql 5.7.20 Installation und Konfiguration von Daten- und my.ini-Dateien

1. Erster Download von der offiziellen Website vo...

Eine Lösung für einen Fehler in IE6 mit jquery-multiselect

Bei der Verwendung von jquery-multiselect (einem ...