2015年12月18日金曜日

vpyhton pyode 座標2


# 最終結論GeomBoxの引数の順所が違ったためボールをすりぬけていた。
#        #self.geom = ode.GeomBox(
#        #        space=field.space, lengths=(w, h, l))
#        self.geom = ode.GeomBox(
#                space=field.space, lengths=(l, h, w))
#
# 以下のコードは必要ない
#        #self.vbox.rotate(angle=pi/2.0, axis=(0,1,0))
#        #y軸方向右ねじに回転


rotateを生かす

rotateを殺す



vpython HPより
# coding: UTF-8
# どうやってもボールがすり抜けるやつがある
# C:\myprg_main\python_my_prg\ode_prg\cylinder_geom.py
# 座標のxプラス方向 yのプラス方向 zのプラス方向は c言語のodeの
# 座標の画像とあわしている。zは勝手に緑に設定

# ボールのバウンド状態から判断すると
# Boxクラスのrotate を殺すと vpythonのboxは回転しないで描画されるが
# pyodeのgeomはy軸に90度回転した状態となっている
# pyodeとvpytonの座標は一致するが vpytonに.geom.getRotation()などと
# geomから姿勢をセットするとy軸にたいして90度違ってくるのだろう
# E:\howm\gazou\v_ode_python_no_rotate_zahyou.JPG
# E:\howm\gazou\v_ode_python_rotate_zahyou.JPG
# E:\howm\gazou\vpython_box.jpg

# cylinderについては rotateを使う必要はないようだ。
# ただvpython のcylinderのposがcylinderの端になっているので、
# E:\howm\gazou\vpython_cylinder.jpg
# cylinderyのposを -h/2 をして axis これはcylinderのz軸の長さが
# hとして 全体のposをframe.posで与えてある。
        self.vcyld = cylinder(
                frame=self.frame, pos=(0,0,-h/2),
                axis=(0, 0, h), radius=r) #vpythonの座標系でx,y,zの順
        self.frame.pos = pos


import random
import ode
from visual import *
#from time import sleep

global Flg
Flg = True
#Flg = False
boxList  = []
ballList = []
box_kosuu=5
ball_kosuu=500

class Field:
    scene = display(autoscale=0, forward=norm((-2.0,-1.0,-1.0)))
   
    #物理世界を作成
    world=ode.World()
    world.setGravity((0, -9.81, 0))
    #自由落下させたいなら worldのコメントアウトのほうを生かし
    # 最後の方の ball.body.addForce((0,-1000,0)) を殺す
    #world.setGravity((0, 0, 0))
    #地平面を作成?
    space=ode.Space()

    #衝突関係
    jointgroup=ode.JointGroup()
    ode_floor=ode.GeomPlane(space,(0,1,0),0)
    #0.2の引数を与えないとなぜかシリンダーが地面に少しめり込む
    # いや大丈夫みたい
    #()なかの引数 上の例ではy軸方向に重力が発生
    #多分 spaceの最後の引数が y軸の座標を示す
    ode_floor.setCategoryBits(1)
    ode_floor.setCollideBits(6)
    ode_floor.viz=box(
        pos=(0,-0.03,0),
        width=20,length=20,height=0.06,color=(0.5,0.5,1.0))

    #axis=(10,1,0),
    vball_x=sphere( pos=(7, 0, 0), radius=0.5, color=color.red)  #x軸
    vball_y=sphere( pos=(0, 7, 0), radius=0.5, color=color.blue)#y軸
    vball_z=sphere( pos=(0, 0, 7), radius=0.5, color=color.green) #z軸
    vball_z=sphere( pos=(0, 0, 0), radius=0.5, color=color.white) #原点

    target_fps=50
    #target_fps=30だから1秒間に30回の処理をする
    dt=1.0/target_fps

    def near_callback(self,args,geom1,geom2):
        #isBall = ((ground == o1) || (ground == o2));
        #if (isGround)//地面だけと衝突判定
        #print geom1
        for c in ode.collide(geom1,geom2):
            c.setBounce(1.0)
            c.setMu(5)#摩擦
            c.setMu2(5)
            c.setSoftERP(0.8)
            c.setSoftCFM(0)
            c.setBounceVel(0)
            c.setMotion1(0)
            #random.seed(1)
            j=ode.ContactJoint(self.world,self.jointgroup,c)
            j.attach(geom1.getBody(),geom2.getBody())

    def tick(self):
        for i in  range(len(ballList)):
            ballList[i].update()
        cyld.update()
        #box.update()
        print
        time.sleep(0.2)
        #sleepは import time しなくても使える。vpytonのtimeか?
        self.space.collide((),self.near_callback)
        self.world.step(self.dt)
        self.jointgroup.empty()
        return True

