Vizardの基本

WorldViz社が提供するPythonベースの仮想環境構築用ソフトウェア

はじめ方

1.WorldViz認証をうけ

  • WorldViz社のダウンロードサイトにアクセスする
  • メールアドレス・氏名などを入力して「Submit」する
  • 自動返信メールのリンクからインストーラをダウンロード

SSDを指定しインストール

  • 研究室で支給するPCにはHDDとSSDが搭載されています
  • ざっくり、SSDはプログラム実行用、HDDはデータ保管用です
  • 仮想環境関連のソフトウェアは、SSDにインストールしましょう
  • 逆に、個人のOneDriveなどはHDD側に紐づけたほうが効率的です

初期画面の構成を確認する

  • ツールバー
  • タブ
  • コードブラウザー
  • インタラクティブウィンドウ
  • リソースパネル
  • ヘルプ

公式チュートリアル

最低限のコードで動かしてみる

  • 下記のコードを入力し「F5」キーを押す 
####import vizviz.go()
piazza = viz.addChild('piazza.osgb')####
  • 「W」・「A」・「S」・「D」キーで視点を操作してみる

Wで前進、Sで後退、Aは左でDは右な!
公式チュートリアル

 学習の進め方

チュートリアルを使って学習

  • チュートリアルを開く
  1. ツールバーから、Help > Getting Started 
  2. 開いた画面で、View tutorial > Tutorials and Examples > Full Tutorials listとたどる
  3. Getting your feet wetから順番に最後まで、ひととおり学習する

※ たくさんあるように見えますが、3日あればすべて目を通せるはずです。※ Vizard関連の質問には、このチュートリアルを完了している前提で回答します。
  • Demoの使い方
  1. ツールバーから、Help > Getting Started 
  2. Demosのタブをクリックするとデモの一覧が表示される
  3. Run各デモの挙動を確認する
  4. Openで各デモのソースコードを確認する

  • Exampleの使い方
    1. ツールバーから、Help > Getting Started 
    2. Exampleのタブをクリックすると一覧が表示される
    3. 「Open」で各デモのソースコードを確認する
    4. 変更して挙動を確認したい場合は、ローカルに保存する
※ 元のファイルは絶対に変更しない(できない)

ヘルプとフォーラムで検索

  • ヘルプを開く
  1. ツールバーから、Help > Vizard Help 
  2. 左の検索窓に「lighting」などのワードを入力
  3. 検索結果を問題を解決しそうなトピックを探す
  4. トピックが難しければ、「Back」で最初から解説を読む

  • フォーラムの使い方
    1. ツールバーから、Help > Support Forum
    2. Searchタブを選択し、Human Verificationをチェック
    3. KeyWordを入力し問題を解決しそうなトピックを探す
    4. 研究室では有料アカウントでの質問も可能です

教養としてのPython

東京大学のPython講座

  • Vizardは、Pythonの知識がなくても何となく使えてしまいます。
  • でもVizardが吐き出すエラーコードをちゃんと読み解くにはPythonの知識は必要です。
  • 使う人から作る人になるためには、Pythonの言語構造の学習が近道です。

 コードを書きはじめる前に

.権利関連のクレジット挿入

研究室の機材を用いて開発したコードには、冒頭に下記のような権利関係のクレジットを必ず入れてください。
#####################################################################''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' VIZARD/PYTHON SCRIPT FOR IMMERSIVE 3D EXPERIMENTS.  ALL RIGHTS RESERVED YOSHIOKA LAB, CHIBA UNIVERSITY, JAPAN.
This Script Based on using the following equipment. - WorldViz Vizard 7.0 over - VIVE PRO EYE  - Cyberith Virtualizer Elite2'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''#####################################################################

.各種ショートカット

Alt + 3 : 一括コメントアウトAlt + 3 + Shift : 一括コメントアウト解除
Tab : 一括インデントTab + Shift : 一括インデント削除 F1  :  Vizard HelpF5  :  実行F11:  ファイルの場所を開くF12:  Vizard Directoryを開く
Ctrl + C : コピーCtrl + X : 切り取りCtrl + V : 貼り付けCtrl + Z : 元に戻すCtrl + Y : やり直す Ctrl + F   : 検索Ctrl + H  : 置換Ctrl + S  : 保存Ctrl + W : タブを閉じる
→  公式チュートリアル

基本のコード その1

HMDの接続関連

HTC Vive Pro Eyeとの接続
#Vizardはver6.0以降を使用すること
import vizimport steamvr
viz.go()piazza = viz.addChild('piazza.osgb')
########### SteamVR HMDの設定 #############import steamvrhmd = steamvr.HMD()viz.link(hmd.getSensor(), viz.MainView)

Oculus Rift & Oculus Questとの接続

  • 仮想環境の提示
import vizimport oculushmd = oculus.Rift()viz.link(hmd.getSensor(), viz.MainView)viz.go()
hmd = oculus.Rift()remote = hmd.getRemoteController()if remote.isButtonDown(oculus.BUTTON_REMOTE_UP): pos[1] += incif remote.isButtonDown(oculus.BUTTON_REMOTE_LEFT): pos[0] -= incif remote.isButtonDown(oculus.BUTTON_REMOTE_DOWN): pos[1] -= incif remote.isButtonDown(oculus.BUTTON_REMOTE_RIGHT): pos[0] += inc
Tobii Pro VR Integrationとの接続
import vizimport steamvr
# Launch graphics windowviz.setMultiSample(8)viz.go()
# Connect to Vive HMDhmd = steamvr.HMD()if not hmd.getSensor(): sys.exit('Vive not detected')
# Connect to Tobii eye trackertobii = viz.add('tobii.dle')eyeTracker = tobii.addEyeTracker()if not eyeTracker: sys.exit('Eye tracker not detected')
# Add indicators to place at gaze intersection pointpoint = vizshape.addSphere(radius=0.05, color=viz.GREEN)point.disable(viz.INTERSECTION)point.visible(False)
# Setup keyboard callbacks to display gaze point and calibratevizact.onkeydown('c', eyeTracker.calibrate)vizact.onkeydown('q', eyeTracker.cancelCalibration)vizact.onkeydown('g', point.visible, viz.TOGGLE)
360度立体視映像を投影する
#360度両眼立体視映像の準備#1 Vuze Cameraなどで360度両眼立体視映像を撮影する#2 Vuze VR Studioで「2D 360」形式を指定してレンダー #3 spherical_video_Right、**_Leftとして保存したとする
##########import vizviz.go()
########### SteamVR HMDの設定 #############import steamvrhmd = steamvr.HMD()navigationNode = viz.addGroup()viewLink = viz.link(navigationNode, viz.MainView)viewLink.preMultLinkable(hmd.getSensor()) 
####### 全周囲両眼立体視動画の再生設定 ####### def Video_Play(): ############# 再生する動画の読込と両眼天球への貼り付け ############ video_R_Eye = viz.addVideo('spherical_video_Right.mp4') #右目用動画の読込 video_L_Eye = viz.addVideo('spherical_video_Left.mp4') #左目用動画の読込
#Sphere displayed only for Right Eye sphere_R = vizshape.addSphere(flipFaces=True) sphere_R.texture(video_R_Eye) sphere_R.disable(viz.DEPTH_TEST) sphere_R.drawOrder(-100) sphere_R.disable(viz.RENDER_LEFT) viz.link(viz.MainView,sphere_R,mask=viz.LINK_POS)
#Sphere displayed only for Left Eyeimport vizshape sphere_L = vizshape.addSphere(flipFaces=True) sphere_L.texture(video_L_Eye) sphere_L.disable(viz.DEPTH_TEST) sphere_L.drawOrder(-100) sphere_L.disable(viz.RENDER_RIGHT)
viz.link(viz.MainView,sphere_L,mask=viz.LINK_POS) ################ 動画再生速度の変更モジュール ############### ### (UP&DOWN or MouseRight&Left or MouseWheelUp&Down) ###  def Speed_Increace(): WALK_SPEED[0] = WALK_SPEED[0] + 1/10. if WALK_SPEED[0] >= 4.3: WALK_SPEED[0] = 4.3 video_R_Eye.setRate(WALK_SPEED[0]) video_L_Eye.setRate(WALK_SPEED[0]) #KEY or Click or Wheel vizact.onkeydown(viz.KEY_UP,Speed_Increace) vizact.onmousedown(viz.MOUSEBUTTON_RIGHT,Speed_Increace) vizact.onwheelup(Speed_Increace) def Speed_Decrease(): WALK_SPEED[0] = WALK_SPEED[0] - 1/10. if WALK_SPEED[0] <= 0.1: WALK_SPEED[0] = 0.1 video_R_Eye.setRate(WALK_SPEED[0]) video_L_Eye.setRate(WALK_SPEED[0]) #KEY or Click or Wheel vizact.onkeydown(viz.KEY_DOWN,Speed_Decrease) vizact.onmousedown(viz.MOUSEBUTTON_LEFT,Speed_Decrease) vizact.onwheeldown(Speed_Decrease) ####################################################### ################ 動画再生 ################ import viztask yield viztask.waitKeyDown( ' ' ) #再生開始 print('Spacebar pressed') video_R_Eye.play()  video_L_Eye.play()  video_R_Eye.loop()  video_L_Eye.loop() import vizcam vizcam.PanoramaNavigate()
viztask.schedule( Video_Play())
VR上をキーボードの矢印キーで移動
import vizimport steamvr
# Launch graphics windowviz.setMultiSample(8)viz.go()# Create groundground =viz.addChild('ground.osgb')
# Connect to Vive HMDhmd = steamvr.HMD()if not hmd.getSensor(): sys.exit('Vive not detected')
# Setup navigation node and link to main viewnavigationNode = viz.addGroup()viewLink = viz.link(navigationNode, viz.MainView)viewLink.preMultLinkable(hmd.getSensor())
#Setup arrow key navigationMOVE_SPEED = 3.0def UpdateView(): yaw,pitch,roll = viewLink.getEuler() m = viz.Matrix.euler(yaw,0,0) dm = viz.getFrameElapsed() * MOVE_SPEED if viz.key.isDown(viz.KEY_UP): m.preTrans([0,0,dm]) if viz.key.isDown(viz.KEY_DOWN): m.preTrans([0,0,-dm]) if viz.key.isDown(viz.KEY_LEFT): m.preTrans([-dm,0,0]) if viz.key.isDown(viz.KEY_RIGHT): m.preTrans([dm,0,0]) navigationNode.setPosition(m.getPosition(), viz.REL_PARENT)vizact.ontimer(0,UpdateView)

HMD上 の視点を操作する_moveToメソッド

#PC画面上ではMainView、HMD上ではnavigationNodeを#操作することで視点を操作可能import vizimport vizshapeimport steamvr
hmd = steamvr.HMD()navigationNode = viz.addGroup()viewLink = viz.link(navigationNode, viz.MainView)viewLink.preMultLinkable(hmd.getSensor())
viz.go()
ground = viz.addChild('ground.osgb')ground.setPosition(0,0.01,0)
############       視点移動    ############POINT01 = (-4,0,15)POINT02 = (-20,0,15)
action1 = vizact.moveTo(POINT01,speed=1.5)action2 = vizact.moveTo(POINT02,speed=1.5)actions = vizact.sequence(action1,action2 ) def Move():#スペースキーでactionsを実行 navigationNode.addAction(actions)vizact.onkeydown(' ',Move) def Stop():#sでactionsを中断 navigationNode.clearActions()vizact.onkeydown('s',Stop)
def Trans():#'t'で指定した座標に転送 navigationNode.setPosition(25,0,25) vizact.onkeydown('t',Trans)

HMD上 の視点を操作する_moveメソッド

# SteamVR HMDを使用してユーザーの視点を制御するスクリプト# HMDのセンサー情報を事前に掛け合わせて、PointNodeとviz.MainViewをリンク# これにより等速前進しながらもユーザーの現実世界での動きを仮想空間に反映できる
import viz  # Vizardメインモジュールのインポートimport vizact # アクションを扱うモジュールのインポートimport steamvr # SteamVR HMDを操作するモジュール
hmd = steamvr.HMD() # HMDのセンサー情報を取得するため、インスタンスを作成PointNode = viz.addGroup()  # 座標基準点用のグループノードを作成viewLink = viz.link(PointNode, viz.MainView) # 座標基準点の動きをユーザーの視点にリンクさせるviewLink.preMultLinkable(hmd.getSensor()) # HMDの位置と方向情報を事前に掛け合わせる
viz.go() # Vizardのメインループを開始し、仮想環境をレンダリングviz.addChild('ground.osgb') # 地面のオブジェクトをシーンに追加
#######   視点の等速移動_頭部座標を反映  #######MOVE_SPEED = 1.4 # 移動速度を設定MOVE_DURATION = 10 # 移動時間を設定
# オブジェクトを前進させるアクションを作成(Z方向に等速移動)move_forward = vizact.move(0, 0, MOVE_SPEED, MOVE_DURATION)# moveメソッドの引数(x方向の移動速度、y方向の移動速度、Z方向の移動速度、移動する時間)
# アクションを含んだ関数を定義def Move_Forward(): # 関数名を、Move_Forwardと定義する    PointNode.addAction(move_forward) # PointNodeに対して前進アクションを追加
# スペースキーが押されたときに事前に定義した関数(Move_Forward)を呼び出すvizact.onkeydown(' ', Move_Forward)  

アイトラッキング

HTC Vive Pro Eyeの注視データ出力
#Vizardはver6.0以降を使用すること
import vizimport steamvr
viz.go()piazza = viz.addChild('piazza.osgb')
########### SteamVR HMDの設定 #############import steamvrhmd = steamvr.HMD()viz.link(hmd.getSensor(), viz.MainView)
########## EyeTrackingデータの出力 ############VivePro = viz.add('VivePro.dle') eyeTracker = VivePro.addEyeTracker()
def GAZEonTimer(num):                             gazeMat = eyeTracker.getMatrix()gazeMat.postMult(viz.MainView.getMatrix())line = gazeMat.getLineForward(1000)info = viz.intersect(line.begin, line.end)
GAZE_POSITION = info.pointGAZE_EULER = line.getEuler()
data = str(round(GAZE_POSITION[0],3))+','+str(round(GAZE_POSITION[1],3))+','+str(round(GAZE_POSITION[2],3))+','data += str(round(GAZE_EULER[0],3))+','+str(round(GAZE_EULER[1],3))+','+str(round(GAZE_EULER[2],3))+'\n'print(data)  
viz.callback(viz.TIMER_EVENT, GAZEonTimer)viz.starttimer(0,0.1,viz.FOREVER)
注視位置にオブジェクトを配置
#Vizardはver6.0以降を使用すること
import vizimport steamvrimport vizshape
viz.go()piazza = viz.addChild('piazza.osgb')
########### SteamVR HMDの設定 #############import steamvrhmd = steamvr.HMD()viz.link(hmd.getSensor(), viz.MainView)
########## EyeTrackingデータの出力 ############VivePro = viz.add('VivePro.dle') eyeTracker = VivePro.addEyeTracker()
#Add the fixation point modelpoint = vizshape.addSphere(radius=0.3, color=viz.GREEN)point.disable(viz.INTERSECTION)
def EyePosition_World(): gazeMat = eyeTracker.getMatrix() gazeMat.postMult(viz.MainView.getMatrix()) line = gazeMat.getLineForward(1000) info = viz.intersect(line.begin, line.end) point.setPosition(info.point)recordCallback = vizact.onupdate(0,EyePosition_World)

コントローラーの接続関連

