1/1

はじめてのFujiyama Renderer その7

domeに張り付けた景色を回転させるシーンを作ってみた。pythonの繰り返しを利用している。10度ずつ回転させて36枚の静止画を生成してみます。

#!/usr/bin/env python

# povsphere02.py
# Copyright (c) 2011-2013 Hiroshi Tsubokawa
#export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.6/site-packages/:$HOME/Fujiyama-Renderer/bin/
import fujiyama
rot=0
for f in range(1,37):
si = fujiyama.SceneInterface()
#plugins
si.OpenPlugin('ConstantShader')
si.OpenPlugin('PlasticShader')

#Camera
si.NewCamera('cam1', 'PerspectiveCamera')
#si.SetSampleProperty3('cam1', 'translate', 0, 8, 8, 0)
#si.SetSampleProperty3('cam1', 'rotate', -45, 0, 0, 0)
#Calculate python fujicam.py 0 2 -10 0 1 0
si.SetSampleProperty3('cam1', 'rotate',-5.71, 0.00, 0.00,0)
si.SetSampleProperty3('cam1', 'rotate',0.00, 180.00, 0.00,0)
si.SetSampleProperty3('cam1', 'translate', 0.00, 2.00, -10.00,0)
si.SetProperty1('cam1', 'fov', 25)

#Light
si.NewLight('light1', 'SphereLight')
si.SetProperty3('light1', 'translate', -10, 10, -10)
si.SetProperty3('light1', 'scale', .5, .5, .5)
si.SetProperty1('light1', 'intensity', 1)

si.NewLight('light2', 'SphereLight')
si.SetProperty3('light2', 'translate', 10, 10, -10)
si.SetProperty3('light2', 'scale', .5, .5, .5)
si.SetProperty1('light2', 'intensity', 1)


si.SetProperty1('light1', 'sample_count', 16)

#Texture
si.NewTexture('tex1', '../mip/pisa.mip')

#Shader
si.NewShader('dome_shader', 'ConstantShader')
si.AssignTexture('dome_shader', 'texture', 'tex1')

si.NewShader('floor_shader', 'PlasticShader')
si.SetProperty3('floor_shader', 'diffuse', .2, .25, .3)

intensity = 0
si.NewShader('sphere_shader', 'PlasticShader')
si.SetProperty3('sphere_shader', 'diffuse', intensity, intensity, intensity)
si.SetProperty1('sphere_shader', 'ior', 40)

#Mesh
si.NewMesh('dome_mesh', '../mesh/dome.mesh')
si.NewMesh('floor_mesh', '../mesh/floor.mesh')
si.NewMesh('sphere_mesh', '../mesh/sphere.mesh')

#ObjectInstance
si.NewObjectInstance('dome1', 'dome_mesh')
si.SetProperty3('dome1', 'rotate', 0, rot, 0)
si.SetProperty3('dome1', 'scale', -3, 3, 3)
si.AssignShader('dome1', 'dome_shader')
rot=rot+10

si.NewObjectInstance('floor1', 'floor_mesh')
si.SetProperty3('floor1', 'scale', 50, 50, 50)
si.AssignShader('floor1', 'floor_shader')

si.NewObjectInstance('sphere1', 'sphere_mesh')
si.AssignShader('sphere1', 'sphere_shader')
si.SetProperty3('sphere1', 'translate', 0, 1, 0)
#si.SetProperty3('sphere1', 'scale', .5, .5, .5)

#ObjectGroup
si.NewObjectGroup('group1')
si.AddObjectToGroup('group1', 'sphere1')
si.AssignObjectGroup('sphere1', 'shadow_target', 'group1')
si.AssignObjectGroup('floor1', 'shadow_target', 'group1')

#FrameBuffer
si.NewFrameBuffer('fb1', 'rgba')

#Renderer
si.NewRenderer('ren1')
si.AssignCamera('ren1', 'cam1')
si.AssignFrameBuffer('ren1', 'fb1')
#si.SetProperty2('ren1', 'resolution', 640, 480)
si.SetProperty2('ren1', 'resolution', 320, 240)
si.SetProperty2('ren1', 'pixelsamples', 12, 12)

#Rendering
si.RenderScene('ren1')

#Output
si.SaveFrameBuffer('fb1', ("../sphere%03d" % f) + ".fb")

#Run commands
si.Run()
#si.Print()

ムービーはこちら
http://rman.sakura.ne.jp/pict/out_1.mp4


出力したイメージを変換して動画にするpythonスクリプト例

#fbpict.py
from subprocess import check_call

for i in range(1,37):
name="sphere"
check_call(["fb2exr", (name+"%03d" % i)+".fb", (name+"%03d" % i)+".exr"])
check_call(["exrtopng", (name+"%03d" % i)+".exr", (name+"%03d" % i)+".png"])


check_call(["ffmpeg", "-i", name+"%03d.png","-s", "320x240" ,"-vcodec", "mjpeg", "-sameq", "out.avi"])


ターミナルを複数起動してフレームごとにレンダリングさせるための
pythonスクリプト例。9スレッドで36フレームをそれぞれ4フレームずつレンダリングした。合計約28分。複数のFujiyama Rendererを立ち上げて実行できます。

あらかじめ、.bashrcにPYTHONPATHを記入しておいた方が良いです。

export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.6/site-packages/:$HOME/Fujiyama-Renderer/bin/

>
#start.py
from subprocess import check_call

