如何绘制 3D 球体?

Posted

技术标签:

【中文标题】如何绘制 3D 球体?【英文标题】:How to draw a 3D sphere? 【发布时间】:2010-12-07 18:39:23 【问题描述】:

我想在 html 5.0 画布中绘制一个 3D 球或球体。我想了解有关如何绘制 3D 球体的算法。谁能和我分享一下?

【问题讨论】:

“3d 球体”是什么意思?你的意思是阴影?线框? 除了 3d 球体之外,还有其他类型的球体吗? Idigas:显然存在 4D 的,但是它的可见投影基本上等于 3D 的,但它的大小一直在变化。 你问的很可能是这样的:blog.andreaskahler.com/2009/06/… 【参考方案1】:

您将需要对一个球体进行建模,并使其具有不同的颜色,以便在它旋转时您可以看到它不仅是一个球体,而且还在被渲染。

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

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

一旦您了解如何做到这一点,或者使用 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++;
     
   
 

【讨论】:

这些例子太棒了。虽然他们建议在 Chrome 中查看它们,但挥舞旗帜图片和 iPhone(默认渲染器)在 Safari 中运行良好。 我认为 Chrome 只是因为它可能更快,但现在 Safari 4、Firefox 3.5、Chrome 和 Opera 10 应该都能很好地展示这些。 死链接(整个域)。 @brichins - 谢谢。我更改了网址并输入了一些代码来提供帮助。【参考方案2】:

你可以尝试使用three.js 库,它从核心webgl 编程中提取了大量代码。在您的 html 中包含来自 three.js lib 的 three.js 库。

你可以在 safari 浏览器上使用画布渲染器,webgl 可以在 chrome 上使用

请找到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();

【讨论】:

最后一个 JSFIDDLE 演示。 :-) 谢谢!【参考方案3】:

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


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

我已经用 javascript 为 canvas 重写了它,我有一个 demo rendering the earth as a sphere

(来源:haslers.info)

我的机器上大约 22 fps。这与它基于渲染的 Java 版本差不多,如果不是快一点的话!

现在我已经很久没有写 Java 代码了——而且它很迟钝——所以我真的不记得它是如何工作的,我只是将它移植到 JavaScript。然而,这是来自代码的慢版本,我不确定更快的版本是由于我用来操作像素的 Java 方法中的优化,还是由于它计算出从哪个像素渲染的数学加速质地。当时我也与一个拥有类似小程序的人通信,该小程序比我的要快得多,但我不知道他们在 JavaScript 中是否可以实现任何速度改进,因为它可能依赖于 Java 库。 (我从未见过他们的代码,所以我不知道他们是如何做到的。)

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

一段时间后,我会尝试转换我的更快版本,看看能否在 JavaScript 版本中获得任何速度改进。

【讨论】:

JavaScript+Canvas 演示仅适用于 Firefox。 Chrome 给了我与这个问题相同的错误:***.com/questions/982000/… 还没来得及看快速版本,但是有一些简单的改进可以让它达到 40fps。 我知道链接坏了。我已经为我的域切换了 dns 主机,需要设置 dns 记录...有时间我会更新它们。【参考方案4】:

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

至于算法,ray tracing 是最简单的,但也是迄今为止最慢的——所以你可能不想在&lt;CANVAS&gt; 中使用它来做任何非常复杂的事情(特别是考虑到缺乏可用的图形加速在那种环境中),但如果你只想做一个球体,它可能已经足够快了。

【讨论】:

鉴于光源没有改变,他也可以预渲染它并只blit一个位图;^)

以上是关于如何绘制 3D 球体?的主要内容,如果未能解决你的问题,请参考以下文章

在 Matplotlib 中绘制一个 3d 立方体、一个球体和一个向量

如何在使用QuTiP绘制Bloch球体时给出aplot标题

用python绘制3d球体的最简单方法?

批处理文件(bat)装逼 之全彩滚动我爱你 绘制五彩爱心 绘制3D球体

用Unity3D制作一个球体的场景如何做

100个 Unity踩坑小知识点| 在编辑器中绘制正方体虚线球体虚线(Gizmos 辅助线框)