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

ไทย

日本語

中文