11

私が探しているもの

シーン全体を満たす three.js シーン内のグリッドを表示します。この場合、シーンはウィンドウ全体です。

このグリッドは 3D のサーフェスを表し、マウスを使用して移動できます。THREE.TrackballControlsこのグリッドはカメラの方を向いているため、マウスでトラックボールを引っ張るまでは、最初は平らな (2D) サーフェスのように見えます。

グリッド ラインの幅は、レンダラーの幅と同じにする必要があります。

私がしたこと

これまでに行ったことに対して、動作するjsFiddleをセットアップしました。

まず、シーンの境界を見つけます (これはすべて 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();

};

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

これらの関数は、各画面コーナーのベクトルを提供します。

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);
},

画面の一番上に線を表すジオメトリを作成し、画面の上から下に向かって線を描画してみます。

// 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);
    }
}

問題

このメソッドは機能しません。jsFiddle では、最初の行が画面から始まり、行の幅が画面の幅を埋めません。

4

4 に答える 4

29

ThreeJS r57 以降、GridHelper と呼ばれるヘルパーがあり、これを使用すると、他の幾何学的オブジェクトと同様に、簡単にグリッドを描画できます。

GridHelper は 2 つのパラメーターを取ります。1 つ目はグリッドのサイズで、2 つ目は 2 つの線の間のステップのサイズです

以下は、サイズ = 100、ステップ = 10 で、シーンにグリッドを描画するコードです。

var grid = new THREE.GridHelper(100, 10);
scene.add(grid);

あなたの場合、drawGrid というメソッドを使用することを避け、それを上記の 2 行のコードに直接置き換えるか、上記の 2 行のコードを drawgrid メソッドに追加することができます。

実際の例は、次のリンクから入手できます

グリッド ヘルパーの例

于 2014-11-28T12:58:23.373 に答える
12

このようにグリッドを描くことができます。

// each square
var planeW = 50; // pixels
var planeH = 50; // pixels 
var numW = 50; // how many wide (50*50 = 2500 pixels wide)
var numH = 50; // how many tall (50*50 = 2500 pixels tall)
var plane = new THREE.Mesh(
    new THREE.PlaneGeometry( planeW*numW, planeH*numH, planeW, planeH ),
    new THREE.MeshBasicMaterial( {
        color: 0x000000,
        wireframe: true
    } )
);

scene.add(plane);
于 2012-11-23T06:14:19.147 に答える
11

したがって、コードには 2 つのバグがあります。

まず、 の行から始めて、各行をMAX_Y最後の行から一定の距離だけ下に置きます。比較的マイナーなバグはgetNWScreenVectorgetNEScreenVectorラインの頂点を の高さに配置しMAX_Y、次に

line.position.y = this.MAX_Y - (c * this.gridBlockSize);

の行に平行移動を追加するとMAX_Y - (c * this.gridBlockSize)、最終的な y 位置がになりますがMAX_Y + MAX_Y - (c * this.gridBlockSize)、これはMAX_Y多すぎます。getNWScreenVectorあなたのプログラムにとってとから派生する行で始めることが理にかなっている場合は、行を次のようにgetNEScreenVector変更する必要があります。line.position.y

line.position.y = -c * this.gridBlockSize;

線がjsFiddleの中央に配置されていることがわかりますが、まだサイズが正しくありません。これは、シーンが遠近法であるという事実を考慮していないためです。すべての線の z 座標が 0 に設定されているため、 を設定するthis.camera.position.z = 1000と、カメラから 1000 単位離れます。キャンバスのピクセル幅と同じ幅のものが、1000 単位離れた遠近法で描画されたときに同じ幅になると想定する理由はありません。

代わりに、必要な大きさを計算できます。ここでは遠近法の完全な説明には立ち入りませんが、画面を覆うために線がカバーする必要がある領域の広さを理解することができます。カメラ コンストラクターで 45 度の垂直 FOV を指定し、カメラとラインの間の距離を 1000 に指定しました。Three.jsは基本的に、パースペクティブ マトリックスを作成する方法をピークにすると、ソリューションを示します。

まず、0 が画面の中心にあるため、画面の上半分の垂直距離が必要です。Math.tan(45 / 2 * (Math.PI / 180))(ラジアンに変換された角度の半分のタンジェント) は、垂直距離をカメラからの距離で割った値を与えるため、高さを次のように計算できます。

halfDisplayHeight = 1000 * Math.tan(45 / 2 * (Math.PI / 180));

またはそれを2倍にします

this.DISPLAY_HEIGHT = 2 * 1000 * Math.tan(45 / 2 * (Math.PI / 180));

キャンバスが正方形でない限り、水平視野は同じではありませんが、ライン領域の幅と高さの比率は画面の幅と高さの比率に比例します。three.js と同様に、カメラ コンストラクターに提供した縦横比を掛けるだけで、幅を計算できます。

this.DISPLAY_WIDTH = this.DISPLAY_HEIGHT * (this.SCREEN_WIDTH / this.SCREEN_HEIGHT);

これらは、線を配置するために使用する値です。すべて一緒に:

this.DISPLAY_HEIGHT = 2 * 1000 * Math.tan(45 / 2 * (Math.PI / 180));
this.DISPLAY_WIDTH = this.DISPLAY_HEIGHT * (this.SCREEN_WIDTH / this.SCREEN_HEIGHT);
this.MAX_X = this.DISPLAY_WIDTH / 2;
this.MIN_X = 0 - (this.DISPLAY_WIDTH / 2);
this.MAX_Y = this.DISPLAY_HEIGHT / 2;
this.MIN_Y = 0 - (this.DISPLAY_HEIGHT / 2);

最後に、線を領域全体に広げたいので、設定する必要があります

this.gridBlockSize = this.DISPLAY_HEIGHT / numHorizontalGridLines;

ここで動作していることがわかります: http://jsfiddle.net/pa46hxwo/

ただし、これを行う別の方法があります。これは、線を同じに保ちながら、カメラを線に近づけて、線の幅がその距離でのキャンバスのピクセル幅とちょうど等しくなるようにすることです。この式は について上記を作り直したものですが、DISPLAY_HEIGHT高さを解く代わりに、高さが画面の高さと等しいときの距離を解きます。

this.camera.position.z = this.SCREEN_HEIGHT / (2 * Math.tan(45 / 2 * (Math.PI / 180)));

ここで確認できます:http://jsfiddle.net/0jtykgrL/

これはコードの小さな変更ですが、キャンバスの大きさに応じてカメラの位置が変わることを意味し、正確に配置する必要がある他のコンテンツに影響を与える可能性があるため、選択はあなた次第です。

于 2012-06-21T00:13:30.890 に答える