2012-01-13 25 views
5

मैं एक शेडर लिख रहा हूं जो कभी-कभी 2 डी मानचित्र पर एक बिंदु चमक बनाता है। ("चमक" बस एक उज्ज्वल रंगीन पिक्सेल है।) मैं चमकदार ब्लॉक को अनंत (अनंत) विमान पर यादृच्छिक रूप से और समान रूप से वितरित करना चाहता हूं, लेकिन मैं चाहता हूं कि स्पार्कलिंग एक्स और वाई निर्देशांक के आधार पर निर्धारक हो। मैंने निर्देशांक से बीज बनाने और उस बीज से जावा Random बनाने की कोशिश की, लेकिन मेरे प्रयासों ने अब तक पहचानने योग्य पैटर्न में परिणाम प्राप्त किए हैं। इस समारोह को अक्सर (कई लाख बार) कहा जाएगा ताकि प्रदर्शन महत्वपूर्ण हो।मैं एक्स/वाई निर्देशांक से निर्धारित छद्म यादृच्छिक पैटर्न कैसे निर्धारित कर सकता हूं?

मैंने पहली बार अपने hashCode() कार्यान्वयन की नकल करने की कोशिश की, जो टकराव से बचने के लिए प्राइम नंबर गुणक का उपयोग करता है। इसके परिणामस्वरूप मानचित्र पर एक दृश्यमान गैश लगाया गया जहां अंक की एक श्रृंखला ने एक ही बीज साझा किया।

मैं तो इतना तरह निर्देशांक श्रृंखलाबद्ध द्वारा एक बीज बनाने की कोशिश की:

long seed = ((long) x << 32) | (long) y; 
Random rand = new Random(seed); 

यह पैटर्न वाली डेटा में परिणाम के साथ ही, हालांकि पैटर्न के रूप में स्पष्ट नहीं है लगता है। चयनित निर्देशांक लाइनों में दिखाई देते हैं, समान रूप से वितरित नहीं होते हैं।

मैंने एमडी 5 या अन्य क्रिप्टोग्राफिक हैशिंग एल्गोरिदम का उपयोग करने से बचा है क्योंकि मुझे प्रदर्शन प्रभाव से डर है।

+1

यदि आप एलसीएम से कई लाख छद्म यादृच्छिक संख्याएं उत्पन्न कर रहे हैं और एक 2-डी वर्ग में साजिश कर रहे हैं तो आप पहचानने योग्य 'पैटर्न' देख सकते हैं, जब तक कि आप क्रिप्टो मजबूत जनरेटर का उपयोग न करें। के-विमानों के लिए खोजें। आप probbaly एक nonlinear congruential छद्म यादृच्छिक संख्या जनरेटर का उपयोग करना चाहते हैं। –

उत्तर

2

linear congruential generatorjava.util.Random में लागू किसी भी चुने गए SEED के लिए दोहराने का लाभ है। इन घोषणाओं,

private static final int SEED = 42; 
private static final int N = 128; 
private static final int MAX_X = 1024; 
private static final int MAX_Y = 1024; 
private final Random rnd = new Random(SEED); 
private final List<SparklePoint> list = new ArrayList<SparklePoint>(N); 

इस प्रकार आप आयत (0, 0, MAX_X, MAX_Y) में N अनियमित रूप से चुने अंक की एक (दोहराने योग्य) सूची को प्रारंभ कर सकते हैं को देखते हुए:

public void init(int seed) { 
    for (int i = 0; i < N; i++) { 
     int x = rnd.nextInt(MAX_X); 
     int y = rnd.nextInt(MAX_Y); 
     list.add(new SparklePoint(x, y)); 
    } 
} 

यह प्रत्येक बिंदु एक Timer जिसका अवधि देने का सुविधाजनक हो सकता है एक ही अनुक्रम से चुना जाता है:

private class SparklePoint implements ActionListener { 

    private static final int MAX_DELAY = 1000; 
    private final Point p; 
    private final Timer t; 
    private boolean bright; 

    public SparklePoint(int x, int y) { 
     p = new Point(x, y); 
     t = new Timer(rnd.nextInt(MAX_DELAY), this); 
     t.setRepeats(false); 
     t.start(); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     t.stop(); 
     if (bright) { 
      // darken p 
     } else { 
      // brighten p 
     } 
     bright = !bright; 
     t.setDelay(rnd.nextInt(MAX_DELAY)); 
     t.start(); 
    } 
} 
+0

