最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

【Minecraft】worldedit|generate 深入解析gmegabuf()緩沖函數(shù)——從原理到應(yīng)用

2023-08-07 19:40 作者:MHols_  | 我要投稿

一、格式和用法

https://worldedit.enginehub.org/en/latest/usage/other/expressions/

(megabuf有全局的gmegabuf和本地的megabuf,為了方便,下文只寫gmegabuf)

看wiki翻譯不難理解,gmegabuf本質(zhì)上是一個數(shù)組,數(shù)組默認(rèn)為0;

提供了三個函數(shù)?

1.1、gmegabuf()

先講這兩個

  • gmegabuf(索引值):調(diào)用數(shù)組對應(yīng)索引值處的值,后期調(diào)用使用

  • gmegabuf(索引值,值):把“值”存進(jìn)數(shù)組對應(yīng)索引值的位置,前期賦值使用

//calc

首先介紹另一個指令://calc 表達(dá)式,這個指令能計算輸出表達(dá)式的值,單純運行表達(dá)式而不進(jìn)行生成操作,比如

或者默認(rèn)gmegabuf(0)是0,所以

先在gmegabuf里存入設(shè)定好的值,用第二個函數(shù)?(g)megabuf(index,?value)

我們分兩次輸入,因為帶個g,是全局緩沖器,只要不重進(jìn)游戲就不會自動清零,這就體現(xiàn)了緩沖器gmegabuf的強大之處,本來很長的指令可以分開,一條指令先給緩沖器數(shù)組賦值,另一條用來調(diào)用,調(diào)用內(nèi)容包括索引和對應(yīng)的值,比如

先在數(shù)組索引為0的位置賦值2*random()-1
再調(diào)用數(shù)組索引為0處的值

隨機數(shù)

上面先給gmegabuf數(shù)組索引為0的位置賦值為 一個為2*random()-1的數(shù),gmegabuf(0,2*random()-1)

random()返回的是個0~1的數(shù),所以2*random()-1在-1~1之間,與在一個選區(qū)里用generate調(diào)用random()不同,generate它會在每個坐標(biāo)處都運行一次你寫的指令,即每個位置都會獨立運行一次獲取隨機數(shù)的函數(shù)random(),使得整個選區(qū)內(nèi)的每個位置得到的隨機值并不統(tǒng)一,而事先用//calc在gmegabuf內(nèi)存入隨機數(shù),就能讓隨機數(shù)確定下來,然后在//generate中用gmegabuf(索引)代替random(),讓每個坐標(biāo)處的調(diào)用的隨機數(shù)都是這個數(shù)組gmegabuf的內(nèi)容,是同一個,所以用gmegabuf相關(guān)函數(shù)能在一些需要固定的隨機數(shù)的情況下很好用,就比如預(yù)先設(shè)置圓的隨機半徑等隨機變量或者點的隨機坐標(biāo)(三個一組,xyz)

存儲變量

如果有fawe的話,里面有個//br scmd 散點執(zhí)行命令的筆刷,具體看wiki

https://intellectualsites.github.io/fastasyncworldedit-documentation/basic-commands/main-commands-and-permissions.html#_brush_scmd_scatter_radius_points_cmd_radius1_cmd1cmd2

效果圖

(指令不縮進(jìn)是為了方便復(fù)制)

我這里先限定了圓柱的最大和最小半徑和最大最小高度,然后用/calc 存入到gmegabuf里,然后再在后面的generate里用gmegabuf(index)調(diào)出之前的已經(jīng)確定的隨機數(shù),然后只需一點就能生成高度和半徑的隨機的圓柱了(另外里面夾的選區(qū)命令也要隨最大半徑和高度改變)

也可以簡單的改造成一個隨機球形的筆刷:

1.2、gclosest

  • gclosest(x,y,z,起始查找的索引值,查找的次數(shù),步幅):查找與xyz最近的一組連續(xù)的gmegabuf內(nèi)的值的索引并返回

比如有一系列已經(jīng)賦完值的gmegabuf,選區(qū)里用generate,其中有一句i=gclosest(x,y,z,0,100,3),意思就是,假如選區(qū)里的一點,xyz對應(yīng)帶入,然后計算從gmegabuf索引0開始3個為一組來與xyz一一比較,比較次數(shù)上限100次,最后是索引為98,99,100的一組與xyz的值進(jìn)行比較,然后找到最接近xyz的那一組(三個)

