φυβλαςのβλογ
phyblasのブログ



maya python เบื้องต้น บทที่ ๑๖: การหมุน
เขียนเมื่อ 2016/03/10 23:14
แก้ไขล่าสุด 2021/09/28 16:42
ผ่านมาหลายบท ตอนนี้สามารถทำให้วัตถุเคลื่อนที่ได้แล้ว แต่ถ้าวัตถุแค่เคลื่อนที่ไปเรื่อยๆเฉยๆมันก็ดูแข็งทื่อ ดังนั้นบทนี้มารู้วิธีการทำให้วัตถุหมุน

การหมุนสามารถทำได้หลายวิธีด้วยกัน วิธีหนึ่งคือการปรับแกนดังที่พูดถึงไปแล้วใน บทที่ ๘

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

ค่าองค์ประกอบที่กำหนดทิศทางการหันของวัตถุทั่วไปคือ rx (rotateX), ry (rotateY) และ rz (rotateZ)

โดยการใช้ฟังก์ชัน getAttr() ปรับค่า สามารถทำให้หมุนไปในทิศทางไหนก็ได้ เช่น ลองสร้างแท่งสี่เหลี่ยมยาวๆมาอันนึง
mc.polyCube(w=1,h=20,d=1)





แล้วตั้งให้หมุนในแกน x
mc.setAttr('.rx',30)



จากนั้นลองให้หมุนในแกน y ดู
mc.setAttr('.ry',45)



จากนั้นลองให้หมุนในแกน z ดู
mc.setAttr('.rz',10)



ก็จะเห็นว่าวัตถุมีการหมุนไปเรื่อยๆ

ค่ามุมหมุนของ ๓ แกนอาจปรับไปพร้อมกันได้ เช่น
mc.setAttr('.r',30,45,10)

แต่ว่าการปรับค่าด้วยวิธีนี้ต้องพิจารณาเรื่องลำดับการหมุนด้วย ทำให้อาจเข้าใจยากหน่อย

ลำดับการหมุนกำหนดโดยค่าองค์ประกอบ ro (rotateOrder)
ro = 0 เป็น xyz
ro = 1 เป็น yzx
ro = 2 เป็น zxy
ro = 3 เป็น xzy
ro = 4 เป็น yxz
ro = 5 เป็น zyx

โดยค่าเริ่มต้นมักตั้งเป็น 0 นั่นคือ xyz

ดังนั้นถ้าเราเริ่มหมุนจาก x แล้วค่อยหมุน y สุดท้ายก็หมุน z ก็จะไม่มีปัญหาอะไร เข้าใจได้ง่าย

แต่ถ้าปรับค่า z แล้วค่อยไปปรับค่า y ก็อาจทำให้ได้ค่าที่แปลกไปจากที่ต้องการ

ในกรณีที่ต้องการแบบนั้นมีวิธีการหมุนที่ดีกว่า คือใช้ฟังก์ชัน rotate()

ฟังก์ชันนี้มีไว้ใช้สำหรับหมุนวัตถุ โดยอาร์กิวเมนต์ ๓ ตัวคือพิกัดการหมุนในแกน x y z ตามลำดับ และอาจใส่อาร์กิวเมนต์ตัวที่ ๔ คือชื่อของวัตถุที่ต้องการหมุน สำหรับในกรณีที่ไม่ได้เลือกวัตถุ แต่ถ้าไม่ใส่ก็จะหมุนวัตถุที่ถูกเลือกอยู่

กรณีที่ไม่ใส่แฟล็กอะไร การใช้ rotate นี้ก็มีค่าเหมือนกับการใช้ setAttr เช่น
mc.rotate(30,45,10) # มีผลเท่ากับ mc.setAttr('.r',30,45,10)

แต่ถ้าใส่แฟล็ก r (relate) ก็จะเป็นการหมุนแบบสัมพัทธ์ คือเทียบกับมุมที่หันอยู่ในตอนนี้ เช่น เริ่มจากลองสร้างวัตถุแล้วให้หมุนไปในมุมแบบตอนแรก
mc.polyCube(w=1,h=20,d=1)
mc.setAttr('.r',30,45,10)

จากนั้นลองหมุนในแกน x แบบสัมพัทธ์
mc.rotate(-30,0,0,r=1)

จะพบว่ามันหมุน ๓๐ องศาตามแกน x จริงๆ แต่พอลองพิมพ์
mc.getAttr('.r')

จะพบว่าค่าที่ได้ไม่ใช่ [0,45,10] แต่เป็น [-12, 42, -19] ทั้งๆที่ตอนแรก x เป็น 30 ถ้าหมุนกลับ -30 ดังนั้น x ก็น่าจะเป็น 0 แต่นี่ไม่ใช่ แถมแกนอื่นยังเปลี่ยนค่าไปด้วย เพราะอะไร?

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

แต่ถ้าหากหมุนแกน z ซึ่งเป็นแกนที่มีลำดับการหมุนอยู่ลำดับสุดท้ายอยู่แล้ว เช่นพิมพ์ต่อไปว่า
mc.rotate(0,0,19,r=1)

เมื่อดูค่ามุมหมุนจะพบว่ามีการเปลี่ยนแปลงแค่ในแกน z ไม่ได้กระทบต่อแกนอื่นไปด้วย

