Jump to content

  • Log In with Google      Sign In   
  • Create Account

TheChubu

Member Since 13 Sep 2012
Offline Last Active Yesterday, 08:24 PM

#5267051 My A* Hierarchical pathfinding.

Posted by TheChubu on 19 December 2015 - 12:08 PM

I see various places where you can simplify equality tests a bit:

.

// This is a more canonical equals, with the instanceof operator, which is a bit more robust.
@Override
public final boolean equals(Object o)
{
  if ( this == 0 ) return true;
  if (o == null || !(o instanceof Node) ) return false;
  return this.equalsNonNull((Node)o);
}
 
// Now we do an equals for when we know we're comparing nodes.
public final boolean equals(Node o)
{
  if ( this == 0 ) return true;
  if (o == null) return false;
  return this.equalsNonNull(o);
}
 
// Most reduced scenario, we know its a Node and that isnt null.
public final boolean equalsNonNull(Node o)
{
  // Here we can use the reduced equalsNonNull of Coordinate.
  // If it could be null, use equals(Position) instead.
  return this.position.equalsNonNull(o.position);
}
 
// Now equals for Coordinate objects:

// Most generic case.
@Override
public final boolean equals(Object o)
{
  if (this == o) return true;
  if (o == null || !(o instanceof Coordinate)) return false;
  return this.equalsNonNull((Coordinate)o);
}
 
// Equals for when we know we're comparing coordinates.
public final boolean equals(Coordinate o)
{
  if ( this == 0 ) return true;
  if (o == null) return false;
  return this.equalsNonNull(o);
}
 
// Most reduced scenario, we know its a Coordinate and that isnt null.
public final boolean equalsNonNull(Coordinate o)
{
  return (this.x == o.x && this.y == o.y);
}

.

And use them where they're needed given assumptions in the surrounding code (ie, you don't always need the generic equals(Object), sometimes you know you're comparing Node/Coordinate, or that something can't be null).

 

Also, reduce your objects, don't use "Coordinate" that only has two fields. Simply put the x/y on the Node or something.

 

For each object you have 12 bytes of overhead, and each object access is more or less a pointer indirection (unless HotSpot can work some magic there too). So a typical "Position2D" object would look in memory like this:

 

12 bytes overhead

+ 4 bytes x coord

+ 4 bytes y coord

+ 4 bytes for 8 byte alignment (everything is 8 byte aligned).

 

Total of 24 bytes and one mandatory indirection for only 8 bytes of useful data. So flatten a bit your structures. Also look up alternative HashMap and ArrayList implementations, like from fastutil's. 

 

Can't help with the algorithmic complexity though biggrin.png




#5266369 good approach to randomly generate the contents of a dungeon or room

Posted by TheChubu on 14 December 2015 - 05:35 PM

funny.jpg

 

... hehehehehehehe

 

(sorry)




#5266055 Cross Platforming: Switching to Java?

Posted by TheChubu on 12 December 2015 - 01:43 PM


Oh, well, but is not maintaining Java on multiple platforms way easier?
I might get downvoted but I'm going to say yes. Library linking/loading is standard and behaves the same in all the OSes that (desktop) Java supports.

 

Now the issue is that desktop Java isn't the same as Android Java. Yes, with desktop Java you get fairly simple multi platform support in all major OSes, with deployment of the application itself as simple as copying exactly the same .jars in all of them. LWJGL is well made, it will automatically load the native lib of the platform you're running the application on (for all the combinations between Linux, Windows, OSX, x86, x86_64).

 

But Android is different, you will have to code specific parts for it (input, display, sound, etc), moreover, you will need to "downgrade" your language support for whatever Java 6/7 bastard Android supports nowadays. iOS was supported through RoboVM for free, but Xamarin bought the company and moved it to their kind of strategy (ie, gotta pay up monthly). Same scenario if you want to use C#.

 

Also while you can reasonably expect the runtime of any OS to run your C++ program (or at worst you need to bundle some tiny binary, say a MSVS2015 redistributable), with Java you need to either bundle a 40-60Mb VM (not as complex as it sounds though) or provide a link for the user to download the VM from Oracle's site (and remember, Oracle bundles crapware with their JRE isntallers). Moreover, the "executable" itself might be multi platform, but it wont get you an OSX installer, Windows installer or a .deb package. That part you have to do on your own, probably regardless of the language you're using.

 

I still think its an scenario better than what you're left with C++, there are plenty of parts of the standard lib that are the same across desktop and Android, deployment is simpler albeit heavier, and ultimately, Java is a much simpler language to manage than C++.




#5265828 ECS: Systems operating on different component types.

Posted by TheChubu on 10 December 2015 - 10:27 PM

Thats an issue I often find myself trying to solve.

 

