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