a.最近在学习OpenGL的东西时,无意发现了一篇关于”分形“的文章。”分形“由于以前接触过一点,记得和”过程内容生成“有莫大的关系,它强大而神奇的功能一直让我很好奇。看了原文作者的这篇文章后,我断定这是一篇学习”分形“的入门级别的好读物。 虽然文章并没有过多解释关于”分形“的数学知识,但通过一个经典算法的学习,会让人对它的应用更有”通透“的理解。因此我决定将它译成中文,供兄弟们一起学习。

b.调子拔得有点高了,实际上这篇文章写于1997年,距离现在已经过去了12年的岁月。因此它是一个不折不扣的老古董。对此我有两个感触:一是国外怎么这么早就有人在研究这玩意,而直到现今我对分形才刚了解没多久,这当中的差距差了多少光年?二是我会不会有点傻x,有人会翻12年前的东西么?不过感觉对我个人的成长还是很值的。原文由Paul Martz所写,在此表示感谢,尽管他本人无论如何也不会知道。

c.这篇文章翻了大概有一个礼拜还多的时间(3月9日——3月18日)。当然和能力和效率有关了,这期间也还要处理很多很复杂的人生问题,包含有:为怎么找工作发愁,为怎么考研发愁,为怎么完成毕设发愁,和女友吵架N多,看《不能承受的生命之轻》,看押井守的《攻壳机动队》3部和《天空杀手》,看杨德昌的《一一》(全是小明推荐来的,呵呵,兄弟啊),和弟兄们交流这些糟心事,一起抽烟喝闷酒。这里权当日记小结一下,不打算阐述更加深刻的思考。

d.还不得不说下博客发布编辑器。我花了一周时间翻文章并不冤枉,可是当我把完成的东西从word里转帖到这里时,却花了一上午的时间,因为格式转换的问题,不得不手动去调,真是郁闷又冤枉。期间还用了SCribeFire,可也没啥用。现在word和在线发布真的无法无缝转换么,jesus christ 

e.因此,发布成在线的html颇费体力,效果也不好,没办法大家凑合看吧。对于习惯于看双语的朋友我提供了pdf版本下载(点击这里下载)。另外我给出原文地址链接: http://gameprogrammer.com/fractal.html 。 想看E文的直接去看。

f.对于翻译,有些词语是我擅自理解翻的,也许保留它们的原文更好(相应在文中以后缀(斜体)给出)。另外有些不太容易理解的关键信息也保留了原文,但在这里不会列出。词语如下:

Generating Random Fractal Terrain   随机分形地形生成
The Definition and Rendering of Terrain Maps  地形图的定义和渲染 
diamond-square algorithm  “菱形-正方形” 算法 (开始我以为是什么“钻石-广场”算法,搞得一头雾水....-_-!)
tessellate 镶嵌
Mandelbrot set  曼德勃罗特集
Midpoint Displacement in One Dimension  一维“中点替换”算法
fractal image compression  分形图像压缩
Chaos and Fractals, New Frontiers of Science  《混沌和分形,科学的新前沿》(网上找了找这方面的资料,没发现有中译本,因此尚不知该书的准确译名是什么)

g.另外是我lookof自己,译者,擅自补充了一些话来让语句变得更通顺或更易理解的,或者是对此作出的一些解释。不得不说明原文并没有这么写,而且兴许我的理解有问题。不过我所作的补充大多都是无关紧要的环节,不会影响大家理解关键的算法思想。对于是关键环节而拿捏不准的地方,我都提供了原文。补充以后缀(下划线)给出。(注:这可不是超链接..... -_-!) 

如: 查阅本文末尾的参考书目(对学习分形知识而言)是一个好的开始。

h.参考书目不译。


随机分形地形生成




---------------------------------------

目录:


第一部分:随机分形地形生成

  • 引言
  • 自相似“一维中点替换”算法
  • 高度图
  • “菱形-正方形”算法
  • 天空云图
  • 其他方法


第二部分:关于示例程序及其源代码

  • 安装
  • 使用示例程序
  • 代码结构
  • 下载示例程序


参考书目


---------------------------------------






第一部分:随机分形地形生成(Generating Random Fractal Terrain)


引言


    10年前,我偶然发现了SIGGRAPH小组于1986年的会议记录,对其中的一篇文章感到特别得肃然起敬。这篇文章的题目是《地形图的定义和渲染》(Definition and Renderingof Terrain Maps),作者是Gavin S.P.Miller1 。该文描述了很多分形地形生成的算法,而且作者也介绍了一种新的算法。小组其他成员认为,这种新算法较之以前是一种改进。

    起初,我对这些算法的印象非常深刻(尽管作者认为这些算法依然有“瑕疵”),它们竟然能创造出如此令人难以置信的风景图片!然而接下来随着深入文章,我被这些精巧绝妙的算法“惊呆”了。

    自那以后我就对分形地形上瘾了。

    隐藏在该算法背后的数学知识可谓相当复杂。尽管如此(幸运的是),能不能完全弄清楚这些数学理论对学习该算法并无影响。这很好。因为假如我在解释算法之前,不得不先解释所有这些数学的话,那我们这辈子也接触不到这个算法了。除此之外,涉及到分形的数学概念光从字面上统计就有成吨的那么多。查阅本文末尾的参考书目(对学习分形知识而言)是一个好的开始。

    出于同样的原因,我不会深入到数学细节里,我无法在这里包含一个分形理论的概观,也无法罗列出每一件它们能够做的事情。取而代之的是,我将描述隐藏在“分形地形生成”背后的概念,然后着重给出一个我个人最喜欢的算法:“菱形-正方形”算法(diamond-squarealgorithm) 。我会告诉大家如何利用这个算法来静态地“镶嵌”(tessellate)一组高度数据,这组高度数据可以用来生成几何地形数据,地形纹理贴图,以及云团纹理贴图。

    利用分形地形你可以做什么?我假设你已经知道了答案,因为这就是你为什么会读本文的原因。随机地形图对于飞行模拟器,以及制作一块纹理贴图来当做背景(比如显示一座遥远的山脉)来说,具有非常好的效果。同样的算法也可以用来为天空云团生成纹理贴图。

    在我继续讲下去前,发布一条免责声明:我不是一个游戏程序员。如果你是因为想要一个更快的渲染地形的算法而读此文的话,你来错了地方。我只是介绍生成这种地形模型的过程。至于你如何渲染,取决于你自己。