See the thing is, you totally can (and I've seen it) create a "messaging" api between systems. Ie, one system fires up an event that goes straight to another system. Which would be the case of the "activate" event for example.

 

Thing is, I feel like event/messaging api is bolted on. The system "should" write data into an entity's component, and the system that handles the response should fetch the data when its their turn. As you described, this isn't something simple to do in many cases.

 

The specific issue here is when this happens. With event systems you need to figure it out because its very important, imagine that if the physics system casts a ray and fires an event, the receiver does something with it, but it probably will be a system that also iterates over its entities. If you make a single event system, they might get processed at the same time, if you do it per system ,you could make a queue that only gets processed when that system is processed, or you could try to do without events and just write data, read data, and make it part of the normal entity-component iteration.

 

Order of system processing and system inter-dependencies are very important for getting consistent results, finding bottlenecks and possibly multi threading some of it.

 

Its still one of the things I'm not decided on, thus why I haven't added an event api on top of dustArtemis.

 

One idea I had for this kind of problem is to have one system in charge of maintaining a needed spatial structure. When entities get added/removed, system iterates over the affected entities and maintains its spatial structure.

 

Different systems can hold a reference to that system, and issue queries to it. So the system thats in charge of activating stuff (SystemA) can query "well, for this direction and reach, SystemB, give me what I am hitting". Thats a data query, and means that SystemA depends on SystemB to work on, that means that SystemA has to be executed after SystemB has updated its internal spatial structure for that frame. That makes dependencies obvious.

 

Then it would be a matter of:

.

for (entity in entitiesBeingHitted)
{
  if (entity.hasComponent(ActivableBehavior)
  {
    entity.addComponent(ActivatedTag);
  }
}

.

Then the system in charge of activated stuff can iterate over the activated entities in that frame and (possibly) execute trigger scripts or something, which in turn could plug other events in other subsystems. In this case I think adding/removing components to entities, and whatever consequence that has in the engine, should be a fast operation for this to work properly.

 

It might get overly complex, and maybe a straightforward but well defined messaging api between systems is better, as I said, I'm evaluating my options.




#5265494 Convert triangle list to a triangle strip?

Posted by TheChubu on 08 December 2015 - 03:52 PM

I know of two tools, NVTriStrip, from nVidia, and another one that tried to improve on it.

 

Here you can read about both of them: http://users.telenet.be/tfautre/softdev/tristripper/vs_nvtristrip.htm

 

TriStripper http://users.telenet.be/tfautre/softdev/tristripper/

 

NVTriStrip http://www.nvidia.com/object/nvtristrip_library.html




#5265484 entity system implementation

Posted by TheChubu on 08 December 2015 - 03:09 PM


Sure that would work. I can't think of any occurrences where i've wanted to see if it has a specific component without actually wanting to do something with it though, not personally.

 

The way I do it I use those bits to "filter" entities per system.

 

Each system maintains a list of the entity IDs it can process. For this to happen, all systems get notified when an entity is added, removed, or any of its components swapped. Now each system needs a fast and sure way to know if the entity has the components required for the system to be "interested" in it. That's where the bit set comes in, all you need to do is:

.

if (entityBits & systemBits) == systemBits)
{
  // keep entity.
}
else
{
  // remove entity.
}

.

Its cheap enough that the "performance concern" there is just maintaining the entity list ordered, not checking the entities themselves.

 

EDIT: Also if it wasn't clear, this way the systems never have to check if an entity has XYZ component in the main processing loop (ie, foreach entity doStuff(entity) ). They just straight use them since validation was made on the added/removed/changed events at the start of the frame.

 

You can find many of those "tricks" in my repo https://github.com/dustContributor/dustArtemis

 

The interesting parts are EntitySystem, Aspect, ComponentManager and EntityManager. Rest you can figure out from following those.

 

Thats Java, so there are more things you can do if you use a language that allows you to flatten objects or use sequentially stored structs.




#5264179 Instancing, and the various ways to supply per-instance data

Posted by TheChubu on 29 November 2015 - 08:15 PM


It seems like this could alleviate restrictions with attrib locations. However, you are limited by GL_MAX_UNIFORM_BLOCK_SIZE

Yes you are... but not totally.

 

Your limit is specifically for the amount of memory it can be bound at that particular UBO slot. AFAIK 64kB for everything except AMD these days. The trick is that the buffer itself can be bigger, much bigger.

 

Taking in account that the expensive part here often is uploading the data (many tiny uploads == bad), you can allocate something like 1Mb, upload all your data there with a couple calls at most (ideally only one), then just call glBindBufferRange in-between drawcalls.

 

Not sure how AMD handles glBindBufferRange, but nVidia, in their presentations, said that glBindBufferRange its a super cheap call to make, and since GCN seems to have the upper hand on memory management, probably its cheap to do with AMD too. Adding to that, since you already pre-uploaded all (or most) of your data to the big buffer, the state changes in between the draw calls should be minimal.

 

EDIT: The memory you can bind to an UBO slot can be as low as 16kB actually. 64kB is a common limit, but not the one that the spec defines as minimum. I recall one Intel forum post that  asked why in D3D11 you can have 64kB for a constant buffer but in OpenGL you only had 16kB, only then the Intel driver team incremented the limit to 32kB. That was for Windows drivers, Linux Intel drivers apparently tend to have better support.




#5264138 Vulkan is Next-Gen OpenGL

Posted by TheChubu on 29 November 2015 - 12:48 PM

 

All the current information I know is under NDA, at best I can say 'there is movement' smile.png

 

I'll sign a NDA if you'll tell me what you know ;D

 

 

Khronos membership is like 15k USD a year. Then you can sign the NDA :P




#5263868 Game Idea: can be done in one month?

Posted by TheChubu on 27 November 2015 - 02:03 PM

I don't think so.

 

You should totally do the game though, but I don't think you'll be able to do it in a month timeframe. If it were me I'd rather give my friend something more complete later than cutting it up now so I can finish it in a month.

 

My 2 cents.




#5261675 simple java question

Posted by TheChubu on 11 November 2015 - 03:58 PM

First: i references "3"

Second: i2 references "3"

Third: i references "0"

 

So by printing i2, you print "3".

 

When you do i2 = i you're copying the value of the reference 'i', not the object that its referencing. So when you do 'i = "0"' you're overwriting the reference value for a reference to another object, but i2 still keeps the reference to "3".

 

This is orthogonal to string's immutability. You could make the same example with StringBuilders (aka, mutable strings) and it would behave the same.

 

Preeety sure Oracle's Java tutorials explain this stuff, you should check them out.




#5260347 Singletons and Game Dev

Posted by TheChubu on 03 November 2015 - 11:48 AM

I hear Android is supposed to have a "smart" way of managing memory, but I've never really dug into that. Kind of interesting to find out that even in simple cases like this it can be that troublesome.

Nah, in that particular case simply using 'float' locals would have worked, probably would work better since it has less indirection. If you go in the commit history, the commit that made the change to static was like "meh, libGDX isn't multi threaded anyway". Thus why I had to look elsewhere for this stuff, since apparently that one part of the framework isn't thread safe justifies the decision of making the rest simply thread hostile.




#5259825 Singletons and Game Dev

Posted by TheChubu on 30 October 2015 - 08:29 PM

However, I've looked at some game libraries and engines (most prominently libGDX and Unity) and I've noticed they have no shame with exposing a lot of data structures globally.

libGDX? You're using libGDX as a reference of some sort?

 

Take a look:

 

https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/math/Matrix4.java#L73

 

Thats exactly what it looks like. A static float[16], whats its used for? Oh nothing too important, just holding effin intermediary results in math functions.

 

What does that means? That you can't possibly  invert a matrix on two separate threads because it will fuck something up. Read that again: You can't use libGDX's math functions on more than one thread. And you know what? Its not the only static used that way in libGDX.

 

I'll just leave you with that bit of information.

 

EDIT: More on topic -> Eff singletons. All of them. I'd simply copy-paste swiftwcoder's words here.




#5257825 Changing city names

Posted by TheChubu on 18 October 2015 - 04:56 PM

Plural people, plural.

 

Los Juegos -> Literally "the games". Juego can be used for gambling but its more of a context thing. "Las Apuestas" it would be more direct. From where I'm from "timba" is slang for gambling, so the name would be "La Timba", sort of "the gambling" literally.

 

Los Paraisos -> The paradises. Singular "El Paraiso", the paradise.




#5257365 GLSL Error C1502 (Nvidia): "index must be constant expression"

Posted by TheChubu on 15 October 2015 - 11:27 AM


Thanks, sadly the same error still occurs.
Have you tried what Mathias suggested? Redefining the array inside the block, not outside?

 

layout (std140) uniform LightSourceBlock
{
    LightSource lights[MAX_LIGHTS];
} LightSources;

 

This works. Its how I define UBOs. Tried it on nVidia hardware (GT21x, Fermi), and AMD (HD 5xxx, HD 4xxx), GLSL 330.




#5257280 GLSL Error C1502 (Nvidia): "index must be constant expression"

Posted by TheChubu on 14 October 2015 - 09:33 PM

lol yeah, I remember when I got this issue (same GLSL version, nVidia hardware), apparently "const int" isn't constant enough for nVidia :D As Mathias said, a #define works fine in this case.






PARTNERS