check_call(["gnome-terminal", "-e", "python povsphere02a.py"])
check_call(["gnome-terminal", "-e", "python povsphere02b.py"])
check_call(["gnome-terminal", "-e", "python povsphere02c.py"])
check_call(["gnome-terminal", "-e", "python povsphere02d.py"])
check_call(["gnome-terminal", "-e", "python povsphere02e.py"])
check_call(["gnome-terminal", "-e", "python povsphere02f.py"])
check_call(["gnome-terminal", "-e", "python povsphere02g.py"])
check_call(["gnome-terminal", "-e", "python povsphere02h.py"])
check_call(["gnome-terminal", "-e", "python povsphere02i.py"])

ありがとうございます。Pythonの勉強になりますね。
  • -
  • -

はじめてのFujiyama Renderer その8 視野変換

とりあえず、カメラ位置と注視点位置から視野変換するPythonスクリプトをRenderMan資料placecam.cを参考に求めてみました。ありがとうございます。
まちがっているところもあるかもしれませんが、それっぽくカメラ位置が求められています。
Fujiyama Rendere0.1.1では、変換の順序は、プロパティを設定する順序に
影響しません。記述の順番は関係しません。
順序を設定するためのプロパティは'transform_order'、
'rotate_order'になり、デフォルトではそれぞれ、ORDER_SRTと
ORDER_XYZになっています。
変換はスケール、回転、移動の順に行われています。
回転はx,y,z軸回転の順に行われています。

以下のfujicam.py、Pythonスクリプトを実行し、出力された変換をコピペでシーンに張り付けてください。なおroll、coneangleは未対応です。

#!/usr/bin/env python
#fujicam.py
import sys
import os
from math import *

PI=3.1415926535897932


def usage():
print "usage: placecam pos_x pos_y pos_z aim_x aim_y aim_z"
print " [coneangle] [roll_angle]"
print " Calculate Fujiyama Renderer transforms needed for camera transform"
print " from light position to aim point with the given roll angle."
sys.exit(1)



def RiRotate(xangle, yangle, zangle):
if (fabs(xangle) > 0.001 or fabs(yangle) > 0.001 or fabs(zangle) > 0.001):
print "rotate %0.2f %0.2f %0.2f" % (xangle, yangle, zangle)



def RiTranslate(dx, dy, dz):
print "translate %0.2f %0.2f %0.2f" % (dx, dy, dz)


"""
/*
* AimZ(): rotate the world so the direction vector points in
* positive z by rotating about the y axis, then x. The cosine
* of each rotation is given by components of the normalized
* direction vector. Before the y rotation the direction vector
* might be in negative z, but not afterward.
*/
"""

def AimZ(direction):
global PI
if (direction[0]==0 and direction[1]==0 and direction[2]==0):
return
#/*
# * The initial rotation about the y axis is given by the projection of
# * the direction vector onto the x,z plane: the x and z components
# * of the direction.
# */
xzlen = sqrt(direction[0]*direction[0]+direction[2]*direction[2])
if (xzlen == 0):
if (direction[1] < 0):
yrot = 180
else:
yrot=0

else:
yrot = 180-180*acos(direction[2]/xzlen)/PI

# /*
# * The second rotation, about the x axis, is given by the projection on
# * the y,z plane of the y-rotated direction vector: the original y
# * component, and the rotated x,z vector from above.
# */
yzlen = sqrt(direction[1]*direction[1]+xzlen*xzlen)
xrot = 180*acos(xzlen/yzlen)/PI; #/* yzlen should never be 0 */

if (direction[1] > 0):
RiRotate(xrot, 0.0, 0.0)
else:
RiRotate(-xrot, 0.0, 0.0)

# /* The last rotation declared gets performed first */
if (direction[0] > 0):
RiRotate( 0.0, -yrot, 0.0)
else:
RiRotate( 0.0, yrot, 0.0)



def PlaceCamera(position, direction, roll):
RiRotate(0.0, 0.0, -roll)
AimZ(direction)
RiTranslate(position[0], position[1], position[2])


def main():
global PI
if len(sys.argv) < 7:
usage()
pos=[0,0,0]
aim=[0,0,0]
dir=[0,0,0]

pos[0] = float(sys.argv[1])
pos[1] = float(sys.argv[2])
pos[2] = float(sys.argv[3])
aim[0] = float(sys.argv[4])
aim[1] = float(sys.argv[5])
aim[2] = float(sys.argv[6])

if len(sys.argv) > 7:
coneangle = float(sys.argv[7])
else:
coneangle = 0.0

if len(sys.argv) > 8:
roll = float(sys.argv[8])
else:
roll = 0.0

print "position: %0.2f, %0.2f, %0.2f"% (pos[0], pos[1], pos[2])
print "aim: %0.2f, %0.2f, %0.2f"% (aim[0], aim[1], aim[2])
print "coneangle: %0.4f"% coneangle
print "roll: %0.2f\n" % roll

if (coneangle != 0.0):
fov = coneangle * 360.0 / PI
print "Projection \"perspective\" \"fov\" [%0.2f]" % fov


dir[0] = aim[0] - pos[0]
dir[1] = aim[1] - pos[1]
dir[2] = aim[2] - pos[2]

PlaceCamera(pos, dir, roll)


if __name__ == "__main__":
main()


いろいろと試したくなります。ありがとうございます。

2013/8/24 : coneangle箇所修正
  • -
  • -

1/1