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