class Ball:
    def __init__(
            self,field,
            m_density=1,
            m_radius=0.2,
            g_radius=0.2,
            v_radius=0.2,
            b_pos=vector(0,0,0),
            b_sp =vector(0,0,0),
            v_color=color.cyan
            ):
        self.body=ode.Body(field.world)
        M=ode.Mass()
        M.setSphere(m_density, m_radius)
        #(密度,半径)
        self.body.setMass(M)
        self.body.setPosition(b_pos)

        #self.body.addForce(b_sp)
        self.geom=ode.GeomSphere(
                space=field.space,
                radius=g_radius
                )
        #このradiusが実際のバウンドを決める
        #多分 sphereの座標が0で radiusが0.3だから
        #posが0.3ぐらいのバウンド点になる
        self.geom.setCategoryBits(1)
        self.geom.setCollideBits(3)
        #ボール同士の衝突を避ける
        #上は Boxのジオメトリを作成
        self.geom.setBody(self.body)
        # 剛体にジオメトリをセット
        #self.frame = frame()
        #self.vball=sphere(
        #    frame=self.frame, radius=v_radius,
        #    color=v_color
        #    )
        self.vball=sphere(
            radius=v_radius,
            color=v_color
            )

    def update(self):
        #pos_tup = self.body.getPosition()
        #boxのジオメトリの位置を得る
        #self.frame.pos = pos_tup
        #mat = self.body.getRotation()

        pos = self.geom.getPosition()
        mat = self.geom.getRotation()
        #self.frame.pos = pos
        #self.frame.axis = mat[0], mat[3], mat[6]
        #self.frame.up = mat[1], mat[4], mat[7]
        self.vball.pos = pos
        self.vball.axis = mat[0], mat[3], mat[6]
        self.vball.up = mat[1], mat[4], mat[7]

class MetaBall:
    def __init__(self, field):

        pos=vector(0,0,0)
        for x in range(-4, 4):
            for z in range(-4, 4):
                pos.x = x
                pos.z = z
                pos.y = 5
                ballList.append(Ball(field, b_pos=pos))