自相似


    藏在任何“分形”背后的一个关键概念是:自相似。当一个物体放大它自己后,它的局部子集相似于(或者相同于)整体和周围的局部子集。2 

    想一想人体的循环系统,这就是一个自然界中“自相似”的好例子。从最大的动脉和静脉开始,一路直下到最小的毛细血管,都是一模一样的枝杈结构。如果你不知道你是在用显微镜观察它们的话,你就会分不清哪个是毛细血管,哪个是动脉。

    现在考虑一个简单的球体。它是自相似的吗?不是。 非常显著地放大很多倍以后,它就不再像个球了,而是像一个平面。如果你不相信我,只要看看外面好了。除非你阅读本文的时候正好位于外太空的轨道上(汗。。。太幽默了),否则你将看不出任何关于“地球是圆的”这一迹象。球体是非自相似的,描述它的最佳途径是传统的欧几里德几何,而非分形几何。

    地形算是“自相似”这一范畴。你手中握着的岩石断面的锯齿边有着相同的不规律性,就像遥远地平线的一条山脊一样。(因此地形的这个特点)就允许我们利用分形思想来产生仍然像地形的地形,而不用考虑地形呈现时的缩放比例。

    一条关于“自相似”的旁注:最严格的意义,它指的是“自相同”,就是说,无论放大或是缩小多少倍,它自己的精确的微观拷贝版本都是可见的。(that is, exact miniaturecopies of itself are visible at increasingly small or large scales.)(我自己的理解是,它的局部是严格相同于整体的,即局部和整体一模一样,并且可以无穷无尽细分下去)。实际上我不知道自然界中是否存在“自相同”的分形现象。但是曼德勃罗特集(Mandelbrotset)是自相同的。我不能再深入去讲曼德勃罗特集了,更多信息请查阅参考书目。
    

“一维中点替换”算法(Midpoint Displacement in One Dimension )


    我稍后会讲到的“菱形-正方形”算法,使用了一种二维“中点替换”算法。为了帮助你掌握它,我们首先看看在一维下的“中点替换”算法。

    一维“中点”替换算法是在遥远的地平线上画一条山脊线的极好算法。它是这样工作的:

以一条水平线段开始.
重复很多次{
对场景中的每一条线段{
找到线段的中点.
在y轴上用一个随机值替换中点值.
缩小随机值的取值范围.
}
}

    你缩减随机值取值范围的幅度是多少?这取决于你想要的效果有多“粗糙”。每一轮你缩减的越多,最后的山脊线就会越“平滑”。如果你基本不缩减,最后的山脊线就会像锯齿一样参差不齐。这表明你可以把“粗糙度”设定为一个常数,我呆会儿会解释怎么做。

我们来看一个例子。现在我们有一条线段,X轴上它在区间[-1.0,1.0]里,Y轴上每一处都是0 。 开始的时候,我们设定一个随机值的取值范围[-1.0, 1.0](可以随意设)。 所以我们将在这个范围里产生一个随机值,然后用这个随机值替换中点值。完成这步后,我们有:


现在开始第二轮循环。我们这时有两端线段,每一段都是原始线段的一半。我们让随机值取值范围也减半,所以现在变成[-0.5,0.5] 。我们为两个中点值各自在这个范围里生成一个随机值以之替换。现在的结果是:


 

我们再次缩减随机值取值范围,因此现在它变成了[-0.25,0.25] 。在这个范围里再生成四个随机值,用来替换现在的四个中点值,完成后我们有:

 

    你应该注意两点。

    首先,它是递归的。而事实上,它也可非常自然地用迭代手法来实现。因此在(一维画线)这个例子里,无论是递归还是迭代都可行。但是对于生成“表面(即地形)”的代码而言,用迭代实现比用递归实现有更多的好处。因此为了(画“线”和画“面”)一致起见,给出的示例程序中,无论画“线”还是画“面”,都是用迭代方法实现的。

    其次,这是一个非常简单的算法,然而,它却创造处一个非常复杂的结果。这就是分形算法的魅力所在。几条非常简单的指令就能创造出一个非常丰富而且细腻的图像。

    这里我扯句题外话:只要用一组精巧的指令集就能创造出一幅复杂图像的实现,引领起一个新技术领域的研究,被称为“分形图像压缩( fractal image compression)”技术。该技术的思想是,存储用来创造图形的简单而又递归的指令,而不是存储图像本身。这种技术对于创造出自然界中真正有“分形”现象的图像而言,效果是极其好的,因为指令比图像数据占据的空间要小得多。《混沌和分形,科学的新前沿》3 (Chaosand Fractals, New Frontiers of Science 3 ) 有一个章节和一个附录是专门讲这个话题的,一般来讲对任何一个“分形迷”而言,都值得一读。

    言归正传。

不必费多少劲儿,你就可以把这个(一维“中点”替换)函数的输出结果读入到一个绘图程序里,来生成点类似这样的东西:

 

      这种图像可以用来,打个比方说,作为一幅窗外的风景。于此一件不错的事情是,它是环绕的(即把两个边对接起来是契合的),这样你就可以用一张相对较小的图片来包裹整个场景。当然,如果你不介意无论从哪个方向看,都会看到同一座山的话。

    接下来,在我们进入“二维分形表面”这一话题之前,你需要了解下什么是“粗糙度常数”。这是一个决定每次循环时随机值取值范围应当缩减多少的值,因而这个值会决定最终结果的粗糙程度。示例程序中我们使用了一个在区间[0.0,1.0]之间的浮点型数,我们称它为H 。那么2^(-H) 就是一个在区间[0.5,1.0]之间的值。随机值取值范围在每一轮循环中都会乘以这个值(指的是2^(-H)。当H设置为1时,随机值取值范围每轮循环都会减半,得到的结果是一个非常光滑的不规则形状;当H设置为0时,取值范围则根本不会缩减,得到的结果将是非常参差不齐的锯齿状形状。(这里关于H的理解有点搞头,不过经过本人详细推敲,这段话是没有问题的。H无疑是指粗糙度常数,但随机值取值范围每次乘的数是2^(-H) 。比如就像上面说的,如果你定的这个常数为1,那么就会使随机值取值范围每次都乘1/2,即第一次在[0,1]内取一个随机值,第二次在[0,0.5]内取,第三次在[0,0.25]内取。这样看来,H是通过控制2^(-H) 来间接控制随机值取值范围的。如果兄弟们还有不明白的可来信询问。:-))

以下是随着H值的变化,所渲染出来的不同的山脊线:

 

高度图


    上面描述的“中点替换”算法使用了一个表征高度值的一维数组来实现。这个高度值指的是每条线段端点的垂直位置。该数组实际上就是一维的高度图。它反应的是X轴索引到高度值Y的映射。

    为了模拟随机地形,我们欲把上面那个算法(指“中点替换”算法)推广到三维空间,而且为了达到这个目的,我们需要一个表征高度的二维数组。这个数组把X轴和Z轴的联合索引映射到表征高度的Y轴上去(就是说Y是X与Z的多元函数,高数里的内容)。注意,虽然我们的最终目标是要产生一个三维坐标信息,但这里这个二维数组仅仅存储Y轴上的值,X轴和Z轴的值我们可以在解析数组的时候即时动态地生成。

