2012-12-30 8 views
6

यह ओपनजीएल प्रश्न और सी ++ संगठनात्मक प्रश्न के अधिक से कम है।ओपनजीएल राज्य समूह

मेरे पास नोड्स के साथ एक साधारण दृश्य ग्राफ (एक एन-पेड़) होने वाला है (इस प्रश्न के लिए) सभी कुछ ज्यामिति प्रस्तुत करेंगे। अधिक विशिष्ट होने के लिए, उनमें से प्रत्येक के पास draw() विधि के अंदर कुछ ओपनजीएल ड्रा कमांड हैं।

अनुकूलन कारणों के लिए, मैं समान वस्तुओं को एकसाथ बैच करना चाहता हूं और उन्हें एक साथ में आकर्षित करना चाहता हूं। इस कारण से मैं ओपनजीएल के लिए "राज्य सेट" कह रहा हूं, इसे व्यक्त करने का एक तरीका चाहूंगा। एक राज्य सेट ओपनजीएल बाइंड का सिर्फ एक गुच्छा है, या एक्स ऑब्जेक्ट्स पर ड्रॉ से पहले सेट किए गए कमांड को ऑब्जेक्ट्स पर कॉल किया जाता है, और बाद में अनसेट हो जाता है।

तो एक राज्य सेट में कम से कम set() और unset() है और इस राज्य सेट का उपयोग करने वाले नोड्स के ड्रा कमांड के पहले और बाद में प्रतिपादन प्रणाली द्वारा कॉल किया जाएगा।

मेरा सवाल यह है कि राज्य के सेट को कैसे व्यक्त किया जाए? निश्चित रूप से कार्यों का एक गुच्छा कर सकता है, लेकिन मैं एक सेट नाम देने और इसे याद करने में सक्षम होना चाहूंगा। नोड ए की तरह LIGHTING_AND_SHADOW का राज्य सेट है और नोड बी में CEL_SHADING है।

इस कारण से एक अमूर्त वर्ग stateSet कहा जाता है जो अनिवार्य रूप से set() और unset() तरीकों के लिए एक इंटरफेस होने की पुष्टि करने और प्रत्येक राज्य सेट होने के लिए वारिस यह एक अच्छा विचार की तरह लगता है से। लेकिन, अनिवार्य रूप से नाम प्राप्त करने के लिए वस्तुओं की एक गुच्छा के निर्माण की आवश्यकता है। ऐसा लगता है कि एक बेहतर तरीका हो सकता है।

आदर्श रूप से मैं सभी stateSets की एक सूची रखना चाहता हूं जिसे आसानी से याद किया जा सकता है। प्रस्तुति शुरू होने से पहले उदाहरण के लिए, दृश्य ग्राफ में अपने stateSet द्वारा सभी नोड्स को सॉर्ट करने में सक्षम होना अच्छा होगा।

कोई विचार?

+0

ऐसा लगता है जैसे आप हमें अपने राज्य सेट में नाम देने के लिए कह रहे हैं। क्या आप थोड़ा सा विस्तार कर सकते हैं कि आप किस प्रकार की सहायता की तलाश में हैं। – Mads

+0

यदि सक्रिय जीएलएसएल प्रोग्राम आपके "राज्य सेट" का हिस्सा है तो आप अपने जीएलएसएल प्रोग्राम क्लास का "राज्य सेट" हिस्सा बना सकते हैं: प्रत्येक व्यक्ति को पता है कि इसे किस राज्य को सेट करने की आवश्यकता है और प्रोग्राम को सक्रिय करने की आवश्यकता है। फिर आप प्रतिपादन से पहले नोड्स प्रति-प्रोग्राम को समूहबद्ध करते हैं। – Gigi

उत्तर

2

आप सिंगलटन पैटर्न का उपयोग करके अपने राज्यों को लागू कर सकते हैं। फिर, एक और सिंगलटन राज्य ट्रैकर वर्ग इन राज्य वर्गों के उदाहरणों का प्रबंधन करता है, और केवल एक राज्य सेट करता है जब यह पहले से सेट नहीं होता है। एक कच्चे कार्यान्वयन के लिए नीचे देखें।