Viveコントローラーとの接続 その2
import vizviz.go()World = viz.add('piazza.osgb')
################## VIVE ##################import steamvrhmd = steamvr.HMD()viz.link(hmd.getSensor(), viz.MainView)
######### コントローラー 複数台接続 #########Controller = steamvr.getControllerList()
for controller in steamvr.getControllerList(): # Create model for controller controller = controller controller.model = controller.addModel() controller.model.disable(viz.INTERSECTION) controller.distance = 1 viz.link(controller, controller.model)
def printer1(): print('Controller1_TriggerON')vizact.onsensordown(Controller[0], steamvr.BUTTON_TRIGGER, printer1)
def printer2(): print('Controller2_TriggerON')vizact.onsensordown(Controller[1], steamvr.BUTTON_TRIGGER, printer2)
#######################################def print_on_timer():Pad_x= Controller[0].getTrackpad() [0]Pad_y= Controller[0].getTrackpad() [1]
if Controller[0].getTrackpad() [0]> 0.5: print ('Pused Value:'), Controller[0].getTrackPad()[0]if Controller[0].getTrackpad() [1]> 0.5: print ('Pused Value:'), Controller[0].getTrackPad()[1]if Controller[0].getTrigger() > 0.5: print ('Pused Value:'), Controller[0].getTrigger()
vizact.ontimer(0.01,print_on_timer)
Viveコントローラーのトラックパッドで移動
import vizviz.go()World = viz.add('piazza.osgb')
################## VIVE ##################import steamvrhmd = steamvr.HMD()viz.link(hmd.getSensor(), viz.MainView)
######### コントローラー 複数台接続 #########Controller = steamvr.getControllerList()
for controller in steamvr.getControllerList(): # Create model for controller controller = controller controller.model = controller.addModel() controller.model.disable(viz.INTERSECTION) controller.distance = 1 viz.link(controller, controller.model)
###############  トラックパッドで移動  ############### MOVE_SPEED = 0.5 def UpdateView():yaw,pitch,roll = viewLink.getEuler()m = viz.Matrix.euler(yaw,0,0)dm = viz.getFrameElapsed() * MOVE_SPEED 
if Controller[0].getTrackpad()[1] > 0.7: #トラックパッド上を触って前進print ('Pused Value:'), Controller[0].getTrackpad()m.preTrans([0,0,dm])navigationNode.setPosition(m.getPosition(), viz.REL_PARENT)                       if Controller[0].getTrackpad()[1] < -0.2: #トラックパッド下を触って後退print ('Pused Value:'), Controller[0].getTrackpad()m.preTrans([0,0,-dm])navigationNode.setPosition(m.getPosition(), viz.REL_PARENT)       vizact.ontimer(0.01,UpdateView) ####################################################
Viveコントローラー2台のトリガーで移動
import vizimport steamvr
# Launch graphics windowviz.setMultiSample(8)viz.go()# Create groundground =viz.addChild('ground.osgb')
# Connect to Vive HMDhmd = steamvr.HMD()if not hmd.getSensor(): sys.exit('Vive not detected')
# Setup navigation node and link to main viewnavigationNode = viz.addGroup()viewLink = viz.link(navigationNode, viz.MainView)viewLink.preMultLinkable(hmd.getSensor())
###############  move  ############### Controller = steamvr.getControllerList() for controller in steamvr.getControllerList(): # Create model for controller controller = controller controller.model = controller.addModel() controller.model.disable(viz.INTERSECTION) controller.distance = 1.0 viz.link(controller, controller.model) MOVE_SPEED = 3.0def UpdateView(): yaw,pitch,roll = viewLink.getEuler() m = viz.Matrix.euler(yaw,0,0) dm = viz.getFrameElapsed() * MOVE_SPEED if Controller[0].getTrigger(): m.preTrans([0,0,dm]) navigationNode.setPosition(m.getPosition(), viz.REL_PARENT)vizact.ontimer(0,UpdateView)
def UpdateView(): yaw,pitch,roll = viewLink.getEuler() m = viz.Matrix.euler(yaw,0,0) dm = viz.getFrameElapsed() * MOVE_SPEED if Controller[1].getTrigger(): m.preTrans([0,0,-dm]) navigationNode.setPosition(m.getPosition(), viz.REL_PARENT)vizact.ontimer(0,UpdateView)
Viveコントローラー操作によるオブジェクトの移動
### モジュールをインポート ###import vizimport vizshape  import vizact
### 実行 ###viz.fov(80)      viz.MainView.setPosition([0, 1.5, 0]) viz.go()        ground = viz.addChild('ground.osgb')
### リストで初期値を設定(global関数を使わずに済む) ###Height = [0] Height[0] = 1.25  #上下の初期値
Side = [0] Side[0] = 0       #左右の初期値
Distance = [0] Distance[0] = 2.5#奥行の初期値### 壁 ###Wall = vizshape.addBox(size = [5.0,2.5,0.1])Wall.setPosition(Side[0],Height[0],Distance[0])#設定した初期値に壁を配置############################## VIVE HMD ################################import steamvr
# Setup SteamVR HMDhmd = steamvr.HMD()if not hmd.getSensor(): sys.exit('SteamVR HMD not detected')
# Setup navigation node and link to main viewnavigationNode = viz.addGroup()viewLink = viz.link(navigationNode, viz.MainView)viewLink.preMultLinkable(hmd.getSensor())
######################### VIVE CONTROLLER ##############################VIVE左右コントローラーのリスト作成 Controller = steamvr.getControllerList()#Add controllersfor controller in steamvr.getControllerList():
# Create model for controller controller.model = controller.addModel(parent=navigationNode) if not controller.model: controller.model = viz.addGroup(parent=navigationNode) controller.model.disable(viz.INTERSECTION) viz.link(controller, controller.model)
####  コントローラー0による操作(なめらかな操作などに応用) ###########def print_on_timer(): Pad_x= Controller[0].getTrackpad() [0]#Pad_xはTrackPadの左右方向の反応値(-1から1) Pad_y= Controller[0].getTrackpad() [1]#Pad_yはTrackPadの上下方向の反応値(-1から1)
if Controller[0].getTrackpad() [0]> 0.5:#TrackPadの右を押すと右に移動 Side[0] += 0.01 Wall.setPosition(Side[0],Height[0],Distance[0]) print ('con_0 Pad_x value:' , Controller[0].getTrackpad()[0]) if Controller[0].getTrackpad() [0]< -0.5:#TrackPadの左を押すと左に移動 Side[0] -= 0.01 Wall.setPosition(Side[0],Height[0],Distance[0]) print ('con_0 Pad_x value:' , Controller[0].getTrackpad()[0]) if Controller[0].getTrackpad() [1]> 0.5:#TrackPadの上を押すと上に移動 Height[0] += 0.01 Wall.setPosition(Side[0],Height[0],Distance[0]) print ('con_0 Pad_y value:' , Controller[0].getTrackpad()[1]) if Controller[0].getTrackpad() [1]< -0.5:#TrackPadの下を押すと下に移動 Height[0] -= 0.01 Wall.setPosition(Side[0],Height[0],Distance[0]) print ('con_0 Pad_y value:' , Controller[0].getTrackpad()[1]) if Controller[0].getTrigger() > 0.5:#Triggerを押すと奥に移動 Distance[0] += 0.01 Wall.setPosition(Side[0],Height[0],Distance[0]) print ('con_0 Tri Value:', Controller[0].getTrigger()) vizact.ontimer(0.01,print_on_timer)
#####   コントローラー1による操作(ON,OFFの切り替えなどに応用) ##########
#TrackPadに触れると壁を初期位置に戻すdef Reset(): Side[0] = 0 Height[0] = 1.25 Distance[0] = 2.5 Wall.setPosition(Side[0],Height[0],Distance[0]) print ('con_1 Pad ON:')vizact.onsensordown(Controller[1], steamvr.BUTTON_TRACKPAD, Reset)#Triggerを押すたびに壁が手前に動く def pull(): Distance[0] -= 0.1 Wall.setPosition(Side[0],Height[0],Distance[0]) print ('con_1 Tri ON:')vizact.onsensordown(Controller[1], steamvr.BUTTON_TRIGGER, pull)
Viveコントローラーとオブジェクトの位置をリンク
###ライブラリ###import viz import vizshapeimport timeimport steamvr###基本設定###viz.go()viz.fov(80)viz.MainView.setPosition(0,1.2,0)viz.setMultiSample(4)viz.clearcolor(0.62,0.8,0.88)  
hmd = steamvr.HMD()viz.link(hmd.getSensor(), viz.MainView)
###地面の作成###ground = vizshape.addBox(color = viz.WHITE)ground.setScale(50,0.1,50)ground.setPosition(0,-0.05,0)ground.disable(viz.LIGHTING)
#鉄パイプの作成Pipe1 = vizshape.addCylinder(height = 1.8,radius = 0.015,topRadius = None,bottomRadius = None,axis = vizshape.AXIS_Y,slices = 20,bottom = False,top = False)Pipe1.color(0.7,0.7,0.7)Pipe1.disable(viz.LIGHTING)Pipe1.setPosition(0,0.1,0)Pipe1.setEuler(90,90,0)
#鉄パイプ中央に目印作成Ring = vizshape.addCylinder(height = 0.05,radius = 0.016,topRadius = None,bottomRadius = None,axis = vizshape.AXIS_Y,slices = 20,bottom = False,top = False,color = viz.BLUE)Ring.setParent(Pipe1)
###############    コントローラーの設定(VR用)       ##########
Controller = steamvr.getControllerList()
for controller in steamvr.getControllerList(): controller = controller controller.model = controller.addModel() controller.model.disable(viz.INTERSECTION) controller.distance = 1 link = viz.link(controller, Pipe1)       #コントローラーの位置とパイプの位置をリンクさせる link.preEuler([0, 105, 0])               #コントローラーとパイプの角度の関係を設定(コントローラ-を地面に置いたときにパイプが平らに置けるように)
Viveコントローラーで地面をポイントする
### 各種インポート ###import vizimport vizshapeimport mathimport steamvr
viz.go()viz.setMultiSample(4)viz.fov(80)
# Setup SteamVR HMDhmd = steamvr.HMD()if not hmd.getSensor(): sys.exit('SteamVR HMD not detected')
# Setup navigation node and link to main viewnavigationNode = viz.addGroup()viewLink = viz.link(navigationNode, viz.MainView)viewLink.preMultLinkable(hmd.getSensor())
############### コントローラのセット ###########################Controller = steamvr.getControllerList()
for controller in steamvr.getControllerList(): # Create model for controller controller = controller controller.model = controller.addModel() controller.model.disable(viz.INTERSECTION) controller.distance = 1 viz.link(controller, controller.model)
#################### 地面の生成 ################ground =vizshape.addBox(size=[16,0.1,200],pos=[0,0,0])
############# 動くボールをつくる ##################ball = vizshape.addSphere(radius=0.05,color=viz.GREEN)ball.setPosition(0,0.1,0)def updateDirect():
X = viz.MainView.getPosition()[0] Z = viz.MainView.getPosition()[1] Y = viz.MainView.getPosition()[2] height = Controller[0].getPosition()[1] Yaw   = Controller[0].getEuler()[0] Pitch = Controller[0].getEuler()[1] Roll  = Controller[0].getEuler()[2]
B1 = ball.getPosition()[0] B2 = ball.getPosition()[1] B3 = ball.getPosition()[2] tp =  Controller[0].getTrackpad()[1] tpp = Controller[0].getTrackpad()[0] #コントローラーのトリガーを押しながら地面を指し、ボールを移動させる if Controller[0].getTrigger() > 0.5: ball.setPosition([(height / math.tan((Pitch)*math.pi/180)) * math.sin(Yaw*math.pi/180)+X, 0.1 , height / math.tan((Pitch)*math.pi/180)* math.cos(Yaw*math.pi/180)+Y]) #操作がないときボールに与えられたすべてのアクション(直進)を一旦停止 elif -0.5< tp <0.5 and -0.5< tpp <0.5 : ball.clearActions() #トラックパッドで細かい調節も可能 else: if tp >0.5: move = vizact.move(0,0,0.5,0.1) if tpp >0.5: move = vizact.move(0.5,0,0,0.1) if tp < -0.5: move = vizact.move(0,0,-0.5,0.1) if tpp < -0.5: move = vizact.move(-0.5,0,0,0.1) ball.add(move) #コントローラーのGRIPを押してボール位置をリセットする def Ball_Reset(): ball.setPosition(0, 0.1, 0) vizact.onsensordown(Controller[0], steamvr.BUTTON_GRIP, Ball_Reset) #ボールの位置座標を出力 print(round(B1,2),round(B2,2),round(B3,2))
vizact.onupdate(0, updateDirect)

トラッカーの接続関連

Viveトラッカーとの接続
import vizimport steamvr
viz.go()piazza = viz.addChild('piazza.osgb')
########### SteamVR HMDの設定 #############import steamvrhmd = steamvr.HMD()viz.link(hmd.getSensor(), viz.MainView)
########## トラッカーのデータ出力 ############tracker1 = steamvr.getTrackerList()[0]tracker2 = steamvr.getTrackerList()[1]
def TrackeronTimer(num):Tracker1_pos = tracker1.getPosition()Tracker2_pos = tracker2.getPosition()
data   = str(round(Tracker1_pos[0],3))+'\t'+str(round(Tracker1_pos[1],3))+'\t'+str(round(Tracker1_pos[2],3))+'\t'data += str(round(Tracker2_pos[0],3))+'\t'+str(round(Tracker2_pos[1],3))+'\t'+str(round(Tracker2_pos[2],3))+'\n'print(data)
viz.callback(viz.TIMER_EVENT, TrackeronTimer)

Viveトラッカーによる歩行

import vizimport vizactimport vizshapeimport viztrackerimport mathimport timeimport viztask
viz.go()viz.setMultiSample(4)viz.fov(80)
###########VIVE##################import steamvr
# Setup SteamVR HMDhmd = steamvr.HMD()if not hmd.getSensor(): sys.exit('SteamVR HMD not detected')
# Setup navigation node and link to main viewnavigationNode = viz.addGroup()viewLink = viz.link(navigationNode, viz.MainView)viewLink.preMultLinkable(hmd.getSensor()) #####################  視点の移動制御  ###################### global View_SPD #関数をまたいで使用できるようにボールスピード(View_SPD)をグローバル変数に設定View_SPD = 0.0000001 #View_SPDの初期値を0.1M/Sに設定view = viz.MainView##########VIVE################## R_foot =vizshape.addCylinder(0.10,0.03)L_foot =vizshape.addCylinder(0.10,0.03)
tracker1 = steamvr.getTrackerList()[0]tracker2 = steamvr.getTrackerList()[1]
viz.link(tracker1,R_foot)viz.link(tracker2,L_foot)###################################足踏みで進む##################################################def footstamp(): L_foot_pos = tracker1.getPosition() R_foot_pos = tracker2.getPosition() L_z= L_foot_pos[1] R_z= R_foot_pos[1] print(L_z, R_z) view = viz.MainView #画面表示の主視点をviewと名付ける global View_SPD #関数をまたいで使用できるようにボールスピード(View_SPD)をグローバル変数に設定 V=0.15 if L_z <= V and  R_z <= V: global View_SPD view.clearActions() #ボールに与えられたすべてのアクション(直進)を一旦停止 navigationNode.clearActions() View_POS = viz.MainView.getPosition() curr_time = time.clock() #現在の時間をcurr_timeとする print(round(curr_time,2),round(View_POS[2],2),round(View_SPD,2)) #時刻、位置、スピードをインタラクティブに表示 if L_z > V or  R_z > V: global View_SPD View_SPD = 1.0 #グローバル変数View_SPDを2.0m/sに変更(加速) View_POS = viz.MainView.getPosition() moveTWD = vizact.moveTo(pos=[0,0,50],speed=1.5) #加速したView_SPDで直進する運動を作成 view.addAction(moveTWD) #主視点に”moveTWD”を適用 navigationNode.addAction(moveTWD) curr_time = time.clock() #現在の時間をcurr_timeとする print(round(curr_time,2),round(View_POS[2],2),round(View_SPD,2)) #時刻、位置、スピードをインタラクティブに表示
vizact.ontimer(0,footstamp)  #足の判定を呼び続ける


データの計測と出力

外部ファイル(.txt)へのデータの出力 →WorldVizの解説
import vizimport math #roundを使うために必要 import datetime #ファイル名に日付を入れるのに必要import time #経過時間を計測するのに必要
viz.go()piazza = viz.addChild('piazza.osgb')

#### 被験者番号の設定SUBJECT_NUMBER = 1 #被験者番号の入力
#### データ出力先のファイルの指定(なければ作成)FileName='Experiment'+datetime.datetime.today().strftime("%Y%m%d")+'_Sub'+str(SUBJECT_NUMBER)+'.txt'expelimental_data = open(FileName,'a') 
#### ヘッダー(第一行)の挿入 Header = 'Sub'+'Lap'+'\t'+'PosX'+'\t'+'PosY'+'\t'+'PosZ'+'\t'+'Yaw'+'\t'+'Pitch'+'\t'+'Roll'+'\n'expelimental_data.write(Header)
#### タイマーの設定(複数のタイマーを同時に走らすこともできる) TIMER_ID = 1 #タイマーはID番号で管理 TIMER_PERIOD = 0.1 #出力間隔[s]
#### データ出力START_TIME =time.time() #プログラムを動かしはじめた時刻を記録
def onTimer(num): PASSED_TIME = time.time()-START_TIME POS = viz.MainView.getPosition() ORI = viz.MainView.getEuler() data  = str(SUBJECT_NUMBER)+'\t'+str(round(PASSED_TIME,1))+'\t' data += str(round(POS[0],2))+'\t'+str(round(POS[1],2))+'\t'+str(round(POS[2],2))+'\t' data += str(round(ORI[0],2))+'\t'+str(round(ORI[1],2))+'\t'+str(round(ORI[2],2))+'\n' print(data) expelimental_data.write(data) viz.starttimer(TIMER_ID, TIMER_PERIOD, viz.PERPETUAL)viz.callback(viz.TIMER_EVENT,  onTimer)
外部ファイル(.csv)へのデータの出力 
import vizimport math #roundを使うために必要 import datetime #ファイル名に日付を入れるのに必要import time #経過時間を計測するのに必要
viz.go()piazza = viz.addChild('piazza.osgb')

#### 被験者番号の設定SUBJECT_NUMBER = 1 #被験者番号の入力
#### データ出力先のファイルの指定(なければ作成)FileName='Experiment'+datetime.datetime.today().strftime("%Y%m%d")+'_Sub'+str(SUBJECT_NUMBER)+'.csv'expelimental_data = open(FileName,'a') 
#### ヘッダー(第一行)の挿入 Header = 'Sub'+','+'Lap'+','+'PosX'+','+'PosY'+','+'PosZ'+','+'Yaw'+','+'Pitch'+','+'Roll'+'\n'expelimental_data.write(Header)
#### タイマーの設定(複数のタイマーを同時に走らすこともできる) TIMER_ID = 1 #タイマーはID番号で管理 TIMER_PERIOD = 0.1 #出力間隔[s]
#### データ出力START_TIME =time.time() #プログラムを動かしはじめた時刻を記録
def onTimer(num): PASSED_TIME = time.time()-START_TIME POS = viz.MainView.getPosition() ORI = viz.MainView.getEuler() data  = str(SUBJECT_NUMBER)+','+str(round(PASSED_TIME,1))+',' data += str(round(POS[0],2))+','+str(round(POS[1],2))+','+str(round(POS[2],2))+',' data += str(round(ORI[0],2))+','+str(round(ORI[1],2))+','+str(round(ORI[2],2))+'\n' print(data) expelimental_data.write(data) viz.starttimer(TIMER_ID, TIMER_PERIOD, viz.PERPETUAL)viz.callback(viz.TIMER_EVENT,  onTimer)
時間の計測
"""""""""""""""""""""""""""""""""""""""旧バージョンではimport time によりモジュールをインポートし、viz.tick()の代わりにtime.clock()を用いた。vizard7では使用できなくなっている。"""""""""""""""""""""""""""""""""""""""###   モジュールのインポート   ###import viz import vizshapeimport csv
###      基本設定    ###viz.go()viz.fov(80)viz.clearcolor(viz.WHITE)###   時間計測の準備   ###
#start_timeにはプログラム開始時からの時間が記録されるstart_time = viz.tick() #時間リセット用リストの定義reset_time = [0]reset_time[0] = 0#Timerの設定TIMER_ID = 1 #データ保存タイマーIDTIMER_PERIOD = 0.1 #データ保存間隔[s]
###    地面の作成     ###ground = vizshape.addBox(color = viz.WHITE)ground.setScale(50,0.1,50)ground.setPosition(0,-0.05,0)
###   Excelデータの作成    ###expelimental_data = open('timer'+'.csv', 'a') 
#ヘッダーの入力header =  'time'+'\n'expelimental_data.write(header) ####    0.1秒ごとに行う処理    ####
def onTimer(num):  curr_time = viz.tick() - reset_time[0] #現在時間ーリセット時間(初期値0)
data =  str(round(curr_time,1))+'\n'    #curr_timeを小数第1まで書き込む expelimental_data.write(data) print(data) ### タイマーを開始しデータを記録 ### viz.callback(viz.TIMER_EVENT, onTimer)viz.starttimer(TIMER_ID, TIMER_PERIOD, viz.PERPETUAL)
#スペースキーを押した時間がreset_time[0]となるdef ResetTimer(): reset_time[0] = viz.tick()vizact.onkeydown(' ',ResetTimer)

