φυβλαςのβλογ
บล็อกของ 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)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

ไทย

日本語

中文