चुनौती है कि उस बीज को शुरू करने के लिए उत्पन्न करें। मैं निरंतर बीज का उपयोग नहीं कर सकता क्योंकि किसी भी समय, मैं केवल मानचित्र का एक छोटा सा भाग खींच रहा हूं। यदि मैं उत्पत्ति से बहुत दूर खींच रहा हूं, तो मैं 'रैंडम' स्पिन नहीं चाहता हूं जब तक कि यह मेरे द्वारा खींचे गए निर्देशांक तक पहुंच न जाए। –

+0

आह, मैंने सोचा कि चयनित बिंदुओं का सेट निरंतर बना रहा है; मैं वर्तमान दृश्य क्षेत्र के बाहर बिंदुओं को अनदेखा करने के लिए दृश्य को अनुकूलित करने के लिए देख सकता हूं। – trashgod

3

एक पीएस में बिट्स मिश्रण के लिए निम्नलिखित एक बहुत ही कुशल कार्य है eudo यादृच्छिक लेकिन नियतात्मक फैशन:

public static final long xorShift64(long a) { 
    a ^= (a << 21); 
    a ^= (a >>> 35); 
    a ^= (a << 4); 
    return a; 
} 

तो तुम x और y समन्वय से एक छद्म यादृच्छिक लंबे परिणाम आप की तरह कुछ कर सकते हैं चाहते हैं:

long mix = xorShift64(x) + Long.rotateLeft(xorShift64(y),32) + 0xCAFEBABE; 
    long result = xorShift64(mix); 

मैं इस दृष्टिकोण का उपयोग किया है पहले ग्राफिक्स में सफलतापूर्वक, बहुत अच्छे परिणाम देता है! यादृच्छिक संख्याओं की गुणवत्ता java.util.Random जितनी अच्छी है, लेकिन यह बहुत तेज है ....

+0

दिलचस्प लग रहा है। क्या आप ऐसे किसी भी लेख के बारे में जानते हैं जो इस तरह के निर्माण के टकराव-प्रतिरोध का मूल्यांकन करता है? (एक छोटे से नक्शे के प्रयोजनों के लिए, यह कम महत्वपूर्ण है, लेकिन मैं उत्सुक हूँ।) –

0

यह ऐसा कुछ है जो मैंने किया (वांछित प्रभाव उत्पन्न करता है) लेकिन निश्चित रूप से सही नहीं है।

MessageDigest md5; 
try { 
    md5 = MessageDigest.getInstance("MD5"); 
} catch (NoSuchAlgorithmException e) { 
    e.printStackTrace(); 
    return null; 
} 
md5.update(new byte[] { 
    (byte)(x >>> 24), 
    (byte)(x >>> 16), 
    (byte)(x >>> 8), 
    (byte)x, 
    (byte)(z >>> 24), 
    (byte)(z >>> 16), 
    (byte)(z >>> 8), 
    (byte)z 
}, 0, 8); 
byte[] digest = md5.digest(); 
long seed = digest[0] + (digest[1] << 8) + (digest[2] << 16) + (digest[3] << 24) + (digest[4] << 32) + (digest[5] << 40) + (digest[6] << 48) + (digest[7] << 56); 
Random random = new Random(seed); 
विशेष रूप से अत्यधिक शब्द होने से

अलावा, Random के उपयोग शायद जरूरत से ज्यादा है, क्योंकि मैं केवल खींच दो बार फोन nextInt()। यह एक विशिष्ट सीमा में मूल्यों को उत्पन्न करने के लिए उपयोगी है, लेकिन मुझे वैसे भी मॉड्यूलो अंकगणितीय के साथ ऐसा करने में सक्षम होना चाहिए।

मुझे लगता है कि एमडी 5 एक अच्छी तरह से समझी गई एल्गोरिदम है, और इस एप्लिकेशन के लिए क्रिप्टोग्राफिक सुरक्षा महत्वपूर्ण नहीं है। हालांकि, मुझे निश्चित रूप से कुछ तेज (और कम गन्दा) पसंद आएगा।

संबंधित मुद्दे

 संबंधित मुद्दे