鑑賞時間 の計測

############   モジュールのインポート  #######import vizimport vizshapeimport vizcamimport math##########  目標点の設定   ###########
n = 4                   #目標点の個数を設定Area_MAX = 2            #counterが反応する目標点からの最大距離(m)Deg = 30                #counterが反応する角度(目標点正面を向くと0) Points = []Counts = []for x in range(n): Points.append(x) Counts.append(x) Counts[x] = 0  #nで指定した個数だけ目標点の座標を記すPoints[0] = (2,9)     #x=2(左右), y=9(奥行)Points[1] = (1,6)      Points[2] = (-3,5)    Points[3] = (0,3)      
#############    周囲環境   ##################viz.go()viz.fov(100)#HMDをつなぐときはコメントアウトground = viz.addChild('ground.osgb')
#目標点の位置に円柱を配置して視覚化Pole_1 = vizshape.addCylinder(height=3,radius=0.1,pos=(Points[0][0],1.5,Points[0][1]),color=viz.RED)   #高さ3m,半径0.1mPole_2 = vizshape.addCylinder(height=3,radius=0.1,pos=(Points[1][0],1.5,Points[1][1]),color=viz.BLUE)Pole_3 = vizshape.addCylinder(height=3,radius=0.1,pos=(Points[2][0],1.5,Points[2][1]),color=viz.GREEN)Pole_4 = vizshape.addCylinder(height=3,radius=0.1,pos=(Points[3][0],1.5,Points[3][1]),color=viz.WHITE)
#############    0.1秒ごとに行う処理   ##################def Counter(num):   POS_HEAD = viz.MainView.getPosition() ORI_HEAD = viz.MainView.getEuler() X = POS_HEAD[0] Y = POS_HEAD[2] A = ORI_HEAD[0]#被験者が向いている角度(yaw)
for k in range(n): #目標点と自分を結ぶ直線が、Y軸に直行なベクトル(0,1)となす角を求める。 cosP = (Points[k][1]-Y)/math.sqrt(pow(Points[k][0]-X,2)+pow(Points[k][1]-Y,2))  #目標点との位置関係によってPの符号が変わる if Points[k][0]<X: P = -math.degrees(math.acos(cosP)) else: P = math.degrees(math.acos(cosP)) #被験者がエリア内にいるとき if math.sqrt(pow(Points[k][0]-X,2)+pow(Points[k][1]-Y,2))<Area_MAX: #被験者が見ている方向が目標点の方向±Deg°になったらカウントする if -(180-Deg/2)<=A<=(180-Deg/2) and  A-Deg<=P<=A+Deg: Counts[k]+=0.1 if A<-(180-Deg/2) or (180-Deg/2)<A: if A-Deg<=P<=A+Deg or abs(A)-Deg<=P<=abs(A)+Deg: Counts[k]+=0.1 data  = 'count1'+'\t'+str(round(Counts[0],2))+'\t'+'count2'+'\t'+str(round(Counts[1],2))+'\t'+'count3'+'\t'+str(round(Counts[2],2))+'\t'+'count4'+'\t'+str(round(Counts[3],2))+'\n' print(data) viz.callback(viz.TIMER_EVENT, Counter)viz.starttimer(1, 0.1, viz.PERPETUAL)#############   キーボード操作   ###############keyCam = vizcam.KeyboardCamera()          #wasdキーで空間を動かす

基本的なオブジェクトの配置と調整

白い部屋 (addBoxの基本)

### 必要なモジュールをインポートする ###import vizshape  #壁などの立体を作成するために必要
### 実行 ###viz.fov(80)      #PC画面上での視野角が80度になる(VR使用時はコメントアウト)viz.MainView.setPosition([0, 1.5, 0])  #PC画面上での初期視点高さを1.5mに設定viz.go()         #出力結果を画面に表示するために必須
### 前の壁 ###Wall_front= vizshape.addBox(size = [5.0,2.5,0.1])#横幅5m,高さ2.5m,厚さ0.1mWall_front.setPosition(0,1.25,2.5)#壁の中心の座標を指定(高さ1.25m,前方2.5m)
### 後の壁 ###Wall_back= vizshape.addBox(size = [5.0,2.5,0.1])#横幅5m,高さ2.5m,厚さ0.1mWall_back.setPosition(0,1.25,-2.5)#壁の中心の座標を指定(高さ1.25m,後方2.5m)
### 右の壁 ###Wall_right= vizshape.addBox(size = [0.1,2.5,5.0])#厚さ0.1m,高さ2.5m,奥行5mWall_right.setPosition(2.5,1.25,0)#壁の中心の座標を指定(高さ1.25m,右側2.5m)
## 左の壁 ###Wall_left= vizshape.addBox(size = [0.1,2.5,5.0])#厚さ0.1m,高さ2.5m,奥行5mWall_left.setPosition(-2.5,1.25,0)#壁の中心の座標を指定(高さ1.25m,左側2.5m)
## 天井 ###Ceiling = vizshape.addBox(size = [5,0.1,5.0])#厚さ0.1m,5m×5mCeiling.setPosition(0,2.55,0)#天井の中心の座標を指定(高さ2.55m※厚さを考慮)Ceiling.disable(viz.LIGHTING)#ライティングをオフ(どの角度でみても色が変わらない)
##  床  ###slab1 = viz.addTexQuad(size = [5,5])#5m×5m(addTexQuadは厚さがない)slab1.setEuler([0,90,0])#地面に水平にさせるために回転させるslab1.disable(viz.LIGHTING)#ライティングをオフ(どの角度でみても色が変わらない)


円柱 (addCylinderの基本)

import vizimport vizshapeimport steamvr
# Launch graphics windowviz.setMultiSample(8)viz.go()
#hmd = steamvr.HMD()## Setup navigation node and link to main view#navigationNode = viz.addGroup()#viewLink = viz.link(navigationNode, viz.MainView)#viewLink.preMultLinkable(hmd.getSensor())
render1 = vizshape.addCylinder(height=10,radius=0.25)render1.color(r=0.83,g=0.6, b=0.85) render1.setPosition((0,0.0, 20))
render2 = vizshape.addCylinder(height=10,radius=0.25)render2.color(r=0.83,g=0.6, b=0.85)render2.setPosition((-3,0.0, 10))
render3 = vizshape.addCylinder(height=10,radius=0.25)render3.color(r=0.83,g=0.6, b=0.85)render3.setPosition((3,0.0, 10))

for文による繰り返し(box大量配置)

import vizimport vizshapeviz.go()
########## ボックス #############Wide = 4 #道幅x = 2    #左右に設置する個数y = 2    #前後に設置する個数
x_start = -(20+Wide)*x+10+Wide/2y_start = -(20+Wide)*y+10
for X in range (2*x):for Y in range (2*y): Box_FrontRight = vizshape.addBox(size=[20,3,20],color=[0.8,0.8,0.8]) # Box_FrontRight.disable(viz.LIGHTING) Box_FrontRight.setPosition(x_start+(20+Wide)*X,1.5,y_start+(20+Wide)*Y)

天井を上下させる

### インポート ###import vizimport vizshape
### 実行 ###
viz.fov(80)viz.MainView.setPosition([0, 1.5, 0])  ground  = viz.addChild('ground.osgb')viz.go()
CEILING_HEIGHT =[0] #グローバル設定(時系列出力データに載せるために必要)
### 調整空間 ###def AdjustingSpace(CL_HEIGHT): #前にセットしたオブジェクトをすべて取り除く children = viz.MainScene.getChildren() for child in children:      child.remove() ### 前の壁 ### Wall_front= vizshape.addBox(size = [5.0,10.0,0.1]) Wall_front.setPosition(0,0,2.5) ### 後の壁 ### Wall_back= vizshape.addBox(size = [5.0,10.0,0.1]) Wall_back.setPosition(0,0,-2.5) ### 右の壁 ### Wall_right= vizshape.addBox(size = [0.1,10.0,5.0]) Wall_right.setPosition(2.5,0,0) ## 左の壁 ### Wall_left= vizshape.addBox(size = [0.1,10.0,5.0]) Wall_left.setPosition(-2.5,0,0) ## 床 ### slab1 = viz.addTexQuad(size = [5,5]) slab1.setEuler([0,90,0]) slab1.disable(viz.LIGHTING) UpLight = viz.addLight() ; UpLight.setEuler(0,-90,0) ; UpLight.intensity(0.6) DownLight = viz.addLight() ; DownLight.setEuler(0,90,0)  ; DownLight.intensity(1)
### 動く天井 ### CEILING_HEIGHT[0] =CL_HEIGHT Ceiling = vizshape.addBox(size = [5.0,0.1,5.0]) Ceiling.setPosition(0,CEILING_HEIGHT[0],0) Ceiling.disable(viz.LIGHTING) ### 天井をあげる関数 ### def Increace():   CEILING_HEIGHT[0] = CEILING_HEIGHT[0] + 5.0/100.   Ceiling.setPosition(0, CEILING_HEIGHT[0], 0)   print('Increace', CEILING_HEIGHT[0])     vizact.onkeydown(viz.KEY_UP,Increace)#↑キーで天井が上昇 ### 天井をさげる関数 ### def Decreace(): CEILING_HEIGHT[0] = CEILING_HEIGHT[0] - 1.0/100. Ceiling.setPosition(0, CEILING_HEIGHT[0], 0) print('Decreace', CEILING_HEIGHT[0])
vizact.onkeydown(viz.KEY_DOWN,Decreace)#↓キーで天井が下降###########  コントローラーと接続すると以下のコードも使用可能 ######### def Increace2():# if Controller[0].getTrigger() > 0.5:# CEILING_HEIGHT[0] = CEILING_HEIGHT[0] + 1.0/100.# Ceiling.setPosition(0, CEILING_HEIGHT[0], 0)# print('Increace', CEILING_HEIGHT[0])# # vizact.ontimer(0.1,Increace2)# # def Decrease2():# if Controller[1].getTrigger() > 0.5:# CEILING_HEIGHT[0] = CEILING_HEIGHT[0] - 1.0/100.# Ceiling.setPosition(0, CEILING_HEIGHT[0], 0)# print('Decrease', CEILING_HEIGHT[0])## vizact.ontimer(0.1,Decrease2)
vizact.onkeydown('a',AdjustingSpace,2.1) #aキーを押すと初期高さ2.1mからの調整vizact.onkeydown('b',AdjustingSpace,2.6) #bキーを押すと初期高さ2.6mからの調整
### プログラムの終了 ###vizact.onkeydown('k',viz.quit)

サイズを調節する

import vizimport vizshape
viz.go()viz.setMultiSample(4)viz.fov(80)
#################### 地面の生成 ################ground =viz.addChild('ground.osgb')
############# サイズを変更するバーをつくる #############
bar = vizshape.addBox(size = [1,0.1,0.1],color=viz.YELLOW)bar.setPosition(0,0.5,2)bar.disable(viz.LIGHTING)
x,y = [0],[0]x[0],y[0] = 1,1
def change(): bar.setScale(x[0],1,y[0]) #barのサイズ=元のサイズ[1,0.1,0.1]×Scale[x[0],1,y[0]] print('size:',round(x[0]*1,2),0.1,round(y[0]*0.1,2))
#奥行(Y方向)は元のサイズが横幅(X方向)の1/10なので感度を10倍に設定しているdef biggerY(): y[0]+=1 change()def smallerY(): y[0]-=1 y[0] = max(0,y[0]) change()def biggerX(): x[0]+=0.1 change()def smallerX(): x[0]-=0.1 x[0] = max(0,x[0]) change() vizact.onkeydown(viz.KEY_UP,biggerY)#上キーで奥行長く vizact.onkeydown(viz.KEY_DOWN,smallerY)#下キーで奥行短く vizact.onkeydown(viz.KEY_RIGHT,biggerX)#右キーで横幅長く vizact.onkeydown(viz.KEY_LEFT,smallerX)#左キーで横幅短く

基本のコード その2

彩色とテクスチャー

オブジェクトの彩色

### モジュールをインポート ###import vizshape  
### 実行 ###viz.fov(80)      viz.MainView.setPosition([0, 1.5, 0]) viz.go()        
### 前の壁 ####一般色であれば、色名指定で変更できるWall_front= vizshape.addBox(size = [5.0,2.5,0.1],color = viz.RED)Wall_front.setPosition(0,1.25,2.5)
### 後の壁 ####rgb値(それぞれ最大1)で指定することもできるWall_back= vizshape.addBox(size = [5.0,2.5,0.1],color = [0,1,0])Wall_back.setPosition(0,1.25,-2.5)
### 右の壁 ####colorは後から変更可能(実験途中で変更する場合などに有効)Wall_right= vizshape.addBox(size = [0.1,2.5,5.0])Wall_right.setPosition(2.5,1.25,0)Wall_right.color(viz.BLUE)
## 左の壁 ####.disable(viz.LIGHTING)を使用すると影ができなくなるWall_left= vizshape.addBox(size = [0.1,2.5,5.0])Wall_left.setPosition(-2.5,1.25,0)Wall_left.color([1,1,0.2])Wall_left.disable(viz.LIGHTING)#ライティングをオフ(どの角度でみても色が変わらない)
#背景色の変更viz.clearcolor([1,1,1])

テクスチャのはり方

#通常は使用したい画像を実験ファイルと同じフォルダに保存しておく#今回はあらかじめVIZARDに入っているbrick.jpgを使用### モジュールをインポート ###import vizimport vizshape  
### 実行 ###viz.fov(80)      viz.MainView.setPosition([0, 1.5, 0]) viz.go()        #画像をインポートbrick = viz.addTexture('brick.jpg')#タイル画像用に再度インポートbricks = viz.addTexture('brick.jpg')bricks.wrap(viz.WRAP_T, viz.REPEAT)bricks.wrap(viz.WRAP_S, viz.REPEAT)
### 前の壁 ####画像べた張り。サイズが合っていないと画像が歪むWall_front= vizshape.addBox(size = [5.0,2.5,0.1])Wall_front.setPosition(0,1.25,2.5)Wall_front.texture(brick)Wall_front.disable(viz.LIGHTING)#ライティングをオフ(どの角度でみても色が変わらない)
### 後の壁 ####タイル風。壁を横5分割、高さ2.5分割、奥行き0.1mに分割しておく。1区分に1枚の画像matrix = vizmat.Transform()matrix.setScale(5.0,2.5,0.1)
Wall_back= vizshape.addBox(size = [5.0,2.5,0.1])Wall_back.setPosition(0,1.25,-2.5)Wall_back.texmat(matrix)Wall_back.texture(bricks)Wall_back.disable(viz.LIGHTING)#ライティングをオフ(どの角度でみても色が変わらない)
### 右の壁 ####タイル風。壁を横10分割、高さ2.5分割、奥行き0.1mに分割しておく。1区分に1枚の画像matrix2 = vizmat.Transform()matrix2.setScale(10,2.5,0.1)
Wall_right= vizshape.addBox(size = [0.1,2.5,5.0])Wall_right.setPosition(2.5,1.25,0)Wall_right.texmat(matrix2)Wall_right.texture(bricks)Wall_right.disable(viz.LIGHTING)#ライティングをオフ(どの角度でみても色が変わらない)
## 左の箱 ####各面に違う画像をはるときはsplitFaces=Trueにしてnodeを指定するWall_left= vizshape.addBox(size = [2.0,2.5,2.0],splitFaces=True)Wall_left.setPosition(-4,1.25,0)Wall_left.texmat(matrix,node='right')Wall_left.texture(bricks,node='right')Wall_left.disable(viz.LIGHTING)#ライティングをオフ(どの角度でみても色が変わらない)


壁面をカラフルに配色する

import vizimport randomimport vizshape
viz.setMultiSample(4)viz.MainView.setPosition(-20,1.5,0)viz.MainView.setEuler(270,0,0)viz.MainScene.fog(0.005)#奥をかすませるviz.go()
ground = vizshape.addBox(size = [200,0.01,200], color = [1,1,1])ground.disable(viz.LIGHTING)ground.setPosition([0,0,0])
#####  壁の設定   ######x_range = 100 #壁の横の長さy_range = 9 #壁の縦の長さ
road_width = 6 #道の幅員wall_size = [0.3,0.3]#グリッド幅rate_color= 80 #色を塗る割合[%]
colors = [[0,0,1],[0,1,0],[0,1,1]] #RGB 色を追加してもOK(5色とか)
#############z = road_width/2z2 = -zcenter = -(x_range/2)colorwall = int(x_range*y_range*rate_color/100)#塗る枚数
###  壁をつくる関数  ###def make_wall(z): walls = [] for x in range(x_range): for y in range(y_range): wall = viz.addTexQuad(size = wall_size) wall.setPosition([center+x*wall_size[0],y*wall_size[1]+wall_size[1],z]) wall.disable(viz.LIGHTING) walls.append(wall)
random.shuffle(walls) for s in range(len(colors)): for v in range(int(colorwall/len(colors))): walls[s*int(colorwall/len(colors))+v].color(colors[s]) return walls wall1 = make_wall(z)wall2 = make_wall(z2)
for x in range(x_range*y_range): wall2[x].setEuler([180,0,0])

関数の実行方法

キーボード操作による関数の実行

