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



maya python เบื้องต้น บทที่ ๓๕: การใส่ภาพบนพื้นผิวโพลิกอน
เขียนเมื่อ 2016/03/14 15:19
แก้ไขล่าสุด 2021/09/28 16:42
ในบทที่แล้วได้แนะนำการใส่ภาพลงบนผิว NURBS ไปแล้ว คราวนี้จะเป็นการใส่ภาพลงบนโพลิกอน ซึ่งขั้นตอนจะแตกต่างกันเล็กน้อย

ขอใช้ภาพนี้เป็นตัวอย่าง ภาพจากเรื่อง gochuumon wa usagi desu ka หรือเรียกย่อๆ ว่า gochiusa


(คลิกเพื่อดูภาพใหญ่)


ภาพตัวอย่างนำมาจาก http://poppyoreos.deviantart.com/art/GochiUsa-Alice-in-Wonderland-Vector-462617042 โดยมีการตัดขอบซ้ายขวาออกไปเพื่อให้ได้ภาพสัดส่วน 8:5

หากใครอยากจะลองทำตามตัวอย่างก็สามารถใช้ภาพนี้ หรืออาจหาภาพของตัวเองมาใช้ดูได้

ลองสร้างลูกบาศก์แล้วเอาภาพมาติดดูกันเลย
mc.shadingNode('lambert',asShader=1,n='phap_gochiusa') # สร้างโหนดวัสดุ
mc.shadingNode('file',at=1,n='file_gochiusa') # สร้างโหนดเท็กซ์เจอร์ไฟล์ภาพ
mc.connectAttr('file_gochiusa.oc','phap_gochiusa.c') # เชื่อมโหนดวัสดุเข้ากับโหนดไฟล์ภาพ
s = '<พาธและชื่อไฟล์ภาพ>' # กำหนดไฟล์ภาพ
mc.setAttr('file_gochiusa.ftn',s,typ='string') # ตั้งพาธไฟล์ให้โหนดไฟล์ภาพ
mc.polyCube(w=4,h=4,d=4,n='gochiusa') # สร้างลูกบาศก์
mc.hyperShade(a='phap_gochiusa') # ใส่วัสดุให้ลูกบาศก์

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

แต่ครั้งนี้วัตถุมีรูปร่างซับซ้อน ไม่ได้เป็นแค่ผืนผ้าสี่เหลี่ยม แต่เป็นสี่เหลี่ยมหกหน้า ดังนั้นภาพก็เลยออกมาแปลกๆอย่างที่เห็น



และโพลิกอนก็ไม่สามารถใช้ place2dTexture แบบที่ใช้กับผิว NURBS ด้วย แต่ต้องใช้อีกวิธี

ปกติแล้วเวลาที่ใส่ภาพให้กับผิวโพลิกอนนั้นภาพจะถูกแปะในลักษณะไหนขึ้นอยู่กับการกาง UV

สามารถดูการกาง UV ได้โดยเลือกโหมดทางมุมซ้ายบนเป็น modeling (モデリング)



แล้วไปที่เมนู UV แล้วกดเลือก UV > UV Editor (UV エディタ)



เข้ามาถึงจะเห็นภาพของเราถูกบีบเป็นสี่เหลี่ยมจตุรัส อยู่ในมุมขวาบน ในนั้นนอกจากมีเส้นกริดแล้วหากมองชัดๆก็จะเห็นสี่เหลี่ยม ๖ อัน วางเรียงคล้ายลูกเต๋าที่คลี่ออก



สี่เหลี่ยมแต่ละอันแทนแต่ละหน้าของ ลูกบาศก์ และภาพที่ปรากฏบนลูกบาศก์ก็จะตรงตามที่อยู่ในช่องที่เทียบเท่ากันภาพนั้น ลองมองเทียบกันดูได้ เวลากดเลือกดูหน้าไหนหน้านั้นจะมีสีขึ้นมาเห็นได้ง่ายขึ้น

หากเราเลื่อนจุดหรือเส้นขอบต่างๆในแผนภาพนี้ก็จะสามารถเปลี่ยนภาพที่ปรากฏให้เป็นไปตามที่ต้องการได้

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

ที่จะใช้ในงานนี้ก็คือคำสั่งที่ช่วยปรับ UV ให้โดยอัตโนมัติตามความเหมาะสม นั่นคือฟังก์ชันที่ชื่อว่า polyProjection()

polyProjection() เป็นฟังก์ชันที่จะสร้างวัตถุที่เหมือนกับเป็นเครื่องฉายเพื่อทำการแม็ป UV ตามแนวที่ฉาย

การแม็ปโดยหลักๆแล้วมีอยู่ ๓ แบบคือ เป็นระนาบ แบบทรงกระบอก และแบบทรงกลม

สิ่งที่กำหนดรูปแบบการแม็ปคือ แฟล็ก t (type)
t='planar' ระนาบ (ค่าตั้งต้น)
t='cylindrical' ทรงกระบอก
t='spherical' ทรงกลม

ในที่นี้เราจะใช้แบบระนาบ คือให้ภาพฉายตรงไปแนวเดียว

