জেনেটেড জ্যামিতির জন্য কীভাবে সারফেস নরমাল গণনা করা যায়


12

আমার একটি ক্লাস রয়েছে যা কলিং কোড থেকে ইনপুটগুলির উপর ভিত্তি করে 3 ডি আকার তৈরি করে। ইনপুটগুলি দৈর্ঘ্য, গভীরতা, আর্ক ইত্যাদির মতো জিনিসগুলি My প্রজ্বলিত হলে, আমার আকারের ভুল পৃষ্ঠের নরমালগুলি থেকে গণনা করা হচ্ছে এমন থেকে খুব উদ্ভট রঙিন / টেক্সচার থাকে। আমার সমস্ত গবেষণা থেকে আমি বিশ্বাস করি যে আমার গণিতটি সঠিক, মনে হচ্ছে আমার কৌশল বা পদ্ধতিতে কিছু ভুল।

একটি উচ্চ স্তরে কীভাবে কোনও উত্পন্ন আকারের জন্য পৃষ্ঠের নরমালগুলি প্রোগ্রামালিকভাবে গণনা করা যায়? আমি আমার কোডের জন্য আইওএসে সুইফট / সিনকিট ব্যবহার করছি তবে একটি জেনেরিক উত্তর ভাল।

আমার দুটি অ্যারে রয়েছে যা আমার আকৃতির প্রতিনিধিত্ব করে। একটি হ'ল 3 ডি পয়েন্টের একটি অ্যারে যা আকারটি তৈরি করে এমন শীর্ষগুলিকে উপস্থাপন করে। অন্যান্য অ্যারে হ'ল প্রথম অ্যারের সূচকের তালিকা যা ত্রিভুজগুলিতে উল্লম্বকে মানচিত্র করে। আমাকে সেই ডেটা নেওয়ার এবং তৃতীয় অ্যারে তৈরি করা দরকার যা পৃষ্ঠের নরমালগুলির একটি সেট যা আকারের আলোতে সহায়তা করে। ( SCNGeometrySourceSemanticNormalসিনকিটিতে দেখুন )

উল্লম্ব এবং সূচকগুলির তালিকা বর্গের ইনপুটগুলির উপর নির্ভর করে সর্বদা পৃথক থাকে তাই আমি পৃষ্ঠের স্বাভাবিকগুলি প্রাক-গণনা বা হার্ড কোড করতে পারি না।


আরও প্রসঙ্গ প্রয়োজন। আপনি কি প্যারাম্যাট্রিক পৃষ্ঠের জন্য বিশ্লেষণাত্মক নরমাল গণনা করার চেষ্টা করছেন? একটি অন্তর্নিহিত পৃষ্ঠ? অথবা আপনি জেনেরিক ত্রিভুজ জাল থেকে নরমাল গণনা করতে চান? অথবা অন্য কিছু?
নাথান রিড 1

ধন্যবাদ, আমি আরও বিশদ যুক্ত করেছি। আপনার প্রশ্নের উত্তর দেওয়ার জন্য আমাকে জেনেরিক ত্রিভুজ জাল থেকে নরমাল গণনা করতে হবে। যদিও স্পষ্ট হওয়া যায় যে ইনপুটগুলির উপর নির্ভর করে জাল আলাদা। আমার আকৃতিটি একটি 3D তীর, উদাহরণ হিসাবে এখানে এটির 2 টি বিভিন্ন রূপের (যেমন রেডিয়াল এবং লিনিয়ার) এর একটি স্ক্রিনশট রয়েছে। শ্রেণীর অনুরোধ অনুসারে জালটির প্রস্থ, গভীরতা, দৈর্ঘ্য, আর্ক এবং ব্যাসার্ধকে পরিবর্তন করে। cl.ly/image/3O0P3X3N3d1d আপনি দেখতে পাচ্ছেন যে অদ্ভুত আলোয় আমি এটি সমাধান করার জন্য আমার দুর্বল প্রচেষ্টা দিয়ে পাচ্ছি।
ম্যাকিনজোশ

3
সংক্ষিপ্ত সংস্করণটি হ'ল: প্রতিটি স্পর্শটিকে সমস্ত ত্রিভুজগুলির স্পর্শকারীগুলির স্বাভাবিকের যোগফল হিসাবে গণনা করুন। যাইহোক, এটি সবকিছু মসৃণ করে তুলবে, যা আপনি এই আকারের জন্য চান তা নাও হতে পারে। আমি পরে একটি সম্পূর্ণ উত্তর প্রসারিত করার চেষ্টা করব।
নাথান রিড 1

মসৃণ আমি কি জন্য যাচ্ছি!
ম্যাকিনজোশ

4
বেশিরভাগ ক্ষেত্রে, আপনি বিশ্লেষণীভাবে শীর্ষস্থানীয় অবস্থানগুলি গণনা করেন, আপনি বিশ্লেষণাত্মকভাবেও সাধারণগুলি গণনা করতে পারেন। প্যারামিট্রিক পৃষ্ঠের জন্য, নরমালগুলি হ'ল দুটি গ্রেডিয়েন্ট ভেক্টরের ক্রস প্রোডাক্ট। ত্রিভুজটির স্বাভাবিকের গড় গণনা করা কেবল একটি আনুমানিকই এবং প্রায়শই দৃষ্টিকটুভাবে দরিদ্র মানের ফলাফল হয়। আমি একটি উত্তর পোস্ট করব, তবে আমি ইতিমধ্যে এসও ( স্ট্যাকওভারফ্লো / প্রশ্ন / 27233820/… ) এ একটি বিস্তারিত উদাহরণ পোস্ট করেছি এবং আমরা নিশ্চিত করতে পারি না যে আমরা এখানে প্রতিলিপিযুক্ত সামগ্রী চাই কিনা।
রেটো কোরাডি

