φυβλαςのβλογ
บล็อกของ phyblas



maya python เบื้องต้น บทที่ ๑๕: การทำภาพเคลื่อนไหวด้วยเอ็กซ์เพรชชัน
เขียนเมื่อ 2016/03/10 22:04
แก้ไขล่าสุด 2021/09/28 16:42
ในบทก่อนๆนี้เราได้ทำภาพเคลื่อนไหวโดยใช้ระบบคีย์เฟรม ในบทนี้จะแนะนำอีกวิธีที่ใช้การได้ดีเช่นกัน คือใช้เอ็กซ์เพรชชัน

เอ็กซ์เพรชชัน เป็นวิธีการตั้งให้ค่าองค์ประกอบที่กำหนดเปลี่ยนแปลงไปตามเวลาโดยการกำหนดสมการความสัมพันธ์บางอย่างขึ้น

โดยทั่วไปสามารถกำหนดเอ็กซ์เพรชชันได้โดยเข้าไปที่ expression editor (エクスプレッション エディタ)

เข้าได้โดยดูที่เมนูด้านบน กดที่ Window (ウィンドウ)

ตามด้วย Animation Editors (アニメーション エディタ)

แล้วคลิก Expression Editor (エクスプレッション エディタ)



ช่องด้านล่างเป็นที่สำหรับพิมพ์เอ็กซ์เพรชชัน

อย่างไรก็ตาม เราสามารถตั้งเอ็กซ์เพรชชัน ได้โดยไม่ต้องมาเปิดดูหน้าต่างนี้แต่ใช้การเขียนโค้ดไพธอน

วิธีการคือใช้ฟังก์ชัน expression() โดยใส่เอ็กซ์เพรชชันที่ต้องการเขียนไว้ในแฟล็ก s (string)

พิมพ์ mc.expression(s=เอ็กซ์เพรชชันที่ต้องการเขียน)

โค้ดที่ใช้ในการพิมพ์เอ็กซ์เพรชชันนั้นเป็นภาษา MEL ซึ่งเป็นภาษาสั่งการหลักของมายา ไม่สามารถใช้ไพธอนในการเขียนได้

เทียบกับไพธอนแล้ว MEL มีคำสั่งอะไรต่างๆน้อยกว่า ไม่ได้เพียบพร้อมเท่า ดังนั้นอาจใช้งานได้ไม่ยืดหยุ่นเท่าไพธอน

อย่างไรก็ตาม เราสามารถใส่คำสั่งของไพธอนลงไปใน MEL ได้ด้วยการพิมพ์ python("โค้ดไพธอนที่ต้องการ")



วิธีการเขียนอาจมีได้หลากหลาย ขึ้นอยู่กับความสะดวก

โค้ดในภาษา MEL จะคั่นด้วย ; เสมอไม่ว่าจะขึ้นบรรทัดใหม่หรือไม่ ต่างจากไพธอนที่จะคั่นแค่กรณีที่ไม่ขึ้นบรรทัดใหม่ ดังนั้นถ้าไม่ใช่บรรทัดสุดท้ายจะต้องมีเครื่องหมาย ; ปิดท้าย

การประกาศตัวแปรในภาษา MEL นั้นจะต้องใช้ชื่อที่ขึ้นต้นด้วย $ เสมอ ทำให้แยกได้ชัดว่าถ้าเป็น $ ก็คือตัวแปรที่เราประกาศขึ้นใช้เองเพื่อใช้งาน

ในภาษา MEL ไม่ได้มีพวกค่าคงที่เช่นค่า π เตรียมเอาไว้แบบไพธอน จึงต้องกำหนดค่าเอาเอง $pi=3.14159265359

ยกตัวอย่างวิธีการใช้
mc.polyCube(n='watthu')
mc.expression(s='$A=10; $f=1; $k=0.5; $pi=3.14159265359; watthu.ty = exp(-$k*time)*$A*cos(2*$pi*$f*time);')

โดยที่ $A=10; $f=1; $k=0.5; $pi=3.14159265359; คือการประกาศค่าของตัวแปรที่เป็นค่าคงที่