ทิศของระนาบการฉายนั้นสามารถกำหนดได้ด้วยแฟล็ก md (mapDirection)
md='x' ตามแนวแกน x
md='y' ตามแนวแกน y
md='z' ตามแนวแกน z

เพียงแต่ว่าแต่ละหน้าหันไปคนละทิศกันจึงต้องทำการแม็ปแต่ละหน้าแยกกันหมด ลองทำเฉพาะด้านเดียวก่อน คือหน้า f[0] ซึ่งตั้งฉากกับแกน z ดังนั้น md='z'
mc.polyProjection('gochiusa.f[0]',t='planar',md='z')



ตอนนี้จะเห็นว่าเฉพาะหน้า f[0] ปรากฏเต็มรูปแล้ว แต่ว่ายังไม่สมบูรณ์เพราะภาพถูกปรับขนาดให้เต็มขนาดเท่ากับหน้าโดยอัตโนมัติ แต่ยังไม่ได้สัดส่วน

สิ่งที่ต้องทำต่อไปคือการปรับค่าอะไรต่างๆให้เหมาะสม

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

ค่าที่ปรับได้มีดังต่อไปนี้
pcx projectionCenterX ศูนย์กลางระนาบฉายในแกน x
pcy projectionCenterY ศูนย์กลางระนาบฉายในแกน y
pcz projectionCenterZ ศูนย์กลางระนาบฉายในแกน z
rx rotateX มุมหมุนระนาบฉายในแกน x
ry rotateY มุมหมุนระนาบฉายในแกน y
rz rotateZ มุมหมุนระนาบฉายในแกน z
pw projectionWidth ความกว้างระนาบฉาย
ph projectionHeight ความสูงระนาบฉาย
icx imageCenterX ศูนย์กลางของรูปในแกน x
icy imageCenterY ศูนย์กลางของรูปในแกน y
ra rotationAngle มุมเอียงของรูป
isu imageScaleU มาตราส่วนของรูปในแนว u (จำนวนภาพที่วนซ้ำ)
isv imageScaleV มาตราส่วนของรูปในแนว v

ก่อนอื่นขอปรับเพื่อให้ขยายเห็นหน้าจิโนะจังคนเดียวก่อน ทำโดยการปรับ
mc.setAttr('polyPlanarProj1.isu',0.25) # ปรับมาตราส่วนของภาพ
mc.setAttr('polyPlanarProj1.isv',0.4) # ด้านกว้างกับยาวต้องเป็น 5:8 เท่าภาพเดิมเพื่อไม่ให้ภาพเบี้ยว
mc.setAttr('polyPlanarProj1.icx',0.85) # ย้ายศูนย์กลางมาบริเวณมุมขวาบน
mc.setAttr('polyPlanarProj1.icy',0.6)
mc.setAttr('polyPlanarProj1.ra',180) # หมุนพลิกกลับด้าน



อย่างไรก็ตาม ที่จริงแล้วค่าต่างๆเหล่านี้สามารถตั้งได้ตั้งแต่ตอนที่ใช้ฟังก์ชัน polyProjection() ด้วยการใส่แฟล็กเพิ่มลงไป ชื่อแฟล็กจะเหมือนกันกับชื่อค่าองค์ประกอบที่เขียนไปข้างต้น

แต่มีอันที่ต่างไปคือ
pw (projectionWidth) ใช้แฟล็ก psu (projectionScaleU)
ph (projectionHeight) ใช้แฟล็ก psv (projectionScaleV)

โดยปกติแล้วหากใช้แฟล็ก md ไปแล้ว ค่า pcx, pcy, pcz, rx, ry, rz, psu (pw), psv (ph) จะถูกปรับอัตโนมัติ แฟล็กเหล่านี้จะไม่มีผล

แต่การปรับอัตโนมัติมักจะไม่ได้ตรงกับความต้องการนัก ดังนั้นหากรู้แล้วว่าต้องการค่าเท่าไหร่ก็กำหนดค่าต่างๆที่แฟล็กเหล่านี้เองทั้งหมดเลยก็ได้

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



ลองเริ่มฉากใหม่ จากนั้นก็พิมพ์ตามนี้ โค้ดช่วงต้นๆเหมือนเดิม แต่ตอนสร้างระนาบให้ f[0] มีการใส่แฟล็กจำนวนมากแทน md และมีการใช้ polyProjection() กับหน้า f[1] และ f[4] ด้วย ส่วนอีก ๓ หน้าที่เหลือยังคงเดิม
mc.shadingNode('lambert',asShader=1,n='phap_gochiusa')
mc.shadingNode('file',at=1,n='file_gochiusa')
mc.connectAttr('file_gochiusa.oc','phap_gochiusa.c')
s = '<พาธและชื่อไฟล์ภาพ>'
mc.setAttr('file_gochiusa.ftn',s,typ='string')
mc.polyCube(w=4,h=4,d=4,n='gochiusa')
mc.hyperShade(a='phap_gochiusa')
mc.polyProjection('gochiusa.f[0]',t='planar',
pcx=0,pcy=0,pcz=0,rx=0,ry=0,rz=0,psu=4,psv=4,
icx=0.85,icy=0.6,ra=180,isu=0.25,isv=0.4)
mc.polyProjection('gochiusa.f[1]',t='planar',
pcx=0,pcy=0,pcz=0,rx=-90,ry=45,rz=0,psu=4,psv=4,
icx=0.25,icy=0.55,ra=0,isu=0.4,isv=0.64)
mc.polyProjection('gochiusa.f[4]',t='planar',
pcx=0,pcy=0,pcz=0,rx=0,ry=90,rz=0,psu=4,psv=4,
icx=0.61,icy=0.5,ra=0,isu=0.3,isv=0.48)

