Füllen three.js die Szene mit dem Gitter
, Was ich bin auf der Suche nach
Anzeigen eines Rasters innerhalb eines three.js Szene, füllt die ganze Szene. In diesem Fall, die Szene ist das ganze Fenster.
Dieser raster stellt eine Oberfläche in 3D und kann verschoben werden, um mit der Maus mit THREE.TrackballControls
Dieses Gitter ist direkt in die Kamera also zunächst sieht es aus wie eine Ebene (2D) Fläche, bis auf den trackball gezogen wird, um mit der Maus.
Die Breite der Rasterlinien sollte gleich der Breite des Renderers.
, Was ich Tat
Ich habe setup eine funktionierende jsFiddle für das, was ich bisher getan habe.
Ersten finde ich die Grenzen der Szene (dies alles ist in der jsFiddle),
App = function(sceneContainerName) {
this.sceneContainerName = sceneContainerName;
this.SCREEN_WIDTH = window.innerWidth;
this.SCREEN_HEIGHT = window.innerHeight;
this.MAX_X = this.SCREEN_WIDTH / 2;
this.MIN_X = 0 - (this.SCREEN_WIDTH / 2);
this.MAX_Y = this.SCREEN_HEIGHT / 2;
this.MIN_Y = 0 - (this.SCREEN_HEIGHT / 2);
this.NUM_HORIZONTAL_LINES = 50;
this.init();
};
Setup three.js
init: function() {
//init scene
this.scene = new THREE.Scene();
//init camera
//View Angle, Aspect, Near, Far
this.camera = new THREE.PerspectiveCamera(45, this.SCREEN_WIDTH / this.SCREEN_HEIGHT, 1, 10000);
//set camera position
this.camera.position.z = 1000;
this.camera.position.y = 0;
//add the camera to the scene
this.scene.add(this.camera);
this.projector = new THREE.Projector();
//init renderer
this.renderer = new THREE.CanvasRenderer();
//start the renderer
this.renderer.setSize(this.SCREEN_WIDTH, this.SCREEN_HEIGHT);
this.drawGrid(this.NUM_HORIZONTAL_LINES);
this.trackball = new THREE.TrackballControls(this.camera, this.renderer.domElement);
this.trackball.staticMoving = true;
var me = this;
this.trackball.addEventListener('change', function() {
me.render();
});
//attach the render-supplied DOM element
var container = document.getElementById(this.sceneContainerName);
container.appendChild(this.renderer.domElement);
this.animate();
},
Diese Funktionen stellen einen Vektor für jedes Bildschirm-Ecke,
getNWScreenVector: function() {
return new THREE.Vector3(this.MIN_X, this.MAX_Y, 0);
},
getNEScreenVector: function() {
return new THREE.Vector3(this.MAX_X, this.MAX_Y, 0);
},
getSWScreenVector: function() {
return new THREE.Vector3(this.MIN_X, this.MIN_Y, 0);
},
getSEScreenVector: function() {
return new THREE.Vector3(this.MAX_X, this.MIN_Y, 0);
},
Ich einige geometrie, wird eine Linie an der Spitze des Bildschirms, und versuchen, Linien zu zeichnen, von oben beginnend und hinunter an den unteren Rand des Bildschirms.
//drawGrid will determine blocksize based on the
//amount of horizontal gridlines to draw
drawGrid: function(numHorizontalGridLines) {
//Determine the size of a grid block (square)
this.gridBlockSize = this.SCREEN_HEIGHT / numHorizontalGridLines;
var geometry = new THREE.Geometry();
geometry.vertices.push(this.getNWScreenVector());
geometry.vertices.push(this.getNEScreenVector());
var material = new THREE.LineBasicMaterial({
color: 0x000000,
opacity: 0.2
});
for (var c = 0; c <= numHorizontalGridLines; c++) {
var line = new THREE.Line(geometry, material);
line.position.y = this.MAX_Y - (c * this.gridBlockSize);
this.scene.add(line);
}
}
Das problem
Diese Methode nicht funktioniert, in der jsFiddle die erste Zeile startet den Bildschirm und die Breite der Linien nicht füllen den Bildschirm-Breite.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Also es gibt zwei Fehler in deinem code.
Ersten, Sie beginnen mit der Zeile an
MAX_Y
und dann jede Zeile einen festen Abstand unter der letzten. Der relativ geringe Fehler ist, dass ingetNWScreenVector
undgetNEScreenVector
Sie setzen die Linie der Eckpunkte in einer Höhe vonMAX_Y
, dann indu bist das hinzufügen einer übersetzung, um die Linie der
MAX_Y - (c * this.gridBlockSize)
gibt, die eine Letzte y-position derMAX_Y + MAX_Y - (c * this.gridBlockSize)
, die eineMAX_Y
zu viele. Wenn es Sinn macht, um Ihr Programm zu starten, mit Linien absteigend vongetNWScreenVector
undgetNEScreenVector
, dann sollten Sie dieline.position.y
Linie nurKönnen Sie sehen, dass die Zeilen zentriert auf jsFiddle, aber Sie sind immer noch die Größe falsch. Dies ist, weil Sie nicht Buchhaltung für die Tatsache, dass Ihre Szene ist in Sicht. Ihre Zeilen haben alle Ihre z-Koordinaten auf 0 gesetzt, so dass, wenn Sie setzen
this.camera.position.z = 1000
Sie sind 1000 Einheiten von der Kamera Weg. Es gibt keinen Grund zu vermuten, dass etwas mit der gleichen Breite wie die Breite der pixel des canvas-Bereichs wird die gleiche Breite, wenn Sie in Perspektive gezeichnet von 1000 Einheiten entfernt.Stattdessen können wir berechnen wie groß Sie sein müssen. Ich will nicht, um eine vollständige Erklärung der Perspektive hier, aber wir können herausfinden, wie groß ein Bereich, den die Linien decken müssen um den Bildschirm zu verdecken. Sie haben angegeben ein vertikales FOV von 45 Grad in deiner Konstruktor Kamera und einem Abstand von 1000 zwischen der Kamera und Ihre Zeilen. Three.js im Grunde zeigt die Lösung, wenn Sie eine Spitze, wie schafft es die Perspektive matrix: makePerspective
Zuerst benötigen wir den vertikalen Abstand von der oberen Hälfte des Bildschirms, da 0 ist in der Mitte des Bildschirms.
Math.tan(45 /2 * (Math.PI /180))
(Tangens des halben Winkels, Umgerechnet in Bogenmaß) gibt den vertikalen Abstand geteilt durch den Abstand von der Kamera Weg, so können Sie berechnen die Höhe mitoder doppelklicken Sie auf
Die horizontale FOV ist nicht das gleiche, es sei denn, die Leinwand ist quadratisch, aber die Breite und Höhe-Verhältnis des line-Bereich wird proportional zur Breite und Höhe-Verhältnis von dem Bildschirm. Wie three.js tut, kann man nur multiplizieren, indem Sie das Seitenverhältnis auch die Kamera-Konstruktor, um herauszufinden, die Breite:
Diese sind die Werte, die Sie verwenden sollten für die Platzierung Ihrer Linien. Alle zusammen:
Schließlich, Sie werden wollen, verbreiten Sie die Linien über die gesamte Fläche, so sollte man
Können Sie sehen, dass die Arbeit hier: http://jsfiddle.net/SeNDk/55/
Es ist ein weiterer Weg, dies zu tun, obwohl, was ist zu halten die Linien der gleiche, aber bewegen Sie die Kamera näher an Ihre Linien, so dass die Breite der Linien nur zufällig gleich die pixel-Breite der Leinwand bei dieser Distanz. Die Formel ist nur eine Umarbeitung der obigen für
DISPLAY_HEIGHT
, aber statt der Lösung des für die Höhe, die wir lösen für eine Entfernung, wenn die Höhe gleich der screen-Höhe:Können Sie sehen, dass hier: http://jsfiddle.net/SeNDk/53/
Es ist eine viel kleinere änderung an Ihrem code, aber es bedeutet, dass die Kamera position ändert sich je nachdem, wie groß die Leinwand ist, kann das Auswirkungen auf andere Inhalte, die Sie benötigen, um präzise, so dass die Wahl liegt bei Ihnen.
projector.unprojectVector
um die Ecken des Bildschirms. Hier ist die jsFiddle für, die. Das Gitter passt perfekt, aber alles, was ich zeichne, auf die Szene relativ zu diesem Gitter zu sein scheint, stecken auf der äußeren Kante der trackball Szene, die navigation nicht so intuitiv. Ihre Lösungen helfen.Seit ThreeJS r57 ab, es ist ein Helfer namens GridHelper verwenden, die Sie leicht zu ziehen, ein schönes Gitter, genau wie jedes andere geometrische Objekt.
GridHelper nimmt 2 Parameter. Erste ist die Größe des Rasters und die 2. ist die Größe der Schritt zwischen 2 Linien
Unten ist der code zum zeichnen des Rasters auf die Szene, mit der Größe = 100 und step = 10
In Ihrem Fall, können Sie vermeiden, dass die Methode drawGrid und ersetzen Sie direkt, dass mit den oben genannten zwei Zeilen code, oder Sie können diese über zwei Zeilen code mit in der drawgrid-Methode.
Einem live-Beispiel ist hier im folgenden link
Grid-Helper Beispiel
Können Sie zeichnen ein raster wie dieses.
Dieser thread geholfen, mit einer variation der Technik, die angewendet auf A-Rahmen und mit einem leichten twist; dynamisch erstellen und der Größe des Gitters als Funktion der bounding-box der Szene-Kinder.
Hinweis: Die folgende Methode aufgerufen werden muss, um den die bounding-box-Koordinaten, die zunächst null, im Gegensatz zu den umgebenden Bereich, der pre-berechnet für Sie:
'boundingBox.geometrie.computeBoundingBox();'
Codepen für diese 'Szene-ario' (Wortspiel beabsichtigt) kann hier gefunden werden: https://codepen.io/ubermario/pen/JvZMPg