### モジュールをインポート ###import vizimport vizshape  import vizact
### 実行 ###viz.fov(80)      viz.MainView.setPosition([0, 1.5, 0]) viz.go()        ground = viz.addChild('ground.osgb')### 壁 ###Wall = vizshape.addBox(size = [5.0,2.5,0.1])Wall.setPosition(0,1.25,2.5)
Height = 1.25  #壁の高さの初期値Distance = 2.5 #壁までの距離の初期値#fキーを押したとき壁までの距離を遠くするdef Far(): global Distance #Distanceが他の関数内でも参照できるように Distance = 5.0 Wall.setPosition(0,Height,Distance)vizact.onkeydown('f',Far)#入力キーによって処理が変わる。r,bキーで色を変更、1,2,3キーでサイズ変更def Choice(key): if str(key) == 'red': Wall.color(viz.RED) elif str(key) == 'blue': Wall.color(viz.BLUE) else: Wall.setScale(int(key),int(key),int(key))vizact.onkeydown('r',Choice,'red')vizact.onkeydown('b',Choice,'blue')vizact.onkeydown('1',Choice,1)vizact.onkeydown('2',Choice,2)vizact.onkeydown('3',Choice,3)#上キー、マウスホイール上回転で壁の位置を高くするdef Up(): global Height#Heightが他の関数内でも参照できるように Height += 0.1 Wall.setPosition(0,Height,Distance)vizact.onkeydown(viz.KEY_UP,Up)vizact.onwheelup(Up)#下キー、マウスホイール下回転で壁の位置を低くするdef Down(): global Height#Heightが他の関数内でも参照できるように Height -= 0.1 Wall.setPosition(0,Height,Distance)vizact.onkeydown(viz.KEY_DOWN,Down) vizact.onwheeldown(Down)#スペースキーで変更をリセットdef Normal(): global Height   #Heightが他の関数内でも参照できるように global Distance #Distanceが他の関数内でも参照できるように Height = 1.25 Distance = 2.5 Wall.setPosition(0,Height,Distance) Wall.setScale(1,1,1) Wall.color(viz.WHITE)vizact.onkeydown(' ',Normal)#0キーを押してから3秒後に終了するdef Finish(): def Fin(): viz.quit() vizact.ontimer2(3,0,Fin)vizact.onkeydown('0',Finish)


キーの打鍵回数により処理変更

import viz import vizshapeimport timeimport steamvr###基本設定###viz.go()viz.fov(80)viz.MainView.setPosition(0,1.2,0)viz.setMultiSample(4)viz.clearcolor(0.62,0.8,0.88)  ###地面の作成###ground = vizshape.addBox(color = viz.WHITE)ground.setScale(50,0.1,50)ground.setPosition(0,-0.05,0)ground.disable(viz.LIGHTING)###角材の作成## wood = []for x in range (6): wood.append(x) wood[x] = vizshape.addBox(size = [1.5,0.1,0.1],color = [0.5,0.3,0.1]) wood[x].setPosition(0,-20,0)# wood[x].disable(viz.LIGHTING) n = [0]n[0] = 0
def number():#'n'の値に応じた処理を行わせる
print(n[0]) if n[0] == 0: wood[2].setEuler(10,0,0)        wood[0].setPosition(-1.7,0.05,3) wood[1].setPosition(-1.7,0.05,3.2) wood[2].setPosition(-1.7,0.15,3.1) if n[0] == 1: for x in range (6): wood[x].setPosition(0,-20,0) wood[5].setEuler(10,0,0) wood[3].setPosition(1.7,0.05,3) wood[4].setPosition(1.7,0.05,3.2) wood[5].setPosition(1.7,0.15,3.1) if n[0] == 2: for x in range (6): wood[x].setPosition(0,-20,0) n[0] += 1  #スペースキーを一度押すごとに'n'の値を1ずつ増加させる vizact.onkeydown(' ',number)
他の関数で更新した値を別の関数で使う(グローバル変数) →WorldVizの解説
import vizimport math
viz.go()piazza = viz.addChild('piazza.osgb')
########### グローバル変数の初期値の設定 #############POS_HEAD = 0
########### グローバル変数の更新 #############def get_on_timer(): global POS_HEAD POS_HEAD = viz.MainView.getPosition()vizact.ontimer(0.01,get_on_timer)
########### 別の関数で更新されたグローバル変数の読込 #############def print_on_timer(): global POS_HEAD print (POS_HEAD)# print (str(round(POS_HEAD[0],2)),str(round(POS_HEAD[1],2)),str(round(POS_HEAD[2],2))) #適当な桁で四捨五入しておくとよいvizact.ontimer(0.1,print_on_timer)

条件を入力してプログラムを実行する

import vizimport vizactimport vizshapeimport vizcamimport vizinput
############   仮想環境の基本設定  ###########viz.go()viz.fov(80)viz.setMultiSample(4)
ground = viz.addChild('ground.osgb')
#############  壁の作成  ##############
Wall_front= vizshape.addBox(size = [5.0,2.5,0.1])Wall_front.setPosition(0,1.25,2.5) ############    実験空間の選択肢   ############Height = vizinput.input('身長は何cm?')#開始前に数字を入力し実験空間を選択するEye_Height = int(Height)/100 - 0.15 #int()でHeightを数字情報として扱う#視点高さを入力情報により設定するviz.MainView.setPosition([0,Eye_Height,0])#壁の色を入力情報により設定するchoices = ['red','green','blue','yellow','orange']Wall_Color = viz.choose('壁の色を選択',choices)
if str(choices[Wall_Color]) == 'red': #str()でchoices[Wall_Color]を文字情報として扱う Wall_front.color(viz.RED)elif str(choices[Wall_Color]) == 'green': Wall_front.color(viz.GREEN)elif str(choices[Wall_Color]) == 'blue': Wall_front.color(viz.BLUE)elif str(choices[Wall_Color]) == 'yellow': Wall_front.color(viz.YELLOW)elif str(choices[Wall_Color]) == 'orange': Wall_front.color(viz.ORANGE)


位置座標による処理実行

###########各種インポート###############import vizimport vizshapeimport vizcamviz.go()
spin_count = [0]   #ドアの開閉記録用spin_count[0] = 0##########PC画面用#################
viz.setMultiSample(4)viz.MainView.setPosition([0,1.4,-5.5])#原点から5.5m手前の1.4m高さからスタート
##########周辺環境の構築##########
viz.clearcolor(0.62,0.8,0.88)        #スカイブルーのRGB数値ground = viz.addChild('ground.osgb') #地面の作成ground.setPosition(0,0,-24)
###############玄関ドア作成##################outdoor = viz.addChild('outdoor.osgb')outdoor = vizshape.addBox([1.0,2.2,0.1])outdoor.setPosition(0,1.1,1)#ドアは奥行き1mの場所に設置
pivot = viz.addGroup()pivot.setCenter(-0.5,0,1)outdoor.setParent(pivot)
#右キーでドアを開けるdef OpenDoor(): if  spin_count[0] == 0: spin=vizact.spin(0,1,0,70,1.8) pivot.addAction(spin) spin_count[0] = spin_count[0]+1 vizact.onkeydown(viz.KEY_RIGHT,OpenDoor)
#ドアを0.2m越えると自動で閉まるdef CloseDoor(): if viz.MainView.getPosition()[2]  >1.2:#位置座標の奥行が1.2mを越えたら if  spin_count[0] == 1: spin_count[0] = spin_count[0]-1 spin2=vizact.spin(0,-1,0,70,1.8) pivot.addAction(spin2)
vizact.ontimer(0,CloseDoor)
#WASDキーで視点を操作するviz.cam.setHandler(vizcam.KeyboardCamera())

エリア進入で処理実行

#エリアに入るたびにカウントが+1され壁面緑色に変化############   モジュールのインポート  #################import vizimport vizshapeimport vizcam#############    記録用リストの定義  ##################count = [0] #エリア進入回数カウント用In_Out = [0]#エリア進入有無を記録(エリア内→1、エリア外→0)#############    周囲環境   ##################ground = viz.addChild('ground.osgb')viz.MainView.setPosition([0,1.2,-2])#スタート地点は原点から2m手前viz.fov(80)viz.go()
area =vizshape.addBox(size=[1,0.1,1],pos=[0,0,0]) #エリア(可視化するため板を置いている)Wall =vizshape.addBox(size=[5,3,0.1],pos=[0,0,2],color=viz.RED) #前面に壁を作成
############ 0.1秒ごとに行う処理 ################
def onTimer(num): #位置情報を取得 X = viz.MainView.getPosition()[0] Z = viz.MainView.getPosition()[1] Y = viz.MainView.getPosition()[2] if -0.5 < X < 0.5 and -0.5 < Y < 0.5: #エリアに入ったときの処理 if In_Out[0] == 0:                #In_Out[0]が0だったら In_Out[0] = 1                 #In_Out[0]を1にする
count[0]+=1                   #count[0]を+1する Wall.color(viz.GREEN) else:                                 #エリア外の処理 In_Out[0] = 0                     #In_Out[0]を0にする Wall.color(viz.RED) #カウント番号を出力 print('count'+'\t'+str(count[0])+'\n') viz.callback(viz.TIMER_EVENT, onTimer)viz.starttimer(1, 0.1, viz.PERPETUAL)#############   キーボード操作   ###############keyCam = vizcam.KeyboardCamera()          #wasdキーで空間を動かす

エリア進入で処理実行(複数エリア)

#エリア1とエリア2を交互に2回ずつ踏んで処理を実行############   モジュールのインポート  #################import vizimport vizshapeimport vizcam#############    記録用リストの定義  ##################count = [0] #エリア進入回数カウント用#############    周囲環境   ##################ground = viz.addChild('ground.osgb')viz.MainView.setPosition([0,1.2,-2])#スタート地点は原点から2m手前viz.fov(80)viz.go()
area1 =vizshape.addBox(size=[1,0.1,1])#エリア1(可視化するため板を置いている)area1.setPosition(-2,0,0)             #エリア1を左側に配置area2 =vizshape.addBox(size=[1,0.1,1])#エリア2(可視化するため板を置いている)area2.setPosition(2,0,0)              #エリア2を右側に配置
Wall =vizshape.addBox(size=[5,3,0.1]) #前面に壁を作成Wall.setPosition(0,0,2)              Wall.color(viz.RED)
############ 0.1秒ごとに行う処理 ################
def onTimer(num): #位置情報を取得 X = viz.MainView.getPosition()[0] Z = viz.MainView.getPosition()[1] Y = viz.MainView.getPosition()[2] if -2.5 < X < -1.5 and -0.5 < Y < 0.5: #エリア1に入ったときの処理 #countが0ならcountを+1 & Wallを緑に if count[0]==0: count[0]+=1 Wall.color(viz.GREEN) #countが2ならcountを+1 & Wallを青に if count[0]==2: count[0]+=1 Wall.color(viz.BLUE)
if 1.5 < X < 2.5 and -0.5 < Y < 0.5: #エリア2に入ったときの処理 #countが1ならcountを+1 & Wallを黄に if count[0]==1: count[0]+=1 Wall.color(viz.YELLOW) #countが3ならcountを+1  & Wallを白に if count[0]==3: count[0]+=1 Wall.color(viz.WHITE) #カウント番号を出力 data  = 'count'+'\t'+str(count[0])+'\n' print(data) viz.callback(viz.TIMER_EVENT, onTimer)viz.starttimer(1, 0.1, viz.PERPETUAL)#############   キーボード操作   ###############keyCam = vizcam.KeyboardCamera()          #wasdキーで空間を動かす

矢印の作成と操作

テキストの表示

### 各種インポート ###import vizimport vizact#############    周囲環境   ##################
ground = viz.addChild('ground.osgb')viz.fov(80)viz.go()
################# コメント ####################未定義のエラー回避のため事前に空白のコメントを作成しておくとよいtext = 3*[0]for i in range(3): text[i] = viz.addText(' ', pos=[0, 0, 0],parent=viz.WORLD)#テキストは日本語非対応。関数にすると好きな時に実行できるdef TextStart(): text[0] = viz.addText('Start',pos=[-1.5, 1.5, 2],parent=viz.WORLD)#テキスト・位置を指定 text[0].color(viz.WHITE)#色を指定 text[0].setScale([0.3, 0.3, 0.3])#大きさを指定
def TextGoal(): text[1] = viz.addText('Goal', pos = [1.5, 1.5, 2], parent = viz.WORLD)#テキスト・位置を指定 text[1].color(viz.WHITE)#色を指定 text[1].setScale([0.3, 0.3, 0.3])#大きさを指定 def RemoveText(): for i in range(2):#text[0]からtext[1]までを削除 text[i].remove()
vizact.onkeydown('1', TextStart)#'1'でTextStartを実行vizact.onkeydown('2', TextGoal)#'2'でTextGoalを実行vizact.onkeydown('3', RemoveText)#'3'でRemoveTextを実行#{}とformatを利用することで変動する値や、結果の表示も可能def Time(num): text[2].remove() result='Time : "{}s".' text[2] = viz.addText(result.format(round(viz.tick(),1)),pos=[-0.5, 1.5, 2],parent=viz.WORLD) text[2].color(viz.WHITE) text[2].setScale([0.2, 0.2, 0.2])
viz.callback(viz.TIMER_EVENT, Time)viz.starttimer(1, 0.1, viz.PERPETUAL)#矢印をテキストで表示することもできるArrow = viz.addText('↑',pos=[0, 1.0, 1.4],parent=viz.WORLD)Arrow.color(viz.BLACK)Arrow.setEuler([0,90,0])Arrow.setScale([0.4, 0.4, 0.4])

矢印の作成

#※簡易な矢印はテキストでも代用可能############   モジュールのインポート  #################import vizimport vizshapeimport vizcam#################  矢印の設定  ##################
L = 1.6      #全体の長さ(m)W  = 0.1     #太い部分の幅(m)T_L = 0.2    #先端部の長さ(m)T_W = 0.5    #先端部の幅(m)
Col = [1,0,0]#色の指定[1,0,0]は赤#############    周囲環境   ##################
ground = viz.addChild('ground.osgb')viz.MainView.setPosition([0,1.4,0])viz.fov(80)viz.go()
#############    矢印の作成   ##################
#slices=2で平面的な矢印になるArrow = vizshape.addArrow(length = L,radiusRatio = (W/L)/2,tipLengthRatio=T_L/L,tipRadiusRatio=T_W/W,slices=2,color=Col)#setPositionは矢印の先端の座標を指定Arrow.setPosition(0.8,0.8,2)#lookAtは矢印が指し示す座標を指定#roll=90→水平、roll=0→垂直Arrow.lookAt(point=[5,2,2],roll=90)
#############   キーボード操作   ###############keyCam = vizcam.KeyboardCamera()          #wasdキーで空間を動かす

矢印の長さを距離に応じて変更

############   モジュールのインポート  #################import vizimport vizshapeimport vizcamimport math#################  条件設定  ##################[GoalX,GoalY]=[0,6]    #目標点の座標指定Area_MAX = 3           #矢印の縮小が始まる際の目標点との距離(m)Area_MIN = 1.5         #矢印の縮小が終わる際の目標点との距離(m)#############    周囲環境   ##################ground = viz.addChild('ground.osgb')viz.fov(80)viz.go()#目標点に円柱を配置して視覚化Pole = vizshape.addCylinder(height=2,radius=0.2)   #高さ2m,半径0.2mPole.setPosition(GoalX,1,GoalY)#矢印の作成Arrow = vizshape.addArrow(tipRadiusRatio=2,slices=2)############ 0.1秒ごとに行う処理 ################
def onTimer(num): #位置情報&頭角度情報を取得 X = viz.MainView.getPosition()[0] Y = viz.MainView.getPosition()[2] A = viz.MainView.getEuler()[0] #Arrowの位置を被験者の移動に追従させる Distance = 1.0         #Arrowの先端から被験者までの距離 Arrow_X = math.sin(-A*math.pi/180)*(-Distance)+X Arrow_Y = math.cos(-A*math.pi/180)*(Distance)+Y Arrow.setPosition(Arrow_X,1.4,Arrow_Y) Arrow.lookAt([GoalX,1.4,GoalY],roll=90)
#目標点との距離に応じてArrowの長さ変える  #Area_MIN<目標点との距離<Area_MAXのとき、矢印はだんだん短くなる if Area_MIN<math.sqrt(pow((GoalX-X),2)+pow((GoalY-Y),2))<Area_MAX: Arrow.setScale([1,1,1*(math.sqrt(pow((GoalX-X),2)+pow((GoalY-Y),2))-Area_MIN)/(Area_MAX-Area_MIN)]) #目標点との距離<=Area_MINのとき、矢印の長さは0 elif math.sqrt(pow((GoalX-X),2)+pow((GoalY-Y),2))<=Area_MIN: Arrow.setScale(1,1,0)
viz.callback(viz.TIMER_EVENT, onTimer)viz.starttimer(1, 0.1, viz.PERPETUAL)
#############   キーボード操作   ###############keyCam = vizcam.KeyboardCamera()          #wasdキーで空間を動かす

矢印回答タスク

import vizimport random
viz.MainView.setPosition([0,1.0,-2])viz.go()
stop_num=[0]num=[0] #number of command pressed corectlymiss=[0] #number of missed commanddetime = 10 #default time  datafile = open("all.csv", mode = 'a') # 新しいファイルを作成Header = 'Time'+','+'Num'+','+'Miss'+'\n'datafile.write(Header)
def WriteData(): data  = str(detime)+','+str(round(num[0],1))+','+str(round(miss[0],1))+'\n' print(data) datafile.write(data) ################COMMAND######################key_list=['↑','↓','→','←']command_list=[0,1,2,3] #convert key into 'int'command=[]for x in range(100): #make 400 commands random.shuffle(command_list) for y in command_list: command.append(y) def check_command(key): if stop_num[0]  == 0: if key == command[num[0]]: num[0] = num[0]+1 else: miss[0] = miss[0]+1 num[0] = num[0]+1 for s in range(3): text[s].remove() WriteCommand() vizact.onkeydown(viz.KEY_UP,check_command,0)vizact.onkeydown(viz.KEY_DOWN,check_command,1)vizact.onkeydown(viz.KEY_RIGHT,check_command,2)vizact.onkeydown(viz.KEY_LEFT,check_command,3)################COMMAND_TEXT################board = viz.addTexQuad(size = [0.54,0.32],pos=[0,0.95,0.2],color=viz.BLACK)text=[0,0,0]
def WriteCommand(): text[0] = viz.addText(str(key_list[command[num[0]+1]]),pos=[-0.235, 0.9, 0.19],scale=[0.1, 0.1, 0.1],parent=viz.WORLD) #next command text[1] = viz.addText(str(key_list[command[num[0]]]),pos=[-0.035, 0.9, 0.19],scale=[0.15, 0.15, 0.15],parent=viz.WORLD) #current command  text[2] = viz.addText(str(key_list[command[num[0]+1]]),pos=[0.165, 0.9, 0.19],scale=[0.1, 0.1, 0.1],parent=viz.WORLD) #next command#######################Text##########################Intro=[0] def OverText(): WriteData() for textnum in range(3): text[textnum].remove() stop_num[0] = 1 Intro[0] = viz.addText('The experiment is over.\nThank you for your cooperation!',pos=[-0.25, 0.95, 0.19],parent=viz.WORLD) Intro[0].setScale([0.03, 0.03, 0.03]) WriteCommand() vizact.ontimer2(detime,0,OverText)