watthu.ty ในที่นี้แทนองค์ประกอบ ty ของวัตถุ ในที่นี้กำหนดให้ค่าเป็นไปตามสมการที่ต้องการ ซึ่งมีค่าแปรเปลี่ยนไปตามเวลา time

time คือเวลาในหน่วยวินาที เป็นตัวแปรพิเศษที่กำหนดใช้ในภาษา MEL ไม่จำเป็นต้องขึ้นต้นด้วย $ นอกจาก time แล้วยังสามารถใช้ frame ซึ่งหมายถึงเวลาในหน่วยเฟรม

บางครั้งอาจเพิ่มแฟล็กไปอีกตัว คือ o (object) คือชื่อของวัตถุ ในกรณีนี้จะพิมพ์แบบนี้
mc.polyCube(n='watthu')
mc.expression(o='watthu',s='$A=10; $f=1; $k=0.5; $pi=3.14159265359; ty = exp(-$k*time)*$A*cos(2*$pi*$f*time);')

จะเห็นว่าพอกำหนดชื่อวัตถุแล้วภายในสมการจะพิมพ์แค่ ty โดยไม่ต้องใส่ชื่อของวัตถุแล้ว การเขียนแบบนี้อาจสะดวกในกรณีที่ต้องอ้างอิงถึงค่าของวัตถุนี้ในสมการหลาย ครั้ง

ถ้าจะแทนที่ค่า π ด้วยค่าจากฟังก์ชัน math.pi ของไพธอนก็อาจเขียนแบบนี้ python("math.pi")

แต่ค่าที่คืนกลับมาจะเป็นสายอักขระ ต้องใช้ float() เพื่อแปลงเป็นจำนวนจริงที่ต้องการอีกทีเป็น float(python("math.pi")) โดยรวมแล้วอาจเขียนเป็น
import math
mc.polyCube(n='watthu')
mc.expression(s='$A=10; $f=1; $k=0.5; watthu.ty = exp(-$k*time)*$A*cos(2*float(python("math.pi"))*$f*time);')



หรือถ้าต้องการประกาศตัวแปรจากในโค้ดไพธอนเลยก็อาจเขียนแบบนี้
import math
watthu = mc.polyCube()
A=10
f=1
k=0.5
mc.expression(o=watthu[0],s='ty = exp(-%f*time)*%f*cos(2*%f*%f*time);'%(k,A,math.pi,f))

ในนี้จะเห็นว่าตัวแปรต่างๆเข้าไปแทนค่า %f ตามลำดับ

ตัวแปรที่ใช้ไม่เพียงแค่ใช้ให้ขึ้นกับเวลา แต่ยังให้ขึ้นกับค่าองค์ประกอบอื่นได้ด้วย เช่นเมื่อเราติดสปริงที่ปลายมวลไปด้วย ก็สามารถใช้ค่า ty ของวัตถุเพื่อกำหนดความยาวของสปริงได้
import math
watthu = mc.polyCube(w=4,h=4,d=4)
spring = mc.polyHelix(c=20,h=20,r=0.1,w=3)
A=10
f=1
k=0.5
mc.expression(s=watthu[0]+'.ty = exp(-%f*time)*%f*cos(2*%f*%f*time);'%(k,A,math.pi,f),n='watthu_ty')
mc.expression(s=spring[1]+'.h = 20+'+watthu[0]+'.ty',n='spring_h')
mc.expression(s=spring[0]+'.ty = -10+'+watthu[0]+'.ty/2-2',n='spring_ty')



ในตัวอย่างนี้ได้ถือโอกาสเพิ่มแฟล็กอีกตัวหนึ่งลงไปด้วย นั่นคือ n (name) เป็นแฟล็กที่ใช้กำหนดชื่อของเอ็กซ์เพรชชัน เพื่อจะใช้อ้างอิงภายหลัง

ถ้าไม่กำหนดชื่อไว้มันจะถูกตั้งชื่อโดยอัตโนมัติเป็น expression ตามด้วยตัวเลขไปเรื่อยๆตามลำดับ

ฟังก์ชัน expression() สามารถใช้เพื่อดูเอ็กซ์เพรชชันที่ตั้งไปก่อนหน้านี้ได้ด้วย โดยใส่ชื่อของเอ็กซ์เพรชชันที่ต้องการหาค่าเป็นอาร์กิวเมนต์ จากนั้นใส่แฟล็ก q=1,s=1 เช่น
print(mc.expression('spring_h',q=1,s=1))