class Cylinder:
    #多分pyodeとvpythonの座標系は一緒だったな
    def __init__(self, field, r, h, pos):
        self.body = ode.Body(field.world)
        M = ode.Mass()
        M.setCylinder(1, 3, r, h)#密度,方向1はx軸の向き,半径,長さ
        #方向のパラメータは役にたっていない
        self.body.setMass(M)
        self.body.setPosition(pos)
        #とりあえずbodyのシリンダーの位置はboxのように物体の重心にあるものとして設定
        #vpythonとpyodeのposが合うか?
        self.geom = ode.GeomCylinder(space=field.space, radius=r, length=h)#vpythonの座標でx,y,z
        self.geom.setBody(self.body)
        self.geom.setCategoryBits(2)
        self.geom.setCollideBits(3)
        self.frame = frame()
        #self.vbox = box(
        #        frame=self.frame, width= 1, height= 2, length= 5)
        self.vcyld = cylinder(
                frame=self.frame, pos=(0,0,-h/2),
                axis=(0, 0, h), radius=r) #vpythonの座標系でx,y,zの順
        self.frame.pos = pos
        #self.vcyld = cylinder(
        #        pos=(-h/2,0,0),
        #        axis=(h, 0, 0), radius=r) #vpythonの座標系でx,y,zの順

        #self.vcyldd2 = cylinder(
        #        pos=(0,1.5,-5/2), axis=(0,0,5), radius=1,
        #        color=color.yellow
        #        )

        #self.vbox.pos = (0, 1, 0)
        #方向w:z h:y l:x
        #self.visual.rotate(angle=visual.pi/2.0, axis=(0,1,0))

    def update(self):
        #self.body.setPosition((0, 1.5, 0))

        ##pos_tup = self.body.getPosition()
        ##self.frame.pos = pos_tup

        #v1 = vector(pos_tup[0], pos_tup[1], pos_tup[2])
        #pos_tup = tuple(v1)
        #self.frame.pos = pos_tup
        #self.frame.pos.x = pos_tup[0]
        #self.frame.pos.y = pos_tup[1] - self.vcyld.axis.x/2
        #self.frame.pos.z = pos_tup[2]
        #self.vcyld.pos = pos

        ##mat = self.body.getRotation()

        #self.vbox.pos = pos
        #self.frame.pos = pos

        pos = self.geom.getPosition()
        mat = self.geom.getRotation()
        self.frame.pos = pos
        self.frame.axis = mat[0], mat[3], mat[6]
        self.frame.up = mat[1], mat[4], mat[7]
       
class Box:
    def __init__(self, field, w, h, l, pos):
        #初期的設定では、Carクラスのなかで以下行のようにしているので
        #self.body = Box(field, width=2.0, height=0.5, length=3.5)

        self.body = ode.Body(field.world)
        M = ode.Mass()
        M.setBox(20, w, h, l)
        self.body.setMass(M)
        self.body.setPosition(pos)
        self.geom = ode.GeomBox(
                space=field.space, lengths=(w, h, l))
        self.geom.setBody(self.body)
        self.geom.setCategoryBits(2)
        self.geom.setCollideBits(3)
        self.frame = frame()
        self.vbox = box(
            frame=self.frame, width=w, height=h, length=l)
        self.vbox.rotate(angle=pi/2.0, axis=(0,1,0))
        #y軸方向右ねじに回転
        #なぜ 上のコードが必要かと言えば、pyodeのwは odeのl方向
        # pyodeのlは vpythonのw方向になる
        #ゆえに引数のみ vpythonとodeの引数でxとyが入れ替えて作成するか
        #self.vbox.rotate(angle=pi/2.0, axis=(0,1,0)) を実行すればいい
        #注意 vpythonとodeのCylinderでは posの位置が違う
        #端と重心の位置の違い
   
    def update(self):
        pos = self.geom.getPosition()
        mat = self.geom.getRotation()
        self.frame.pos = pos
        self.frame.axis = mat[0], mat[3], mat[6]
        self.frame.up = mat[1], mat[4], mat[7]



if __name__=='__main__':
    field = Field()
    metaball = MetaBall(field)

    ##Cylinderのバウンド状態を調べる
    cyld=Cylinder(field, 1, 5, (0,1.5,0))

    ##boxのバウンド状態を調べる
    #box = Box(field, 3, 2, 7, (0,1,0))
   
    #field.tick()
    #while Flg:
    # aキーで「世界」の進行を止めたり進めたり
    print 'aキーで「世界」の進行を止めたり進めたり'
    Flg = False
    while True:
        if field.scene.kb.keys:
            s1 = field.scene.kb.getkey()
            if s1 == 'a':
                Flg =True
                #print Flg
            while Flg:
                time.sleep(1)
                s1 = field.scene.kb.getkey()
                if s1 == 'a':
                    Flg = False
                    #print 'if'
                    #print Flg
                elif s1 != 'a':
                    Flg = True
                    #print 'else'
                    #print Flg
               
        field.tick()

0 件のコメント:

コメントを投稿

About

参加ユーザー

連絡フォーム

名前

メール *

メッセージ *

ページ

Featured Posts