व्यक्तिगत रूप से मैं ड्रॉ फ़ंक्शन को ऑब्जेक्ट क्लास से बाहर रखने की सलाह देता हूं। मैं ऑब्जेक्ट को लोकेशन से बाहर रखने की सलाह भी देता हूं।
वह ड्रा () विधि OpenGL, OpenGL ES, Direct3D दोनों में से निम्न स्तर प्रतिपादन एपीआई के साथ काम करने जा रही है, उन API या इंजन API पर आपकी रैपिंग परत। यह हो सकता है कि आपको बीच में स्वैप करना पड़े (यदि आप उदाहरण के लिए OpenGL + OpenGL ES + Direct3D का समर्थन करना चाहते थे।
गेमऑबजेक्ट में बस मूल जानकारी होनी चाहिए, जैसे कि विज़ुअल उपस्थिति जैसे कि मेष या हो सकता है कि एक बड़ा बंडल जिसमें shader निविष्टियाँ, एनीमेशन स्थिति और इतने पर शामिल हों।
इसके अलावा, आप एक लचीला ग्राफिक्स पाइपलाइन चाहते हैं। यदि आप कैमरे पर उनकी दूरी के आधार पर वस्तुओं को ऑर्डर करना चाहते हैं तो क्या होगा। या उनकी सामग्री प्रकार। यदि आप 'चयनित' ऑब्जेक्ट को एक अलग रंग बनाना चाहते हैं तो क्या होगा। इसके बारे में अगर वास्तव में सू के रूप में आप एक वस्तु पर एक आकर्षित समारोह कहते हैं, इसके बजाय यह इसे प्रस्तुत करने के लिए कार्रवाई की एक कमांड सूची में डालता है (सूत्रण के लिए आवश्यक हो सकता है)। आप दूसरी प्रणाली के साथ उस तरह का काम कर सकते हैं लेकिन यह एक PITA है।
जो मैं सुझाता हूं वह सीधे ड्राइंग के बजाय है, आप उन सभी वस्तुओं को बांधते हैं जिन्हें आप किसी अन्य डेटा संरचना में चाहते हैं। उस बाइंडिंग को केवल ऑब्जेक्ट लोकेशन और रेंडरिंग जानकारी के संदर्भ में होना चाहिए।
आपके स्तर / विखंडू / क्षेत्र / नक्शे / हब / पूरे / जो कुछ भी एक स्थानिक सूचकांक दिया जाता है, इसमें ऑब्जेक्ट शामिल होते हैं और उन्हें समन्वित प्रश्नों के आधार पर लौटाते हैं और एक साधारण सूची या ओक्ट्री जैसी कोई चीज हो सकती है। यह भौतिक विज्ञान के दृश्य के रूप में 3rd पार्टी भौतिकी इंजन द्वारा कार्यान्वित कुछ के लिए एक आवरण भी हो सकता है। यह आपके लिए "सभी वस्तुओं को क्वेरी करने की अनुमति देता है जो कैमरे के दृश्य में हैं उनके आसपास कुछ अतिरिक्त क्षेत्र के साथ" या सरल गेम के लिए जहां आप बस पूरी सूची को हथियाने के लिए सब कुछ प्रस्तुत कर सकते हैं।
स्पेसियल इंडेक्स में वास्तविक स्थिति की जानकारी नहीं होती है। वे अन्य वस्तुओं के स्थान के संबंध में पेड़ों की संरचनाओं में वस्तुओं को संग्रहीत करके काम करते हैं। वे एक प्रकार की हानिपूर्ण कैश के रूप में हो सकते हैं, जो किसी वस्तु की त्वरित खोज को उसकी स्थिति के आधार पर अनुमति देता है। आपके वास्तविक X, Y, Z निर्देशांक की नकल करने की कोई वास्तविक आवश्यकता नहीं है। अगर आप रखना चाहते हैं तो आप कह सकते हैं
वास्तव में आपके खेल की वस्तुओं को भी अपने स्थान की जानकारी रखने की आवश्यकता नहीं है। उदाहरण के लिए एक वस्तु जिसे एक स्तर में नहीं रखा गया है उसके पास x, y, z निर्देशांक नहीं होना चाहिए, इसका कोई मतलब नहीं है। आप इसे विशेष सूचकांक में शामिल कर सकते हैं। यदि आपको उसके वास्तविक संदर्भ के आधार पर ऑब्जेक्ट के निर्देशांक देखने की आवश्यकता है तो आप ऑब्जेक्ट और दृश्य ग्राफ के बीच एक बंधन रखना चाहते हैं (दृश्य ग्राफ निर्देशांक के आधार पर वस्तुओं को लौटाने के लिए हैं, लेकिन वस्तुओं के आधार पर निर्देशांक वापस करने में धीमी हैं) ।
जब आप किसी Object को Level पर जोड़ते हैं। यह निम्नलिखित कार्य करेगा:
1) एक स्थान संरचना बनाएँ:
class Location {
float x, y, z; // Or a special Coordinates class, or a vec3 or whatever.
SpacialIndex& spacialIndex; // Note this could be the area/level/map/whatever here
};
यह तीसरे पक्ष के भौतिकी इंजन में किसी वस्तु के संदर्भ में भी हो सकता है। या यह किसी अन्य स्थान (एक ट्रैकिंग कैमरा या संलग्न वस्तु या उदाहरण के लिए) के संदर्भ के साथ एक ऑफसेट निर्देशांक हो सकता है। बहुरूपता के साथ यह या तो निर्भर हो सकता है अगर यह एक स्थिर या गतिशील वस्तु है। निर्देशांक अद्यतन किया जाता है जब यहाँ स्थानिक सूचकांक के लिए एक संदर्भ रखने के द्वारा भी स्थानिक सूचकांक हो सकता है।
यदि आप गतिशील मेमोरी आवंटन के बारे में चिंतित हैं, तो मेमोरी पूल का उपयोग करें।
2) अपनी वस्तु, उसके स्थान और दृश्य ग्राफ के बीच एक बंधन / लिंकिंग।
typedef std::pair<Object, Location> SpacialBinding.
3) बाइंडिंग को उचित बिंदु पर स्तर के अंदर स्थानिक सूचकांक में जोड़ा जाता है।
जब आप रेंडर करने की तैयारी कर रहे हैं।
1) कैमरा प्राप्त करें (यह सिर्फ एक और ऑब्जेक्ट होगा, सिवाय इसके कि यह स्थान खिलाड़ियों के चरित्र पर नज़र रखेगा और आपके रेंडरर के पास इसका विशेष संदर्भ होगा, वास्तव में यह वास्तव में इसकी आवश्यकता है)।
2) कैमरे के SpacialBinding जाओ।
3) बाइंडिंग से स्पेसियल इंडेक्स प्राप्त करें।
4) कैमरे को दिखाई देने वाली (संभवतः) वस्तुओं को क्वेरी करें।
5A) आपको दृश्य जानकारी संसाधित करने की आवश्यकता है। GPU और इतने पर अपलोड किए गए टेक्स्ट। यह अग्रिम में किया जाएगा (जैसे कि लेवल लोड पर), लेकिन शायद रनटाइम पर किया जा सकता है (एक खुली दुनिया के लिए, आप सामान तब लोड कर सकते हैं जब आप एक चंक के पास होते हैं, लेकिन अभी भी अग्रिम में किया जाना चाहिए)।
5B) वैकल्पिक रूप से एक कैश्ड रेंडर ट्री का निर्माण करें, यदि आप बाद में समय पर दिखाई दे सकते हैं तो आस-पास की वस्तुओं को गहराई / सामग्री के प्रकार या ट्रैक करना चाहते हैं। अन्यथा आप केवल स्थानिक सूचकांक को क्वेरी कर सकते हैं यह आपके खेल / प्रदर्शन आवश्यकताओं पर निर्भर करेगा।
आपके रेंडरर को एक रेंडरबाइंडिंग ऑब्जेक्ट की आवश्यकता होगी जो ऑब्जेक्ट, निर्देशांक के बीच लिंक करेगा
class RenderBinding {
Object& object;
RenderInformation& renderInfo;
Location& location // This could just be a coordinates class.
}
फिर जब आप रेंडर करते हैं, तो बस सूची चलाएं।
मैंने ऊपर संदर्भों का उपयोग किया है, लेकिन वे स्मार्ट पॉइंटर्स, रॉ पॉइंटर्स, ऑब्जेक्ट हैंडल आदि हो सकते हैं।
संपादित करें:
class Game {
weak_ptr<Camera> camera;
Level level1;
void init() {
Camera camera(75.0_deg, 1.025_ratio, 1000_meters);
auto template_player = loadObject("Player.json")
auto player = level1.addObject(move(player), Position(1.0, 2.0, 3.0));
level1.addObject(move(camera), getRelativePosition(player));
auto template_bad_guy = loadObject("BadGuy.json")
level1.addObject(template_bad_guy, {10, 10, 20});
level1.addObject(template_bad_guy, {10, 30, 20});
level1.addObject(move(template_bad_guy), {50, 30, 20});
}
void render() {
camera->getFrustrum();
auto level = camera->getLocation()->getLevel();
auto object = level.getVisible(camera);
for(object : objects) {
render(objects);
}
}
void render(Object& object) {
auto ri = object.getRenderInfo();
renderVBO(ri.getVBO());
}
Object loadObject(string file) {
Object object;
// Load file from disk and set the properties
// Upload mesh data, textures to GPU. Load shaders whatever.
object.setHitPoints(// values from file);
object.setRenderInfo(// data from 3D api);
}
}
class Level {
Octree octree;
vector<ObjectPtr> objects;
// NOTE: If your level is mesh based there might also be a BSP here. Or a hightmap for an openworld
// There could also be a physics scene here.
ObjectPtr addObject(Object&& object, Position& pos) {
Location location(pos, level, object);
objects.emplace_back(object);
object->setLocation(location)
return octree.addObject(location);
}
vector<Object> getVisible(Camera& camera) {
auto f = camera.getFtrustrum();
return octree.getObjectsInFrustrum(f);
}
void updatePosition(LocationPtr l) {
octree->updatePosition(l);
}
}
class Octree {
OctreeNode root_node;
ObjectPtr add(Location&& object) {
return root_node.add(location);
}
vector<ObjectPtr> getObjectsInRadius(const vec3& position, const float& radius) { // pass to root_node };
vector<ObjectPtr> getObjectsinFrustrum(const FrustrumShape frustrum;) {//...}
void updatePosition(LocationPtr* l) {
// Walk up from l.octree_node until you reach the new place
// Check if objects are colliding
// l.object.CollidedWith(other)
}
}
class Object {
Location location;
RenderInfo render_info;
Properties object_props;
Position getPosition() { return getLocation().position; }
Location getLocation() { return location; }
void collidedWith(ObjectPtr other) {
// if other.isPickup() && object.needs(other.pickupType()) pick it up, play sound whatever
}
}
class Location {
Position position;
LevelPtr level;
ObjectPtr object;
OctreeNote octree_node;
setPosition(Position position) {
position = position;
level.updatePosition(this);
}
}
class Position {
vec3 coordinates;
vec3 rotation;
}
class RenderInfo {
AnimationState anim;
}
class RenderInfo_OpenGL : public RenderInfo {
GLuint vbo_object;
GLuint texture_object;
GLuint shader_object;
}
class Camera: public Object {
Degrees fov;
Ratio aspect;
Meters draw_distance;
Frustrum getFrustrum() {
// Use above to make a skewed frustum box
}
}
चीजों को एक-दूसरे को 'जागरूक' बनाने के लिए। यही है टकराव का पता लगाना। इसे संभवत: ऑक्ट्री में लागू किया जाएगा। आपको अपने मुख्य ऑब्जेक्ट में कुछ कॉलबैक प्रदान करने की आवश्यकता होगी। यह सामान बुलेट जैसे एक उचित भौतिकी इंजन द्वारा सबसे अच्छा नियंत्रित किया जाता है। उस स्थिति में बस Octree को PhysicsScene से बदलें और CollisionMesh.getPosition () जैसी किसी चीज़ की लिंक के साथ स्थिति।