Jump to content
  • Advertisement


  • Content count

  • Joined

  • Last visited

Community Reputation

1468 Excellent

About Tispe

  • Rank
    Advanced Member

Personal Information

  • Interests

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. The example I gave is just a simplification to get to the issue, ambiguous access from multiple inheritance. The component here is actually going to hold (or for that matter be) a proxy pointer to the data allocated somewhere else (in the system<T>). Should the system move the data to another memory location this component will have its proxy pointer updated by the system. The proxy pointer is built from bi-directional smart pointers to ensure that a component get/set is only one indirection away, and should either the component be destructed or the data no longer be available in the system get/set and update proxy pointer will not crash the program. With this I can create an entity and select its components using templates. I can also give it overloaded operators, such as, myEntity = pos1; and, myEntity = vel2;
  2. Hi I want to test out a polymorphic entity component system where the idea is that the components of an entity are "compositioned" using templated multiple inheritance. But I am running into an issue because I am stacking a bunch of methods with the same names inside a class (but they have different signatures). I want these methods to be overloaded by the template type but my compiler says the access is ambiguous. I have issues making them unambiguous with the using declaration because the paramter pack expansion causes a syntax error. Can anyone here give me some advice on this? template <class T> class component { T m_data; protected: component() {}; ~component() {}; public: void set(const T& data) { m_data = data; }; }; template <class ...Ts> class entity : public component<Ts>... { public: entity() {}; ~entity() {}; //using component<Ts>::set...; // syntax error }; struct position { float x{}; float y{}; float z{}; }; struct velocity { float x{}; float y{}; float z{}; }; int main() { entity<position, velocity> myEntity; position pos = { 1.0f, 1.0f, 1.0f }; velocity vel = { 2.0f, 2.0f, 2.0f }; myEntity.set(pos); // error C2385: ambiguous access of 'set' //myEntity.set(vel); return 0; }
  3.   I can see that it is slow doing random array access on entities using indices to update data in response to unpredictable input. But there is only one way to layout data in memory at one time without duplication, and it seems reasonable to me that the data layout should best suit the heaviest workload for the most gains in terms performance(fps).   I thought that when doing heavy CPU calculations such as physics/collision, it is preferable to streamline dataflow from memory to cpu cores/threads. Meaning we want to structure and pack data only relevant for those operations as closely and as contiguous as possible, am I missing something?
  4. The unique ID is supposed to be global for all entities, not just players. Over a network in client-server-client situations IDs would be consistent.   If I reserve the ID #42 for "m_Players[42]" then what would then happen if I want to to something with "m_SomeObjects[42]", for example: m_Players[13]->shoot(42,9000)? Should someObjects[42] be hit or should "m_Players[42]"? I would between different types of entities have to translate first from local ID(index) to a global ID then back down to the appropiate entity container.   Another situation for example is when a large number of players or entities are spawned, such that you end up with IDs with values in the thousands. Then later on most of them could be cleared away leaving behind some entities with large ID values. I'm thinking I could be making more problems then I solve.
  5. Hello   I want to know more about how to effectively index players by ID.   Suppose I have a vector that store all players in one place (yes I can break them apart for ECS but for the purpose of the question I have them together): struct player { unsigned int ID; char name[32]; float xpos, ypos, zpos; float xvel, yvel, zvel; int health; // more to come }; std::vector<player> m_Players;  Each player has a unique ID of type unsigned int which can be anything. If there are 6 players and one of them has for some reason has the highest ID value: 9999, then I don't want to have an allocated array of players of size 9999 where 9993 of them are unused to address them directly by ID(myPlayer = m_Players[9999]). I want a array of players of size 6, and I want an array of indices mapping IDs to their position in the player array, such that I can access each player by ID. The reason I don't directly want to use a std::map<id,player> is that I want to effectively traverse the player array in another places. std::unordered_map<unsigned int, unsigned int> m_Index; bool update(const unsigned long ID, float xvel, float yvel, float zvel) { auto search = m_Index.find(ID); if (search == m_Index.end()) return false; auto index = search->second; if(index >= m_Players.size()) return false; auto& myPlayer = m_Players.at(index); if(ID != myPlayer.ID) return false; myPlayer.xvel = xvel; myPlayer.yvel = yvel; myPlayer.zvel = zvel; return true; } void advance(const float timeDelta) { for(auto& myPlayer : m_Players) { myPlayer.xpos += xvel*timeDelta; myPlayer.ypos += yvel*timeDelta; myPlayer.zpos += zvel*timeDelta; } } /* void advance_parallel(const float timeDelta) { parallel_for(auto& myPlayer : m_Players) { myPlayer.xpos += xvel*timeDelta; myPlayer.ypos += yvel*timeDelta; myPlayer.zpos += zvel*timeDelta; } } */  Now, different players can be in different situations, for example, some players might be culled away, some players might be on differnt teams and so on. So I want to know if index maps could be suitable for these purposes: std::unordered_map<unsigned int, unsigned int> m_Index_inactivePlayers; std::unordered_map<unsigned int, unsigned int> m_Index_renderablePlayers; std::unordered_map<unsigned int, unsigned int> m_Index_redTeamPlayers; std::unordered_map<unsigned int, unsigned int> m_Index_blueTeamPlayers; void redTeamHealthBoost(int health) { for(auto& [ID, index] : m_Index_redTeamPlayers) { if(index >= m_Players.size()) continue; auto& myPlayer = m_Players.at(index); if(ID != myPlayer.ID) continue; myPlayer.health += health; } }  Any thoughts, input or comments is much appreciated.
  6. Tispe


  7. Obviously you don't want every particle to issue a draw call. So instancing all particles to a single draw call is the way forward.   You need an instance buffer that you should update every frame. If each of the 100K particles are going to carry 29 bytes of information then we are looking at a ~2,76MB big instance buffer. If you are updating 120 times a second we are looking at 330MB/s of bandwidth just for this one effect. Additionally you are using the CPU to calculate 330MB/s worth of data, even if you spread it out on all cores this is in my mind a huge performance hit.     What if you just copied the instance buffer ONCE to device memory and let the GPU calculate the new positions? Let's say your instance buffer contains 100K particles, that only carry an initial state, such as spawn time, death time, a random chaos value, spawn position and velocity. Then just have one global time variable. Then in the shader calculate if it should be drawn and where?
  8. Tispe

    Advanced Intersection Test Methods

    I learned nothing from reading this.
  9. Tispe

    Carpentry and Magic Resizing Logs

    Where can I get said refactoring tools?
  10. Tispe

    Most GUI libraries are terrible

    I have been rolling my own IMGUI, quite simple and effective.
  11. Interesting. Would you happen to know if the compiler utilizes the SSE instructions for D3DXMATRIX and D3DXVECTOR3 operations on the CPU?   I'm interested in learning how I should implement skeleton animation for 1000+ characters. Where, each bone will be affected by 1-4 animation tracks and then each bone will be tranformed to its parent bone. There could be 120 bones in each skeleton.
  12. Tispe

    Fun with Modern C++ and Smart Pointers

    Are Smart Pointers in widespread use in gaming studios? Or do professionals prefer normal pointers?
  13. Well explained and simple. Though I can't see why a camera can be inside two trees at the same time. And should a tree be standing next to a wall, could this push the camera through that wall?   Another "bug", might be if you come at an high speed and for the next frame, the camera has passed through the center and you are basically pushed out from the back of the tree.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!