我個人猜想,里面的計算邏輯是找到(gmegabuf(i)-x)^2+(gmegabuf(i+1)-y)^2+(gmegabuf(i+2)-z)^2的最小值所對應(yīng)的索引值 i,事實證明確實是這樣的,假如步長是4會是怎么樣,我測試的好像是前三個正常計算,第4個不參與與xyz的計算。如果是2?算了,不想這么多了,主要以3為主

舉個小例子

存儲坐標(biāo)

變相地實現(xiàn)了參數(shù)方程形式的表達(dá)式,用一個適當(dāng)?shù)牟介L,畫出足夠的近乎連續(xù)的點

還有我動態(tài)里的二維謝爾賓斯基集Sierpinski,是同一個道理

還有動態(tài)里的這個?


二、gmegabuf()在voronoi的應(yīng)用

首先先了解一下voronoi圖,這個網(wǎng)站動圖解釋的很形象

http://datagenetics.com/blog/may12017/index.html#:~:text=Each%20of%20the%20boundaries%27%20partitions%20off%20the%20space,Voronoi%2C%20a%20Ukrainian%20mathematician%2C%20who%20died%20in%201908

2.1、gclosest

第一步,我們需要一些隨機的點的坐標(biāo),下面就稱作樣點

一般我們賦值順序都是 x y z,先gmegabuf(i,2*random()-1)存為x坐標(biāo),接著gmegabuf(i+1,0)存為y坐標(biāo),賦值為0是因為下面介紹都是xz平面內(nèi)的圖案,用不到y(tǒng),其實不寫也行,反正默認(rèn)就是0,最后是z,gmegabuf(i+2,2*random()-1),跟x一樣,范圍在-1~1是為了在generate里方便使用

我們需要的是大量的xz坐標(biāo)在-1~1間的點,一個個賦值不現(xiàn)實,我們需要用到for循環(huán),但是在we表達(dá)式中,單個循環(huán)最大上限是256次,所以我們需要嵌套循環(huán),實現(xiàn)最多256x256=65536次循環(huán),當(dāng)然如果繼續(xù)嵌套還能更多

for循環(huán)函數(shù)的用法wiki有,不贅述

這里是3個為一組用來分別作為一個點的xyz坐標(biāo),總共有n=1000個點,但索引k已經(jīng)到了3000了

最后加個1是為了讓它成功運行,因為需要返回一個值,不然可能會報錯

選一塊選區(qū),generate,使用gclosest函數(shù)找到與選區(qū)里每個位置方塊最接近的那一組gmegabuf存的坐標(biāo),返回這組的第一個的索引值作為data用于區(qū)分顏色,呈現(xiàn)效果

data=i/3%16;1 ,i/3是因為索引值i是3個為一組(i,i+1,i+2),實際上不除也能區(qū)分各個區(qū)域,但它們是3的倍數(shù),當(dāng)%15時少顏色

與樣點的距離

我們用gclosest()得到了選區(qū)里每個位置坐標(biāo)相距最近的樣點的索引值 i ,也就同時得到了樣點的坐標(biāo),只需要用第一個介紹的函數(shù)gmegabuf(i)、gmegabuf(i+2)調(diào)用出樣點的xz坐標(biāo),從而實現(xiàn)一些更有趣的效果

我們先獲取了樣點的xz坐標(biāo),用大寫XZ來區(qū)分,進(jìn)而計算了選區(qū)每個位置和與它最近樣點的距離r=sqrt((x-X)^2+(z-Z)^2);然后擴大60倍能與16取余當(dāng)作data的值,就的得到了這一個漸變的圖案,然后換上黑白漸變的材質(zhì)

快速替換材質(zhì)

這里推薦eztaK和Zeranny想到的快速替換材質(zhì)的辦法

https://docs.google.com/document/d/1-o4dyb0ahlnn4tDgWfoTvUEQ2yBKDx_9qnUFWMJXgY0/edit#heading=h.tn6tq6bczdc6

順便一說,他們寫的文檔也很推薦去看看

他并沒有解釋原理只講了用法,我簡單解釋一下,先用queryAbs獲取每個位置的方塊type和data,然后讓非目標(biāo)type的方塊不操作,return 0,如果是該type的方塊讓它的xyz全都指向同一世界顏色表的起始位置,然后讓x或z根據(jù)前面檢測的data的數(shù)值向x或z方向移動對應(yīng)數(shù)值,就實現(xiàn)了按照data的值去上色的效果,具體點說,白色混凝土的data是0所以d=0,z+=0,所以就被替換成了第一個的方塊(z=-97),橙色混凝土data是1,d=1,z+=1,所以被替換成了第二個方塊(z=-96)其他同理

