如何绘制3D球体?

时间:2009-10-18 13:09:16

标签: html5 html5-canvas

我想在HTML 5.0画布中绘制3D球或球体。我想了解关于如何绘制3D球体的算法。谁能与我分享?

4 个答案:

答案 0 :(得分:9)

你需要为一个球体建模,并让它变成不同的颜色,这样当它旋转时你可以看到它不仅是一个球体,而是被渲染。

否则,空间中的球体,如果它只是一个纯色,那么它周围没有参考点就像一个圆圈。

首先,您将尝试绘制一个带有矩形的圆,因为这是您拥有的主要原语。

一旦你理解了如何做到这一点,或者使用Path方法创建一个新的图元,例如三角形,并创建一个圆,那么你就可以将它移动到3D了。

3D只是一个技巧,因为您将获取您的模型,可能是由等式生成的,然后展平它,当您确定将看到哪些部分,然后显示它。

但是,您需要根据它们与光源的距离以及基于该部分与光源的角度来更改三角形的颜色。

这是您可以开始进行优化的地方,因为如果您逐个像素地执行此操作,那么您就是光线追踪。如果您有较大的块和点光源,并且对象在旋转但没有移动,那么您可以重新计算每个三角形的颜色变化,然后只需更改颜色来模拟旋转。

算法将取决于您想要进行的简化,以便在您获得经验时回过头来询问,展示您到目前为止所做的工作。

以下是这样做的示例,下面我复制了3D球体部分,但请查看整个article

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++;
     }
   }
 }
}

答案 1 :(得分:6)

更新:此代码非常陈旧且有限。现在有用于3D球体的库:http://techslides.com/d3-globe-with-canvas-webgl-and-three-js/


十多年前,我编写了一个Java小程序来渲染纹理球体,通过实际数学来计算球体表面在场景中的位置(不使用三角形)。

我在JavaScript for canvas中重写了它,我有一个 demo rendering the earth as a sphere

alt text
(来源:haslers.info

我的机器上大约有22 fps。这与基于呈现的Java版本一样快,如果不是更快一点!

现在已经很长时间了,因为我编写了Java代码 - 而且它非常迟钝 - 所以我真的不记得它是如何工作的,我只是将它移植到了JavaScript中。然而,这是来自代码的慢速版本,我不确定更快的版本是否是由于我用来操纵像素的Java方法的优化,或者是数学中的加速,它确定了从哪个像素渲染质地。我当时也和那些拥有类似applet的人相对应,这个applet比我的快得多,但我不知道他们在JavaScript中是否有任何速度提升是可能的,因为它可能依赖于Java库。 (我从未见过他们的代码所以我不知道他们是怎么做到的。)

因此可能可以提高速度。但这很适合作为概念证明。

如果您对比较速度感兴趣,那么Java版本就在这里:

这些都是死链接,直到我下次更新我的网站

<击>

<击>

<击>

我会花一些时间来转换我的速度更快的版本,看看我是否可以在JavaScript版本中获得任何速度提升。

答案 2 :(得分:4)

你可以尝试使用three.js库,它从核心webgl编程中抽象出大量代码。在three.js lib的html中加入three.js库。

你可以在safari浏览器中使用canvas渲染器,webgl可以用于chrome

请找到JS FIDDLE FOR SPHERE

var camera,scene,material,mesh,geometry,renderer

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

答案 3 :(得分:0)

嗯,球体的图像在屏幕上总是呈圆形,因此唯一重要的是阴影。这取决于放置光源的位置。

至于算法,ray tracing是最简单的,但也是迄今为止最慢的 - 所以你可能不想用它在<CANVAS>中做任何非常复杂的事情(特别是考虑到缺乏在该环境中可用的图形加速度),但如果您只想做一个球体,它可能足够快。