twglを使ってコードを書きなおしたが、結局素のWebGL2.0で書き直すことにした。理由としては
- twglは初期設定を楽にする代わりに、レンダリング時の処理が複雑になっていて、パフォーマンス的に気になる
- twglはインターリーブ配列に対応していない
- 興味本位
の3点である。3番目が比重としては一番大きい気がする。
インターリーブに興味を持ったのは以下の記事を読んだから。 https://qiita.com/emadurandal/items/0bb83b545670475f51a3
今時であればインターリーブにしなくても速いらしいが。そういうわけでtwglの使用をやめ、素のWebGL2.0で書き直すことにしたのである。 といってもメインのシェーダーコードはtwglのサンプルコードそのまんまではあるのだが。行列ライブラリはglMatrixを使用した。
WebGL2.0は確かに冗長なコードにはなるが、慣れると面倒くささはかなり減った。WebGLはCっぽいAPIで、いじっているとなんかこう昔懐かしい感じがするのがよい。
このコードをもうちょっと整理したりして、元のゲームに適用しようと考えている。
Blenderからのメッシュデータをインターリーブ配列にしてJSONデータとしてエクスポートするコードも今回Pythonで書いた。Pythonでまともなコードを書くのはこれが初めてである。書くにあたってはthree.jsのエクスポータを参考にした。
# exports each selected object into its own file
# -*- coding: utf-8 -*-
import math
import mathutils
import bpy
import os
import json
print(os.getcwd())
import debug
#debug.start_debug()
XZ_Y = "XZ_Y"
X_ZY = "X_ZY"
XYZ = "XYZ"
_XY_Z = "_XY_Z"
def flip_axes (a, dir=XYZ):
"""
:function to swap vectors:
"""
if dir == XZ_Y:
a = (a[0], a[2], -a[1])
elif dir == X_ZY:
a = (a[0], -a[2], a[1])
elif dir == _XY_Z:
a = (-a[0], -a[1], a[2])
return (a[0], a[1], a[2])
# export to blend file location
basedir = os.path.dirname(bpy.data.filepath)
if not basedir:
raise Exception("Blend file is not saved")
obj = bpy.context.scene.objects.active
bpy.ops.object.mode_set(mode='OBJECT')
mesh = obj.to_mesh(bpy.context.scene, True, 'RENDER')
# 三角形化
backup = obj.data
hide = obj.hide
obj.data = mesh
obj.select = True
bpy.context.scene.objects.active = obj
bpy.ops.object.modifier_add(type='TRIANGULATE')
bpy.ops.object.modifier_apply(apply_as='DATA',modifier='Triangulate')
bpy.ops.object.modifier_add(type='EDGE_SPLIT')
bpy.context.object.modifiers['EdgeSplit'].use_edge_angle = False
bpy.context.object.modifiers['EdgeSplit'].use_edge_sharp = True
bpy.ops.object.modifier_apply(apply_as='DATA', modifier='EdgeSplit')
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.normals_make_consistent()
#bpy.ops.mesh.set_normals_from_faces()
bpy.ops.object.editmode_toggle()
obj.data = backup
# obj.select = False
rot = mathutils.Matrix.Rotation(-math.pi, 4, 'Z')
mesh.transform(rot * obj.matrix_world)
mesh.update(calc_tessface=True)
#mesh.calc_normals()
#bpy.ops.mesh.set_normals_from_faces()
mesh.calc_tessface()
scale_ = 1.0
mesh.transform(mathutils.Matrix.Scale(scale_, 4))
#print(len(mesh.vertices)*3,len(mesh.uv_layers[0].data),len(mesh.tessfaces)*3)
# mesh.update(calc_tessface=True)
# debug.start_debug()
objects = {}
data = []
float_size = 4
objects['position_size'] = 3
objects['texcoord_size'] = 2
objects['stride']= (objects['position_size'] + objects['texcoord_size']) * float_size
for (pos,uv) in zip(mesh.vertices,mesh.uv_layers[0].data):
uv = uv.uv
pos = pos.co
data.extend(pos)
data.extend(uv)
print(data)
objects['data'] = data
indices = []
indices_offset = 0
objects['indices'] = indices
drawinfos = []
objects['drawInfos'] = drawinfos
for i,material_ in enumerate(mesh.materials):
drawinfo = {}
material = {}
drawinfo['material'] = material
material['u_diffuse'] = list(material_.diffuse_color) + [1.0]
material['u_specular'] = list(material_.specular_color) + [1.0]
material['u_specularFactor'] = material_.specular_intensity
material['u_shininess'] = material_.specular_hardness
count = 0
# 頂点
for face in [f for f in mesh.tessfaces if f.material_index == i]:
indices.extend(face.vertices)
count += 3
drawinfo['count'] = count
drawinfo['offset'] = indices_offset
indices_offset += count * 2
drawinfos.append(drawinfo)
# JSONファイルとして保存
name = bpy.path.clean_name(obj.name)
path = os.path.join(basedir,name)
with open(path + '.json','w') as f:
json.dump(objects,f,ensure_ascii=False, indent=2, sort_keys=True, separators=(',', ': '));
#json.dump(objects,f);
print("written:", path + ".json")
ただまだきちんとアドオンとして動くようにはなっていないが。
で、今後であるが、元のゲームのコードに今回の成果を適用しつつ、AIを使って敵の動きを実装できないか研究することにした。このゲームは仮想画面320px x 240pxでローポリのキャラを動かすつもりなので、グラフィック処理の負荷はかなり低いと思っている。なのでJSであってもAIをリアルタイムで処理するためのリソースはあると思っていて、実装してみようと思っている。うまくすれば敵配置の省力化とか、敵の動きをリアルにできそうな気もするしね。WebGL2.0にしたのでGPGPUも多少やりやすいはずだし、それも活用すればJSでも十分動くものが作れるんではないかと。ただここでいうAIというのは、今流行っている深層学習とかではないけどね。
ゲームAIに興味を持ったのは以下の記事を読んだからだが。
http://news.denfaminicogamer.jp/interview/gameai_miyake
最後に、今の時点の成果物は以下の通り。
https://github.com/sfpgmr/www/tree/master/contents/test/twgl/