Math 如何光栅化球体

Math 如何光栅化球体,math,Math,所以,我试图创建一个球体,它的外部有“块”,有点像内置的地雷船。(我不知道圆圈外侧的术语是什么)。问题是,我不知道如何得到一个像中点圆算法这样的方程来计算球体。最好是lua或java,这样我就能更容易地阅读任何答案。我不想知道如何用trig计算球体上的点,我已经知道了怎么做。这是用我自己的MiniBasic版本编写的 10 REM Shaded textured sphere 20 INPUT width 30 INPUT height 40 INPUT bwidth 50 INPUT

所以,我试图创建一个球体,它的外部有“块”,有点像内置的地雷船。(我不知道圆圈外侧的术语是什么)。问题是,我不知道如何得到一个像中点圆算法这样的方程来计算球体。最好是lua或java,这样我就能更容易地阅读任何答案。我不想知道如何用trig计算球体上的点,我已经知道了怎么做。

这是用我自己的MiniBasic版本编写的

10  REM Shaded textured sphere 
20 INPUT width 
30 INPUT height 
40 INPUT bwidth 
50 INPUT bheight 
60 REM Sphere radius 
70 LET r = 100 
80 REM light direction 
90 LET lx = 0 
100 LET ly = 0.2 
110 LET lz = -1 
120 LET ambient = 0.1 
130 REM camera z position 
140 LET cz = -256 
150 REM Sphere colour 
160 LET red = 255 
170 LET green =0 
180 LET blue = 100 
190 REM Normalize light  
200 LET len = SQRT(lx*lx+ly*ly+lz*lz) 
210 LET lx = -lx/len 
220 LET ly = -ly/len 
230 LET lz = -lz/len 
240 FOR i = 0 TO height -1 
250 FOR ii = 0 TO width -1 
260 LET x = ii - width /2 
270 LET y = i - height/2 
280 LET dpx = x 
290 LET dpy = y 
300 LET dpz = -cz 
310 LET a = dpx*dpx + dpy*dpy + dpz*dpz 
320 LET b = 2 * ( dpz  * cz)  
330 LET c = cz * cz 
340 LET c = c - r * r 
350 LET bb4ac = b * b - 4 * a * c 
360 IF ABS(a) < 0.001 OR bb4ac < 0 THEN 560 
370 LET mu1 = (-b + SQRT(bb4ac)) / (2 * a) 
380 LET mu2 = (-b - SQRT(bb4ac)) / (2 * a) 
390 LET spx = mu1 * x 400 LET spy = mu1 * y 
410 LET spz = mu1 * 256 - 256 
420 LET nx = spx / r 
430 LET ny = spy / r 
440 LET nz = spz / r 
450 LET costh = nx*lx + ny *ly + nz*lz 
460 IF costh > 0 THEN 480 
470 LET costh = 0 
480 LET lum = ambient + (1 - ambient) * costh 
490 LET v = ACOS(nz)/PI 495 LET nx = nx  * 0.999 
510 LET u = ACOS(nx * SIN(PI * v)) / PI   
535 LET v = -ACOS(ny)/PI + 1.0  
536 LET u = 1 - u 
540 GETPIXELB u * bwidth, v * bheight, red, green, blue 
550 SETPIXEL ii, i,  red * lum,  green *lum,  blue *lum 
560 NEXT ii 
570 NEXT i 
10 REM着色纹理球体
20输入宽度
30输入高度
40输入宽度
50输入马力
60雷姆球面半径
70设r=100
80雷姆光方向
90设lx=0
100设ly=0.2
110设lz=-1
120让环境温度=0.1
130 REM摄像机z位置
140设cz=-256
150 REM球体颜色
160让红色=255
170让绿色=0
180让蓝色=100
190 REM使光正常化
200让len=SQRT(lx*lx+ly*ly+lz*lz)
210设lx=-lx/len
220设ly=-ly/len
230设lz=-lz/len
i=0至高度-1时为240
ii=0至宽度-1的250
260让x=ii-宽度/2
270设y=i-高度/2
280设dpx=x
290设dpy=y
300设dpz=-cz
310设a=dpx*dpx+dpy*dpy+dpz*dpz
320设b=2*(dpz*cz)
330设c=cz*cz
340设c=c-r*r
350设bb4ac=b*b-4*a*c
360如果ABS(a)<0.001或bb4ac<0,则为560
370设mu1=(-b+SQRT(bb4ac))/(2*a)
380设mu2=(-b-SQRT(bb4ac))/(2*a)
390设spx=mu1*x 400设spy=mu1*y
410设spz=mu1*256-256
420设nx=spx/r
430让ny=间谍/r
440让nz=spz/r
450设成本=nx*lx+ny*ly+nz*lz
460如果成本>0,则为480
470设costh=0
480 LET lum=环境温度+(1-环境温度)*成本
490设v=ACOS(nz)/PI 495设nx=nx*0.999
510设u=ACOS(nx*SIN(PI*v))/PI
535设v=-ACOS(ny)/PI+1.0
536设u=1-u
540 GetPixelbu*b宽度,v*b高度,红色,绿色,蓝色
550像素ii、i、红色*亮度、绿色*亮度、蓝色*亮度
560下一个ii
570下一个i