空間操作

空間リセット & 使用可能3D環境まとめ

import vizimport vizactimport vizshape############   データ出力の準備   ############count = [0]                              #空間リセット回数記録用############   仮想環境の基本設定  ###########viz.go()viz.fov(80)viz.setMultiSample(4)ground = viz.addChild('ground.osgb')#リセット前の地面を作成############ 空間をリセットする関数 ############def ChangeMode(): #空間を全削除する children = viz.MainScene.getChildren() for child in children: child.remove() #HMDを使用する場合は以下3行を再度記述 # navigationNode = viz.addGroup()# viewLink = viz.link(navigationNode, viz.MainView)# viewLink.preMultLinkable(hmd.getSensor()) count[0] += 1   #空間をリセットするときに1カウント print(count[0]) #カウント数を出力 if count[0] == 1: ground = viz.addChild('ground_grass.osgb') elif count[0] == 2: ground = viz.addChild('ground_gray.osgb') elif count[0] == 3: ground = viz.addChild('ground_stone.osgb') elif count[0] == 4: ground = viz.addChild('ground_wood.osgb') elif count[0] == 5: ground = viz.addChild('lab.osgb') elif count[0] == 6: ground = viz.addChild('maze.osgb') elif count[0] == 7: ground = viz.addChild('piazza.osgb') elif count[0] == 8: ground = viz.addChild('pit.osgb') elif count[0] == 9: ground = viz.addChild('gallery.osgb') elif count[0] == 10: ground = viz.addChild('dojo.osgb') elif count[0] == 11: ground = viz.addChild('sky_day.osgb') elif count[0] == 12: ground = viz.addChild('sky_night.osgb') elif count[0] == 13: ground = viz.addChild('court.ive') elif count[0] == 14: ground = viz.addChild('panorama.ive') elif count[0] == 15: viz.quit()
vizact.onkeydown(' ',ChangeMode)#スペースキーで実験空間をリセット

軸を指定して回転させる

######## 各種インポート #########import vizimport vizshape##########    周囲環境   ############ground = viz.addChild('ground.osgb')viz.setMultiSample(4)viz.go() #空skytex=viz.add(viz.ENVIRONMENT_MAP,'sky.jpg')sky=viz.add('skydome.dlc')sky.texture(skytex)#ボールball = viz.add('white_ball.wrl')#俯瞰図用にボールを作成ball.setPosition(0,0.1,0)##########    回転動作   ############pivot1 = viz.addGroup()pivot1.setCenter(0,0,0)#回転軸1の中心座標を決めるsky.setParent(pivot1)#空を回転軸1に結び付ける
pivot2 = viz.addGroup()pivot2.setCenter(0,0,5)#回転軸2の中心座標を決めるball.setParent(pivot2)#ボールを回転軸2に結び付ける
def Spin_1(): spin=vizact.spin(0,1,0,6,5)#回転方向(x,y,z)&回転速度&回転時間 pivot1.addAction(spin)vizact.ontimer2(10,0,Spin_1)#10秒後に回転軸1を回転
def Spin_2(): spin=vizact.spin(0,1,0,150)#回転方向(x,y,z)&回転速度(時間はデフォルトForever) pivot2.addAction(spin)vizact.ontimer(0,Spin_2)#起動と同時に回転がはじまる

animation path の利用


import vizimport vizactimport vizshapeimport randomimport math
viz.go()viz.setMultiSample(4)viz.fov(80)
################# 地面の生成 ################path_G = viz.addAnimationPath() #仮想のラインを生成path_G.addControlPoint(0,pos=[0,0,0]) #Ground =[] #地面を格納する配列for i in range (0,4): #4回繰り返し Ground.append([]) #地面の配列のなかに ground = viz.addChild('ground.osgb') #指定サイズの地面を viz.link(path_G, ground, offset =(0,0,i*50)) #50mずつずらしながら並べて Ground[i].append(ground) #格納する ################# 左側壁の列の生成 ################path_L = viz.addAnimationPath() #仮想のラインを生成path_L.addControlPoint(0,pos=[-3,1,0]) #仮想のラインを左3m高さ1mに移動
L_WALLS =[] #左側壁を格納する配列for i in range (0,20): #20回繰り返し L_WALLS.append([]) #左側壁の配列のなかに wall = vizshape.addBox(size = [0.2,2.0,2.0]) #指定サイズの壁を viz.link(path_L, wall, offset =(0,0,i*2.5)) #2.5mずつずらしながら並べて L_WALLS[i].append(wall) #格納する ################# 右側壁の列の生成 ################path_R = viz.addAnimationPath() #仮想のラインを生成positions = [[3,1,0], [3,1,10]]                         #仮想のラインに2つの点を指定for x, pos in enumerate(positions): path_R.addControlPoint(x+1,pos=pos) R_WALLS =[] #右側壁を格納する配列for i in range (0,20): #20回繰り返し R_WALLS.append([]) #右側壁の配列のなかに wall = vizshape.addBox(size = [0.2,2.0,2.0]) #指定サイズの壁を viz.link(path_R, wall, offset =(0,0,i*2.5)) #2.5mずつずらしながら並べて R_WALLS[i].append(wall) #格納する
#pathにリンクさせたものすべてが指定した複数の点に沿って移動していくpath_R.setLoopMode(viz.CIRCULAR)                        #移動モードを選択path_R.setConstantSpeed(viz.ON,1.45)                    #移動速度を1.45 m/sに設定vizact.onkeydown(' ', path_R.reset) #pathをリセットする
def Stop_room(): #pathを止める関数 path_R.pause() def Start_room(): #pathを動かす関数 path_R.play() vizact.ontimer(3, Stop_room) #3秒後にpathを止めるvizact.onkeydown(viz.KEY_UP, Start_room) #上キーでpathを動かす

animation path を関数で操作

#上下キーでポールの高さを操作import vizimport vizshapeimport math#######################################################################################viz.go() viz.MainScene.fog(0.1) viz.MainView.setPosition([0.8,1.5,0])   
##########地面の作成##########ground = vizshape.addBox(color=viz.WHITE)ground.setScale(100,0.01,100)ground.setPosition(0,-0.05,0)##################ポール列を動かす#################def columns(Pole_Height,Pole_Span):
#動く道Pをつくる pathP = viz.addAnimationPath() #道Pを秒速1.3m(歩く速さ)で動かす pathP.setConstantSpeed(viz.ON,1.3) #道Pを動かす pathP.play()
#道Pの起点をつくる Path_Height = [0] Path_Height[0] = 0 positionsP = [[0,Path_Height[0],Pole_Span-20],[0,Path_Height[0],-20]]
for x,pos in enumerate(positionsP): pathP.addControlPoint(x+1,pos=pos) #道Pをループさせる pathP.setLoopMode(viz.LOOP)
#ポール列を作成し道Pにリンクさせる ColumnsP =[] for i in range (0,100):     #ポールの個数 ColumnsP.append([]) columnP = vizshape.addCylinder(height=Pole_Height,radius=0.06)      #ポールは道Pの下にも伸びるため高さ2倍 viz.link(pathP, columnP,offset =(0,Pole_Height/2,Pole_Span*i))                   #歩道の厚み分ポールをあげる ColumnsP[i].append(columnP) #ポール列の高さを上げる def Increace():# if Controller[0].getTrigger() > 0.5:#コントローラーとの接続時に使用可能 pathP.clearControlPoints() Path_Height[0] = Path_Height[0]+ 0.01
positionsP = [[0,Path_Height[0],Pole_Span-20],[0,Path_Height[0],-20]] for x,pos in enumerate(positionsP): pathP.addControlPoint(x+1,pos=pos) # vizact.ontimer(0.01,Increace)#コントローラーとの接続時に使用可能 vizact.onkeydown(viz.KEY_UP,Increace)
#ポール列の高さを下げる def Decreace():# if Controller[1].getTrigger() > 0.5:#コントローラーとの接続時に使用可能 pathP.clearControlPoints() Path_Height[0] = Path_Height[0]- 0.01
positionsP = [[0,Path_Height[0],Pole_Span-20],[0,Path_Height[0],-20]] for x,pos in enumerate(positionsP): pathP.addControlPoint(x+1,pos=pos) # vizact.ontimer(0.01,Decreace)#コントローラーとの接続時に使用可能 vizact.onkeydown(viz.KEY_DOWN,Decreace) columns(0.8,1.5)#ポールの高さと間隔を指定して関数を実行

初期アバターを動かす

#Vizardに初期搭載されているアバターは3種類#アバター追加はMixiamoからとりこむ#追加したアバターはアニメーション追加するためstate番号は異なるimport vizimport vizactimport vizfx
viz.MainView.setPosition(0,1.5,-5)viz.setMultiSample(4)viz.fov(80)viz.go()#女性アバターの追加female = viz.add('vcc_female.cfg')female.setPosition([0,0,2.5])female.state(11)#走りfemale.setEuler(180, 0, 0) #女性アバターの追加(vizfxを使うと影が反映される)female_fx = vizfx.addAvatar('vcc_female.cfg')female_fx.setPosition([-1,0,2.5])female_fx.state(11)female_fx.speed(0.5)female_fx.setEuler(180, 0, 0) #男性アバタ1ーの追加male = viz.add('vcc_male.cfg')male.setPosition([-5,0,2.5])male.state(1)#立位状態male.setEuler(180, 0, 0) #男性アバタ2ーの追加male2 = viz.add('vcc_male2.cfg')male2.setPosition([5,0,2.5])male2.state(1)#立位状態male2.setEuler(180, 0, 0) 
#######  動作の定義  ########spin0 = vizact.spinTo(euler=[0,0,0], speed=400)spin180 = vizact.spinTo(euler=[180,0,0], speed=400)
action1 = vizact.moveTo([5,0,0.5],speed=0.8)action2 = vizact.moveTo([-5,0,0.5],speed=0.8)action3 = vizact.moveTo([0,0,0.5],speed=1.11)action4 = vizact.moveTo([0,0,2.5],speed=1.11)
fem_action = vizact.sequence(action3,spin0,action4,spin180) 
def Action(): female.addAction(fem_action) male.addAction(action2) male.state(2)#歩行 male2.addAction(action1) male2.state(2)#歩行vizact.ontimer2(10,0,Action)#起動後10秒で処理が実行

応用テクニック

PC画面に俯瞰図を表示

#※PC画面上で確認する用(VR上では無効)############   モジュールのインポート  #################import vizimport vizshapeimport vizcam############   俯瞰図の追加   #################
subView = viz.addView()subView.setPosition([0,10,0]) #高さ10mからの視点subView.setEuler([0,90,0])    #真下を見下ろす角度subWindow = viz.addWindow()subWindow.setSize([0.5,0.5])  #サブウインドウのサイズを変更(全画面に対する比率)subWindow.setPosition([0,1])  #サブウインドウの位置を変更(全画面に対する位置)subWindow.setView( subView )
#############    周囲環境   ##################ground = viz.addChild('ground.osgb')viz.fov(80)viz.go()
ball = viz.add('white_ball.wrl')#俯瞰図用にボールを作成############ 0.1秒ごとに行う処理 ################
def onTimer(num): #位置情報を取得 X = viz.MainView.getPosition()[0] Y = viz.MainView.getPosition()[2] #ボールを位置情報に合わせて動かす moving_ball = vizact.moveTo([X,0.1,Y]) ball.addAction(moving_ball) viz.callback(viz.TIMER_EVENT, onTimer)viz.starttimer(1, 0.1, viz.PERPETUAL)
#############   キーボード操作   ###############keyCam = vizcam.KeyboardCamera()          #wasdキーで空間を動かす

2点を結ぶ角度の算出

############   モジュールのインポート  #################import vizimport vizshapeimport vizcamimport math#############    周囲環境   ##################ground = viz.addChild('ground.osgb')viz.fov(80)viz.go()
#オブジェクトの作成Bar = vizshape.addBox(size=[0.05,0.05,2])#角度を指定しないとき正面方向に伸びる(重要)Bar.setPosition(0,1.3,2)[X1,Y1]=[-2,2]    #目標点1の座標指定[X2,Y2]=[4,4]     #目標点2の座標指定
#目標点に円柱を配置して視覚化Pole1 = vizshape.addCylinder(height=2,radius=0.2)   #高さ2m,半径0.2mPole1.setPosition(X1,1,Y1)Pole2 = vizshape.addCylinder(height=2,radius=0.2)   #高さ2m,半径0.2mPole2.setPosition(X2,1,Y2)
#################      目標点1と目標点2を結ぶ向きにBarを回転させる     ################
#目標点1と2を結ぶ直線が、正面方向となす角を求める。2次元ベクトルの内積の公式を利用#正面方向のベクトルと2つの目標点を結ぶベクトルがなす角を求めるcosP = (Y2-Y1)/math.sqrt(pow(X2-X1,2)+pow(Y2-Y1,2))
#目標点1と目標点2の位置関係によってPの符号が変わる #Vizard上で正面からの角は―180°~180°であるが、上の計算式でのPは0°~180°までの値しかとらないためif X2<X1: P = -math.degrees(math.acos(cosP))else: P = math.degrees(math.acos(cosP))Bar.setEuler(P,0,0) print(P)#############   キーボード操作   ###############keyCam = vizcam.KeyboardCamera()          #wasdキーで空間を動かす

距離一定で追従する

############   モジュールのインポート  #################import vizimport vizshapeimport vizcamimport math#############    周囲環境   ##################ground = viz.addChild('ground.osgb')viz.fov(80)viz.go()
Screen = vizshape.addBox(size=[1,1,0.05])Distance = 2.0         #Screenから被験者までの距離を設定する############ 0.1秒ごとに行う処理 ################
def onTimer(num): #位置情報&頭角度情報を取得 X = viz.MainView.getPosition()[0] Z = viz.MainView.getPosition()[1] Y = viz.MainView.getPosition()[2] A = viz.MainView.getEuler()[0]
#頭角度に合わせてScreenの位置情報を移動 #計算は被験者の位置を中心に座標を回転させる三角関数を使用 Line_X = math.sin(-A*math.pi/180)*(-Distance)+X Line_Y = math.cos(-A*math.pi/180)*(Distance)+Y
Screen.setPosition(Line_X,Z,Line_Y)#位置情報を変更する Screen.setEuler(A,0,0)             #頭角度に応じてScreenの角度を変更
viz.callback(viz.TIMER_EVENT, onTimer)viz.starttimer(1, 0.1, viz.PERPETUAL)
#############   キーボード操作   ###############keyCam = vizcam.KeyboardCamera()          #wasdキーで空間を動かす
Excelの値を参照する →参考Excelファイル
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""☆事前準備1タブのTools>Pacage Manager>Searchでopenpyxlを検索しインストール
☆事前準備2DATA.xlsxのファイルの中#########################################シート1(3つの実験結果が記録されている)A2~C1001に0~10000までの数値が記録済み        A    B    C1     con1 con2 con32      17   8   117
1001   41   24   0 ########################################シート2(30種類の色のデータを記載)A1:1色目のr値、B1:1色目のg値,C1:1色目のb値E1:1色目を適応する最小値、F1:1色目を適応する最大値        A    B    C    D    E    F1       1  0.07 0.07      8000 10000   2     0.99 0.18 0.10      7724 8000   
30    0.88   1    1        0   275
☆事前準備3DATA.xlsxは閉じておく
☆事前準備4DATA.xlsxを実験データと同じフォルダに保存"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
######## 各種インポート #########import vizimport vizshapeimport openpyxl
viz.go()#############################
def Analysis(num): #1000個(10×100)のタイル(square)を作成し配置。 #Square_List[0]~Square_List[999]に格納 Square_List =[] for X in range (10): for Y in range (100): Square = vizshape.addBox(size=[1,0.01,1])  Square.setPosition(X-1,0,Y-0.5) Square.disable(viz.LIGHTING) Square_List.append(Square) wb = openpyxl.load_workbook('DATA.xlsx')#読み込むExcelファイル ws1 = wb.worksheets[0]#ws1=Excelのシート1(3つの実験結果が記録されている) ws2 = wb.worksheets[1]#ws2=Excelのシート2(30種の色のでデータを記載) #各行row(2~1001)に対して、列col(1~3)の値を取得してvaluesのリストに格納する #values[0]:1列目のデータ、values[1]:2列目のデータ、values[0]:3列目のデータ row_num = 1 for row in ws1.iter_rows(min_row=2): row_num += 1 values = [] for col in row: values.append(col.value) for k in range(30): #シート2の値を利用してタイルに色をつける #Analysis実行時に指定したnumによってシート1で参照する列が異なる #シート2(Ek)<シート1の値<シート2(Fk)のとき、r=シート2(Ak),g=シート2(Bk),b=シート2(Ck) #k(0~29)なので参照する行はk+1(1~30) if ws2.cell(k+1,5).value < values[num-1]<= ws2.cell(k+1,6).value: r = ws2.cell(k+1,1).value g = ws2.cell(k+1,2).value b = ws2.cell(k+1,3).value #タイル(square)に色をつける #Square_List(0~999)に対してrow_num(2~1001)であるため-2 Square_List[row_num-2].color([r,g,b]) #######     参照する条件を選択する(1~3)   ##########def Change(keyID):
children = viz.MainScene.getChildren() for child in children: child.remove() if keyID == 1: Analysis(1) elif keyID ==2: Analysis(2) elif keyID ==3: Analysis(3) def quit_analysis(): expelimental_data.close() viz.quit()
############    初期設定      #############Analysis(1)
#############   キーボード操作   #############vizact.onkeydown('1',Change,keyID=1)vizact.onkeydown('2',Change,keyID=2)vizact.onkeydown('3',Change,keyID=3)vizact.onkeydown('k',quit_analysis)

ブランコ(振り子&視点操作)