ผลที่ได้จะออกมาเป็นแบบนี้ นอกจากหน้า f[0] มีจิโนะจัง หน้า f[1] กับ f[4] ก็ยังมีรูปของ ๔ คนที่เหลือ



ส่วนอีก ๓ หน้าที่เหลือลองไปใส่ภาพอะไรก็ได้ตามที่ต้องการกันดู

ทั้งหมดนี้เป็นตัวอย่างของการฉายแนวระนาบ ส่วนแบบทรงกระบอกและทรงกลมก็สามารถทำได้ในลักษณะเดียวกันเพียงแต่จะซับซ้อนกว่า



สรุปขั้นตอนการใส่ภาพบนผิวโพลิกอน
๑. mc.shadingNode('<ชนิดวัสดุ>',asShader=1,n='<ชื่อโหนดวัสดุ>') สร้างโหนดวัสดุที่ใช้เป็นภาพ
๒. mc.shadingNode('file',at=1,n='<ชื่อโหนดไฟล์ภาพ>') สร้างโหนดเท็กซ์เจอร์ชนิดไฟล์
๓. mc.connectAttr('<ชื่อโหนดไฟล์ภาพ>.oc','<ชื่อโหนดวัสดุ>.c') เชื่อมต่อโหนดไฟล์ภาพกับโหนดวัสดุ
๔. mc.setAttr('<ชื่อโหนดไฟล์ภาพ>.ftn',<พาธและชื่อไฟล์ภาพ>,typ='string') ระบุไฟล์ที่เก็บภาพ
๕. mc.select('<ชื่อวัตถุหรือผิว>') เลือกวัตถุที่ต้องการแปะภาพ
๖. mc.hyperShade(a='<ชื่อโหนดไฟล์ภาพ>') เชื่อมต่อโหนดไฟล์ภาพเข้ากับวัตถุหรือผิว
๗. mc.polyProjection('<ชื่อวัตถุหรือผิว>',<แฟล็กต่างๆสำหรับปรับค่า>) สร้างโหนดระนาบฉายเชื่อมต่อกับวัตถุหรือผิว
๘. ปรับค่าองค์ประกอบของระนาบฉายให้เป็นไปตามที่ต้องการ (อาจไม่ต้องปรับแล้วถ้ากำหนดค่าตั้งแต่ในแฟล็กของ polyProjection())



อีกตัวอย่าง ลองสร้างกรอบรูปที่มีรูปใส่อยู่ขึ้นมา

ภาพตัวอย่างที่ใช้ในนี้คือปราสาทฮิโกเนะ (彦根城) จังหวัดชิงะ



ที่มาของภาพ https://phyblas.hinaboshi.com/20130225
mc.shadingNode('lambert',asShader=1,n='phiumai') # สร้างโหนดวัสดุกรอบรูป
mc.setAttr('phiumai.c',0.14,0.04,0.02,typ='double3')
mc.polyCube(w=45.4,h=1.5,d=35.4,n='kroprup') # สร้างกรอบรูป
mc.hyperShade(a='phiumai')
mc.select('.f[1]')
mc.polyExtrudeFacet(off=2.5) # สร้างหลุมเว้าลงไป
mc.polyExtrudeFacet(ltz=-0.6)
mc.polyBevel('kroprup',o=0.2) # ปรับขอบให้มนขึ้นหน่อย
mc.shadingNode('anisotropic',asShader=1,n='phap') # สร้างโหนดวัสดุภาพ
mc.shadingNode('file',at=1,n='filephap') # สร้างโหนดไฟล์ภาพ
mc.connectAttr('filephap.oc','phap.c') # เชื่อมโหนดไฟล์กับวัสดุ
s = '<พาธและชื่อไฟล์ภาพ>'
mc.setAttr('filephap.ftn',s,typ='string') # เชื่อมต่อโหนดไฟล์เข้ากับไฟล์ภาพ
mc.select('kroprup.f[13]') # เลือกผิวหน้าที่เป็นรูปภาพ
mc.hyperShade(a='phap') # เชื่อมต่อเข้ากับโหนดวัสดุภาพ
mc.polyProjection('kroprup.f[13]',md='y') # สร้างโหนดฉาย กำหนดทิศเป็นแกน y
mc.select('kroprup')
mc.move(0,0.75,0)
mc.rotate(70,0,0,p=[0,0,16.7]) # จับหมุนให้ตั้งขึ้นเอียงเล็กน้อย





อ้างอิง

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


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

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

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

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> 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月

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

ไทย

日本語

中文