通过为每一个高度值分配一种颜色,你可以把一幅高度图显示成一幅图片。下面的这幅高度图,用白色表示地形中高的地方(Y值大),用黑色表示地形中低的地方(Y值小): 

    用这种方式渲染一幅高度图对生成“云团纹理贴图”也是有效的,这个呆会儿我会解释。同样,这种方式也可以用来随机生成一幅高度图(个人认为,这才是这篇文章的精髓。因为后面介绍的算法就是在解决“随机生成一幅高度图”这个问题的)。

    现在,我来介绍如何生成“存储高度图信息”的二维数组。(即如何随机生成一幅高度图。)


“菱形-正方形”算法


    正如我在本文开始的时候提到的,我是在Gavin S. P. Miller 的文章中第一次知道了“随机地形生成”这个概念。具有讽刺意义的是,在文中,Miller把“菱形-正方形”算法看作一种存在“缺陷”的算法,之后他就开始介绍另一种基于“加权平均和控制点”的算法了。(andhe then goes on to describe a different algorithm based on weighted averaging and control points. )

(下面一段话,考虑到自己翻功拙劣,于是原文附上。因为我并不能太好地表达他的意思。好在这段是评论Miller对该算法的看法的,不是理解算法的关键。)

    Miller对“菱形-正方形”算法的抱怨根源于他尝试利用该算法来生成一座山。(山会坐落在X轴和Z轴所代表的平面网格中)。他要求平面网格的中心位置的高度(也就是峰值)是人工赋值的,而其它所有点的高度都是随机产生的。如果Miller当初仅仅让中心点的高度也同样随机产生,那么连他也会不得不承认,该算法就像一个地形生成器一样工作得那么优雅。“菱形-正方形”算法可以用来生成一座带有一个峰顶的山,这是通过对数组“种入”随机数来办到的。当然不仅仅是只对数组的中心点这一个点植入一个种子数来达到可接受的结果。(呃,太绕了,就是说其它的点也需如此吧。建议大家看原句,我好菜。)他也对其它固有的折痕问题发了点牢骚。但是(不管怎样),你该有自己的判断。这个算法最初由Fournier,Fussell, 和Carpenter 所描述4

(Miller's complaints with the diamond-square algorithm stem from his attempt to force the algorithm into creating a mountain, that is, with a peak, by artificially increasing theheight of the grid center-point. He lets all other points in the array generate randomly. If Miller had simply generated the center-point randomly, then even he would've had to admit that the algorithm works pretty decently as a terrain generator. The Diamond-Squarealgorithm can be used to force a mountain with a peak, by "seeding" the array with values. More than just the center point of the array must be seeded to achieve acceptable results. He complains of some inherent creasing problems as well. But you judge foryourself. The algorithm is originally described by Fournier, Fussell, and Carpenter 4.)
    
    算法思想是这样的:你以一个大而空的代表点的二维数组阵列开始。有多大?简单起见,这个阵列应该是个正方形。而且每一维的尺寸应该是2的几次方再加1(比如33x33, 65x65, 129x129等等)。将四个角落的点设成相同的值。看看你得到的东西,它是一个正方形。

    举一个简单的例子,让我们使用一个 5x5的数组。(我们将在后面谈到这幅图像,所以别把它忘到脑后。)在图a中,被赋值的四个角落的点用黑色高亮显示:


    下面是算法的起点,共分为两个阶段:


     “菱形”阶段:利用构成正方形的四个点,在这个正方形的中点,也就是两条对角线交汇的地方,生成一个随机值。中点值等于,四个边角点值求平均后再加上这个随机值。当在网格中有多个正方形时,这样就会为你产生菱形。(这里讲的很模糊,我也是摸索了很久才弄明白作者指的是什么意思。这里给一点提示,看着图b,用眼睛把左边的两个边角点,连同那个中心点连起来,顺序是:左上点->中心点->左下点。这样你就得到了一个菱形的右半部分。看出来了吗?它的左半部分呢?其实是循环顺延到了右边,也就是右上点->中心点->右下点构成了这个菱形的左半部分。不过,在作者看来,半个菱形就可以算是菱形了。所以,这里一共有四个菱形:左上点->中心点->左下点、右上点->中心点->右下点、左上点->中心点->右上点、左下点->中心点->右下点。)


     “正方形”阶段:利用构成菱形的四个点,在这个菱形的中点生成一个和上一步相同取值范围区间的随机值。同样这个中点值等于,四个边角点值求平均后再加上这个随机值。这样就又会给你产生正方形。(看着图c,左上点->中上点->中心点->左中点构成了一个正方形,容易看出该图一共排布着4个这样的正方形。)

    所以,如果你“种下”1个正方形并且只做了一轮这样的循环后,你将最终得到4个正方形。两轮循环你就得到16个正方形,三轮就有64个了。它增长的很快。正方形的数量等于 2^(i*2) ,i是循环迭代的轮数。(Thenumber of squares generated is equal to 2^(I+2), where I is the number of iterations through the recursive subdivision routine.)(必须指出,我翻的和原文并不一致,尤其是在那个关键公式上有些出入。原因是,无论我怎么理解,我都搞不清楚2^(I+2)的意义。如果2^(I+2)指的是得到的正方形的个数,I无论指什么意思,都不能满足1,4,16,64这样的增长规律。因为I增长必是按1累加的,即1,2,3这样的顺序,可是当I等于1时,结果就会出现8,这是不可能的。如果出现预期的结果,那么I必须以2累加,即0,2,4等等,可是这时I又表明什么意思呢?无法解释。唯有把公式解释为2^(I*2),一切疑问都烟消云散。这时I指的是迭代次数。I=0时(还没有迭代),只有1个正方形;I=1时(第一次迭代),出现4个正方形;I=2时(第二次迭代),16个正方形;I=3时(第三次迭代),64个正方形。这样就很好,一切都非常和谐。关于此疑问我已给原作者发了询问邮件。不过,对于他是否能够回复,我和兄弟们一样期待。。。。-_-!)

    现在我们对照前面5幅图,逐一看看当我们执行“菱形-正方形”算法的那两个阶段时发生的一切。

    对于第一轮的“菱形”阶段,我们在这个数组的中心(即正方形的中心点)生成了一个值,这个值是基于四个边角值得出的。我们计算四个边角值的平均值(如果这四个值相等的话,这一步其实是不必做的),然后加上一个范围在区间[-1.0,1.0]里的随机值。如图b所示,新产生的点用黑色表示,已经存在的点则用灰色表示。

    接下来是“四边形”阶段。我们在和上一阶段相同的随机数取值范围内生成一个随机值。在这个阶段一共有四个菱形。它们全部相交在原正方形的中心点。所以我们要分别计算这四个菱形的中心点。对每一个菱形,求它的四个边角值的平均值,再加上那个随机值,就是各自中心点的值。如图c所示,新产生的点用黑色表示,已经存在的点则用灰色表示。

