2011-09-01 14 views
5

असल में मुझे विषय शीर्षक में दिए गए विषय से संबंधित कई प्रश्न हैं।बिजली बनाने के लिए पर्लिन शोर का उपयोग करना?

मैं पहले से ही अपने आवेदन में बिजली बनाने के लिए पर्लिन कार्यों का उपयोग कर रहा हूं, लेकिन मैं अपने कार्यान्वयन के बारे में पूरी तरह से खुश नहीं हूं।

निम्नलिखित प्रश्न शुरुआती और बेहतर पर्लिन शोर कार्यान्वयन पर आधारित हैं।

इस मुद्दे को सरल बनाने के लिए, मान लीजिए कि मैं एक डीडी पर्लिन फ़ंक्शन का उपयोग करके इन नोड्स पर एन नोड्स वाली क्षैतिज रेखा की ऊंचाई को संशोधित करके एक साधारण 2 डी बिजली बना रहा हूं।

  1. जहां तक ​​मैं समझ गया है, दो बाद पर्लिन समारोह के लिए पारित मान कम से कम एक से अलग करना होगा, या जिसके परिणामस्वरूप दो मान समान हो जाएगा। इसका कारण यह है कि सरल पर्लिन कार्यान्वयन के साथ, रैंडम फ़ंक्शन एक int तर्क के साथ काम करता है, और बेहतर कार्यान्वयन मानों में मैप किए गए हैं [0..255] और फिर मानों के साथ इंडेक्स के रूप में उपयोग किए जाते हैं [0..255 ] एक यादृच्छिक वितरण में। क्या वह सही है?

  2. मैं कैसे प्राप्त करूं कि पर्लिन फ़ंक्शन द्वारा लौटाया गया पहला और अंतिम ऑफसेट मान (यानी नोड्स 0 और एन -1 के लिए) हमेशा 0 (शून्य) होता है? अभी मैं अपने पर्लिन फ़ंक्शन को प्राप्त करने के लिए एक साइन फ़ंक्शन (0 .. पीआई) मॉड्यूलेशन कर रहा हूं, लेकिन यह वास्तव में मैं नहीं चाहता हूं। बस उन्हें शून्य पर सेट करना वह नहीं है जो मैं चाहता हूं, क्योंकि मैं अपने सिरों पर एक अच्छा बिजली पथ w/o jaggies चाहता हूं।

  3. मैं पर्लिन फ़ंक्शन कैसे बदलूं (ताकि मुझे दो अलग-अलग पथ मिल सकें जो मैं बिजली के लिए एनीमेशन प्रारंभ और अंत फ्रेम के रूप में उपयोग कर सकता हूं)? मैं निश्चित रूप से प्रत्येक नोड मान के लिए प्रति पथ गणना के लिए एक निश्चित यादृच्छिक ऑफ़सेट जोड़ सकता हूं, या बेहतर पर्लिन शोर के लिए एक अलग सेटअप क्रमपरिवर्तन तालिका का उपयोग कर सकता हूं, लेकिन क्या बेहतर विकल्प हैं?

+1

यह सवाल बहुत अच्छा है। – sharptooth

+0

http://www.noisemachine.com/talk1/23.html –

उत्तर

2
  1. कि कैसे आप इसे और नमूना यह से लागू पर निर्भर करता है। एकाधिक ऑक्टेट्स का उपयोग करके काउंटर इंटीग्रर्स को थोड़ा सा मदद मिलती है।

    प्रत्येक के लिए किए गए ऑक्टेट और अतिरिक्त इंटरपोलेशन/नमूनाकरण पेरिन शोर में अधिक शोर प्रदान करता है। सिद्धांत रूप में, आपको विभिन्न पूर्णांक स्थितियों का उपयोग करने की आवश्यकता नहीं है; आप किसी भी बिंदु पर नमूना करने में सक्षम होना चाहिए और यह आस-पास के मूल्यों के समान (लेकिन हमेशा समान नहीं) होगा।

  2. मैं पेर्लिन को केवल योजक के बजाय गुणक के रूप में उपयोग करने का सुझाव दूंगा, और बिजली के दौरान वक्र का उपयोग करूंगा। उदाहरण के लिए, रेंज में पर्लिन [-1.5, 1.5] और बिजली पर एक सामान्य वक्र (दोनों सिरों पर 0, केंद्र में 1), lightning + (perlin * curve) आपके सिरों के बिंदु अभी भी रखेगा। कैसे आप अपने पर्लिन शोर जनरेटर को क्रियान्वित किया है के आधार पर आप की तरह कुछ जरूरत हो सकती है:

    lightning.x += ((perlin(lightning.y, octaves) * 2.0) - 0.5) * curve(lightning.y);

    अगर perlin रिटर्न [0,1] या

    lightning.x += (perlin(lightning.y, octaves)/128.0) * curve(lightning.y);

    अगर यह रिटर्न [0 , 255]। माना जाता है कि lightning.x किसी दिए गए मान के साथ शुरू हुआ, शायद 0, जो कुछ हद तक जुड़ी रेखा प्रदान करेगा जो अभी भी मूल प्रारंभ और अंत बिंदुओं से मिलेगा।

  3. बिजली में जोड़े गए प्रत्येक आयाम के लिए शोर में आयाम जोड़ें।यदि आप एक आयाम (क्षैतिज जाली) में बिजली को संशोधित कर रहे हैं, तो आपको 1 डी पेर्लिन शोर की आवश्यकता है। यदि आप इसे एनिमेट करना चाहते हैं, तो आपको 2 डी की आवश्यकता है। यदि आप बिजली चाहते थे जो दो धुरी और एनिमेटेड पर घिरा हुआ था, तो आपको 3 डी शोर की आवश्यकता होगी, और इसी तरह।