class SingletonStateClass1 { 
public: 
    static SingletonStateClass1* getInstance() { 
     if(! instanceFlag) { 
      single = new SingletonStateClass1(); 
      instanceFlag = true; 
      return single; 
     } 
     else { 
      return single; 
     } 
    } 
    void set() { 
     // Do setting stuff 
    } 
    void unset() { 
     // Do unsetting stuff 
    } 
    ~SingletonStateClass1() { 
     instanceFlag = false; 
    } 

private: 
    static bool instanceFlag; 
    static SingletonStateClass1 *single; 
    SingletonStateClass1() {} //private constructor 
}; 
bool SingletonStateClass1::instanceFlag = false; //needs to be set so that the first call to getInstance() works ok. 


//ASSUME THERE IS ANOTHER CLASS WITH SIMILAR DESIGN, NAMED: SingletonStateClass2 

class SingletonStateTracker { 
public: 
    static SingletonStateTracker* getInstance() { 
     if(! instanceFlag) { 
      single = new SingletonStateTracker(); 
      state1 = SingletonStateClass1::getInstance(); 
      state2 = SingletonStateClass2::getInstance(); 
      instanceFlag = true; 
      isSetState1 = false; 
      isSetState2 = false; 
      return single; 
     } 
     else { 
      return single; 
     } 
    } 

    // Only setting a state unsets the other states 
    void set1() { 
     if (!isSetState1) { 
      if (isSetState2) { 
       state2->unset(); 
       isSetState2 = false; 
      } 
      state1->set(); 
      isSetState1 = true; 
     } 
    } 
    void set2() { 
     if (!isSetState2) { 
      if (isSetState1) { 
       state1->unset(); 
       isSetState1 = false; 
      } 
      state2->set(); 
      isSetState2 = true; 
     } 
    } 

private: 
    static bool instanceFlag; 
    static bool isSetState1; 
    static bool isSetState2; 
    static SingletonStateTracker *single; 
    static SingletonStateClass1 *state1; 
    static SingletonStateClass2 *state2; 
    SingletonStateTracker() {} //private constructor 
}; 
bool SingletonStateTracker::instanceFlag = false; //needs to be set so that the first call to getInstance() works ok. 




class DrawableObject1 { 
public: 
    DrawableObject1() { 
     tracker = SingletonStateTracker::getInstance(); 
    } 
    void draw() const 
    { 
     tracker->set1(); 
     //DO YOUR OBJECT SPECIFIC OPENGL DRAW STUFF HERE 
    } 
private: 
    SingletonStateTracker* tracker; 
}; 

class DrawableObject2 { 
public: 
    DrawableObject2() { 
     tracker = SingletonStateTracker::getInstance(); 
    } 
    void draw() const 
    { 
     tracker->set2(); 
     //DO YOUR OBJECT SPECIFIC OPENGL DRAW STUFF HERE 
    } 
private: 
    SingletonStateTracker* tracker; 
}; 


/* Below two classes show a crude usage of the above design */ 
class Scene { 
    // ... other stuff ... 

public: 
    DrawableObject1 obj1a; 
    DrawableObject1 obj1b; 
    DrawableObject2 obj2; 
    // ... other stuff ... 
}; 

class Viewer { 
    // ... other stuff ... 
public: 
    void draw() { 
     scene->obj1a.draw(); //This call unsets state2, sets state1 
     scene->obj1b.draw(); //This call does not set any state since state1 is already set 
     scene->obj2.draw(); //This call unsets state1, sets state2 
    } 
private: 
    Scene* scene; 
    // ... other stuff ... 
}; 