F3對準(zhǔn)目標(biāo)方塊,右下方的坐標(biāo)就是該方塊的坐標(biāo)

另外我自己改進(jìn)了一下,讓它不止16種方塊,寫的有點臃腫了,一些特殊情況可能會用,但不多,就不多解釋了

聊到deform了,那就再說一下deform和gmegabuf、voronoi的應(yīng)用,我們可以用deform實現(xiàn)和之前專欄類似的原理的改變地形的效果

把x和z對應(yīng)的高度統(tǒng)一到距離自己最近的樣點的坐標(biāo)值的高度

重疊

有時候我們想實現(xiàn)一些特殊的效果,比如在不同的樣點處生成一個圓,但是如果用gclosest進(jìn)行查找離自己最近樣點的索引值,就會導(dǎo)致原本是這個半徑范圍內(nèi)的位置但卻在另一個樣點的領(lǐng)域內(nèi),就會有voronoi的邊界,就比如

我們想讓這個圓上下重疊起來,不能用gclosest進(jìn)行索引的查找,需要一個個地使用索引的值,讓每個樣點都單獨畫一個自己為中心的圓

為什么用return而不是break,因為這里有多個個循環(huán),在里面的break并不能退出所有循環(huán),return 1就直接結(jié)束此位置的計算,可能會節(jié)省資源,返回1就會生成方塊,其他不滿足if條件的并完成了循環(huán)就自然返回了后面的0,即不生成。這是個我認(rèn)為一個很重要的思想,之后也會用到

下面是在此基礎(chǔ)上做的一些應(yīng)用

這個難點在于螺旋紋的部分,我把原來atan2()的只有2pi的范圍擴充了一下,并修復(fù)了缺失的部分厚度


與邊緣的距離

https://iquilezles.org/articles/voronoilines/

與邊緣的距離是指在voronoi圖中距離兩個區(qū)域的分界線的距離

一開始我只是想把前面的voronoi圖中加上分界線,思路是找到一個辦法計算出每個點距離本區(qū)域邊界的距離,辦法是判斷該點的上下左右周圍的點是否與它自己屬于同一個區(qū)域,即索引值是否一致,不一致就說明抵達(dá)了邊界,而這個與邊界的距離就是用于判斷的周圍的點與中心自身的距離。如圖

八個方向

藍(lán)色玻璃是要檢測是否位與邊緣相距d的點,綠色玻璃是以它為中心相距為d的點,左下角的綠色玻璃我換成了紅色玻璃,是與藍(lán)色不一個區(qū)域的點(白色和棕色)此時,中心的藍(lán)色就滿足給定的條件,這里就return 1

一開始我是這么寫的,四個方向很清晰但臃腫。為了減少字符數(shù)量以便在此基礎(chǔ)上實現(xiàn)更多效果就需要優(yōu)化簡短一下

檢測了八個方向

d為檢測半徑的長度,等同于最終想要邊界的厚度的一半。另外這個是有y方向上的檢測的,所以也能檢測立體的區(qū)域,只不過我們現(xiàn)在的樣點都在xz上而已。

如果要做反向效果,不能把I!=i變成I==i,因為我們的思路是只要有一個方向滿足I!=i就返回1,而不是要求所有方向都滿足I!=i。而是要變后面的,換成 if(I!=i){return 0}}1,這樣才有效果。還有如果要區(qū)分顏色,可以在返回1的前加個data=的表達(dá)式

//generate 251 n=100;d=0.01;i=gclosest(x,y,z,0,n,3)for(u=-1,1)for(v=-1,1)for(w=-1,1){I=gclosest(x+d*u,y+d*v,z+d*w,0,n,3)if(I!=i){return 0}}1

接著我們在d這個變量上搞點好玩的東西,比如讓它隨著坐標(biāo)的變化而變化

//generate 251 n=150;d=0.1*(max(sqrt(x^2+z^2)-0.5,0));i=gclosest(x,y,z,0,n,3)for(u=-1,1)for(v=-1,1)for(w=-1,1){I=gclosest(x+d*u,y+d*v,z+d*w,0,n,3)if(I!=i){return 0}}1

d=0.1*(max(sqrt(x^2+z^2)-0.5,0));d的大小與原點的歐式距離相關(guān),越遠(yuǎn)越大,與0進(jìn)行max()為了當(dāng)d成負(fù)數(shù)還是能檢測的,需要排除