+0

आपके उत्तरों (1.) और (3.) वास्तव में सहायक थे। (2.) बिल्कुल वही है जो मैं करता हूं, लेकिन ऐसा नहीं करना चाहता। फिर भी, बहुत बहुत धन्यवाद, यह मुझे और मिला। – karx11erx

+0

मुझे यकीन नहीं है कि 2 के लिए एक बेहतर तरीका है; निश्चित रूप से कोई भी जटिल नहीं होने के बिना, मैं साथ आ सकता हूं। यदि आप कोई समस्या है तो आप वक्र के साथ खेलकर बेहतर परिणाम प्राप्त कर सकते हैं। – ssube

+0

2 डी शोर का उपयोग करके मैं 1 डी बिजली पथ को कैसे एनिमेट करूँगा? मैं काफी समझ नहीं सकता। क्या आप विलुप्त समय (फ्रेम में, 0 से <एनीमेशन फ्रेम गिनती -1 -1) की गिनती करेंगे? – karx11erx

1

peachykeen के उत्तर पढ़ने और इंटरनेट में कुछ (अधिक) स्वयं के शोध करने के बाद, मुझे मेरे लिए काम करने के लिए निम्नलिखित समाधान मिल गया है।

  1. पर्लिन शोर के अपने कार्यान्वयन के साथ

    , के एक मूल्य रेंज का उपयोग कर [0.0 .. 1.0] बिजली पथ नोड्स सबसे अच्छा काम करते हैं, मूल्य पारित करने के लिए (डबल) एम/(डबल) एन नोड M के लिए पर्लिन शोर समारोह।

  2. शोर फ़ंक्शन करने के लिए एफ 'नोड 0 और नोड एन -1 के लिए समान मान लौटाएं, निम्न सूत्र लागू किया जा सकता है: एफ' (एम) = ((एम - एन) * एफ (एन) + एन * एफ (एन - एम))/एम। बिजली पथ ऑफसेट शुरू करने और 0 के साथ समाप्त करने के लिए, आपको बस पथ की गणना करने के बाद सभी बिजली पथ ऑफसेट से एफ '(0) घटाएं।

  3. प्रत्येक पथ नोड के लिए ऑफसेट कंप्यूटिंग से पहले बिजली पथ randomize करने के लिए, एक यादृच्छिक ऑफसेट आर गणना की जा सकती है और, मूल्यों शोर समारोह के लिए पारित करने के लिए जोड़ा है, ताकि एक नोड का ऑफ़सेट हे = एफ '(N + आर)। बिजली को एनिमेट करने के लिए, दो बिजली पथों को गणना (प्रारंभ और अंत फ्रेम) की आवश्यकता होती है, और फिर प्रत्येक पथ चरम को अपनी प्रारंभ और अंत स्थिति के बीच ले जाना पड़ता है। एक बार अंत फ्रेम तक पहुंचने के बाद, अंत फ्रेम प्रारंभ फ्रेम बन जाता है और एक नया अंत फ्रेम गणना की जाती है। 3 डी पथ के लिए, प्रत्येक पथ नोड एन के लिए दो ऑफ़सेट वैक्टरों की गणना की जा सकती है जो नोड एन और एक दूसरे पर पथ के लंबवत होते हैं, और दो 1 डी पर्लिन शोर मानों के साथ स्केल किए जा सकते हैं ताकि नोड स्थिति को प्रारंभ से अंत तक फ्रेम स्थिति में ले जाया जा सके। । यह 3 डी पर्लिन शोर करने से सस्ता हो सकता है और मेरे आवेदन में काफी अच्छा काम करता है।

