ใน
บทที่แล้วได้แนะนำการใส่ภาพลงบนผิว 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]) # จับหมุนให้ตั้งขึ้นเอียงเล็กน้อย
อ้างอิง