উত্তর:


10

আপনি কেবল সম্পূর্ণ মসৃণ ফলাফল চান না। নাথন রিডের মন্তব্য পদ্ধতির সময়: "প্রতিটি মুখোমুখি সাধারণের মুখের জন্য গণনা করুন, তাদের যোগফল করুন, যোগফলকে সাধারণ করুন", সাধারণত এটি কাজ করে যা কখনও কখনও দর্শনীয়ভাবে ব্যর্থ হয়। তবে এখানে এটির কোনও গুরুত্ব নেই, আমরা এটির সাথে একটি প্রত্যাখ্যানের ধারা যুক্ত করে সেই পদ্ধতিটি ব্যবহার করতে পারি।

এক্ষেত্রে আপনি কেবল চান যে নির্দিষ্ট অংশগুলি নির্দিষ্ট অন্যান্য অংশগুলির বিরুদ্ধে ছড়িয়ে দেওয়া উচিত নয়। আপনি নির্বাচনী শক্ত প্রান্ত চান। সুতরাং উদাহরণস্বরূপ, ফ্ল্যাট শীর্ষ এবং নীচে পৃথক ত্রিভুজ স্ট্রিপ ফর্ম, পাশাপাশি প্রতিটি সমতল এলাকা।

চিত্র আমরা পরে

চিত্র 1 : ফলাফল আপনি চান।

বাস্তবে আপনি কেবল বাঁকানো অংশের শীর্ষকোষকে গড়তে চান অন্যরা যে সমস্ত সাধারণ ব্যবহার করতে পারে তারা একা তাদের ত্রিভুজ গঠন করে। সুতরাং আপনি জালটিকে 9 টি আলাদা অঞ্চল হিসাবে বিবেচনা করা ভাল যা অন্যগুলি ছাড়া পরিচালনা করা হয়।

জাল এবং স্বাভাবিকগুলি দেখানো]

চিত্র 2 : জাল কাঠামো এবং নরমালগুলি দেখায় এমন চিত্র।

আপনি অবশ্যই প্রাথমিকভাবে শীর্ষস্থানীয় সাধারণ থেকে নির্দিষ্ট কোণগুলির বাইরে থাকা নরমালগুলি না রেখে স্বয়ংক্রিয়ভাবে এটিকে কমিয়ে আনতে পারেন। সুডোকোড:

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));
}

তদুপরি, উপরোক্ত উদাহরণে, ক্রস পণ্যটির দৈর্ঘ্য আবের অভ্যন্তরের অঞ্চলের সাথে সমানুপাতিক । সুতরাং বেশ কয়েকটি ত্রিভুজ দ্বারা ভাগ করা একটি শীর্ষবিন্দুতে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ওজনকে পৃথক করে ত্রিভুজের পণ্যগুলি যোগ করে সর্বশেষ পদক্ষেপ হিসাবে স্বাভাবিক করা যায়।

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);
}

আপনি quads সঙ্গে কাজ করেন, তাহলে সেখানে একটা চমৎকার কৌতুক আপনি ব্যবহার করতে পারেন হল: একটি চতুর্ভুজ ABCD , ব্যবহার crossProduct(c - a, d - b)এবং এটি চমত্কারভাবে মামলা পরিচালনা করবে যেখানে চতুর্ভুজ আসলে একটি ত্রিভুজ হয়।

আইজিগো কুইলিজ এই বিষয়টিতে কয়েকটি সংক্ষিপ্ত নিবন্ধ লিখেছিলেন: একটি জালের চতুর নরমালাইজেশন , এবং সাধারণ এবং এন পার্শ্বযুক্ত বহুভুজের ক্ষেত্রফল

আংশিক ডেরিভেটিভস থেকে সাধারণ

আংশিক ডেরাইভেটিভগুলি থেকে সাধারণগুলি ফ্রেগমেন্ট শেডারে গণনা করা যায়। পিছনের গণিতটি একই, এই সময়টি স্ক্রিন স্পেসে করা ব্যতীত। অ্যাঞ্জেলো পেস-এর এই নিবন্ধটি কৌশলটি বর্ণনা করেছে: সাধারণ ছাড়াই সাধারণ


1
চতুর্থ উপায় আছে, শিল্পী সরবরাহ করেছেন নরমাল;)
জুন

@ জুজা: আমি ধরে নিয়েছি আপনি সাধারণ মানচিত্রের কথা উল্লেখ করছেন? আমি ম্যানুয়ালি রচিত সাধারণ সম্পর্কে কখনও শুনিনি।
জুলিয়েন গের্টল্ট

1
না, ম্যানুয়ালি রচিত নরমালগুলি। এটি কখনও কখনও ঘটে থাকে যে প্রোগ্রামারদের মডেলগুলির চেয়ে আপনার শিল্পী কীভাবে স্বাভাবিক হওয়া উচিত সে সম্পর্কে আরও জানেন। অন্তর্নিহিত গণনাগুলি থেকে স্বাভাবিকগুলি আসে বলে ধরে নিলে গণনা ইঞ্জিনগুলিতে এটি কখনও কখনও কিছুটা সমস্যাযুক্ত হয়। তবে অবশ্যই এটি ঘটে এবং আপনি গাণিতিক মডেলিংয়ে অনেক সময় বাঁচান।
joojaa

1
এগুলিকে মাঝে মাঝে "স্পষ্ট স্পষ্ট নরমালস" (3 ডিএস সর্বোচ্চ এবং মায়া পরিভাষা) হিসাবে উল্লেখ করা হয়।
দুসান বসজাক 'পাইলহেড'
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.