แฟล็กของ rotate() มีลักษณะคล้าย move() นั่นคือมีแฟล็กสำหรับหมุนเฉพาะบางแกน
x (rotateX)
y (rotateY)
z (rotateZ)
xy (rotateXY)
xz (rotateXZ)
yz (rotateYZ)

วิธีการใช้คล้ายกับของ move() ดังนั้นไม่กล่าวซ้ำ



นอกจากนี้แล้วสิ่งสำคัญที่ต้องพูดถึงก็คือเรื่องของจุดพีว็อต (ピボット, pivot) ซึ่งเป็นจุดแกนกลางในการหมุน

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

จุดพีว็อตนั้นมี ๒ จุดแยกกัน คือจุดพีว็อตของการหมุน กับจุดพีว็อตของมาตราส่วน ในที่นี้ขอพูดถึงพีว็อตของการหมุนก่อน

การย้ายจุดพีว็อตสามารถทำได้โดยคำสั่ง move() เหมือนกับวัตถุทั่วไป

เช่น ลองสร้างวัตถุแบบเดิมขึ้นมาใหม่แล้วย้ายพีว็อต
chue = mc.polyCube(w=1,h=20,d=1)
mc.select(chue[0]+'.rotatePivot')
mc.move(10,10,10)

หรืออาจกดเลือกที่ตัววัตถุแล้วพิมพ์แค่ .rotatePivot ดังนั้นอาจพิมพ์เป็นแบบนี้ได้เลย
chue = mc.polyCube(w=1,h=20,d=1)
mc.move(10,10,10,'.rotatePivot')

จุดพีว็อตไม่สามารถมองเห็นได้ถ้าไม่ตั้งให้มันแสดงผล สามารถให้แสดงได้โดยพิมพ์
mc.setAttr(chue[0]+'.displayRotatePivot',1)



หรือใช้ชื่อย่อเป็น
mc.setAttr(chue[0]+'.drp',1)

เพื่อให้แน่ใจว่าย้ายไปแล้วจริงๆสามารถพิมพ์
mc.getAttr('.rotatePivot')

ก็จะได้ตำแหน่งของจุดพีว็อต

พอย้ายจุดไปแบบนี้แล้ว พอลองพิมพ์
mc.rotate(0,120,0,chue[0])

จะพบว่าวัตถุถูกหมุนแล้วย้ายตำแหน่งไปไกล โดยแกนกลางการหมุนอยู่ที่พีว็อต



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

ดังนั้นหากต้องการให้วัตถุอยู่ห่างจากจุดพีว็อตก็ต้องมาทำการกำหนดตำแหน่งพีว็อตอีกที



ด้วยการย้ายพีว็อต เราอาจสามารถสร้างวัตถุที่มีสมมาตรแนวหมุนขึ้นมาได้อย่างง่าย เช่น
for i in range(36):
    mc.polyCylinder(r=1,h=2) # สร้างทั้งหมด 36 ชิ้น
    mc.move(10,0,0) # ทุกอันถูกย้ายไปในตำแหน่งนี้หมด
    mc.rotate(0,10*i,0,p=[0,0,0]) # แต่ถูกหมุนด้วยมุมที่ต่างกัน



หรือซับซ้อนกว่านั้น เช่น
for j in range(18):
    for i in range(36):
        mc.polyCylinder(r=1,h=2)
        mc.move(10,0,0)
        mc.move(0,0,0,'.rotatePivot')
        mc.rotate(0,10*i,10*j)



ที่จริงแล้วมีวิธีที่ง่ายกว่านั้นไปอีก โดยที่ไม่ต้องไปยุ่งอะไรกับพีว็อตเลย คือใช้แฟล็ก p (pivot) ในฟังก์ชัน rotate เพื่อกำหนดจุดศูนย์กลางในการหมุน โดยไม่จำเป็นต้องย้ายตำแหน่งพีว็อตก่อนเลย

ดังนั้นตัวอย่างนี้อาจเขียนใหม่ได้เป็น
for j in range(18):
    for i in range(36):
        mc.polyCylinder(r=1,h=2)
        mc.move(10,0,0)
        mc.rotate(0,10*i,10*j,p=[0,0,0])

สามารถทำภาพเคลื่อนไหวให้วัตถุหมุนไปมาได้โดยใช้ expression() หรือ setKeyframe()

ตัวอย่างการใช้เอ็กซ์เพรชชัน ลองจำลองการหมุนไปส่ายไป คล้ายลูกข่าง
mc.polyCone(r=4,h=20,ax=[0,-1,0],n='thaeng')
mc.expression(o='thaeng',s='rx = 60+15*cos(time*10)')
mc.expression(o='thaeng',s='ry = time*45')



ตอนต่อไปจะพูดถึงเรื่องมาตราส่วน ซึ่งเป็นเรื่องที่มีความใกล้เคียงกัน และมีความเกี่ยวข้องกันอยู่



อ้างอิง

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


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

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

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

หมวดหมู่

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

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

目次

日本による名言集
モジュール
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
機械学習
-- ニューラル
     ネットワーク
javascript
モンゴル語
言語学
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月

もっと前の記事

ไทย

日本語

中文