这就是第一回合。如果你用线把这九个点连起来,你会得到像下面这样的线框图: 


    现在让我们进入第二回合。我们再次以“菱形”阶段开始。第二回合在两个方面区别于第一回合。首先,我们这次有了4个正方形,而不是1个。所以我们需要分别计算这4个正方形的中心点。其次,同时这也才是最关键的,这次随机值的取值范围区间要被缩减。比如拿这个例子来说,我们设置的H值为1的话,那么随机值的取值范围就会从(-1.0 ,1.0),缩减到(-0.5,0.5)。如图d所示,我们计算的四个正方形的中心点用黑色表示。

    最后,我们进行这一回合的“正方形”阶段。因为一共有12个菱形中心点,所以我们现在需要计算12个新值。图e中用黑色标出了它们。

现在,这个数组中的25个点已经全部生成。现在我们也许会得到如下的一幅线框图:

 

如果分配一个更大的数组,我们就能继续循环更多次的回合,在每轮回合中增加更多的细节。比如,经过5轮回合,我们的表面也许看起来会像这样:


    我之前提过,数组中每一维的尺寸应该是2的几次方再加1。这是因为,一个二维数组需要的浮点型数的个数是(2^I+1)^2,8轮回合下来,就会需要一个257x257大的数组。这对于32位的IEEE浮点数类型来说,会吃掉比256KB还多的内存。

    这是一笔很大的开销。使用字符类型代替浮点类型会有所帮助。示例程序用的是浮点型。但如果内存对你来说真的很吃紧的话,你就得用字符型,用一个范围在-128到128的有符号字符类型来替换示例程序中的浮点型应该很简单。但是当你生成它们时,要小心夹紧这些值:即便在第一回合你把它们限制在-128到128内,在随后的循环中,仍然有可能超出这个范围,由此产生一个“溢出条件”。这在当H较小时尤其可能发生。

    示例程序告诉我们另一种解决空间问题的方法。首先我们分配一个很大的数组,然后用“菱形-正方形”算法来为其赋值。之后用“从顶部到底部”的正投影视角将这个数组渲染成一幅图像,然后把这幅图像作为纹理贴图来回读给第二个只需占用较小内存的数组。一旦渲染出来的那副图像从帧缓冲区那里被回读完毕,你就可以释放第一个占用很大内存的数组了,尽管示例程序并没有这么做(指释放内存)

下面是这种纹理贴图的一个例子:

 

      这张图人为地把峰顶涂成白色,把峡谷涂成绿色,二者之间的部分则涂成灰色。你可以用示例程序提供的的源代码来随意实施你自己的配色方案。

(下面这段位于两个分界线的文字我仍然附上原文(汗颜....),并且原文在上,翻译在下,上下对比以作参考。原因是作者文字之简单但意图之模糊相当打击本人信心。我觉得自己没有能力很好地理解他到底是什么意思,但依然试图翻一翻,并且根据意思和一些有限的推理作出大胆假设。这段信息后面又有一段位于两个分界线的文字,那是我对此段文字的一些理解。如果只看原文就懂的朋友可绕过理解文字不看,不过我希望还是看看,帮忙校正一下是不是我在扯淡。)


-------------------------------------------

Earlier I had mentioned that there are advantages to implementing this routine iterative rather than recursive. Here's why: A recursive implementation might take the form:

 Do diamond step.
 Do square step.
 Reduce random number range.
 Call myself four times.

That's a nice simple implementation, and I have no doubt that it would work. But it requires that some points be generated with insufficient data. Why? After the first pass, you'llbe called upon to perform the square step without having all four corners of a diamond. 

Instead, I've implemented this iteratively, and the basic pseudocode looks like this:

 While the length of the side of the squares 
 is greater than zero {
 Pass through the array and perform the diamond 
 step for each square present.
 Pass through the array and perform the square 
 step for each diamond present.
 Reduce the random number range.
 }

This eliminates the problem of missing diamond corners found in the recursive implementation. But you'll run into this problem again anytime you generate a point on the edge of thearray. It turns out this is only a concern in the square step. You can easily overcome this and simultaneously make the surface wrappable by taking into account that one of the four diamond corner points lies on the other side of the array. (Another key tomaking the surface wrappable is to remember to seed the four corners with the same value.)


之前我说过,用“迭代”比用“递归”更好。因为,一个“递归”手法的实现很可能是这样的形式:

执行一步“菱形”阶段的操作
执行一步“正方形”阶段的操作
缩减随机值取值范围区间

调用自己四次

 


这个实现很简单,而且我也不怀疑它能运行。但这个方法的漏洞是,其中有一些点要在数据不足的情况下被生成。为什么呢?在执行完第一阶段后,你还尚未得到菱形的全部四个边角值时,就要执行“正方形”阶段了。

相反,我用“迭代”手法来实现这个算法的话,基本的伪代码类似这样:

当正方形的变长大于0时{
传递数组,为当前每个正方形执行“菱形”阶段。
传递数组,为当前每个菱形执行“正方形”阶段。
缩减随机值取值范围区间

}

 

这样就解决了用“递归手法实现时“丢失的菱形角落”的漏洞问题。但是(即便你用“迭代”方法实现)只要你在数组的边缘上生成一个点时你会再次碰上这个问题。不过这个问题只会在“正方形”阶段出现。你可以很容易地解决这个问题,你可以把这个表面“包裹”起来,假想菱形其中的一个角落(丢失的那个角落)落在了数组的另一边上。(另外使表面可以被“包裹”的一个关键是(在数组的四个角上)“种下”相同的四个值。)

-------------------------------------------


(以下是我对上面文字做的理解)

-------------------------------------------

我对作者的话存在两点疑惑:

1. 作者先说递归也是行得通的( I have no doubt t hat it would work. ),但又说这样会生成一些“残疾”的点,因为这些点是在数据不足时产生的( it requires that some points be generated with insufficient data.)。点是生成了,但却是残疾的,那么这个实现方法到底算“成”还是算“不成”呢?作者告诉我们,采用“迭代”比采用“递归”更优,开始我以为是性能效率上的比较,因为我们知道,“非递归”的开销确实要小于“递归”的开销,“递归”仅仅是代码上看上去简洁了不少而已。但是作者介绍到这里时,却到了伤筋动骨的地步,简直感觉如果用“递归”的话就会残疾了似的。到底是怎么回事呢,弄不清楚。

