Saying C++ has no inheritance really is your biggest feat of stupidity in this thread. What's next, complaining that resolving the vtable is too slow and we should use only non-virtual functions? Perhaps you'll complain that a pointer is too slow to look up or heap memory too slow to access?
As for your missile experiment: You enable shadow rendering to show how slow evaluating if statements is??? If anything it proves how slow shadow rendering is when loads of smoketrails are drawn but that's no surprise. Tell ya what, I'll run that test with smoketrails disabled on my missiles just for the heck of it, after all it's the if statements, not the rendering that's slowing things down, right?
Testing with smoketrails enabled, projectiles=50 and 15 units firing that weapon the only time I got a slideshow was when those 750 missiles impacted simultaneously using the default explosion.
Another test, with smoketrails disabled and a CEG instead of the default explosion had no slideshow at all and 50% more FPS while the missiles were in the air (ZOMG if statements!)
Using a LaserCannon had no difference in speed.
However, switching to los rendering instead of shadows gave huge gains for all of these tests. Note that I deliberately made the units fire synchronously and at the limit of their range
Saying C++ has no inheritance really is your biggest feat of stupidity in this thread.
First off, if you have to attack that sub-point to get anywhere, then you are speaking from a position of weakness. It's like the Winston Churchill speech, where he annotated his text with a note saying, "argument weak here- shout".
I note that you haven't even bothered attacking the main substance of my remarks about how the lack of proper includes is the main problem with the weapons code- it's all stuff that was more-or-less built individually, over time, by multiple authors. It needs clean-up. And I think it's time to quit worrying about backwards-compatibility, and start aiming at the future.
Moreover, while we can argue semantics, I personally think that my statement about inheritance was functionally accurate.
When most people think of "inheritance", they're thinking of LUA-style inheritance, where you just build a function somewhere, and all functions that are a sub-set of that function inherit all properties of the parent (ok, ok, LUA people, that's usually in the context of a table that contains a function, but meh).
I'm not sure how saying that that's different, in significant ways, from how in C++ you're explicitly calling sub-functions together in an include to build a larger piece of logic... is stupid. It's a very different process, both computationally and in terms of coding style.
As for your experiment, I want to see Fraps video proof, or it didn't happen. I use as few missile weapons as possible, even with smoketrails pointing to null data, because they are so fricking slow compared to any other weapon in Spring.
Look at that massive mess of code again! Just look at that! You could make it a quarter of that length, just by splitting out the cases for different, specific weapon-type usages, and using a better rendering method, such as just using billboarded, non-shadowcasting sprites for the smoketrails! Instead of thinking it over, you do some half-assed test and then basically try to tell me that IFs aren't costly, when I stated that the issue isn't an IF, but whether the IF is in a high-frequency loop of the function? :rolleyes:
If you watch the CPU counter when you launch such and event, you will see what I mean- it's a world of difference, not just on the GPU side of things. The logic that's running just to do the bends on the smoketrail sections alone is eating a fair amount of CPU on math steps alone.
Make your universal weapons, it's obvious you need to learn that lesson the hard way, and I don't see any point in trying to talk you out of it- if you've read my arguments here, and reject them, then only doing it, and seeing the results, will convince you, and that's OK with me. Just don't make anybody else have to use them, because nobody else will want to- you will understand why, if you ever get it done.
If you come up with a neato feature, I'll just port it over to an efficient single-case weapon class. Viva la GPL. Which means that I'll have to take some time away from developing PURE, since that BeamBolt thingy, all by itself, is worth doing, but meh, I should have done this last year, when I got interested in this topic in the first place.
I wrote a long reply picking your points apart but then I decided only to write the most important point down so it's not missed:
There's O(n├é┬▓) code in the update loop and you're worried about a few if statements?
QFT. If statements might mean that there's some unnecessary nesting, but that should be just factored out into smaller functions. If maintainability is the problem, rip out the problem code into it's own function and work on that.
Either way, the whole "many classes vs. one class" issue is silly. Classes don't have to be tiers. Really, in each case that you have an "if" statement, a new class should be used, but _within_ the owning class.
I mean, it's messy to think about, but it works best if you imagine the TDF as a representation of the objects themselves. For each concept that is mutually exclusive, you make classes.
For example, your "weapon" object owns an "impacthandler" object, that can be the "simpleimpacthandler" or the "noexplodeimpacthandler". The "trailgenerator" can be null or the "billboardtrailgenerator" or the "ribbontrailgenerator". And so on. The tree of TDF tags represents directly the tree of objects and their fields.
That way you get the best of both worlds - you can construct KDR's all-singing-all-dancing weapons, and also you get the different behaviours properly seperated into classes, as Argh desires. This "one size fits all" approach of KDR ends up with monolithic classes, and the "single-tier specialized classes" approach Argh suggests reduces the freedom of modders.
No, I don't hate that idea- it means that many un-necessary instructions get cut out of time-sensitive loops, so that we don't have IF statements checking stuff like noExplode every frame, and all LOS weapons share one piece of common code for stuff like avoidFriendly, instead of having it within the projectile code itself. That's exactly what I want. My impression was that KDR doesn't seem to understand that's what I want, even though I've said that in about 5 different ways here.
It'd result in higher efficiency along the way, too, because during the process of cleaning that stuff up, we'll probably find a fair amount of waste and garbage, like that "laser" tag in WeaponDefHandler that doesn't need to be there anymore (I removed it from SWS during the general cleanup of the codebase, only old SWTA might have it, and who cares about that?), that artificial rise in FlameProjectiles that should be a game-design controlled variable (sinking missiles, anybody? could be useful ).
Then each WeaponProjectile could be a very short piece of code, #including any of the functions that it actually needs to perform correctly, cutting out anything that it doesn't within the loop. We'd have consistency and an easier-to-maintain codebase.
As Mr. Frumious pointed out, entirely correctly, the more code that is required for a given Weapon type, the slower it will get, due to memory access and other issues. That's inevitable, and should be reviewed for performance vs. benefit very, very carefully. IOW, the fewest minimum things should be made "must do, every weapon, every frame". It's fine if there are 50 different functions that could run if a designer wants them all to run, but most of the time, there should be a very tiny skeleton of minimum requirements and some rendering code, and that's it.
Not a whole lot different from how everything but the Missile code works. I keep picking on that, not because I don't think your improvements aren't improvements, KDR- I have a feeling that's one of the reasons you've been arguing with me so much, and I'm sorry, you just didn't know how much I loathed that class
New features are great. But there should be at least 6 different distinct classes of Missile, or IF case statements should be loaded if the function is loaded, instead of one with lots of per-frame IF statements, like the following:
Both of these functions could be put into a separate #include, "projectileMovementTypes", that would have functions for all of this stuff (think- we could have Wobble and Dancing for just about anything!) and only run per-frame if they were part of the TDF definition, otherwise they shouldn't ever get called. IOW, we need to call stuff like this either ONCE, during game start, or every frame- the burden of CPU cost should be on the game designer. Not hardcoded, regardless of whether it's being used to do anything or not. You see my point now?
That's all I wanted here- that, and I want to write a few all-new weapons classes and fix a few things that have been bugging me. This whole thing has been a complete waste of time, frankly.
Can we declare a truce and move on now?
If we're really on the same page, KDR, then I'd rather help you to clean up stuff than fight. If we are in agreement about the whole issue of structure, where my chief concern is speed and figuring out new ways to do old things, like BeamBolt, which replicates and improves LaserCannon, then we both basically want the same thing here.
Both of these functions could be put into a separate #include, "projectileMovementTypes", that would have functions for all of this stuff (think- we could have Wobble and Dancing for just about anything!) and only run per-frame if they were part of the TDF definition, otherwise they shouldn't ever get called.
That would cause incomprehensible code bloat, you'd need to create a new weapon type for every combination of tags.
Besides, this whole argument is baseless. Benchmarks or it didn't happen.
That would cause incomprehensible code bloat, you'd need to create a new weapon type for every combination of tags.
Can't we just have weapons call only those functions that are activated via TDFParser? So that, for example, if we want to have a noExplode BeamLaser, noExplode == 1, and if noExplode == 0, then that logic is never called? The problem, as I see it, is that a totally "universal weapon" is going to be massively bloated, because it will be chock-full of IFs-per-frame, but we could get closer to that goal without the bloat if we had some strict archetypes that could make use of a fairly wide number of properties.
For example... a weapon that fires a projectile that, upon deletion, becomes another weapon... that's a pretty distinctive archetype. It should be its own weapon, because it's going to need some logic that's entirely unique to it. Or, like the Beamlaser, where we're using a unique drawing method. That's the kind of stuff where we need an archetype and some separation, just like we do now. All I'm advocating is for the stuff that needs to be universally applied to get fixed, so that it's universally applied and in a common include for easy maintenance, and for the stuff that's designer-chosen to be in a separate include, so that people wanting to make a new weapon in Spring can look at the available functions that people have already made, and combine a few to make unique archetypes.
For example... all projectiles that obey gravity should be using the same Heightmod and basic movement code. If you want to make a new weapon for Spring with gravity as part of the archetype, you should just call that function. But you shouldn't have to include 5 other things that you'll never need as part of that, nor should you write up a whole new set of logic, either- the first is inefficient, the second means that maintenance becomes a thankless chore.
Argh: what you describe is possible (for those technically inclined, weapons would have to be JIT-ed), just not feasible in this engine. If spring was written in Lisp, who knows. But it's C++ and if/else is as good as it gets - and it's not slow, it's nothing (= immeasurably little) compared to LOS and pathfinding.
Argh, are the weapons handler changes you proposed on the first page getting put into SVN or what? I'd like to know this soon, as I would prefer a non suck ass way of creating custom projectile weapons without having to hack beamweapons.
This is also due to the fact that with beamweapons/lasercannon, you have to hack around with the thickness vs duration vs velocity to get your textures to come out the way you want them to look, whereas I'd prefer a system that blends a texture into a 3d model and lets you work it accordingly.
I agree with Fruminous, using "modules" for the different things is the way to go.
BTW, Argh, it would NOT be the same speed as ifs since instead of one function call (e.g. Update() or Draw()) that contains the whole code you get one call per module with the whole stack allocation deal (if is just a conditional goto, a function call must at least store the return address).
I know what you want but I think your reason for wanting it is nonsense. Also you don't seem to understand that #includes are performed at compile time, not at runtime. The modder cannot affect them at all.
Besides, you say that code shouldn't be run when the TDF doesn't call for it, well, guess what those if statements do!
Also Fruminous never claimed it would bring a performance increase, the load of code doesn't slow anything down if it's skipped because of if statements anyway. Monolithic classes are simply bad style for maintenance reasons, not because they're slower.
Users browsing this forum: No registered users and 1 guest
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum