LoginSignup
4
8

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-05-19

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

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

【改良版】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

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

shadertoy.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('//----------------------------------------------------------------')






4
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
8