Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 06 Oct 2006
Offline Last Active Today, 07:34 PM

#5302324 Pixel Shader 'stage Did Not Run'

Posted by phil_t on Today, 12:27 PM

Also make sure to check that the vertices aren't outside the near/far plane.

#5301579 Do My Swordsmen Look Like Cyborgs?

Posted by phil_t on 20 July 2016 - 10:18 AM

The blue shoulder pads (?) dominate the image, so that's really all I can see at a first glance. So they end up looking like big buggy eyes or something.


Maybe make the body stand out more from the green background, reduce the intensity of the blue, and maybe draw more attention to the sword?



Just thought of what they reminded me of:



#5301149 Basic Multithreaded Question

Posted by phil_t on 17 July 2016 - 10:32 PM

Copying the array means either one of two things: A) Your array is so small that copying is cheap; if it's that small, you shouldn't be multithreading it anyway. or B) The array is large, but you're taking the easy way out instead of understanding the problem (which sometimes is the economic thing to do, if you don't have time to waste doing the research).


Or the array is small and cheap to copy, but the computation you're performing is expensive and makes sense to spread over multiple threads...

#5301028 Object Referencing

Posted by phil_t on 16 July 2016 - 07:15 PM

I'm not using it for every pointer, but for any pointer that has a strong ownership of an object, so like an entity has a strong ownership of it's components, so it holds a reference to it, and etc.


So an entity owns its components? Have the entity manage them with a vector of unique_ptrs. There's no need for reference counting or garbage collection, since an entity will outlive its components.

#5300999 Object Referencing

Posted by phil_t on 16 July 2016 - 01:52 PM

Do you think that a garbage collector is worth implementing, or is a simple smart_ptr implementation enough?


You don't say what your scenario is. Is this for a game? What will you be using these objects for?


And using reference counting by default (your own implementation, or shared_ptr, or whatever), is a sign that you don't really understand your object lifetime or ownership semantics.

#5299810 Does Object Pooling with a Vector in C++ have problems with memory?

Posted by phil_t on 08 July 2016 - 03:27 PM

Finally, you really don't need to use Raw pointers as well. This goes back to using modern C++. Using something simple like std::shared_ptr rather than Bullet*. This makes your code easier to understand as well. For instance, It could be implied BulletPool manages the lifetime of your Bullets, but it is not explicit. Who has to delete all those bullets? What if the pool is destroyed and thus all pointers to the bullets but you have a dangling Bullet pointer that was set using ::GetBullet(). A shared pointer would help avoid that issue.


I'm not sure what you're suggesting. Are you suggesting the OP hand out shared_ptr<Bullet> instead of Bullet* from his BulletPool class? That doesn't make any sense - the point of BulletPool is to manage handing out bullets that were allocated from a contiguous block of memory. That's in direct conflict the allocation/free strategy for shared_ptr (or any smart pointer).


You *could* provide some wrapper around Bullets that are handed out which would have a reference to the pool so they could "return" themselves to the pool when they go out of scope.


FWIW, there are few cases I would recommend shared_ptr, and this is certainly not one of them. They're useful if it's not possible to known the lifetime if your objects, but in general for games object lifetime is well-understood. So there's really no reason to use them for something like bullets.

#5299032 Creating Entities from XML in a Data-Oriented ECS

Posted by phil_t on 04 July 2016 - 12:38 PM


I created a very simple demo for this, and it appears to work fine. However, I am attempting to suss out how I would set this system up to read an entity specification file in XML/JSON/whatever. If I were going in the more object-oriented fashion of ECS this would be a bit simpler; I could create a bunch of factories that take as a parameter the current entry in the file and return a new instance of a component object. However, I am attempting to approach this in a more data-oriented fashion. I need to put values into tables, not return a separate instance of a class. As such, I would need a reference to the table in question.