2. 对比递归的伪代码和迭代的伪代码,我没看出什么本质的不同,如果是区别在于后者传递了数组的话,我完全可以把数组设计成一个全局变量,然后同样传递给递归函数,这不同样可以办到么?因此我想这不是递归的死穴。另外,我不清楚为什么要“调用自己四次”??


经过一段时间思考,我忽然得出这样的猜测(不保证正确,这里正是需要大家拍砖校正的地方):

     这就像是当初学数据结构时关于“图的遍历”的两种方法似的:深度遍历和广度遍历。这里的“递归”实现就像是深度遍历一样,它会盯住一个根“菱形-正方形”结构,逐步分解成更小的“菱形-正方形”结构(通过不停压栈),直到到达最小(这里调用四次即到达最小),然后返回上一级,然后遍历完这一级所有的结构,然后再返回上一级,直到栈被弹空。这样带来的问题是,当要求其中某一个结构的中心点时,会遇到围绕这个结构的四个边角,有一个角落点是不属于这个大结构的情况(那个角落点属于邻近的那个大结构里的点),但是由于“递归”的算法,你在当前大结构未被返回前,是无法计算邻近的那个大结构的点的值的,因此就带来了“丢失的角落”问题。这属深度遍历的特性所致,可谓死穴。

     而迭代就像广度遍历那样,先把当前一级的所有结构都遍历完毕,才深入到下一层去遍历更小的结构,这样当下一层的小结构需要用到邻近的边角值来计算中心点时,因这些边角值属上一层的点,已被完全计算出来,因此就不存在什么障碍了,这样就很好地解决了递归的死穴问题。

-------------------------------------------