import vizimport vizshapeimport vizactimport math
viz.addChild('piazza.osgb')viz.clearcolor(viz.SLATE)viz.go()
###########VIVE###################import steamvr### Setup SteamVR HMD#hmd = steamvr.HMD()#if not hmd.getSensor():# sys.exit('SteamVR HMD not detected')### Setup navigation node and link to main view#navigationNode = viz.addGroup()#viewLink = viz.link(navigationNode, viz.MainView)#viewLink.preMultLinkable(hmd.getSensor())
CYCLES_PER_SEC      = 0.15 #周期AMPLITUDE           = 60.0 #振幅#支柱column_1 = vizshape.addCylinder(height = 3.0,radius = 0.05,pos = [0, 1.5, 0],color = viz.RED)column_2 = vizshape.addCylinder(height = 3.0,radius = 0.05,pos = [0, 1.5, 0],color = viz.RED,parent=column_1)column_2.setPosition([0, 0, 2])#上の棒Bar = vizshape.addCylinder(height = 2.0,radius = 0.05,pos = [0, 1.5, 0],color = viz.BLUE ,parent=column_1)Bar.setAxisAngle([1,0,0, 90])Bar.setPosition([0, 1.5, 1])#緑のジョイントj1 = viz.addChild('joint.wrl',pos = [0, 0.5, 0],parent=Bar)j2 = viz.addChild('joint.wrl',pos = [0, -0.5, 0],parent=Bar)j1.setAxisAngle([1,0,0, 90])j2.setAxisAngle([1,0,0, 90])#振り棒c4 = viz.addChild('cylinder.wrl',parent=j1)c5 = viz.addChild('cylinder.wrl',parent=j2)c4.setScale([0.5,5,0.5])c5.setScale([0.5,5,0.5])#乗り台plate = vizshape.addBox(size=[0.5,0.01,2],parent=c4)plate.setPosition([0,0.5,1])plate.setAxisAngle([0,1,0, 180])###########     乗り台に視点を合わせる    #############viewLink = viz.link(plate,viz.MainView,srcFlag=viz.ABS_GLOBAL)viewLink.preEuler( [270, 10, 180] )viewLink.preTrans( [0, 0.3, 0] )###########     振り子運動を実行    ##############def AnimateNode():    angle = math.sin(viz.tick() * CYCLES_PER_SEC * 2*math.pi) * AMPLITUDE    c4.setAxisAngle([0,0,1, angle])    c5.setAxisAngle([0,0,1, angle])vizact.ontimer(0,AnimateNode)

コントローラーでスライダーを動かす

import vizimport vizshapeimport datetimeimport steamvr#初期設定Size = 4 #スライダーの長さSub = 1  #被験者番号Num = 1  #実験番号
x = [0]x[0]=-Size/2  #バーの初期値を設定
viz.go() ######## HMD装着 ######## import steamvrhmd = steamvr.HMD()viz.link(hmd.getSensor(), viz.MainView)
navigationNode = viz.addGroup()viewLink = viz.link(navigationNode, viz.MainView)viewLink.preMultLinkable(hmd.getSensor())
###### コントローラー接続 ######Controller = steamvr.getControllerList()for controller in steamvr.getControllerList(): #Create model for controller controller = controller controller.model = controller.addModel() controller.model.disable(viz.INTERSECTION) controller.distance = 1.0 viz.link(controller, controller.model)
######## スライダー作成 #########シリンダーの作成   cylinder = vizshape.addCylinder(height = Size,radius = 0.02,axis = vizshape.AXIS_X,  pos=[0,1.6,3])#バーの配置Box = vizshape.addBox(size=(0.1,0.5,0.1))Box.setPosition(-Size/2,1.6,3) 
### コントローラーでスライダーを動かす ###def increase(): if Controller[0].getTrackpad()[0] > 0.7: #トラックパッド右で増加         if x[0]<Size/2: x[0] = x[0]+0.01 Box.setPosition(x[0],1.6,3) print('Increace', round(x[0]/Size+1/2,3)) vizact.ontimer(0.01,increase)
def decrease(): if Controller[0].getTrackpad()[0] < -0.2: #トラックパッド左で減少  if x[0]>-Size/2: x[0] = x[0]-0.01 Box.setPosition(x[0],1.6,3) print('Decreasse', round(x[0]/Size+1/2,3)) vizact.ontimer(0.01,decrease)                                                          
#############   キーボード操作   ###############datafile = open('slider_'+datetime.datetime.today().strftime("%Y%m%d")+'.csv','a')Header = 'Sub'+','+'Num'+','+'Value'+'\n'datafile.write(Header)
def WriteData(): data  = str(Sub)+','+str(Num)+','+str(round(x[0]/4+1/2,3))+'\n' datafile.write(data) datafile.close() viz.quit() vizact.onkeydown(' ',WriteData)            #スペースキーで実験を終了

応用テクニック: ナビゲーション

目的地に向かう矢印を常に表示する

##############################################################################################################################################################################''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' VIZARD/PYTHON SCRIPT FOR IMMERSIVE 3D EXPERIMENTS.  ALL RIGHTS RESERVED YOSHIOKA LAB, CHIBA UNIVERSITY, JAPAN.
This Script Based on using the following equipments. - WorldViz Vizard 7.0 over '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#######################################################################################
import vizimport vizactimport vizshapeimport viztrackerimport vizproximityimport randomimport mathimport csvimport datetimeimport vizinputimport timeimport viztaskimport vizmatimport projectorimport sysimport vizcamimport vizfximport vizconnectimport vizinfo
viz.go()viz.setMultiSample(4)viz.fov(80)
viz.MainView.setPosition([-0.5,1.5,0.5])viz.MainView.setEuler([0,0,0])#viz.MainView.collision(viz.ON)
# Add a white directional light pointing down light = vizfx.addDirectionalLight(euler=(0,90,0), color=viz.WHITE)
###########VIVE###################import steamvr### Setup SteamVR HMD#hmd = steamvr.HMD()#if not hmd.getSensor():# sys.exit('SteamVR HMD not detected')### Setup navigation node and link to main view#navigationNode = viz.addGroup()#viewLink = viz.link(navigationNode, viz.MainView)#viewLink.preMultLinkable(hmd.getSensor())
################################## グローバル変数一覧  #####################################POS_HEAD = [0] #頭位置[x,y,z]POS_HEAD[0] = 0ORI_HEAD = [0] #頭角度[r,p,y]ORI_HEAD[0] = 0
#print POS_HEAD
reset_time = [0] #時刻リセット用変数reset_time[0] = 0
flagLogging = [0] #データ記録フラグflagLogging[0] = False
###############データ出力の準備 #############EVENT_TIMER_ID = 1 #イベントチェックタイマーIDEVENT_TIMER_PERIOD = 0.1 #チェック間隔[s]PROCESS_TIMER_ID = 2 #データ保存タイマーIDPROCESS_TIMER_PERIOD = 0.016666666 #データ保存間隔[s] ≒ 60Hzoutfile = None #出力ファイルオブジェクト(内部用)outcsv = None #CSVフォーマットオブジェクト(内部用)start_time = time.time()         #経過時間(内部用)
#subject = 1 #被験者識別番号、実験開始前に被験者毎に設定する##FileName='tanabe_experiment'+datetime.datetime.today().strftime("%Y%m%d")+'_Sub'+str(subject)+'.txt'#Header ='Subject'+'\t'+'Lap_time'+'\t'#Header +='PosX'+'\t'+'PosY'+'\t'+'PosZ'+'\t'+'Yaw'+'\t'+'Pitch'+'\t'+'Roll'+'\n'#expelimental_data = open(FileName,'a') #expelimental_data.write(Header)


################### 左上に検証用サブウィンドウを作成 ####################UpperLeftWindow = viz.addWindow(pos=(0,1.0),size=(0.25,0.25))UpperLeftWindow.visible(0,viz.SCREEN)BirdView = viz.addView() #Create a new viewpointUpperLeftWindow.setView(BirdView) #Attach the bird's eye view to the upper left windowBirdView.setPosition([-2,6,2]) #Move the view above the center of the roomBirdView.setEuler([90,90,90]) #Rotate the view so that it looks downUpperLeftWindow.fov(60)
#MainViewのポジションを赤いConeにリンクさせるview = viz.MainViewCone = vizshape.addCone(radius=0.1,height=0.3, axis=vizshape.AXIS_Z,color = viz.RED)Cone.renderOnlyToWindows([UpperLeftWindow])viz.link(view,Cone)

################# 軌跡レンダ ################viz.startLayer(viz.LINE_STRIP)viz.vertexColor(viz.YELLOW)lines = viz.endLayer(parent=viz.ORTHO,scene=UpperLeftWindow)
lines.dynamic()
def UpdatePath():
    # Get main view position in bird eye window pixel coordinates    x,y,z = UpperLeftWindow.worldToScreen(viz.MainView.getPosition(),mode=viz.WINDOW_PIXELS)
    # Get position of last line vertex    lx,ly,lz = lines.getVertex(-1)
    # Add new vertex if current position is different from last position    if x != lx or y != ly:        lines.addVertex([x,y,0.0])
vizact.ontimer(0,UpdatePath)
#スペースキーで軌跡削除vizact.onkeydown('',lines.clearVertices)


################# 地面の生成 ################ground = viz.addChild('ground.osgb')ground.setPosition([0,0,0])
################# 迷路の生成 ################wall1 = vizshape.addBox(size = [4,2,0.05])wall2 = vizshape.addBox(size = [0.05,2,4])wall3 = vizshape.addBox(size = [0.05,2,4])wall4 = vizshape.addBox(size = [4,2,0.05])wall5 = vizshape.addBox(size = [0.05,2,3])wall6 = vizshape.addBox(size = [2,2,0.05])wall7 = vizshape.addBox(size = [0.05,2,2])wall8 = vizshape.addBox(size = [0.05,2,1])wall9 = vizshape.addBox(size = [1,2,0.05])
wall1.setPosition([-2,1,0])wall2.setPosition([0,1,2])wall3.setPosition([-4,1,2])wall4.setPosition([-2,1,4])wall5.setPosition([-1,1,1.5])wall6.setPosition([-2,1,1])wall7.setPosition([-2,1,3])wall8.setPosition([-3,1,2.5])wall9.setPosition([-3.5,1,2])
################# ゴールの生成 ################goal = viz.add('logo.wrl',pos=[-3.5,1.2,2.5],euler=[0,0,0],scale=[0.2,0.2,0.2])


####################################被験者がエリア内にいる間矢印を非表示にする######################################################矢印を配置#############cone = viz.addChild('tut_cone.wrl')cone.setScale([0.08,0.08,0.08])cone.color([255,212,0])cone.setEuler(0,90,0)
#Copy main view transform to arrow'stransform every frame #viz.MainView is source object, arrow is destination object coneLink = viz.link(viz.MainView, cone, mask=viz.LINK_POS ) coneLink.preTrans([0, 0.2, 0.5])
#目的地の方向に矢印を回転させるdef HeadingArrow():    POS = cone.getPosition()#    print POS        GOAL_POS =[-3.5,0,2.5]            if GOAL_POS[2] > POS[2]:        DEG = math.atan((POS[0]-GOAL_POS[0])/(GOAL_POS[2]-POS[2]))*(180/math.pi)        cone.setEuler(90-DEG,90,90)        if GOAL_POS[2] < POS[2]:        DEG = math.atan((POS[0]-GOAL_POS[0])/(POS[2]-GOAL_POS[2]))*(180/math.pi)        cone.setEuler(DEG-90,90,90)    vizact.ontimer(0,HeadingArrow)





#############センサー追加準備##############Create proximity manager and set debug on. Toggle debug with d keymanager = vizproximity.Manager()manager.setDebug(viz.ON)debugEventHandle = vizact.onkeydown('d',manager.setDebug,viz.TOGGLE)
#Add main viewpoint as proximity targettarget = vizproximity.Target(viz.MainView)manager.addTarget(target)
#############センサーを追加する#############verts = [ [-1,2], [-2,2], [-2,3], [-3,3], [-3,1], [-1,1] ]sensor = vizproximity.Sensor( vizproximity.PolygonArea(verts,offset=[0,0]), None )
SEN =[0]SEN[0] =True
#経路案内を消すdef Enter(e):    cone.visible(viz.OFF)    SEN[0] = False# text[0].remove()
#経路案内を出すdef Exit(e):    cone.visible(viz.ON)    SEN[0] = True
manager.addSensor(sensor)manager.onEnter(sensor, Enter)manager.onExit(sensor, Exit)
#目的地までの距離を表示d = 0text= [0] #グローバルに定義 text[0] = viz.addText(str(d) + 'm',pos=[2, 0.6, 3.5],scale=[0.05,0.05,0.05],parent=viz.WORLD)
def MeasureDistance():    if SEN[0] == True:        text[0].remove()                POS_NOW = viz.MainView.getPosition()        p1 = [POS_NOW[0],0,POS_NOW[2]]        p2 = [-3.5,0,2.5]                distance = vizmat.Distance(p1,p2)        d = round(distance,2)        print(d)                text[0] = viz.addText(str(d) + 'm',pos=[2, 0.6, 3.5],scale=[0.05,0.05,0.05],parent=viz.WORLD)        textLink = viz.link(viz.MainView, text[0])        textLink.preTrans( [0, -0.1, 0.2] )

vizact.ontimer(0.1,MeasureDistance)

############################### データ出力 ######################################def onTimer(num): # #データを取得し、ファイルへ出力&マスクを移動する# curr_time = time.clock() - reset_time[0]## # POS_HEAD[0] = viz.MainView.getPosition() #頭の位置を取得# ORI_HEAD[0] = viz.MainView.getEuler() #頭の回転角を取得# # data  = str(subject)+'\t'+str(round(curr_time,3))+'\t'# data += str(round(POS_HEAD[0][0],3))+'\t'+str(round(POS_HEAD[0][1],3))+'\t'+str(round(POS_HEAD[0][2],3))+'\t'# data += str(round(ORI_HEAD[0][0],3))+'\t'+str(round(ORI_HEAD[0][1],3))+'\t'+str(round(ORI_HEAD[0][2],3))+'\n'# # print data# # expelimental_data.write(data)## prev_time = curr_time##viz.callback(viz.TIMER_EVENT, onTimer)##viz.starttimer(EVENT_TIMER_ID, EVENT_TIMER_PERIOD, viz.PERPETUAL)################################################################################

目的地までの経路をラインで指示する

##############################################################################################################################################################################''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' VIZARD/PYTHON SCRIPT FOR IMMERSIVE 3D EXPERIMENTS.  ALL RIGHTS RESERVED YOSHIOKA LAB, CHIBA UNIVERSITY, JAPAN.
This Script Based on using the following equipments. - WorldViz Vizard 5.0 over '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#######################################################################################
import vizimport vizactimport vizshapeimport viztrackerimport vizproximityimport randomimport mathimport csvimport datetimeimport vizinputimport timeimport viztaskimport vizmatimport projectorimport sysimport vizcamimport vizfximport vizconnectimport vizinfo
viz.go()viz.setMultiSample(4)viz.fov(80)
viz.MainView.setPosition([-2.5,1.5,3.5])viz.MainView.setEuler([-90,0,0])#viz.MainView.collision(viz.ON)
# Add a white directional light pointing down light = vizfx.addDirectionalLight(euler=(0,90,0), color=viz.WHITE)
###########VIVE###################import steamvr### Setup SteamVR HMD#hmd = steamvr.HMD()#if not hmd.getSensor():# sys.exit('SteamVR HMD not detected')### Setup navigation node and link to main view#navigationNode = viz.addGroup()#viewLink = viz.link(navigationNode, viz.MainView)#viewLink.preMultLinkable(hmd.getSensor())
################################## グローバル変数一覧  #####################################POS_HEAD = [0] #頭位置[x,y,z]POS_HEAD[0] = 0ORI_HEAD = [0] #頭角度[r,p,y]ORI_HEAD[0] = 0
#print POS_HEAD
reset_time = [0] #時刻リセット用変数reset_time[0] = 0
flagLogging = [0] #データ記録フラグflagLogging[0] = False
###############データ出力の準備 #############EVENT_TIMER_ID = 1 #イベントチェックタイマーIDEVENT_TIMER_PERIOD = 0.1 #チェック間隔[s]PROCESS_TIMER_ID = 2 #データ保存タイマーIDPROCESS_TIMER_PERIOD = 0.016666666 #データ保存間隔[s] ≒ 60Hzoutfile = None #出力ファイルオブジェクト(内部用)outcsv = None #CSVフォーマットオブジェクト(内部用)start_time = time.time() #経過時間(内部用)
#subject = 1 #被験者識別番号、実験開始前に被験者毎に設定する##FileName='tanabe_experiment'+datetime.datetime.today().strftime("%Y%m%d")+'_Sub'+str(subject)+'.txt'#Header ='Subject'+'\t'+'Lap_time'+'\t'#Header +='PosX'+'\t'+'PosY'+'\t'+'PosZ'+'\t'+'Yaw'+'\t'+'Pitch'+'\t'+'Roll'+'\n'#expelimental_data = open(FileName,'a') #expelimental_data.write(Header)


################### 左上に検証用サブウィンドウを作成 ####################UpperLeftWindow = viz.addWindow(pos=(0,1.0),size=(0.25,0.25))UpperLeftWindow.visible(0,viz.SCREEN)BirdView = viz.addView() #Create a new viewpointUpperLeftWindow.setView(BirdView) #Attach the bird's eye view to the upper left windowBirdView.setPosition([-2,6,2]) #Move the view above the center of the roomBirdView.setEuler([90,90,90]) #Rotate the view so that it looks downUpperLeftWindow.fov(60)
#MainViewのポジションを赤いConeにリンクさせるview = viz.MainViewCone = vizshape.addCone(radius=0.1,height=0.3, axis=vizshape.AXIS_Z,color = viz.RED)Cone.renderOnlyToWindows([UpperLeftWindow])viz.link(view,Cone)

################# 軌跡レンダ ################viz.startLayer(viz.LINE_STRIP)viz.vertexColor(viz.YELLOW)lines = viz.endLayer(parent=viz.ORTHO,scene=UpperLeftWindow)
lines.dynamic()
def UpdatePath():
    # Get main view position in bird eye window pixel coordinates    x,y,z = UpperLeftWindow.worldToScreen(viz.MainView.getPosition(),mode=viz.WINDOW_PIXELS)
    # Get position of last line vertex    lx,ly,lz = lines.getVertex(-1)
    # Add new vertex if current position is different from last position    if x != lx or y != ly:        lines.addVertex([x,y,0.0])
vizact.ontimer(0,UpdatePath)
#スペースキーで軌跡削除vizact.onkeydown('',lines.clearVertices)