//generate 251 n=150;d=0.1*(max(1-sqrt(x^2+z^2),0));i=gclosest(x,y,z,0,n,3)for(u=-1,1)for(v=-1,1)for(w=-1,1){I=gclosest(x+d*u,y+d*v,z+d*w,0,n,3)if(I!=i){return 0}}1

d=0.1*(max(1-sqrt(x^2+z^2),0));越遠(yuǎn)越小

//generate 251 n=200;d=0.08*(max(1-max(abs(x),abs(z)),0));i=gclosest(x,y,z,0,n,3)for(u=-1,1)for(v=-1,1)for(w=-1,1){I=gclosest(x+d*u,y+d*v,z+d*w,0,n,3)if(I!=i){return 0}}1

d=0.08*(max(1-max(abs(x),abs(z)),0));棋盤距離下的效果,等會就來說說距離公式

同時這個思路其實也可以不需要gmegabuf的參與,用原帶的voronoi()噪聲函數(shù)也能做到這種效果

為什么y沒有+d*v,是因為如果有的話它會計算y方向的差別,可能導(dǎo)致出現(xiàn)大塊的白塊,如果在三維的選區(qū)里是下面這樣的(用data來區(qū)分區(qū)域更明顯)

//generate 251 s=1;f=3;d=0.01;i=voronoi(s,x,y,z,f)for(u=-1,1)for(v=-1,1)for(w=-1,1){I=voronoi(s,x+d*u,y+d*v,z+d*w,f);if(I!=i){return 0}}data=i*16%16;1

以上是事先規(guī)定了與邊緣距離d的大小然后檢測判斷來實現(xiàn)的效果,如果我們想獲得這個距離并利用應(yīng)該怎么辦?這個小節(jié)的第一張圖是一個辦法,找到與自己最近的樣點與第二近的樣點,然后求出來距離,但是要找到與自己第二近的點需要把所有點都進(jìn)行一邊循環(huán),并且求距離的公式也會很長,所以不是很方便使用。

所以我想到的另一個思路是,還是檢測與自身相鄰d的點是否觸及另一個區(qū)域,但這個d需要從0開始一點點增加,直到觸及到另一個區(qū)域,這個時候的d就是大致的該點與最近邊緣的距離

我們在一系列操作后得到了我們想要的d,就能有更多好玩的效果了

首先可以把前面的給更新?lián)Q代一下

//g 251 n=100;a=0;i=gclosest(x,y,z,0,n,3);for(d=0;a==0;d+=.005){for(u=-1,1)for(w=-1,1){I=gclosest(x+d*u,y,z+d*w,0,n,3)a+=(I!=i)}}d>0.02

d>0.02

//g 251 n=200;a=0;i=gclosest(x,y,z,0,n,3);for(d=0;a==0;d+=.005){for(u=-1,1)for(w=-1,1){I=gclosest(x+d*u,y,z+d*w,0,n,3)a+=(I!=i)}}data=i/3%16;d>0.1*(1-sqrt(x^2+z^2))

d>0.1*(1-sqrt(x^2+z^2))

不是有了d了嗎,我們讓它與y結(jié)合一下:y+1<20*d

這是經(jīng)過材質(zhì)替換后的結(jié)果

顏色表(僅供參考)

覺得直直的不好看,可以在xz方向上加上不同種子的柏林噪聲

更多距離公式

https://www.desmos.com/calculator/yv4dycn9qo?lang=zh-CN

回到voronoi,我們用的找最近樣點的辦法是gclosest,本質(zhì)上是用的歐式距離sqrt(x^2+z^2)來計算的,但如果要用其他的距離公式,比如街區(qū)距離abs(x)+abs(z)或者棋盤距離max(abs(x),abs(z)),就不能在指令里出現(xiàn)gclosest,要手動用for循環(huán)找到最近的點

//generate 251 n=100;r=9;I=0;for(i=0,255)for(j=0;j<255*3;j+=3){k=i*255+j;if(k>n*3)break;X=x-gmegabuf(k)Z=z-gmegabuf(k+2);if((R=abs(X)+abs(Z))<r){r=R;I=k}}data=I%16;1

在R=后面的位置換上距離公式就行,還比如我之前在動態(tài)里發(fā)的三角形距離公式,當(dāng)然如果你有更簡潔的公式能分享就更好了Triangle Voronoi Borders