My first thought is to create a class that acts as a sort of "central database"; it essentially just holds an instance of every component manager, and my entity manager and hands out references to whoever needs it. The class that reads the file could hold a reference to this object, access whatever table it needs and add to it whatever values are specified. This strikes me as not a great idea; there could be quite a few components to manage at the end of this, and that class would become quite large. There's also the issue of having to go into that class every time I need to add or remove components. This may be my rather amateurish opinion, but that doesn't strike me as being particularly extensible over time.




I don't see this as a fundamentally any different problem than it would be with "the more object-oriented fashion of ECS".


In either case, you still need to implement some kind of reflection logic to map properties in the XML/JSon/whatever to actual code. In the traditional case, these would map to properties on a struct. In your case, these would map to method calls on a particular component manager. Or am I not understanding the design in the linked blog properly?

#5298938 Synchronize objects' movements moved by coroutine function

Posted by phil_t on 03 July 2016 - 05:49 PM

Checking for equality of a Vector3 (or any floating point number) is problematic. It's unlikely that the final parameter you pass to Vector3.Lerp will be exactly 1, and unlikely that even if it is, the result will be exactly endPosition. So I'm surprised this code even sends your objects back and forth.


The following code worked for me:


    public float time = 2f;
    public Vector3 endPos;
    private Vector3 startPos;
    private float currentTime;
    // Use this for initialization
    void Start () {
        startPos = transform.position;
    void FixedUpdate()
        currentTime += Time.deltaTime;
        // Sawtooth wave
        currentTime %= time;
        float progress = currentTime / time;
        // Let's turn it into a triangle wave, which is what defines our back and forth movement
        progress = Mathf.Abs((progress - Mathf.Floor(progress + 0.5f)) * 2.0f);
        transform.position = Vector3.Lerp(startPos, endPos, progress);


I think even with this though, the objects will get out of sync eventually due to accumulating fp precision errors. While it may be sufficient for scenario (I don't know), if you want 3 objects to stay in sync over a long period of time, you'll need to base their positions off a single simulation (rather than 3 separate simulations) - or at least ensure that the math calculations that involve Time.deltaTime are identical in all three simulations (they are not in the code I posted, since I'm using "time" to take the modulo of currentTime (and "time" is different among the 3 objects)).

#5298920 class array to list

Posted by phil_t on 03 July 2016 - 02:27 PM

Assuming you have this array:

Ausfaelle Ausfaelle_Line[]={
{ 1, 2, 0, "OUTSID", 1, "EXTERNAL CHECKS    PAGE 3", 0, 1, "sim/cockpit2/annunciators/passenger_oxy_on", NULL },
{ 1, 2, 0, "OUTSID", 1, "EXTERNAL CHECKS    PAGE 3", 0, 1, "sim/cockpit2/annunciators/passenger_oxy_on", NULL },
{ 1, 2, 0, "OUTSID", 1, "EXTERNAL CHECKS    PAGE 3", 0, 1, "sim/cockpit2/annunciators/passenger_oxy_on", NULL },

If you want to add copies of each Ausfaelle to a list, you do:

std::list<Ausfaelle> points;
// Copy from beginning to end of Ausfaelle_Line, and push onto the back of the "points" list:
std::copy(std::begin(Ausfaelle_Line), std::end(Ausfaelle_Line), std::back_inserter(points));

If, instead, you want pointers to the Ausfaelle objects in Ausfaelle_Line (an important distinction), you can do:

    std::list<Ausfaelle*> pointsPointers;
    // Using std::transform here, because the source type is Ausfaelle, but the destination type is Ausfaelle*
    std::transform(std::begin(Ausfaelle_Line), std::end(Ausfaelle_Line), std::back_inserter(pointsPointers),
        [](Ausfaelle &thing) { return &thing; } // "convert" Ausfaelle& to Ausfaelle*

The distinction here is different. Are you wanting to work on copies of the objects in the original array? Or actually references to them?
Other questions you need to think about:
- what is the lifetime of this Ausfaelle data? If you're copying pointers to the objects into a list, you need to ensure the original objects are kept alive as long as you are using that list. Not a problem in the case when you have a static array you've copied from - but if they might come from other sources, you need to consider this
- Why are you using a list, and not a vector?
I might also note that the c++ containers support initializer lists, so you can do this directly:
    std::list<Ausfaelle> Ausfaelle_Line = {
        { 1, 2, 0, "OUTSID", 1, "EXTERNAL CHECKS    PAGE 3", 0, 1, "sim/cockpit2/annunciators/passenger_oxy_on", NULL },
        { 1, 2, 0, "OUTSID", 1, "EXTERNAL CHECKS    PAGE 3", 0, 1, "sim/cockpit2/annunciators/passenger_oxy_on", NULL },
        { 1, 2, 0, "OUTSID", 1, "EXTERNAL CHECKS    PAGE 3", 0, 1, "sim/cockpit2/annunciators/passenger_oxy_on", NULL },
... if that's what you want...

#5298827 Monogame wierdness

Posted by phil_t on 02 July 2016 - 02:55 PM

Not sure of this, but I think the numVertices parameter of DrawUserIndexedPrimitives might specify the range of the vertex buffer to draw from. In that case, it should probably be 6, not 4, since your 2nd rectangle uses indices up to 5. (the XNA documentation isn't very clear on this issue)

#5298744 Does adding Delegates/Function pointers to an entity break ECS ideology?

Posted by phil_t on 01 July 2016 - 03:53 PM

If the OP is talking about function pointers (e.g. to offer pluggable functionality in a component), I don't see anything necessarily conceptually wrong with that. But it's hard to know without knowing your scenario. Technically, that's not code in a component, it's exposing a property of a component that a system can then invoke (whether it's a function ptr, or some enum or numerical identifier that maps to a function).


If you ever want to be able to serialize your components (e.g. for save games, or editor functionality), then it would easier if you used some numerical identifier for the function.


As for your mention of delegates, it's hard to know how you're intending to use them. But it seems like a potential code smell, and there's probably a better way to do what you want that fits more with "ECS ideology", so to speak.


No one can really answer your question without knowing your scenario. Describe what you're trying to accomplish, rather than a particular implementation.

#5298738 Heightmap problems

Posted by phil_t on 01 July 2016 - 02:20 PM

You're casting it to a Uint32* , meaning the when you index it like an array, it is indexed in 4 byte increments. You need to cast it to uint8_t* so you can index it in single byte increments (so you can obtain every third byte).



#5298729 Heightmap problems

Posted by phil_t on 01 July 2016 - 01:47 PM

I don't know SDL, but if it's a 24bit image, each pixel might be 3 bytes instead of 4 (although sometimes 24 bit images store their data in 4 byte chunks for good memory alignment). You're treating it like if it were 4.


That is, each j that gets incremented reads from a position 4 bytes further in the buffer, since you're casting the array to a Uint32*.


Because your source image has equal values for r, g, and b, this error wouldn't be very obvious. You're basically reading an r value, then a g value, then a b value, and so on.


Instead, you may need to index it as a byte array, and increment by j * 3 (and remove the /4 from the pitch calculation).

#5298710 Monogame wierdness

Posted by phil_t on 01 July 2016 - 11:09 AM

Well, the bottom rectangle is drawing as a triangle because specify to only draw a single primitive (1 triangle) in your DrawUserIndexedPrimitives call.


Other than that, I suspect your index buffers (or vertex buffers) are incorrect, or some other parameters to DrawUserIndexedPrimitives are wrong.

#5298556 Sharing object between 2 threads

Posted by phil_t on 29 June 2016 - 03:06 PM

I think you're falling into the trap of "everything must be an object, and all functionality for manipulating the object must be in methods on the object".


You have:

    a) the simulation data

    b) the code that manipulates the data as it runs the simulation

    c) the code that renders the data


There's no reason these all need to be the same object... especially given that you want the possibility of a + b without any dependency on c.  b and c don't need to know about each other.