################# 地面の生成 ################ground = viz.addChild('ground.osgb')ground.setPosition([0,0,0])
################# 迷路の生成 ################wall1 = vizshape.addBox(size = [4,2,0.05])wall2 = vizshape.addBox(size = [0.05,2,4])wall3 = vizshape.addBox(size = [0.05,2,4])wall4 = vizshape.addBox(size = [4,2,0.05])wall5 = vizshape.addBox(size = [3,2,0.05])wall6 = vizshape.addBox(size = [0.05,2,2])wall7 = vizshape.addBox(size = [2,2,0.05])wall8 = vizshape.addBox(size = [1,2,0.05])wall9 = vizshape.addBox(size = [0.05,2,1])
wall1.setPosition([-2,1,0])wall2.setPosition([0,1,2])wall3.setPosition([-4,1,2])wall4.setPosition([-2,1,4])wall5.setPosition([-1.5,1,1])wall6.setPosition([-1,1,2])wall7.setPosition([-3,1,2])wall8.setPosition([-2.5,1,3])wall9.setPosition([-2,1,3.5])
################# ゴールの生成 ################goal = viz.add('logo.wrl',pos=[-0.5,1.2,0.5],euler=[-90,0,0],scale=[0.2,0.2,0.2])


####################################被験者がエリア内にいる時に経路案内のラインを非表示にする######################################################ルートラインを配置##############inport skethupviz.setOption('viz.model.apply_collada_scale',1) route = viz.add('route.dae')route.setPosition([-0.5,0.5,0.5])
#############センサー追加準備##############Create proximity manager and set debug on. Toggle debug with d keymanager = vizproximity.Manager()manager.setDebug(viz.ON)debugEventHandle = vizact.onkeydown('d',manager.setDebug,viz.TOGGLE)
#Add main viewpoint as proximity targettarget = vizproximity.Target(viz.MainView)manager.addTarget(target)
#############センサーを追加する#############verts = [ [-1,4], [-1,2], [-3,2], [-3,3], [-2,3], [-2,4] ]sensor = vizproximity.Sensor( vizproximity.PolygonArea(verts,offset=[0,0]), None )
#ルートラインを消すdef Enter(e): route.visible(viz.OFF) #ルートラインを出すdef Exit(e): route.visible(viz.ON) manager.addSensor(sensor)manager.onEnter(sensor, Enter)manager.onExit(sensor, Exit)


############################### データ出力 ######################################def onTimer(num): # #データを取得し、ファイルへ出力&マスクを移動する# curr_time = time.clock() - reset_time[0]## # POS_HEAD[0] = viz.MainView.getPosition() #頭の位置を取得# ORI_HEAD[0] = viz.MainView.getEuler() #頭の回転角を取得# # data  = str(subject)+'\t'+str(round(curr_time,3))+'\t'# data += str(round(POS_HEAD[0][0],3))+'\t'+str(round(POS_HEAD[0][1],3))+'\t'+str(round(POS_HEAD[0][2],3))+'\t'# data += str(round(ORI_HEAD[0][0],3))+'\t'+str(round(ORI_HEAD[0][1],3))+'\t'+str(round(ORI_HEAD[0][2],3))+'\n'# # print data# # expelimental_data.write(data)## prev_time = curr_time##viz.callback(viz.TIMER_EVENT, onTimer)##viz.starttimer(EVENT_TIMER_ID, EVENT_TIMER_PERIOD, viz.PERPETUAL)################################################################################

コーナーでのみ経路を矢印で指示する

##############################################################################################################################################################################''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' VIZARD/PYTHON SCRIPT FOR IMMERSIVE 3D EXPERIMENTS.  ALL RIGHTS RESERVED YOSHIOKA LAB, CHIBA UNIVERSITY, JAPAN.
This Script Based on using the following equipments. - WorldViz Vizard 7.0 over '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#######################################################################################
import vizimport vizactimport vizshapeimport viztrackerimport vizproximityimport randomimport mathimport csvimport datetimeimport vizinputimport timeimport viztaskimport vizmatimport projectorimport sysimport vizcamimport vizfximport vizconnectimport vizinfo
viz.go()viz.setMultiSample(4)viz.fov(80)
viz.MainView.setPosition([-0.5,1.5,0.5])viz.MainView.setEuler([-90,0,0])#viz.MainView.collision(viz.ON) 
# Add a white directional light pointing down light = vizfx.addDirectionalLight(euler=(0,90,0), color=viz.WHITE)
###########VIVE###################import steamvr### Setup SteamVR HMD#hmd = steamvr.HMD()#if not hmd.getSensor():# sys.exit('SteamVR HMD not detected')### Setup navigation node and link to main view#navigationNode = viz.addGroup()#viewLink = viz.link(navigationNode, viz.MainView)#viewLink.preMultLinkable(hmd.getSensor())
################################## グローバル変数一覧  #####################################POS_HEAD = [0] #頭位置[x,y,z]POS_HEAD[0] = 0ORI_HEAD = [0] #頭角度[r,p,y]ORI_HEAD[0] = 0
#print POS_HEAD
reset_time = [0] #時刻リセット用変数reset_time[0] = 0
flagLogging = [0] #データ記録フラグflagLogging[0] = False
###############データ出力の準備 #############EVENT_TIMER_ID = 1 #イベントチェックタイマーIDEVENT_TIMER_PERIOD = 0.1 #チェック間隔[s]PROCESS_TIMER_ID = 2 #データ保存タイマーIDPROCESS_TIMER_PERIOD = 0.016666666 #データ保存間隔[s] ≒ 60Hzoutfile = None #出力ファイルオブジェクト(内部用)outcsv = None #CSVフォーマットオブジェクト(内部用)start_time = time.time() #経過時間(内部用)
#subject = 1 #被験者識別番号、実験開始前に被験者毎に設定する##FileName='tanabe_experiment'+datetime.datetime.today().strftime("%Y%m%d")+'_Sub'+str(subject)+'.txt'#Header ='Subject'+'\t'+'Lap_time'+'\t'#Header +='PosX'+'\t'+'PosY'+'\t'+'PosZ'+'\t'+'Yaw'+'\t'+'Pitch'+'\t'+'Roll'+'\n'#expelimental_data = open(FileName,'a') #expelimental_data.write(Header)


################### 左上に検証用サブウィンドウを作成 ####################UpperLeftWindow = viz.addWindow(pos=(0,1.0),size=(0.25,0.25))UpperLeftWindow.visible(0,viz.SCREEN)BirdView = viz.addView() #Create a new viewpointUpperLeftWindow.setView(BirdView) #Attach the bird's eye view to the upper left windowBirdView.setPosition([-2,6,2]) #Move the view above the center of the roomBirdView.setEuler([90,90,90]) #Rotate the view so that it looks downUpperLeftWindow.fov(60)
#MainViewのポジションを赤いConeにリンクさせるview = viz.MainViewCone = vizshape.addCone(radius=0.1,height=0.3, axis=vizshape.AXIS_Z,color = viz.RED)Cone.renderOnlyToWindows([UpperLeftWindow])viz.link(view,Cone)
################# 軌跡レンダ ################viz.startLayer(viz.LINE_STRIP)viz.vertexColor(viz.YELLOW)lines = viz.endLayer(parent=viz.ORTHO,scene=UpperLeftWindow)
lines.dynamic()
def UpdatePath():
    # Get main view position in bird eye window pixel coordinates    x,y,z = UpperLeftWindow.worldToScreen(viz.MainView.getPosition(),mode=viz.WINDOW_PIXELS)
    # Get position of last line vertex    lx,ly,lz = lines.getVertex(-1)
    # Add new vertex if current position is different from last position    if x != lx or y != ly:        lines.addVertex([x,y,0.0])
vizact.ontimer(0,UpdatePath)
##スペースキーで軌跡削除#vizact.onkeydown('',lines.clearVertices)


################# 地面の生成 ################ground = viz.addChild('ground.osgb')ground.setPosition([0,0,0])
################# 迷路の生成 ################wall1 = vizshape.addBox(size = [4,2,0.05])wall2 = vizshape.addBox(size = [0.05,2,4])wall3 = vizshape.addBox(size = [0.05,2,4])wall4 = vizshape.addBox(size = [4,2,0.05])wall5 = vizshape.addBox(size = [3,2,0.05])wall6 = vizshape.addBox(size = [0.05,2,2])wall7 = vizshape.addBox(size = [2,2,0.05])wall8 = vizshape.addBox(size = [1,2,0.05])wall9 = vizshape.addBox(size = [0.05,2,1])
wall1.setPosition([-2,1,0])wall2.setPosition([0,1,2])wall3.setPosition([-4,1,2])wall4.setPosition([-2,1,4])wall5.setPosition([-1.5,1,1])wall6.setPosition([-1,1,2])wall7.setPosition([-3,1,2])wall8.setPosition([-2.5,1,3])wall9.setPosition([-2,1,3.5])
################# スタート・ゴールの生成 ################start = viz.add('logo.wrl',pos=[-1,1.2,0.5],euler=[-90,0,0],scale=[0.2,0.2,0.2])start.visible(viz.OFF)
goal = viz.add('logo.wrl',pos=[-2.5,1.2,3.5],euler=[90,0,0],scale=[0.2,0.2,0.2])


####################################被験者がエリア内にいる時に矢印ナビゲーションを表示する######################################################矢印を配置##############inport skethupviz.setOption('viz.model.apply_collada_scale',1)arrow_straight1 = viz.add('arrow_straight.dae') arrow_straight1.setPosition([-1.5,0.5,0.5])arrow_straight1.setEuler([-90,0,0])#arrow_straight1.visible(viz.OFF)arrow_straight2 = arrow_straight1.clone(pos=[-0.5,0.5,2.5])arrow_straight2.setEuler([180,0,0])arrow_straight2.visible(viz.OFF)arrow_right1 = viz.add('arrow.dae')arrow_right1.setPosition([-3,0.5,0.5])arrow_right1.setEuler([-90,0,0])arrow_right1.visible(viz.OFF) arrow_right2 = arrow_right1.clone(pos=[-3.5,0.5,1])arrow_right2.visible(viz.OFF)arrow_right3 = arrow_right2.clone(pos=[-3.5,0.5,3])arrow_right3.visible(viz.OFF)
#############センサー追加準備##############Create proximity manager and set debug on. Toggle debug with d keymanager = vizproximity.Manager()manager.setDebug(viz.ON)debugEventHandle = vizact.onkeydown('d',manager.setDebug,viz.TOGGLE)
#Add main viewpoint as proximity targettarget = vizproximity.Target(viz.MainView)manager.addTarget(target)
#############右折用センサーを追加する#############sensor1 = vizproximity.Sensor( vizproximity.RectangleArea([1,1],center=[-2.5,0.5]), None )
#矢印を消すdef EnterR1(e): arrow_right1.visible(viz.ON) #矢印を出すdef ExitR1(e): arrow_right1.visible(viz.OFF)
manager.addSensor(sensor1)manager.onEnter(sensor1, EnterR1)manager.onExit(sensor1, ExitR1)

sensor2 = vizproximity.Sensor( vizproximity.RectangleArea([1,1],center=[-3.5,0.5]), None )
#矢印を消すdef EnterR2(e): arrow_right2.visible(viz.ON) #矢印を出すdef ExitR2(e): arrow_right2.visible(viz.OFF)
manager.addSensor(sensor2)manager.onEnter(sensor2, EnterR2)manager.onExit(sensor2, ExitR2)

sensor3 = vizproximity.Sensor( vizproximity.RectangleArea([1,1],center=[-3.5,2.5]), None )
#矢印を消すdef EnterR3(e): arrow_right3.visible(viz.ON) #矢印を出すdef ExitR3(e): arrow_right3.visible(viz.OFF) manager.addSensor(sensor3)manager.onEnter(sensor3, EnterR3)manager.onExit(sensor3, ExitR3)

#############直進用センサーを追加する#############sensor4 = vizproximity.Sensor( vizproximity.RectangleArea([1,1],center=[-1.5,0.5]), None )
#矢印を消すdef EnterS1(e): arrow_straight1.visible(viz.ON) #矢印を出すdef ExitS1(e): arrow_straight1.visible(viz.OFF)
manager.addSensor(sensor4)manager.onEnter(sensor4, EnterS1)manager.onExit(sensor4, ExitS1)



############################### データ出力 #####################################verts = [ [-1,4], [-1,2], [-3,2], [-3,3], [-2,3], [-2,4] ]sensor_timer = vizproximity.Sensor( vizproximity.PolygonArea(verts,offset=[0,0]), None )
#タイマーリセット#def Enter(e):# route.visible(viz.OFF)# ##タイマーリセット#def Exit(e):# route.visible(viz.ON)# #manager.addSensor(sensor)#manager.onEnter(sensor, Enter)#manager.onExit(sensor, Exit)
#def onTimer(num): # #データを取得し、ファイルへ出力&マスクを移動する# curr_time = time.clock() - reset_time[0]## # POS_HEAD[0] = viz.MainView.getPosition() #頭の位置を取得# ORI_HEAD[0] = viz.MainView.getEuler() #頭の回転角を取得# # data  = str(subject)+'\t'+str(round(curr_time,3))+'\t'# data += str(round(POS_HEAD[0][0],3))+'\t'+str(round(POS_HEAD[0][1],3))+'\t'+str(round(POS_HEAD[0][2],3))+'\t'# data += str(round(ORI_HEAD[0][0],3))+'\t'+str(round(ORI_HEAD[0][1],3))+'\t'+str(round(ORI_HEAD[0][2],3))+'\n'# # print data# # expelimental_data.write(data)## prev_time = curr_time##viz.callback(viz.TIMER_EVENT, onTimer)##viz.starttimer(EVENT_TIMER_ID, EVENT_TIMER_PERIOD, viz.PERPETUAL)################################################################################

手元にスマホライクなマップを表示する_Basic

#############################################################################################################################################################################''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' VIZARD/PYTHON SCRIPT FOR IMMERSIVE 3D EXPERIMENTS.  ALL RIGHTS RESERVED YOSHIOKA LAB, CHIBA UNIVERSITY, JAPAN.
This Script Based on using the following equipments. - WorldViz Vizard 7.0 over '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''#######################################################################################import vizimport vizshape
viz.go()viz.setMultiSample(4)viz.fov(80)ground = viz.addChild('ground.osgb')
################# Following Display ##################### Video as Texturevideo = viz.addRenderTexture() #Looking Down Camera SettingLookDownCam = viz.addRenderNode()LookDownCam.setEuler( [0, 90, 0] )Camera_Link = viz.link(viz.MainView,LookDownCam)Camera_Link.preTrans( [0, 10, 0] )
# Heading upCamera_Link.preEuler( [0, 90, 0] )
# North_UP#Camera_Link.setMask(viz.LINK_POS)
LookDownCam.setInheritView(False)LookDownCam.setRenderTexture(video)
#Following Display SettingFollowing_Display = vizshape.addPlane(size = [0.04,0.04])Following_Display.texture(video)
Display_Link = viz.link( viz.MainView,Following_Display)Display_Link.preTrans( [0.04, -0.04, 0.1] ) Display_Link.preEuler( [0, -80, 0] ) 
#Following Display SettingDirection_Cone = vizshape.addCone(radius=0.8,height=1)coneLink = viz.link(LookDownCam,Direction_Cone)coneLink.preTrans( [0, 0,  10] )

手元にスマホライクなマップを表示する_Basic_R

########################################################################################################'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''VIZARD/PYTHON SCRIPT FOR IMMERSIVE 3D EXPERIMENTS. ALL RIGHTS RESERVED YOSHIOKA LAB, CHIBA UNIVERSITY, JAPAN.
This Script Based on using the following equipments.- WorldViz Vizard 7.0 over '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''####################################################
import vizimport vizshape
viz.go()viz.setMultiSample(4)viz.fov(80)ground = viz.addChild('ground.osgb')
# Set a Looking Down CameraLookDownCam = viz.addRenderNode()LookDownCam.setInheritView(False)LookDownCam.setEuler( [0, 90, 0] )
# Link the camera to MainView only in position Camera_Link = viz.link(viz.MainView,LookDownCam)Camera_Link.setMask(viz.LINK_POS)Camera_Link.postTrans( [0, 10, 0] ) 
# Set and Link Display with MainviewFollowing_Display = vizshape.addPlane(size = [0.04,0.04])Display_Link = viz.link( viz.MainView,Following_Display)Display_Link.preTrans( [0.04, -0.04, 0.1] ) Display_Link.preEuler( [0, -80, 0] ) 
# Set View from Camera as a texture on Dispaly video = viz.addRenderTexture()LookDownCam.setRenderTexture(video)Following_Display.texture(video)
# Set a arrow that indicate the direction of MainviewDirection_Arrow = vizshape.addArrow(length=0.4,radiusRatio=0.2, tipLengthRatio=0.99)Direction_Arrow.renderOnlyToRenderNodes([LookDownCam], excludeMainPass = True)Arrow_Link = viz.link(viz.MainView,Direction_Arrow)Arrow_Link.postTrans( [0, 6,  0] ) 
def updateOrientation(): euler = viz.MainView.getEuler() Arrow_Link.setEuler([euler[0], 0, 0]) LookDownCam.setEuler( [euler[0], 90, 0] ) # Heading_UPvizact.ontimer(0, updateOrientation)

手元にスマホライクなマップを表示する_Advanced

##############################################################################################################################################################################''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' VIZARD/PYTHON SCRIPT FOR IMMERSIVE 3D EXPERIMENTS.  ALL RIGHTS RESERVED YOSHIOKA LAB, CHIBA UNIVERSITY, JAPAN.
This Script Based on using the following equipments. - WorldViz Vizard 7.0 over '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#######################################################################################
import vizimport vizactimport vizshapeimport viztrackerimport vizproximityimport randomimport mathimport csvimport datetimeimport vizinputimport timeimport viztaskimport vizmatimport projectorimport sysimport vizcamimport vizfximport vizconnectimport vizinfo
viz.go()viz.setMultiSample(4)viz.fov(80)
viz.MainView.setPosition([-3.5,1.5,2.5])viz.MainView.setEuler([0,0,0])#viz.MainView.collision(viz.ON)
# Add a white directional light pointing down light = vizfx.addDirectionalLight(euler=(0,90,0), color=viz.WHITE)
###########VIVE###################import steamvr### Setup SteamVR HMD#hmd = steamvr.HMD()#if not hmd.getSensor():# sys.exit('SteamVR HMD not detected')### Setup navigation node and link to main view#navigationNode = viz.addGroup()#viewLink = viz.link(navigationNode, viz.MainView)#viewLink.preMultLinkable(hmd.getSensor())
################################## グローバル変数一覧  #####################################POS_HEAD = [0] #頭位置[x,y,z]POS_HEAD[0] = 0ORI_HEAD = [0] #頭角度[r,p,y]ORI_HEAD[0] = 0
#print POS_HEAD
reset_time = [0] #時刻リセット用変数reset_time[0] = 0
flagLogging = [0] #データ記録フラグflagLogging[0] = False
###############データ出力の準備 #############EVENT_TIMER_ID = 1 #イベントチェックタイマーIDEVENT_TIMER_PERIOD = 0.1 #チェック間隔[s]PROCESS_TIMER_ID = 2 #データ保存タイマーIDPROCESS_TIMER_PERIOD = 0.016666666 #データ保存間隔[s] ≒ 60Hzoutfile = None #出力ファイルオブジェクト(内部用)outcsv = None #CSVフォーマットオブジェクト(内部用)start_time = time.time() #経過時間(内部用)
#subject = 1 #被験者識別番号、実験開始前に被験者毎に設定する##FileName='tanabe_experiment'+datetime.datetime.today().strftime("%Y%m%d")+'_Sub'+str(subject)+'.txt'#Header ='Subject'+'\t'+'Lap_time'+'\t'#Header +='PosX'+'\t'+'PosY'+'\t'+'PosZ'+'\t'+'Yaw'+'\t'+'Pitch'+'\t'+'Roll'+'\n'#expelimental_data = open(FileName,'a') #expelimental_data.write(Header)


