วิธีการคำนวณพื้นผิวสำหรับเรขาคณิตที่สร้างขึ้น


12

ฉันมีคลาสที่สร้างรูปร่าง 3 มิติตามอินพุตจากรหัสการโทร อินพุตเป็นสิ่งต่าง ๆ เช่นความยาวความลึกส่วนโค้งและอื่น ๆ รหัสของฉันสร้างรูปทรงเรขาคณิตได้อย่างสมบูรณ์แบบ แต่ฉันพบปัญหาเมื่อคำนวณหาค่ามาตรฐานของพื้นผิว เมื่อส่องสว่างรูปร่างของฉันมีการระบายสี / พื้นผิวที่แปลกประหลาดมากจากบรรทัดฐานของพื้นผิวที่ไม่ถูกต้องที่คำนวณ จากการวิจัยทั้งหมดของฉันฉันเชื่อว่าคณิตศาสตร์ของฉันถูกต้องดูเหมือนว่ามีบางอย่างผิดปกติกับเทคนิคหรือวิธีการของฉัน

ในระดับสูงเราจะคำนวณค่าปกติของพื้นผิวสำหรับรูปร่างที่สร้างขึ้นโดยทางโปรแกรมได้อย่างไร ฉันใช้ Swift / SceneKit บน iOS เป็นรหัสของฉัน แต่คำตอบทั่วไปนั้นใช้ได้