ก็จะได้ค่า
polyHelix1.height = 20+pCube1.translateY

จะเห็นว่าค่าที่ได้คืนกลับมาใช้ชื่อองค์ประกอบเป็นชื่อยาว นั่นเพราะมันถูกเปลี่ยนให้เป็นชื่อยาวโดยอัตโนมัติ แม้ว่าตอนที่เรากำหนดจะใช้ชื่อย่อก็ตาม

และเช่นเดียวกับบทที่แล้ว วิธีนี้สามารถนำมาใช้สร้างคลื่นในเส้นเชือกได้เหมือนกัน และดูง่ายกว่าด้วย
import math
A=10.
f=1.
k=0.5
for z in range(-40,41):
    chue = mc.polySphere(r=1,n='w%d'%z)
    mc.move(0,0,z)
    mc.expression(o=chue[0],s='ty = exp(-%f*time)*%f*cos(2*%f*%f*(time-tz/20));'%(k,A,math.pi,f))





บางทีการใช้เอ็กซ์เพรชชันก็อาจทำสิ่งที่ไม่เกี่ยวกับเวลาเลยก็เป็นได้ อาจแค่ใช้สร้างความสัมพันธ์ระหว่างค่าองค์ประกอบหนึ่งกับองค์ประกอบอื่น

เช่นในตัวอย่างนี้ สร้างทรงกระบอกที่เรียงตัวกันเป็นเกลียวรูปร่างแปลกๆ
for i in range(160):
    watthu = mc.polyCylinder(r=1)
    mc.move(i,0,0)
    mc.expression(o=watthu[0],s='ty = 25*pow(cos(tx/10),2)')
    mc.expression(o=watthu[1],s='h = 50*pow(cos('+watthu[0]+'.tx/10),2)')
    mc.expression(o=watthu[1],s='axy = 4*sin('+watthu[0]+'.tx/4)')
    mc.expression(o=watthu[1],s='axz = 4*cos('+watthu[0]+'.tx/4)')



ในนี้จะเห็นว่ากำหนดแค่ tx แต่ให้ไปเป็นตัวกำหนดองค์ประกอบอื่นๆ ได้แก่ความยาวและแกนหมุนของทรงกระบอก

โดยปกติแล้วมักจะใช้เอ็กซ์เพรชชันหนึ่งกำหนดค่าขององค์ประกอบทีละตัวแยกกัน แต่ว่าถ้าอยากกำหนดค่าองค์ประกอบหลายตัวไว้ในเอ็กซ์เพรชชันเดียวกันก็สามารถ ทำได้ เช่นตัวอย่างที่แล้วอาจเขียนใหม่เป็น
for i in range(160):
    watthu = mc.polyCylinder(r=1)
    mc.move(i,0,0)
    mc.expression(s=watthu[0]+'.ty = 25*pow(cos('+watthu[0]+'.tx/10),2); '
    +watthu[1]+'.h = 50*pow(cos('+watthu[0]+'.tx/10),2); '
    +watthu[1]+'.axy = 4*sin('+watthu[0]+'.tx/4); '
    +watthu[1]+'.axz = 4*cos('+watthu[0]+'.tx/4)')

แต่เพื่อความเป็นระเบียบ วิธีการเขียนแบบนี้อาจไม่ค่อยน่าแนะนำนัก



จบบทนี้เราได้เรียนรู้วิธีการสร้างภาพเคลื่อนไหวทั้งสองวิธีแล้วทั้งการใช้ คีย์เฟรมและใช้เอ็กซ์เพรชชัน พอมาถึงตรงนี้แล้วก็คงทำให้สามารถสร้างภาพเคลื่อนไหวอะไรต่างๆได้หลากหลาย ตามที่ต้องการ



อ้างอิง

<< บทที่แล้ว      บทถัดไป >>
หน้าสารบัญ


-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python >> mayapython
-- คอมพิวเตอร์ >> 3D >> maya

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

บทความแต่ละเดือน

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2020年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文