################### 左上に検証用サブウィンドウを作成 ####################UpperLeftWindow = viz.addWindow(pos=(0,1.0),size=(0.25,0.25))UpperLeftWindow.visible(0,viz.SCREEN)BirdView = viz.addView() #Create a new viewpointUpperLeftWindow.setView(BirdView) #Attach the bird's eye view to the upper left windowBirdView.setPosition([-2,6,2]) #Move the view above the center of the roomBirdView.setEuler([90,90,90]) #Rotate the view so that it looks downUpperLeftWindow.fov(60)
#MainViewのポジションを赤いConeにリンクさせるview = viz.MainViewCone = vizshape.addCone(radius=0.1,height=0.3, axis=vizshape.AXIS_Z,color = viz.RED)#Cone.renderOnlyToWindows([UpperLeftWindow])viz.link(view,Cone)

################# 軌跡レンダ ################viz.startLayer(viz.LINE_STRIP)viz.vertexColor(viz.YELLOW)lines = viz.endLayer(parent=viz.ORTHO,scene=UpperLeftWindow)
lines.dynamic()
def UpdatePath():
    # Get main view position in bird eye window pixel coordinates    x,y,z = UpperLeftWindow.worldToScreen(viz.MainView.getPosition(),mode=viz.WINDOW_PIXELS)
    # Get position of last line vertex    lx,ly,lz = lines.getVertex(-1)
    # Add new vertex if current position is different from last position    if x != lx or y != ly:        lines.addVertex([x,y,0.0])
vizact.ontimer(0,UpdatePath)
#スペースキーで軌跡削除vizact.onkeydown('',lines.clearVertices)


############## Screen and Fix Display ################
## Create render texture for camera video feed#video = viz.addRenderTexture()### Create render node for camera#cam = viz.addRenderNode()#cam.fov = 30.0#cam.setSize(1280,720)#cam.setInheritView(False)#cam.setPosition([-10.0, 11.0, 13.0])#cam.setRenderTexture(video)#cam.setMultiSample(viz.AUTO_COMPUTE)#cam.setRenderLimit(viz.RENDER_LIMIT_FRAME)##def UpdateCamera():# cam.lookAt(viz.MainView.getPosition())#vizact.ontimer(0,UpdateCamera)### Get handle to screen object and apply video feed to it#screen = model.getChild('screen')#screen.texture(video)##Display = vizshape.addPlane(size = [0.4,0.4])#Display.setPosition(0,1,2)#Display.setEuler(0,-40,0)#Display.texture(video)##cam.renderOnlyIfNodeVisible([screen,Display])

################## Following Display ##################### Video as Texturevideo3 = viz.addRenderTexture()
# Camera Settingcam3 = viz.addRenderNode()cam3.fov = 30.0cam3.setSize(2000,2000)cam3.setInheritView(False)cam3.setPosition([-1.9, 8, 2.0])cam3.setEuler([0,90,0])cam3.setRenderTexture(video3)cam3.setMultiSample(viz.AUTO_COMPUTE)cam3.setRenderLimit(viz.RENDER_LIMIT_FRAME)
cam3Link = viz.link( viz.MainView,cam3)cam3Link.setMask(viz.LINK_ORI)cam3Link.preEuler( [0, 90, 0] )
#cam3Link = viz.link( viz.MainView,cam3)#cam3Link.setMask(viz.LINK_POS)#cam3Link.preTrans([0, 8, 0])
# keep Look at the Mainview Movement#def UpdateCamera3():# cam3.lookAt(viz.MainView.getPosition())#vizact.ontimer(0,UpdateCamera3)
# Use up/down keys to zoom camera in/out#def CameraZoom(inc):# cam3.fov = viz.clamp(cam3.fov+inc,5.0,70.0)# cam3.setFov(cam3.fov,1.77,0.1,1000)#vizact.whilekeydown(viz.KEY_UP,CameraZoom,vizact.elapsed(-20.0))#vizact.whilekeydown(viz.KEY_DOWN,CameraZoom,vizact.elapsed(20.0))#CameraZoom(0.0)
#Following Display SettingDisplay_Move = vizshape.addPlane(size = [0.05,0.04])Display_Move.texture(video3)#cam3.renderOnlyIfNodeVisible([Display])
viewLink = viz.link( viz.MainView,Display_Move)viewLink.preTrans( [0.05, -0.04, 0.1] ) viewLink.preEuler( [0, -90, 0] )




################# 地面の生成 ################ground = viz.addChild('ground.osgb')ground.setPosition([0,0,0])
################# 迷路の生成 ################wall1 = vizshape.addBox(size = [4,2,0.05])wall2 = vizshape.addBox(size = [0.05,2,4])wall3 = vizshape.addBox(size = [0.05,2,4])wall4 = vizshape.addBox(size = [4,2,0.05])wall5 = vizshape.addBox(size = [0.05,2,3])wall6 = vizshape.addBox(size = [2,2,0.05])wall7 = vizshape.addBox(size = [0.05,2,2])wall8 = vizshape.addBox(size = [0.05,2,1])wall9 = vizshape.addBox(size = [1,2,0.05])
wall1.setPosition([-2,1,0])wall2.setPosition([0,1,2])wall3.setPosition([-4,1,2])wall4.setPosition([-2,1,4])wall5.setPosition([-1,1,1.5])wall6.setPosition([-2,1,1])wall7.setPosition([-2,1,3])wall8.setPosition([-3,1,2.5])wall9.setPosition([-3.5,1,2])

################# ゴールの生成 ################goal = viz.add('logo.wrl',pos=[-0.5,1.2,0.5],euler=[0,0,0],scale=[0.2,0.2,0.2])


####################################被験者がエリア内にいる時に経路案内のラインを非表示にする######################################################ルートラインを配置##############inport skethupviz.setOption('viz.model.apply_collada_scale',1) route = viz.add('route.dae')#route.renderOnlyToRenderNodes([cam3])route.renderToAllRenderNodesExcept([viz.MainView])route.setPosition([-0.5,0.5,0.5])route.setEuler([90,180,0])

#############センサー追加準備##############Create proximity manager and set debug on. Toggle debug with d keymanager = vizproximity.Manager()manager.setDebug(viz.ON)debugEventHandle = vizact.onkeydown('d',manager.setDebug,viz.TOGGLE)
#Add main viewpoint as proximity targettarget = vizproximity.Target(viz.MainView)manager.addTarget(target)
#############センサーを追加する#############verts = [ [-1,2], [-2,2], [-2,3], [-3,3], [-3,1], [-1,1] ]sensor = vizproximity.Sensor( vizproximity.PolygonArea(verts,offset=[0,0]), None )
#地図を消すdef Enter(e): Display_Move.visible(viz.OFF) #地図を出すdef Exit(e): Display_Move.visible(viz.ON) manager.addSensor(sensor)manager.onEnter(sensor, Enter)manager.onExit(sensor, Exit)


############################### データ出力 ######################################def onTimer(num): # #データを取得し、ファイルへ出力&マスクを移動する# curr_time = time.clock() - reset_time[0]## # POS_HEAD[0] = viz.MainView.getPosition() #頭の位置を取得# ORI_HEAD[0] = viz.MainView.getEuler() #頭の回転角を取得# # data  = str(subject)+'\t'+str(round(curr_time,3))+'\t'# data += str(round(POS_HEAD[0][0],3))+'\t'+str(round(POS_HEAD[0][1],3))+'\t'+str(round(POS_HEAD[0][2],3))+'\t'# data += str(round(ORI_HEAD[0][0],3))+'\t'+str(round(ORI_HEAD[0][1],3))+'\t'+str(round(ORI_HEAD[0][2],3))+'\n'# # print data# # expelimental_data.write(data)## prev_time = curr_time##viz.callback(viz.TIMER_EVENT, onTimer)##viz.starttimer(EVENT_TIMER_ID, EVENT_TIMER_PERIOD, viz.PERPETUAL)################################################################################

応用テクニック: 視点の等速移動

スペースキー打鍵中に視点を等速で前進させる(move)

import vizimport vizact
# 初期設定viz.go()ground =viz.addChild('ground.osgb')
# 移動関数MOVE_SPEED = 1.4
def move():    if viz.key.isDown(' '):  # スペースキーが押されている場合にのみ移動        viz.MainView.move([0, 0, MOVE_SPEED * viz.elapsed()])# タイマーイベントを設定して定期的にmove関数を呼び出すvizact.ontimer(0, move)

スペースキー打鍵中に視点を等速で前進させる(setPosition)

import vizimport vizact
# 初期設定viz.go()ground =viz.addChild('ground.osgb')
MOVE_SPEED = 1.4
# 移動関数def move():    if viz.key.isDown(' '):  # スペースキーが押されている場合にのみ移動        viz.MainView.setPosition([0, 1.5, viz.MainView.getPosition()[2] + (MOVE_SPEED * viz.elapsed())])
# タイマーイベントを設定して定期的にmove関数を呼び出すvizact.ontimer(0, move)

スペースキーを一度打鍵したらずっと等速移動(move)

import vizimport vizactimport steamvr
# Vizardの初期設定viz.go()
# 地面を追加groud = viz.addChild('ground.osgb')                                                 # SteamVR HMDの設定hmd = steamvr.HMD()
# HMDの向きと視点の向きをリンクviewLink = viz.link(hmd.getSensor(), viz.MainView)viewLink.setMask(viz.LINK_ORI)
# 等速移動MOVE_SPEED = 1.4def Auto_Move_Forward():    viz.MainView.move([0, 0, MOVE_SPEED * viz.elapsed()], viz.BODY_ORI)    # 前進を開始def start_moving():    vizact.ontimer(0, Auto_Move_Forward)
# スペースキーの押下でstart_moving関数を呼び出すvizact.onkeydown(' ', start_moving)

等速移動しながらもHMDの側方への動きは反映(setPosition)

import vizimport vizactimport steamvr
# Vizardの初期設定viz.go()
# 地面を追加groud = viz.addChild('ground.osgb')                                                 # SteamVR HMDの設定hmd = steamvr.HMD()
# 等速移動MOVE_SPEED = 1.4def Auto_Move_Forward():    HMD = hmd.getSensor()    viz.MainView.setEuler(HMD.getEuler())    viz.MainView.setPosition([        HMD.getPosition()[0],        HMD.getPosition()[1],         viz.MainView.getPosition()[2] + (MOVE_SPEED * viz.elapsed())        ])    # 前進を開始def start_moving():    vizact.ontimer(0, Auto_Move_Forward)
# スペースキーの押下でstart_moving関数を呼び出すvizact.onkeydown(' ', start_moving)

他のソフトウェアとの連携

各種デバイスとの接続(Vizconnect)

Vizconnect(Vizardに標準装備されている各種デバイスとのコネクトツール)

#Vizconnect Sample#
import vizimport vizconnect
viz.setMultiSample(4)vizconnect.go('config.py')
dojo = viz.addChild('dojo.osgb')

Cyberith Virtualizerの接続

Cyberith Virtualizer との接続

import vizimport vizactimport viztaskimport steamvrimport mathimport GazeUtils

#### Viz.go ####viz.setMultiSample(8)viz.go()
#### HMD(and Virtualizer/navigation)Setting ###hmd = steamvr.HMD()navigationNode = viz.addGroup()viewLink = viz.link(navigationNode, viz.MainView)viewLink.preMultLinkable(hmd.getSensor())
#### Cyberith Virtualizer Setting ####from cybsdk2 import *
class VirtPlugin: @staticmethod def AngleToVector(angle): return [math.sin(angle), 0, math.cos(angle)] @staticmethod def VectorScale(vector, scale): return [vector[0]*scale, vector[1]*scale, vector[2]*scale]
def updatevirtualizer(self): playerOrientation = virtualizer.GetPlayerOrientation() movementDirection = virtualizer.GetMovementDirection() movementSpeed = virtualizer.GetMovementSpeed()
movement = VirtPlugin.AngleToVector(playerOrientation * 2 * math.pi + movementDirection * math.pi) movement = VirtPlugin.VectorScale(movement, movementSpeed * 1.2) movement = VirtPlugin.VectorScale(movement, viz.elapsed()) navigationNode.setPosition(movement, viz.REL_PARENT) def ResetOrientation(): virtualizer.ResetPlayerOrientation() hmd.getSensor().reset() virtPlugin = VirtPlugin()
# 1. Get devicevirtualizer = Virt.FindDevice()if virtualizer == None:    print("No Virtualizer Device Found!")
# 2. Open connectionif virtualizer.Open() == False:    print("Unable to connect to Virtualizer!")
# 3. Update every framevizact.onkeydown('r', virtPlugin.ResetOrientation)vizact.ontimer(0, virtPlugin.updatevirtualizer)#######

StarVRとの接続

StarVR ONEとの接続

3dsMax連携

3dsMaxのモデルをvizardに読み込む 


import viz

viz.go()

ball = viz.add('ball.wrl')

  1. 3dsMaxでモデルを作成しテクスチャを割り当てる
  2. レンダラーを「Arnold」に設定する
  3. 光源を設置してテストレンダリング
  4. レンダリング > テクスチャベイク > 3Dモデルをクリック > 追加 >
  5. arnold-rgb > CompleteMapを選択 > 実行
  6. 出力されたテクスチャファイルをわかりやすい場所に保存
  7. 3dsMaxの球体モデルを、書き出し>wrlで保存(cf.ball.wrl)
  8. 保存したwrlファイルをVizard inspecterで開く(右クリック>プログラム>inspecter)
  9. ウィンドウ右側のmaterialの「+」ボタンを開き、  テクスチャファイルをドロップ
  10. 名前をつけて保存(例えばball.osgb, 自動的にosgb形式で保存される)
  11. 同一階層で新規vizardファイルを作成し、下記のコードを走らせる。

import viz

viz.go()

ball = viz.add('ball.osgb')

3dsMax2024でのテクスチャベイク

3dsMAXで、1m四方の立方体を作成して

テクスチャベイクしてFBXで出力する手順


0. 3ds Max起動


1. 立方体の作成


2. マテリアルの設定


3. UVマッピングの設定


4. 照明の追加


5. テクスチャラップの設定


6. テクスチャベイク



7. ベイク後のマテリアル適用


8. FBX形式での出力


9.出力結果の確認

How to Create a VR Experiment with Vizard

Performing Eye Tracking Studies in VR

Mixiamoの連携

Vizard Sample Script for Mixamo to Vizard
#########################################################'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''VIZARD/PYTHON SCRIPT FOR IMMERSIVE 3D EXPERIMENTS. ALL RIGHTS RESERVED YOSHIOKA LAB, CHIBA UNIVERSITY, JAPAN.'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''#########################################################
import vizimport vizactimport vizfx
viz.go()viz.fov(90)ground = viz.addChild('ground.osgb')
viz.MainView.setPosition(0,1.5,-5)
avatar = vizfx.addAvatar('PinkMan.osgb',pos =(-3,0,0),euler =[90,0,0])avatar.state(1)

def avatarTurn(): deg = avatar.getEuler() turn =vizact.turn(deg[0]+180,180,anim=1) avatar.runAction(turn)vizact.onkeydown('0',avatarTurn)
def avatarWalk(): walk = vizact.walkTo([3,0,0],1.5, walkAnim=2) avatar.runAction(walk)vizact.onkeydown('1',avatarWalk)
def avatarRun(): run = vizact.walkTo([-3,0,0],3.0, walkAnim=3) avatar.runAction(run)vizact.onkeydown('2',avatarRun)
def avatarSlowWalk(): SlowWalk = vizact.walkTo([3,0,0],1.1, walkAnim=4) avatar.runAction(SlowWalk)vizact.onkeydown('3',avatarSlowWalk)

Mixiamoのキャラクターの取り込み

AVATAR WORKFLOW TIPS FOR VIZARD 6 →Link

Mixamo to Vizard 手順

  1. Mixiamoでキャラクターを選択しfbxで保存 → Link
  2. キャラクターをvizard inspecterで開き各種調整
  3. OSGB形式で保存
  4. Vizardに読み込む( A = vizfx.addAvatar(***.osgb))

キャラクターのスケール調整

  • SceneGraphのツリー上層に”Transform”のnodeを追加する
  • 追加したTransformのnodeに対して拡大縮小を割り当てる

アニメーションの追加

  • Mixiamoから”WithoutSkin”でアニメーションデータをDL
  • 移動系のアニメーションはinPlaceを指定してDLがよい
  • inspecter右のAnimeationにimportすればState化される

Viveコントローラーとの接続 その1
import vizimport steamvr
viz.go()piazza = viz.addChild('piazza.osgb')
########### SteamVR HMDの設定 #############import steamvrhmd = steamvr.HMD()viz.link(hmd.getSensor(), viz.MainView)
###############  コントローラー操作  ############### 
Controller1 = steamvr.getControllerList()[0]Controller2 = steamvr.getControllerList()[1]
def ControllerState():
Trig_State_1 = Controller1.getTrigger()Pad_State_1 = Controller1.getTrackpad()
Trig_State_2 = Controller2.getTrigger()Pad_State_2 = Controller2.getTrackpad() data = str(Trig_State_1)+','+str(Pad_State_1)+','+str(Trig_State_2)+','+str(Pad_State_2)+'\n'
print(data)  
vizact.ontimer(0,ControllerState)