【改良版！】SDF EditorでShadertoyやGLSLのモデリングが劇的に簡単に！

***21年5月30日に、SDF Editorのソースコードが公開され、
より簡単にGLSL用のコードが出力できるようになりました。***

***下記記事をごらんいただき、本記事は下記記事の参考としてください。***

https://qiita.com/quittardis/items/5002dc5563b0aef2b472

###【改良版】SDF EditorでShadertoyやGLSLのモデリングが劇的に簡単に！

####21/05/25 この記事に続く完結編です->https://qiita.com/quittardis/items/488ec98983367ce1bd78

2日前にQuiitaにポストしたばかりhttps://qiita.com/quittardis/items/7a0d23359fcebaeb21a6
であるが、"SDF Editor" https://joetech.itch.io/sdf-editor
からなんとかGLSLコードをひねりだす工夫だが、前のより良いアプローチがあったので紹介する。

以前のバージョンでは、"SDF Editor"の出力する回転とトランスレーションの階層的なデータを
扱うことができなかったが、今回の"cnvSDF2.py"は"SDF Editor"の吐き出すjsonファイルを
リカーシブ(再帰的）に読み込んでSDFモデルにrotationとtranslationを階層的に配置できる。
また、楕円体以外のSDFを扱えるようにする拡張も簡単になった。

![heli.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/fdda04fb-0cea-5790-0f6f-866b5cdbda36.jpeg)

　これによって、上図のようなモデルのローターを回すとか、複雑なモデルをデザインしやすくなる。
下図は上のモデリング結果をShadertoyで表示した結果。

![shadertoy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430586/7bfd78e9-0df7-90ea-fbfa-969570c9bfa4.png)

以下にgitのリンクを示す。
https://github.com/ultrahamlet/cnvSDF2

リアルタイム表示　http://dcf.jp/viewSDF2.html

SDF chopper
Shadertoy.com
https://www.shadertoy.com/view/NtXGRH

まだ、ポストしていない最新版では楕円体以外のSDFプリミティブをハンドルできる。
"SDF assorted" with cnvSDF3 which can handle other SDF primitives
https://www.shadertoy.com/view/NlfGz4

以下はコンバーターで、sample.json　でセーブした結果を
python cnvSDF2.py
で表示プログラムの変数を得る。
詳しくはgitのReadmeを参考にしていただきたい。

cnvSDF2.py bug fixed 21/05/24 rot = rotate_x(v0)*rotate_y(v1)*rotate_z(v2) -> rot = rotate_xyz(v0,v1,v2)  gitを参照
bugfixed 21/05/21   rot = rotate_x(v0)*rotate_z(v2) -> rot = rotate_x(v0)*rotate_y(v1)*rotate_z(v2)

```
# 21/05/25 修正　　　rotate_xyz
import json
import numpy as np
# rotation matrix
def rotate_xyz(degx,degy,degz):
    # degree to radian
    r = np.radians(degx)
    cr = np.cos(r)
    sr = np.sin(r)
    r = np.radians(degy)
    cp = np.cos(r)
    sp = np.sin(r)
    r = np.radians(degz)
    cy = np.cos(r)
    sy = np.sin(r)

    R_xyz = np.matrix((
        (cy*cp, cy*sp*sr-sy*cr, cy*sp*cr+sy*sr),
        (sy*cp, sy*sp*sr+cy*cr, sy*sp*cr-cy*sr),
        (-sp, cp*sr, cp*cr)
    ))
    return R_xyz

global gcount
global pcount
gcount = 1
pcount = 0

def total(mf):
    #print(">>>> ",mf)
    global gcount
    global pcount
    if(len(mf) < 3):
        prm = 'primitive'
        spos = prim[pcount][1].replace('Vector3','vec3')
       
        #print(">>> ",strm)
        if prim[pcount][0] == 'pEllipsoid':
            #prm = 'vec3 ElRa_' + str(gcount) + ' = ' + spos + ';'
            # rotation string -> values
            prm = 'vec3 ElRa_' + str(gcount) + ' = ' + spos + ';'
        if prim[pcount][0] == 'pBox':
            prm = 'vec3 BoSi_' + str(gcount) + ' = ' + spos + ';'

        print(prm)
        gcount += 1
        pcount += 1
        return
    modi2 = mf[1]
    #print('>>>>>>>>>>>>>>>>>>>>>>>>>> ',modi2)
    if mf[0] == 'mRotation':
      
        rv = mf[2]     #totatuon value
        rt = 'mat3 RoIn_'+str(gcount)
        #
        t = rv.replace('Vector3(','')
        t = t.replace(')','')
        u = t.split(',')
        # get float rotation value
        v0 = -float(u[0])
        v1 = -float(u[1])
        v2 = -float(u[2])
        #rot = rotate_x(v0)*rotate_z(v2)
        rot = rotate_xyz(v0,v1,v2)
        #rot = rotate_x(v0)*rotate_y(v1)*rotate_y(v2)
        e = np.linalg.inv(rot) #inverse matrix
        # output matrix
        strm = str(e)
        strm = strm.replace('[[' ,'mat3(')
        strm = strm.replace(']]' ,');')
        strm = strm.replace(' ' ,'_')
        strm = strm.replace('\n' ,'')
        strm = strm.replace(']_[' ,'_')
        strm = strm.replace('_' ,',')
        strm = strm.replace('(,' ,'( ')
        #
        while  ',,' in strm:
            strm = strm.replace(',,' ,',')
        strm = strm.replace(',)' ,')')
        #
        print(rt,'=', strm)
    if mf[0] == 'mTranslation':
        
        spos = mf[len(mf)-1].replace('Vector3(','') 
        spos = spos.replace(')','')
        u = spos.split(',')
        v0 = -float(u[0])
        v1 = -float(u[1])
        v2 = -float(u[2])
        #print('--------------- tr',v0,v1,v2)
        rt = 'vec3 TrIn_'+str(gcount) #header
        rt = rt + ' = vec3(' + str(v0) +' ,'+ str(v1) + ' ,'  + str(v2) + ');'
        print(rt)
        #spos =  mf[len(mf)-1].replace('Vector3','vec3') + ';'
        #print(rt,'=', spos)
    gcount += 1
    
    for md in modi2:
       total(md)
   

# read json file
f = open('sample.json', 'r')
json_dict = json.load(f)
prim = json_dict['primitives']
j = 0

modi = json_dict['modifiers']
#print('>>>>>>>>>>>>>modifier init >>>>>>>>>>>>> ',modi)
print('//----------------------------------------------------------------')
for md in  modi:
    #print('>>>>>>>>>>>>>modifier>>>>>>>>>>>>> ',md)
    total(md)
    j += 1
print('//----------------------------------------------------------------')






```