sqrt(X%5E2%2BZ%5E2)*cos(2%2F3*asin(cos(3%2F2*(atan2(Z%2CX)%2Bpi%2F3))))%2Fcos(pi%2F3)

規(guī)律樣點

那么如果我們的樣點排列的有規(guī)律會怎么樣,比如一個矩陣,或每行交錯,讓它的voronoi圖呈現(xiàn)蜂窩狀的六邊形

矩陣

n為你想每行的個數(shù),這個可以按需求修改,a=2/n就是對應(yīng)的邊長,不用改

蜂窩

參數(shù)與上同理

如果用這個狀態(tài)下的樣點排列,然后用三角形距離公式來畫voronoi,讓data按角度區(qū)分三個,就會呈現(xiàn)下面的效果

再試試前面的祥云紋樣

另外,我還想分享一個偶然試出來的簡單的六邊形距離公式

https://www.desmos.com/calculator/1wrrjojtvg?lang=zh-CN

我另一個動態(tài)蜂窩地形用到了這個,這里我是用了世界尺度

https://twitter.com/imhols1/status/1638459885850435584?s=20

分為4步,這只是個示例,當(dāng)你明白后會舉一反三

當(dāng)然,如果你并不想有這個距離的限制,只需要用原來的那個就行,注意你的賦值指令的坐標(biāo)的尺度是世界坐標(biāo)的還是-1~1的,加上-c或不加

多邊形頂點

等寬的輻條

限定樣點生成區(qū)域



三、其他

與邊界交點的距離

//g 251:1 s=1;f=5;d=0do{d+=0.005;A=voronoi(s,x+d,1,z,f)B=voronoi(s,x-d,1,z,f)C=voronoi(s,x,1,z+d,f)D=voronoi(s,x,1,z-d,f)}while((A==B)+(B==C)+(C==D)+(A==C)+(A==D)+(B==D)!=1);data=d*50

與第二近的樣點區(qū)域劃分

//generate 251 n=100;l=gclosest(x,y,z,0,n,3);I=0;for(i=0,255)for(j=0;j<255*3;j+=3){k=i*255+j;if(k>n*3)break;if(k==l)continue;a=(x-gmegabuf(I));b=(z-gmegabuf(I+2));I=(((x-gmegabuf(k))^2+(z-gmegabuf(k+2))^2)<a^2+b^2)?k:I;}data=I/3%16+.1

似乎和德羅內(nèi)三角網(wǎng)?(Delaunay)有關(guān)系

一種圓滑邊緣的辦法

//g 251 n=100;a=0;i=gclosest(x,y,z,0,n,3);for(d=0;a==0;d+=.005){for(u=-1,1)for(w=-1,1){I=gclosest(x+d*u,y,z+d*w,0,n,3)a+=(I!=i)}}r=sqrt((x-gmegabuf(i))^2+(z-gmegabuf(i+2))^2);data=i/3%16;d>max(.01,.8*(r-.1))

效果并不好,但盡力了

不相交最大圓

//g 251 n=200;i=gclosest(x,y,z,0,n,3);X=gmegabuf(i);Z=gmegabuf(i+2)r=1;for(l=0,255)for(k=0;k<255*3;k+=3){if((j=l*255+k)>n*3)break;if(j==i)continue;r=min(sqrt((gmegabuf(j)-X)^2+(gmegabuf(j+2)-Z)^2),r)}data=i/3%16;(x-X)^2+(z-Z)^2<(r/2)^2;

玻璃是為了更直觀

終于寫完了,你也看完了,有問題可以評論區(qū)問,也可以進(jìn)群問

群號:135176845


【Minecraft】worldedit|generate 深入解析gmegabuf()緩沖函數(shù)——從原理到應(yīng)用的評論 (共 條)

分享到微博請遵守國家法律
连平县| 鄂尔多斯市| 滨海县| 濮阳县| 黄山市| 古田县| 泽库县| 辉南县| 浏阳市| 开平市| 改则县| 江陵县| 平江县| 龙泉市| 尚义县| 米脂县| 佛山市| 安康市| 桂林市| 绥芬河市| 奈曼旗| 耿马| 新丰县| 高邮市| 汨罗市| 阿尔山市| 巴东县| 九台市| 西和县| 安溪县| 邢台市| 册亨县| 和龙市| 临沧市| 宝应县| 定远县| 芜湖县| 长寿区| 彩票| 鹿邑县| 洞头县|