web-dev-qa-db-ja.com

3D球を描く方法は?

HTML5.0キャンバスで3Dボールまたは球を描画したい。 3D球の描き方についてアルゴリズムを理解したい。誰がこれを私と共有できますか?

19
user165273

球をモデル化し、回転するときに球であるだけでなくレンダリングされていることがわかるように、さまざまな色にする必要があります。

それ以外の場合、すべてが1つの単色である場合、周囲に参照点がない空間内の球は円のように見えます。

まず、長方形で円を描いてみてください。これがメインのプリミティブです。

その方法を理解するか、Pathメソッドを使用して三角形などの新しいプリミティブを作成し、円を作成したら、それを3Dに移動する準備が整います。

3Dは単なるトリックです。おそらく方程式によって生成されたモデルを取得し、それを平坦化して、表示されるパーツを決定し、それを表示します。

ただし、三角形の色は、光源からの距離と、光源に対するその部分の角度に基づいて変更する必要があります。

これは、最適化を開始できる場所です。たとえば、このピクセルごとに実行すると、レイトレーシングが実行されます。より大きなブロックと点光源があり、オブジェクトが回転しているが動き回っていない場合は、三角形ごとに色がどのように変化するかを再計算できます。回転をシミュレートするには、色を変更するだけです。

アルゴリズムは、どのような単純化を行いたいかによって異なります。経験を積むと、戻ってきて質問し、これまでに何をしたかを示します。

これはその例です。以下では3D球体パーツをコピーしましたが、全体を見てください 記事

function Sphere3D(radius) {
 this.point = new Array();
 this.color = "rgb(100,0,255)"
 this.radius = (typeof(radius) == "undefined") ? 20.0 : radius;
 this.radius = (typeof(radius) != "number") ? 20.0 : radius;
 this.numberOfVertexes = 0;

 // Loop from 0 to 360 degrees with a pitch of 10 degrees ... 
  for(alpha = 0; alpha <= 6.28; alpha += 0.17) {
   p = this.point[this.numberOfVertexes] = new Point3D();

   p.x = Math.cos(alpha) * this.radius;
   p.y = 0;
   p.z = Math.sin(alpha) * this.radius;

   this.numberOfVertexes++;
 }

 // Loop from 0 to 90 degrees with a pitch of 10 degrees ... 
 // (direction = 1)

 // Loop from 0 to 90 degrees with a pitch of 10 degrees ...
 // (direction = -1)

 for(var direction = 1; direction >= -1; direction -= 2) {
   for(var beta = 0.17; beta < 1.445; beta += 0.17) {

     var radius = Math.cos(beta) * this.radius;
     var fixedY = Math.sin(beta) * this.radius * direction;

     for(var alpha = 0; alpha < 6.28; alpha += 0.17) {
       p = this.point[this.numberOfVertexes] = new Point3D();

       p.x = Math.cos(alpha) * radius;
       p.y = fixedY;
       p.z = Math.sin(alpha) * radius;

       this.numberOfVertexes++;
     }
   }
 }
}
9
James Black

更新:このコードはかなり古く、制限されています。現在、3D球を実行するためのライブラリがあります: http://techslides.com/d3-globe-with-canvas-webgl-and-three-js/


10年以上前、私はJavaアプレットを作成して、球の表面がシーンのどこにあるかを計算することによって、テクスチャ球をレンダリングしました(三角形を使用していません)。

キャンバス用のJavaScriptで書き直し、地球を球としてレンダリングするデモ

alt text
(出典: haslers.info

マシンで約22fpsを取得します。これは、レンダリングに基づいたJavaバージョンとほぼ同じくらい高速ですが、少し速くはありません!

Javaコードを書いたのは久しぶりです-そしてそれはかなり鈍感でした-それでそれがどのように機能するかを正確に覚えていません、私はそれをJavaScriptに移植しました。しかしこれは遅いバージョンのコードから、そして速いバージョンがピクセルを操作するために使用したJavaメソッドの最適化によるものなのか、それとも計算のスピードアップによるものなのかはわかりません。テクスチャからどのピクセルをレンダリングするか。当時、私よりもはるかに高速な同様のアップルトを持っている人と連絡を取り合っていましたが、JavaScriptで速度の向上が可能かどうかはわかりません。 Javaライブラリに依存している可能性があります(私は彼らのコードを見たことがないので、彼らがどのようにそれをしたのかわかりません。)

したがって、速度を改善できる可能性があります。しかし、これは概念実証としてうまく機能します。

しばらくして、より高速なバージョンをJavaScriptバージョンに変換して、速度を改善できるかどうかを確認します。

6
Sam Hasler

uは、コアwebglプログラミングから多くのコードを抽象化するthree.jsライブラリを試すことができます。 three.js lib からhtmlにthree.jsライブラリを含めます。

uはサファリブラウザにキャンバスレンダラーを使用できます、webglはクロムで動作します

JS FIDDLE FOR SPHERE を見つけてください

varカメラ、シーン、マテリアル、メッシュ、ジオメトリ、レンダラー

function drawSphere() {
    init();
    animate();

}

function init() {
    // camera 

    scene = new THREE.Scene()
    camera = new THREE.PerspectiveCamera(50, window.innerWidth / innerHeight, 1, 1000);
    camera.position.z = 300;
    scene.add(camera);

    // sphere object
    var radius = 50,
        segments = 10,
        rings = 10;
    geometry = new THREE.SphereGeometry(radius, segments, rings);
    material = new THREE.MeshNormalMaterial({
        color: 0x002288
    });
    mesh = new THREE.Mesh(geometry, material);

    //scene 
    ;
    scene.add(mesh);


    // renderer
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

}


function animate() {
    requestAnimationFrame(animate);
    render();

}

function render() {

    mesh.rotation.x += .01;
    mesh.rotation.y += .02;
    renderer.render(scene, camera);


}

// fn callin
drawSphere();
4
Bhupendra

さて、球の画像は画面上で常に円形になるので、重要なのは陰影だけです。これは、光源を配置する場所によって決まります。

アルゴリズムに関しては、 レイトレーシング が最も単純ですが、はるかに遅いので、<CANVAS>で非常に複雑なことを行うためにそれを使用したくないでしょう(特にその環境で利用できるグラフィックアクセラレーションの欠如)が、単一の球を実行したいだけの場合は十分に高速である可能性があります。

0
David