यहाँ एक संदर्भ के रूप में मानक -1 डी पर्लिन शोर (कुछ सामान आभासी क्योंकि मैं पर्लिन शोर में सुधार के लिए आधार के रूप में इस का उपयोग कर रहा है, एक रणनीति पैटर्न आवेदन में मानक या सुधार पर्लिन शोर उपयोग करने की अनुमति है की मेरी कार्यान्वयन है। कोड कुछ सरल कर दिया गया है और साथ ही इसे और अधिक इसे यहाँ प्रकाशित करने) के लिए संक्षिप्त बनाने के लिए:

हैडर फ़ाइल:

#ifndef __PERLIN_H 
#define __PERLIN_H 

class CPerlin { 
    private: 
    int m_randomize; 

    protected: 
    double m_amplitude; 
    double m_persistence; 
    int m_octaves; 

    public: 
    virtual void Setup (double amplitude, double persistence, int octaves, int randomize = -1); 
    double ComputeNoise (double x); 

    protected: 
    double LinearInterpolate (double a, double b, double x); 
    double CosineInterpolate (double a, double b, double x); 
    double CubicInterpolate (double v0, double v1, double v2, double v3, double x); 
    double Noise (int v);  
    double SmoothedNoise (int x); 
    virtual double InterpolatedNoise (double x); 
    }; 

#endif //__PERLIN_H 

कार्यान्वयन:

#include <math.h> 
#include <stdlib.h> 
#include "perlin.h" 

#define INTERPOLATION_METHOD 1 

#ifndef Pi 
# define Pi 3.141592653589793240 
#endif 

inline double CPerlin::Noise (int n) { 
    n = (n << 13)^n; 
    return 1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff)/1073741824.0;  
    } 

double CPerlin::LinearInterpolate (double a, double b, double x) { 
    return a * (1.0 - x) + b * x; 
    } 

double CPerlin::CosineInterpolate (double a, double b, double x) { 
    double f = (1.0 - cos (x * Pi)) * 0.5; 
    return a * (1.0 - f) + b * f; 
    } 

double CPerlin::CubicInterpolate (double v0, double v1, double v2, double v3, double x) { 
    double p = (v3 - v2) - (v0 - v1); 
    double x2 = x * x; 
    return v1 + (v2 - v0) * x + (v0 - v1 - p) * x2 + p * x2 * x; 
    } 

double CPerlin::SmoothedNoise (int v) { 
    return Noise (v)/2 + Noise (v-1)/4 + Noise (v+1)/4; 
    } 

int FastFloor (double v) { return (int) ((v < 0) ? v - 1 : v; } 

double CPerlin::InterpolatedNoise (double v) { 
    int i = FastFloor (v); 
    double v1 = SmoothedNoise (i); 
    double v2 = SmoothedNoise (i + 1); 
#if INTERPOLATION_METHOD == 2 
    double v0 = SmoothedNoise (i - 1); 
    double v3 = SmoothedNoise (i + 2); 
    return CubicInterpolate (v0, v1, v2, v3, v - i); 
#elif INTERPOLATION_METHOD == 1 
    return CosineInterpolate (v1, v2, v - i); 
#else 
    return LinearInterpolate (v1, v2, v - i); 
#endif 
    } 

double CPerlin::ComputeNoise (double v) { 
    double total = 0, amplitude = m_amplitude, frequency = 1.0; 
    v += m_randomize; 
    for (int i = 0; i < m_octaves; i++) { 
    total += InterpolatedNoise (v * frequency) * amplitude; 
    frequency *= 2.0; 
    amplitude *= m_persistence; 
    } 
    return total; 
    } 

void CPerlin::Setup (double amplitude, double persistence, int octaves, int randomize) { 
    m_amplitude = (amplitude > 0.0) ? amplitude : 1.0; 
    m_persistence = (persistence > 0.0) ? persistence : 2.0/3.0; 
    m_octaves = (octaves > 0) ? octaves : 6; 
    m_randomize = (randomize < 0) ? (rand() * rand()) & 0xFFFF : randomize; 
    } 
संबंधित मुद्दे