您可以在嵌套循环中使用或。外环确定与原点不同
z
距离处圆的整数值半径,当内环计算圆的
x
y
元素时,该圆包括球体在
Z
位置垂直于Z轴的横截面,我认为最简单的方法是类似中点圆的算法,扩展到3D

首先,让我们确定要填充哪些块。假设块位于代码< >(0,0,0)和RADIUS <代码> R< /代码>的中间:< /P>
  • 我们只想填充球体内部的盒子。这些正是框
    (x,y,z)
    ,因此
    x²+y²+z²R²
    x²+(|y|+1)²+z²>R²
    x²+y²+(|z|+1)²>R²
  • 第二部分让事情变得棘手,但请记住
    (|a |+1)²=|a |²+2 | a |+1
    。例如,如果
    z
    是球体内长方体的最大坐标,并且如果该长方体有一个显示的面,那么
    z
    面将特别显示,因为
    x+y+(|z+1)²=x²+y²+z²+2 | z |+1
    ,这将至少与
    x
    y
    的类似值一样大

    因此,计算1)球体内部的长方体,2)以
    z
    作为其最大坐标,以及3)以最大可能的z值计算长方体是非常容易的,即,将1与z相加会产生球体外部的长方体。此外,4)对于所有
    x、y、z
    ,都有正值

    然后,这些长方体的坐标可以通过24种不同的方式反映出来,以生成球体表面上的所有长方体。这些都是坐标符号的8个组合乘以轴具有最大坐标的所有3个选项

    以下是如何生成正
    x,y,z
    z
    最大的点:

    maxR2 = floor(R*R);
    zx = floor(R);
    for (x=0; ;++x)
    {
        //max z for this x value.
        while(x*x+zx*zx > maxR2 && zx>=x)
            --zx;
        if (zx<x)
            break; //with this x, z can't be largest
    
        z=zx;
        for(y=0; ;++y)
        {
            while(x*x+y*y+z*z > maxR2 && z>=x && z>=y)
                --z;
            if (z<x||z<y)
                break; //with this x and y, z can't be largest
            FILLBOX(x,y,z); //... and up to 23 reflections of it
        }
    }
    
    maxR2=楼层(R*R);
    zx=楼层(R);
    对于(x=0;;++x)
    {
    //此x值的最大z。
    而(x*x+zx*zx>maxR2&&zx>=x)
    --zx;
    
    如果(zxsee只是代替点/像素来渲染像立方体一样的体素。这会让我做数千次迭代来检查某个点是否已经在已经绘制的立方体中。这会对我的口味造成太多的低效。我不认为低效是太大的问题……你得到了
    PI/4=~0.78
    效率这意味着只有约22%的迭代会浪费在每像素的单个
    if
    和比中点更好的简单迭代上,甚至Bresenhamimagine认为某种编码语言的运行速度真的很慢。如果是这样的话,那么它会运行,比如说在一小时内与你的一起运行。然而,如果你想通过h公认的答案是,它将在43分钟左右结束。这17分钟与真实速度代码相比只是一个小差异,但仍然是一个差异。如果你想要速度,那么你必须利用你的硬件/软件架构,而不是任何优化(显然很复杂,有时甚至不是这样)毫无意义。在一个平台上运行得快的东西在另一个平台上运行得慢。这会在| z |的大值处留下间隙,其中x-y平面上的半径可以跳跃超过1。Bresenham算法的死链接。Bedrockbreaker提供了简洁的代码框架,请参见链接JSFIDLE中的反射代码——结果非常酷。嘿,好了!我想知道你是否能帮我理解第5行和第6行:“while(xx+zxzx>maxR2&&zx>=x)-zx我不太明白while条件下的数学表达式是如何从您在上面的解释中描述的数学推导出来的。@retrovius当我们开始外循环的迭代时,zx保证>=正确的值,因此在第5行和第6行中,我们只需要担心减少正确的数量。第一个con条件,x