下面是一个“菱形的一个角落出现在数组的另一边”的例子。图中,我们在“正方形”阶段生成了一个点,而它恰好落在了数组的边上。灰色表示的是包含了菱形四个角落的位置。这四个位置的值需要求均,以此作为中间新值的基值,图中那个新值用黑色表示。


    注意,图中用黑色表示的有两个点。实际上它们是相等的。每次你在“正方形”阶段计算一个落在数组边上的点时,记得在数组对面的一边也要存储它一遍。为了能够无缝对接,这些点必须完全相同。

    这就意味着,在前面的图e中,我们其实不必把那12个点值全都各自算一遍,因为其中有4个点值是另外一边对应点值的重复。因此我们只有8个点需要计算。

    我将给有兴趣的读者留一个练习:修改示例程序中的源代码,让它在不需要计算“数组边上的重复点值”的情况下也能运行。(“计算重复点值”这件事)对于算法来说真的不是必须的,只是我恰好在代码里写成了那个样子。

    如果直到现在你还没有运行过示例程序,也许现在你该打开它看一看。这个程序的初始状态是一个经过两次迭代而生成的表面。它是用“线框模式”渲染的,也就是简单地用线段连接起数组中的每个点而已。数组中的值被当作Y值对待,而每个点的X轴和Z轴的坐标信息在数组解析的过程中动态生成。用三角形(作为基本图元)可以很容易渲染图像,你可以把每一个正方形刨切成两个三角形(连接正方形的对角线即可得到)。“三角形”一般来说是用来渲染图形的非常优秀的基本图元,因为它永远都是“凸面”的,而且保证三个点绝对在同一平面。

    点击进入“View Options ”对话框。改变“Random seed ”值可以让你生成一个不同的表面,稍稍调高点“Iterations”值,可以为表面增加更多的细节。代码中规定这个值的上限为10,此上限对于我的32M内存,奔腾Pro系统而言已经有点吃不消了,不管怎么看都是黑黑的一片(whichis a little much for my 32 Meg RAM Pentium Pro system and just looks black anyway. )(Meg ,应该是megabyte的缩写,意为“兆字节”)。(五年后,人们会在新的处理器和更高分辨率的屏幕上运行这段代码,然后他们会奇怪干嘛我非要把这个值卡在10以内....) (实际上,这篇文章是写于997年。如今12个年头过去了。我在我的1GM内存,Pentium M 1.73GHz,ATI X600 的机子上运行这段程序,把“Iterations”调到10后得到的依然是一片黑色.....)

    第一个H值控制着表面的粗糙度。默认值设为0.7 。 试着调高或调低这个值,然后注意观察结果。

    是的,这个算法偶尔会出现局部“突起”和一些“褶皱”。但是我比较喜欢这些超现实的“突起”效果,而“褶皱”并不明显,这取决于你从哪个角度去观察它,也和你从上面飞过它时有多快有关系(估计是用来作为飞行模拟的场景时)(and the creasing is not obvious depending on what angle you are viewing it from, or how fast you're flying over it.)


天空云图


    现在我们知道如何来生成一个表面。我们既可以生成并渲染成千上万个三角形,也可以把一个高解析度的纹理贴图贴到一个低解析度的表面上。(这两种方式)无论采用哪一种,都可以营造出非常酷的效果。但是现在我们该怎么生成头顶上的云团呢?实际上它比你想的要简单的多。

    用“菱形-正方形”算法进行“镶嵌”过的数组,非常适合用来描绘一幅天空云团的纹理贴图。只不过这时数组的值,不再代表高度图里Y轴的值,而是表示云团的透明度。最小的值表示“最蓝”,是天空中最晴朗的部分;而最大值表示“最白”,是天空中云层最密布的部分。

轻轻松松解析完数组,你将得到这样一幅纹理贴图:

    

 

    这幅图和本文前面说过的“高度图”很类似,但我把低端和高端的值保持在某个范围,以此来生成一片“云彩斑斓”的天空(but I have clamped the low and highvalues to create patches of clear and clouded sky.)

    运行示例程序,你也可以生成像上面的这样一幅图像。选择 Select rendering type 下拉框,选中2D mesh / clouds选项。(默认状态下它看上去类似像素那样一格一格的,试着把 Cloud iterations值调到8或者更高看看)。接下来设定不同的H值,这样就能得到不同的云团效果。

    如果你回到这篇文章刚开头的地方,你会发现我把所有曾讨论过的东西都组装在了第一张图里。天空是用上面展示的纹理贴图生成的,在一个八棱锥上平铺了多次(The sky is madewith a texture map as shown above, tiled multiple times over an eight-sided pyramid. )(意思是,天空的效果是用八棱锥做的一个天空盒,然后在上面平铺了很多这个贴图而做成的)。表面的几何体是用高解析度纹理贴图渲染的。该纹理贴图由“自顶向下”的正投影视角渲染。这幅图像经过“回读”后被当作一张新贴图使用。(就是前面说过的那个节省内存的技巧。)

    示例程序会展示几乎所有在本文中所提到的图像。


其他方法


    你也许想对“地形生成”施加更多的控制,超过示例程序所提供的功能。比如说,你也许想在开始的几轮回合中先在数组中“种下”一些你自己规定的值,这样像山、峡谷、等等什么的都可以按你的设计来放置。然后再用“菱形-正方形”算法来填充剩余的细节。

    不要像Miller那样,想要生成一座山,却仅仅只对数组的中心点赋一个很大的值。想要产生合理的结果,你起码应该要(用“菱形-正方形”算法)为这个数组“播种”两到三轮。

    你很容易就可以通过改写代码,让数组中已经赋了值的元素不再被分配新值。首先,初始化你的数组,比如说把每个元素都设为-10。接着,最初的几轮迭代用你自己指定的值来“播种”。然后,用那段改写过的代码来只对值为-10的元素分配新值。最初的几轮迭代不会生成任何值,因为你自己规定好的值已经在那了。随后的迭代中,才会根据你规定好的这些值来生成新值。

    如何创造自己的“种子”? 如果你想要的形状是某种已知的可以用数学公式描述的形式,比如正弦曲线,那么直接使用公式就可以生成这些值。但要是别的情况,就得想一些“创造性的办法”来完成它了。我曾见过的一个办法是用“灰度值”来填充你自己的高度图。把“灰度值”和“高度值”进行一一映射,然后存储在你的数组中。接下来再用“菱形-正方形”算法来增加更多的细节。

    除了使用“菱形-正方形”算法,你还可以使用许多其他算的法达到同样的目的。

(以下两段话我不太明白什么意思,不保证翻译质量,遂附上原文。并请大牛拍砖指正。)

(有一种算法是这样的:)在二维数组中随机选取一段范围,为该范围内每一个元素赋一个很小的值。不停地重复这个过程,分别为每一段随机选中的范围里的所有元素都增加一个很小的值。这样也会产生不错的结果,但是该算法的复杂度并不是线性的。如果计算的时间成本对你来说无所谓,那我鼓励你试试这种算法。

(With successive random addition, a random region of the 2D array is incremented by a small amount. Repeat this process over and over, adding a small amount into each randomly chosen region of the array. This generates good results but is not computationallylinear. If compute time is not a concern, I encourage you to try this algorithm out.)


另一种相似的算法是在数组中制造出一个“断层”,然后为其中一边的所有元素赋值,就像“地震”发生时那样。这个过程也需要重复好多次。同样该算法的复杂度也不是线性的,而且你必须迭代几轮才能得到像样的结果。

(Another similar method involves making a "fracture" across the array and incrementing one side of it, as if an earthquake had occurred. Again, repeat several times. This is also not a linear algorithm and takes several passes to get acceptable results.)


欲了解更多其他的方法,请查阅后面的参考书目。


第二部分:关于示例程序及其源代码


安装


    示例程序及其源代码打包在一个zip文件里。使用你最喜欢的zip解压缩软件来解开它。如果你还没有一个zip解压缩软件,可以试试PKware(我们使用winrar就能打开。)

    源代码使用OpenGL API 作为渲染的图形接口。如果你的机器还没有安装OpenGL,你应该先得到它。Microsoft和SGI 都提供了支持Windows 95 的OpengGL版本。但我劝你选用SGI的,因为它在性能和程序健壮性方面都比Microsoft的强出去不少。示例代码链接的是SGI实作版本。因为SGI和Microsoft选择了不同的名字来命名它们的DLL文件,所以代码使用的是SGI的DLL文件。

    下面是“傻瓜式制作酷图像”的说明向导。

双击 Fractal Example 图标。
打开View Options 对话框。
从Select render type下拉菜单中选择2D mesh / rendered。
在 Iterations 框中输入4 。
在 Tile 框中输入3 。
点击 OK 。
 

使用示例程序


    默认状态下,程序显示的是二维网格线框模式。它已经是用“菱形-正方形”算法生成了的。两轮迭代能产生16个正方形。(Two passes were made over the surfaceresulting in eight squares.)(这又是个错误,原文中说是8个正方形,但是按照正确的思路,两轮下来能产生16个正方形。运行程序你也能看到,确实是16个而不是8个。这里应该是作者的一个笔误。)

    你可以使用箭头键来改变视角。使用←和→键可以旋转场景。按住Shift键再按↑和↓键可以令场景向上或向下运动。松开Shift键再按↑和↓键可以令场景向前或向后运动。

    现在解释View Options 对话框。你可以在菜单栏里点击View 选项,或者按Ctrl-O(注意是O不是0)来打开它。这里你可以改变你要想看到的东西,以及为“如何生成它们”设定其属性值。对话框看起来像这个样子:


    Select rendering type 下拉框菜单控制你要显示什么图形。1D midpoint displacement 渲染了一条用“中点替换”算法渲染的线段。

    所有标明有2D mesh 的类型都是利用“菱形-正方形”算法生成的一幅图像。2D mesh / lines 是用线框模式渲染的一个表面。2D mesh / rendered 展示了一个“二维地形”,这个面是用当前纹理贴图(就是选项“2D mesh teximage ”中生成的那个贴图)贴出来的,而天空是用“云团贴图”贴出来的。2D mesh /clouds 允许你只观察“云团贴图”。这是一个简单的二维高度图,蓝色表示小值,白色表示大值。2D mesh teximage  允许你只观察在rendered 模式中展出的那个覆盖地形的纹理贴图。这是一个“自顶向下”观察的正投影表面。使用了不同的颜色来区别这个面不同的“高度值”。

    你可以使用对话框右半边的参数,以此控制这些图形的生成。

    参数Tile 表示需要“排布”多少个表面或者线段。默认值是1。对于线段,这个参数决定了会平铺多少条单位为“1”的线段;而对于表面,把这个参数设为2则表示有2x2个单位为“1”的表面,3则表示有3x3个。如此等等。

    参数Random seed设置了一个新的“随机种子”,以此可以创造出不同的表面。

    参数 Iterations 决定会迭代多少次。数值越大则细节越多。默认值是2,这个参数的取值范围是从1到10。

    你可以调节参数Cloud iterations来设置“云团贴图”的细节度。类似地,你也可以调节参数eximage iterations 来设置“地形贴图”的细节度。

    注意,对话框里一共有三个H值。第一个H值用来生成表面,第二个H值用来“云团贴图”,第三个H值用来生成“地形贴图”。

    当渲染类型选择1D midpoint displacement 或者2D mesh / lines时,勾选Antialiased lines 复选框会采用抗锯齿模式。

    勾选Invert colors复选框会反转背景和线条颜色。

    当渲染类型选择2D mesh / rendered时,Texture linear复选框控制“双线性纹理滤波方式”的开关。勾选此开关后,结果的生成会耗时更长,但最后的图像素质也会更高。

代码结构


    文件fractmod.c 和文件fractmod.h是这个示例程序的C程序代码。 他们包含了“分形生成”模块。

    微软1996年11月的期刊上(http://www.microsoft.com/msj)刊载了一篇文章,提到 CFractalExampleView 类是COpenGLView 类的派生类。COpenGLView类的作者是Ron Fosner,他把这个类描述成原成熟类的“黑客版本”(The COpenGLView class was writtenby Ron Fosner, who describes it as a hacked version of his fully-blown COpenGLView class)。(直到现在,微软期刊上仍有这篇文章,点击这里查看。)想要知道到底怎么回事,你得买一本他写的书《Programmingfor Windows 95 and Windows NT》,该书由Addison-Wesley出版。

    该COpenGLView类有一个虚拟成员函数RenderScene,在CFractalExampleView类中我们重写了它。这里我们做了大部分的渲染工作。这个函数首先检查“渲染类型”。当设置为2D mesh / lines 或者1D midpoint displacement时,那么仍由原RenderScene来处理。否则的话我们调用另一个函数。

    函数CFractalExampleView::OnViewDialog 用来生成View Options 对话框,以及在对话框类和CFractalExampleView类之间设定和检索数据。

    函数CFractalExampleView::OnInitialUpdate负责把所有CFractalExampleView类中的成员变量设定为默认值(包括对话框中的值)。

    其实真没什么必要去更深地解释代码是如何工作的。我假设你是一名很有能力的程序员,而我也尽了最大努力来全面地讨论这些代码了。如果你不熟悉OpenGL,那你也许很想知道的是,那些以“gl”开头的函数其实都是OpenggL API 的调用。微软的Visual C++ 对此API有一些有限的文件。

    我请你为这个程序增添一个功能(There is one feature that is just begging to be added to this code)。在文件FractalExampleView.cpp中,有一个预置的常量DEF_HEIGHT_SCALE (there is a preprocessor constant called DEF_HEIGHT_VALUE)(作者笔误,其实应该是DEF_HEIGHT_SCALE),这个值会被传给位于fractmod.c文件的控制“分形生成”的函数里,以此来达到“缩放”高度值的目的。其实它应该被设定为一个由对话框来控制的变量。请放心地添加这个功能。(意思是,作者认为这个值如果体现在对话框里,直接由用户控制的话会更好更合适,但他的程序没有这么做。因此他希望读者来完成这个功能)。


参考书目


1 Miller, Gavin S. P., The Definition and Rendering of Terrain Maps. SIGGRAPH 1986 Conference Proceedings (Computer Graphics, Volume 20, Number 4, August 1986).

2 Voss, Richard D., FRACTALS in NATURE: characterization, measurement, and simulation. SIGGRAPH 1987 course notes #15.

3 Peitgen, Jurgens, and Saupe, Chaos and Fractals, New Frontiers of Science. Springer-Verlag, 1992.

4 Fournier, A., Fussell, D., Carpenter, L., Computer Rendering of Stochastic Models, Communications of the ACM, June 1982.
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. Tomcat配置虚拟主机

    Tomcat服务器,允许用户在同一台计算机上,配置多个Web站点,在这种情况下,需要为每个Web站点,配置不同的主机名,即配置虚拟主机 现实生活中,为了提高硬件资源的利用率,有很多网站通过配置虚拟主机的方式,实现服务器的共享在Tomcat服务器中,配置虚拟主机,需要使用<…...

    2024/4/11 20:29:40
  2. 进一步熟练掌握burpsuite抓包功能;掌握SQL注入漏洞的基本原理;重现实验内容

    SQL-Inject漏洞的概念原理 概述:数据库注入漏洞,主要是开发人员在过后见代码时,没有对输入边界进行安全考虑,导致攻击者可以通过合法的输入点提交一些精心构建的语句,从而欺骗后台数据库对其进行执行,导致数据库信息泄露的一种漏洞。 一般的网站都会有一个相对应的数据库…...

    2024/4/23 17:42:38
  3. 用多线程下载视频(Java)

    博主自己写的一个多线程下载文件的小程序 /*** 爬虫多线程下载文件* * @author ChenYiFan**/ public class Test {public static void main(String[] args) {try {String urlname = "http://219.147.83.244/695EF05563F718C926E37E9/03000A010059F1DF936FEE01233E8D995A1F…...

    2024/4/21 16:09:49
  4. 五分钟带你了解前端开发,以及前端开发的发展机会

    前端开发 前端开发是创建Web页面或app等前端界面呈现给用户的过程,通过HTML,CSS及JavaScript以及衍生出来的各种技术、框架、解决方案,来实现互联网产品的用户界面交互 。它从网页制作演变而来,名称上有很明显的时代特征。在互联网的演化进程中,网页制作是Web1.0时代的产…...

    2024/4/19 14:13:06
  5. 多人联机射击游戏中的设计模式应用(二)

    (6)观察者模式联机射击游戏可以实时显示队友和敌人的存活信息,如果有队友或敌人阵亡,所有在线游戏玩家将收到相应的消息,可以提供一个统一的中央角色控制类(CenterController)来实现消息传递机制,在中央角色控制器中定义一个集合用于存储所有的玩家信息,如果某玩家角色(Pl…...

    2024/4/18 13:27:42
  6. 利用C语言绘制操作系统图像界面

    阅读博客的朋友可以参看视频: Linux kernel Hacker, 从零构建自己的内核有了C语言这一利器后,不多多拿来用,那就太对不起前面的一系列努力了。那么怎么表现C语言的强大功能呢,如果还只是一味的在界面上输出几行字符,那太没意思,考虑到,我们的目标是做出像windows那样具…...

    2024/4/25 23:23:55
  7. 二维码与条形码的生成和识别使用

    应公司leader分配的任务,要求写一个二维码生成器放入系统settings应用中显示其相关配置信息,为方便以后工作,现将其二维码的生成和识别使用方法总结下来。二维码,我们也称作QRCode,QR表示quick response即快速响应,在很多App中我们都能见到二维码的身影,最常见的莫过于微…...

    2024/4/22 18:08:43
  8. [红日安全]Web安全Day2 - XSS跨站实战攻防

    本文由红日安全成员: Aixic 编写,如有不当,还望斧正。大家好,我们是红日安全-Web安全攻防小组。此项目是关于Web安全的系列文章分享,还包含一个HTB靶场供大家练习,我们给这个项目起了一个名字叫 Web安全实战 ,希望对想要学习Web安全的朋友们有所帮助。每一篇文章都是于基…...

    2024/4/27 7:49:41
  9. Tomcat配置,解决PermGen space问题

    Tomcat配置 jvm 参数 -Xms -Xmx -Xmn -Xss 调优总结 我设置的如下,服务器内存是8G的,用起来还是不错。 set JAVA_OPTS=-Xms4096m -Xmx4096m -XX:PermSize=1024m -XX:MaxPermSize=1024m -XX:NewRatio=2 -Xloggc:gc%RANDOM%.log -XX:+PrintGCDetails常见配置汇总 堆设置 -Xms:…...

    2024/4/17 18:59:41
  10. SQL注入POST参数-注入HTTP报文

    1、SQL注入漏洞介绍 SQL注入攻击指的是通过特殊的输入作为参数拆入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句中进而执行攻击者所要的操作,起主要原因是程序没有细致地过滤用户输入的数据,致使非法数据入侵系统。 任何一个用户可以输入的位置都可能…...

    2024/4/17 18:58:10
  11. 解压版(免安装版)tomcat 配置windows服务以及启动停止方式

    对于解压版的tomcat,需要我们将它配置为windows服务,才可以让它随服务的启动而启动 tomcat配置服务步骤:配置java和tomcat的环境变量,此处省略 运行Win+R打开运行对话框,输入cmd命令打开控制台,进入tomcat安装目录下的bin文件夹,使用service.bat install 服务名(可省略…...

    2024/4/20 12:57:56
  12. 生成对抗网络(GANs)的资料小结,另附:资源|17类对抗网络经典论文及开源代码(附源码)

    1.GANs的一些资料链接************************************************** ************************************************************************************* 【1】GAN学习指南:从原理入门到制作生成演示,总共分几步----- HTTP://www.leiphone.com/news/201701/…...

    2024/4/17 18:58:16
  13. SpringBoot2.x系列教程(三十六)SpringBoot之Tomcat配置

    Spring Boot默认内嵌的Tomcat为Servlet容器,关于Tomcat的所有属性都在ServerProperties配置类中。同时,也可以实现一些接口来自定义内嵌Servlet容器和内嵌Tomcat等的配置。 关于此配置,网络上有大量的资料,但都是基于SpringBoot1.5.x版本,并不适合当前最新版本。本文将带大…...

    2024/4/18 6:59:25
  14. sql注入漏洞表(列)名的暴力破解

    在开始之前我想先在这里提醒选择阅读这篇博客的读者。因为本人初涉安全领域知识。关于对表(列)名的暴力破解任处于摸索于尝试阶段,对于许多概念与知识认识任然存在不足。此博客亦是只起到对现所学知识的一个记录。所以只起到一个阅读和借鉴的作用,并不建议读者用作专业知识…...

    2024/4/18 9:26:23
  15. java读取视频播放时间,很有用啊

    源码点我 最近需要用java处理视频文件,读取视频的时长,在网上查,没找到合适的方法,用JMF吧,支持的格式太少,用JNI去读取其他语言写的API,但比较麻烦。无意中找到了jave这个开源的项目,看了看介绍,是用java来处理多种视频格式之间的转换的,下载了下来,看了看,还真找…...

    2024/4/20 4:12:57
  16. 第一次冲刺会议评审总结

    1.移山小分队 二手书交易平台 这是一个网上卖二手书的平台,第一阶段冲刺结束后,该团队完成了网页的大体设计,实现了图书的搜索、查看评论的功能,并且数据库也连上了。对他们现在的成果我觉得可以加上一些其他的功能。将各种书分类,给出标签,在查找时就可以根据一些标签查…...

    2024/4/14 20:12:12
  17. Tomcat配置成服务启动,添加自定义参数

    Tomcat配置成服务启动tomcat配置成服务启动,网上已经有很多方案了。我这里简单的列一个;首先进入${TOMCAT_HOME}/bin目录 使用win r打开cmd窗口 service install tomcat8 安装服务,服务名称是tomcat8为什么服务名称安装成tomcat8呢,是因为在service.bat里他默认的名称就是t…...

    2024/5/1 7:54:38
  18. 浅谈web前端开发

    有部分同学和朋友问到过我相关问题,利用周末我就浅浅地谈谈我对web前端开发的理解和体会,只能浅浅谈谈,高手请自动跳过本篇文章。毕竟我现在经验并不是很足,连工程师都算不上,更不用说大牛了。今天也不谈技术,技术很多人比我掌握得更好,也大同小异,但是每个人的理解体会…...

    2024/4/18 3:12:57
  19. 无需成对示例、无监督训练,CycleGAN生成图像简直不要太简单

    作者 | Jason Brownlee译者 | Freesia,Rachel编辑 | 夕颜出品 | AI科技大本营(ID: rgznai100) 【导读】图像到图像的转换技术一般需要大量的成对数据,然而要收集这些数据异常耗时耗力。因此本文主要介绍了无需成对示例便能实现图像转换的 CycleGAN 图像转换技术。文章分…...

    2024/4/17 18:58:40
  20. 墨者学院CTF(SQL注入漏洞测试(参数加密))

    靶场地址:https://www.mozhe.cn/bug/detail/SjRRVFpOQWlLWDBJd3hzNGY5cFBiQT09bW96aGUmozhe 1. 靶场截图: 2. 目录扫描 访问可得new目录下list.php源码,即在此处存在注入漏洞 3. 代码审计 <?php header(content-type:text/html;charset=utf-8); //发起原始的http报头 re…...

    2024/4/19 17:41:48

最新文章

  1. Java:Thread类及常见方法大全(画图+源码详解)

    Thread 类是 JVM 用来管理线程的一个类&#xff0c;每一个线程都有一个唯一的 Thread 类与之关联。Java中通常使用 Thread类来进行线程调度&#xff0c;线程管理。 目录 一、Thread 的常见构造方法 二、Thread 的几个常见属性 理解线程是否存活&#xff1a; 理解前台线程与…...

    2024/5/2 10:42:36
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 3d representation的一些基本概念

    顶点&#xff08;Vertex&#xff09;&#xff1a;三维空间中的一个点&#xff0c;可以有多个属性&#xff0c;如位置坐标、颜色、纹理坐标和法线向量。它是构建三维几何形状的基本单元。 边&#xff08;Edge&#xff09;&#xff1a;连接两个顶点形成的直线段&#xff0c;它定…...

    2024/4/30 6:02:33
  4. Linux中的shell脚本之流程控制循环遍历

    3 条件判断 4 流程控制语句 1&#xff09;if 语句 案例&#xff0c;用户输入用户名和密码&#xff0c;判断用户名是否是admin,密码是否是123,如果正确&#xff0c;则显示登录成功 首先我创建了shell文件&#xff0c;touch getpawer 其中getpawer 是我自己命的名 #!/bin/bas…...

    2024/5/1 13:38:30
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/2 9:28:15
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/2 9:07:46
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57