ฉันมีสองอาร์เรย์ที่แสดงถึงรูปร่างของฉัน หนึ่งคืออาร์เรย์ของจุด 3 มิติที่แสดงถึงจุดยอดที่ประกอบเป็นรูปร่าง อาเรย์อีกอันคือรายการดัชนีของอาเรย์แรกที่แมปจุดยอดเป็นรูปสามเหลี่ยม ฉันจำเป็นต้องใช้ข้อมูลนั้นและสร้างอาร์เรย์ลำดับที่ 3 ซึ่งเป็นชุดของบรรทัดฐานพื้นผิวที่ช่วยในการให้แสงสว่างของรูปร่าง (ดูSCNGeometrySourceSemanticNormalใน SceneKit` )

รายการของจุดยอดและดัชนีมักจะแตกต่างกันไปขึ้นอยู่กับอินพุตของคลาสดังนั้นฉันจึงไม่สามารถคำนวณล่วงหน้าหรือรหัสยาก ๆ เกี่ยวกับค่ามาตรฐานพื้นผิวได้


ต้องการบริบทเพิ่มเติม คุณกำลังพยายามคำนวณบรรทัดฐานการวิเคราะห์สำหรับพื้นผิวแบบพารามิเตอร์หรือไม่? พื้นผิวโดยนัย? หรือคุณต้องการคำนวณค่าปกติจากตาข่ายสามเหลี่ยมทั่วไป? หรืออย่างอื่น?
นาธานรีด

ขอบคุณฉันเพิ่มรายละเอียดเพิ่มเติม เพื่อที่จะตอบคำถามของคุณฉันจำเป็นต้องคำนวณบรรทัดฐานจากตาข่ายสามเหลี่ยมทั่วไป แม้ว่าจะมีความชัดเจนว่าตาข่ายจะแตกต่างกันขึ้นอยู่กับอินพุต รูปร่างของฉันเป็นลูกศรสามมิติตัวอย่างเช่นที่นี่เป็นภาพหน้าจอของมัน 2 รูปแบบที่แตกต่างกัน (เช่นรัศมีและเส้นตรง) ชั้นเปลี่ยนความกว้างความลึกความยาวส่วนโค้งและรัศมีของตาข่ายตามที่ร้องขอ cl.ly/image/3O0P3X3N3d1dคุณสามารถเห็นแสงแปลก ๆ ที่ฉันได้รับจากความพยายามที่ไม่ดีของฉันในการแก้ปัญหานี้
macinjosh

3
รุ่นสั้นคือ: คำนวณจุดสุดยอดแต่ละปกติตามผลรวมปกติของบรรทัดฐานของสามเหลี่ยมทั้งหมดที่สัมผัส อย่างไรก็ตามสิ่งนี้จะทำให้ทุกอย่างราบรื่นซึ่งอาจไม่ใช่สิ่งที่คุณต้องการสำหรับรูปร่างนี้ ฉันจะพยายามขยายเป็นคำตอบแบบเต็มในภายหลัง
นาธานรีด

ราบรื่นเป็นสิ่งที่ฉันจะทำ!
macinjosh

4
ในกรณีส่วนใหญ่หากคุณคำนวณตำแหน่งจุดสุดยอดเชิงวิเคราะห์คุณสามารถคำนวณบรรทัดฐานเชิงวิเคราะห์ได้เช่นกัน สำหรับพื้นผิวแบบพาราเมทริกค่าคงที่เป็นผลคูณของเวกเตอร์ไล่สีสองค่า การคำนวณค่าเฉลี่ยของรูปสามเหลี่ยมเชิงบรรทัดฐานเป็นเพียงการประมาณและบ่อยครั้งที่ส่งผลให้คุณภาพแย่ลงมาก ฉันจะโพสต์คำตอบ แต่ฉันได้โพสต์ตัวอย่างโดยละเอียดเกี่ยวกับ SO ( stackoverflow.com/questions/27233820/ … ) และฉันไม่แน่ใจว่าเราต้องการเนื้อหาที่จำลองแบบหรือไม่
Reto Koradi

คำตอบ:


10

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

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

ภาพเราเป็นหลัง

ภาพที่ 1 : ผลลัพธ์ที่คุณต้องการ

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

แสดงตาข่ายและบรรทัดฐาน]

ภาพที่ 2 : ภาพแสดงโครงสร้างตาข่ายและบรรทัดฐาน

คุณสามารถสรุปได้โดยอัตโนมัติโดยไม่รวมบรรทัดฐานที่อยู่นอกมุมที่แน่นอนจากจุดสุดยอดปกติ pseudocode:

For vertex in faceVertex:
    normal = vertex.normal
    For adjVertex in adjacentVertices:
        if anglebetween(vertex.normal, adjVertex.normal )  < treshold:
            normal += adjVertex.normal
    normal = normalize(normal)

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


10

ฉันเห็นส่วนใหญ่สามวิธีในการคำนวณบรรทัดฐานสำหรับรูปร่างที่สร้างขึ้น

บรรทัดฐานการวิเคราะห์

ในบางกรณีคุณมีข้อมูลเพียงพอเกี่ยวกับพื้นผิวเพื่อสร้างบรรทัดฐาน ตัวอย่างเช่นปกติของจุดใด ๆ บนทรงกลมนั้นไม่สำคัญที่จะคำนวณ เมื่อคุณรู้จักอนุพันธ์ของฟังก์ชันคุณก็จะรู้ว่าปกติ

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

บรรทัดฐานเวอร์เท็กซ์

ครอสโปรดัคของเวกเตอร์สองตัวนั้นให้เวกเตอร์ตั้งฉากกับระนาบที่พวกมันอยู่ ดังนั้นการทำให้สามเหลี่ยมเป็นปกติตรงไปตรงมา:

vec3 computeNormal(vec3 a, vec3 b, vec3 c)
{
    return normalize(crossProduct(b - a, c - a));
}

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

vec3 computeNormal(vertex a)
{
    vec3 sum = vec3(0, 0, 0);
    list<vertex> adjacentVertices = getAdjacentVertices(a);
    for (int i = 1; i < adjacentVertices; ++i)
    {
        vec3 b = adjacentVertices[i - 1];
        vec3 c = adjacentVertices[i];
        sum += crossProduct(b - a, c - a);
    }
    if (norm(sum) == 0)
    {
        // Degenerate case
        return sum;
    }
    return normalize(sum);
}

หากคุณกำลังทำงานกับล่ามมีเคล็ดลับที่ดีที่คุณสามารถใช้ได้: สำหรับ quad abcdให้ใช้crossProduct(c - a, d - b)และมันจะจัดการกับกรณีที่ quad เป็นจริงสามเหลี่ยม

Iñigo quilez เขียนบทความสั้น ๆ ไม่กี่ในหัวข้อ: การฟื้นฟูฉลาดของตาข่ายและปกติและพื้นที่ของรูปหลายเหลี่ยม n เข้าข้าง

ปกติจากอนุพันธ์บางส่วน

เกณฑ์ปกติสามารถคำนวณได้ในส่วนย่อยจากอนุพันธ์ย่อยบางส่วน คณิตศาสตร์ที่อยู่ด้านหลังเหมือนกันยกเว้นเวลานี้จะทำในพื้นที่หน้าจอ บทความนี้โดยแองเจโล Pesce อธิบายเทคนิค: Normals โดยไม่ปกติ


1
มีวิธีที่สี่ศิลปินที่จัดมาเป็นปกติ;)
joojaa

@ joojaa: ฉันคิดว่าคุณหมายถึงแผนที่ปกติเหรอ? ฉันไม่เคยได้ยินบรรทัดฐานของผู้แต่งเองมาก่อน
Julien Guertault

1
ไม่บรรทัดฐานที่ประพันธ์ขึ้นเอง บางครั้งมันก็เกิดขึ้นที่ศิลปินของคุณรู้มากขึ้นเกี่ยวกับวิธีการปฏิบัติตนตามปกติมากกว่าที่โปรแกรมเมอร์ทำ บางครั้งมันก็เป็นปัญหาเล็กน้อยสำหรับเอ็นจิ้นการคำนวณหากพวกเขาคิดว่าบรรทัดฐานมาจากการคำนวณพื้นฐาน แต่แน่นอนว่ามันเกิดขึ้นและคุณประหยัดเวลาได้มากในการสร้างแบบจำลองทางคณิตศาสตร์
joojaa

1
สิ่งเหล่านี้บางครั้งเรียกว่า "กฎเกณฑ์ปกติ" (3ds max และคำศัพท์มายา)
'หัวจดหมาย' Dusan Bosnjak
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.