ध्यान दें कि ऊपर डिजाइन बहुत सरल है: यह आप कैसे इसके बारे में जाने के लिए पर एक विचार देना चाहिए। जैसा कि आपने अपने प्रश्न में नोट किया है, आपके पास एक सामान्य इंटरफ़ेस के उत्तराधिकारी के लिए कई राज्य वर्ग हो सकते हैं। कुंजी एक ट्रैकर (ए.के.ए. प्रबंधक) वर्ग है जिसके माध्यम से ऑब्जेक्ट्स सेट करता है। ट्रैकर क्लास का काम राज्य की अनावश्यक सेटिंग को खत्म करना है यदि यह पहले से सेट है, और यदि वे वर्तमान में सेट हैं तो अन्य राज्यों को अनसेट करें।

+0

यह उत्कृष्ट है, मैं निश्चित रूप से इसके साथ चला सकता हूं। जैसा कि आपने सुझाव दिया है, मैं आगे बढ़ूंगा और सेट() unset() और getInstance() के साथ एक स्टेटसेट इंटरफ़ेस बनाउंगा, और प्रबंधक के पास सभी प्रकार की गुड्स हो सकती हैं। मैं विशेष रूप से किसी अन्य स्टेटसेट सेट होने पर अनसेट() को कॉल करने की प्रबंधकों की क्षमता पसंद करता हूं, इस प्रकार उपयोगकर्ता द्वारा अनसेट करने की आवश्यकता को समाप्त कर देता है। एक बार फिर धन्यवाद! -कोडी –

+0

और विचार: एक सुरक्षित डिजाइन परिप्रेक्ष्य से, आप प्रबंधक वर्ग में निजी रूप से राज्य वर्गों की परिभाषा को समाहित करना चाहते हैं। इस तरह, इन वर्गों को सिंगलटन होने की भी आवश्यकता नहीं है, क्योंकि प्रबंधक सुनिश्चित करता है कि इनमें से प्रत्येक राज्य वर्ग का केवल एक स्थिर उदाहरण है, और उनके रचनाकारों के लिए सार्वजनिक पहुंच नहीं है। हालांकि प्रबंधक अभी भी सिंगलटन है। यह थोड़े लॉगर वर्ग है, जहां सिंगलटन का सुझाव दिया जाता है और व्यापक रूप से उपयोग किया जाता है। – meyumer

1

इस कारण stateSet कहा जाता है एक अमूर्त वर्ग बनाने के लिए जो अनिवार्य रूप से set() और unset() तरीकों के लिए एक इंटरफेस है और होने प्रत्येक राज्य के वारिस यह एक अच्छा विचार की तरह लगता है से निर्धारित किया है। लेकिन, को अनिवार्य रूप से नाम प्राप्त करने के लिए ऑब्जेक्ट्स का एक गुच्छा बनाने की आवश्यकता है।

आपका काल्पनिक सार वर्ग कार्यान्वयन वर्चुअल फ़ंक्शन तालिका के माध्यम से काम करता है, जिसे आम तौर पर फ़ंक्शन पॉइंटर्स की सरणी के रूप में कार्यान्वित किया जाता है। स्पष्ट रूप से निर्बाध वस्तुएं जो आप इस मामले में तत्काल करेंगे, वे अर्थपूर्ण स्थिति - उन फ़ंक्शन पॉइंटर्स को धारण करते हैं।

दो समारोह संकेत के कई सरणियों बनाने, शायद आप, विन्यास में, समारोह संकेत दिए गए, नाम सूचकांक के दो सरणियों बनाना चाहिए पिछली बार उपयोग सूचकांक को बनाए रखने, और अगर state_name अलग है अपने stateSet(uint state_name) जांच को देखने के लिए है करने के लिए एक विकल्प के रूप सरणी के माध्यम से अप्रत्यक्ष करने से पहले। मैं static कीवर्ड हालांकि अन्य संकलन इकाइयों से उस वैश्विक स्थिति को छिपाने की सलाह दूंगा।

यह दृष्टिकोण कम स्वचालित सुरक्षा प्रदान करता है - अर्थात् कुछ भी आपको stateSet(uint) में किसी भी पूर्णांक को पार करने से रोकता है और कच्चे सरणी पर कोई रेंज जांच नहीं होती है जबतक कि आप इसे स्वयं नहीं रखते।

दो विकल्प अन्यथा मूल रूप से समान हैं; तो अपने विचार को उचित विचार दें।