Adding data to a Ray

I was thinking of extending a Ray to add some optimization data along with it, but apparently since it implements Savable it has to be final for some reason, throwing that out of the window.

Then I tried copying the class in whole and changing the name, but then it’s no longer classified as a bounding volume somehow?

com.jme3.collision.UnsupportedCollisionException: Collidable:WeaponRay [Origin: (15.484375, 7.675293, 2.125), 
Direction: (0.7961645, -0.17364807, 0.5796278)]
at com.jme3.collision.bih.BIHTree.collideWith(BIHTree.java:476)
at com.jme3.scene.Mesh.collideWith(Mesh.java:998)
at com.jme3.scene.Geometry.collideWith(Geometry.java:450)
at com.jme3.scene.Node.collideWith(Node.java:611)
at com.jme3.scene.Node.collideWith(Node.java:611)
at com.jme3.scene.Node.collideWith(Node.java:611)
at com.jme3.scene.Node.collideWith(Node.java:611)
at com.jme3.scene.Node.collideWith(Node.java:611)
at particle.rayprojectiles.RayAbstract.rayCast(RayAbstract.java:51)
at particle.rayprojectiles.RayAbstract.cycle(RayAbstract.java:32)
at mainpkg.CPU.effectmanagment(CPU.java:1011)
at mainpkg.CPU.simpleUpdate(CPU.java:756)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:239)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:193)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:232)
at java.lang.Thread.run(Unknown Source)

So, any way to accomplish this without making a too convoluted outside system? Thanks!

P.S. If you’re wondering what data I planned to add, it’s the “shooter” node that created the projectile casting the ray so I can check if the node doing the collideWith can ignore the collision with the ray completely. But well, not exactly that important in regards to the issue.

You will have a much easier time doing your own collideWith() processing. Traverse the scene graph yourself, decide what you do/don’t want to do at each level. Way easier than trying to add data to an unrelated class and then you can pass whatever object you want to that code.

Someone should really implement a proper scene graph traverser some day that does a pre-order and post-order call, allowing pruning on the pre-order call. But it’s easy enough to implement outside the scene graph and then you’d have better control over all kinds of things anyway.

You know that’s kind of like answering “how do I patch up this tire” with “just go buy a new car, you’ll have less trouble”.

I don’t really see what kind of system would be better suited for this case. It’ll always have to be recursive to get to the actual geometries and the nodes above them can do the occasional cull by editing their collideWith method as I already have it set up.

Now I suppose I could add some params to the method itself, but that would require replacing every single node I use with a custom one.

Not exactly practical with a huge project.

Edit: Decided to go with the convoluted outside system option instead. :confused: This being on the rendering thread makes it possible to store a static reference of exclusions ¯\ _ (ツ)_/¯

At me a question for self-education, in jME3 the bitwise comparison of collisions is not implemented?

Currently, afaik the only thing that happens when you do a collideWith call is that the node you call it on calls the same method recursively for all of its children until they hit a geometry which then does the math and reports the number of collisions and stores them into the CollisionResult array.

So to abort a collision check you can then override collideWith in a custom Node and make it to, say, return 0 (and with that discard all subsequent collision checks). I have all particles and effect like things in such nodes.

No. It’s like I answered “This tire isn’t good enough I really need tank treads, can we morph the tires into tank treads” with: “You’d be better off replacing the tires with tank treads.”

Things are designed to do a certain thing… sometimes not well. But wanting to add data to Ray is the wrong way to go. It’s just a poopy design. What would you even name the thing? RayWithExtraData? When you come across a situation where you have to give a class a silly name to be accurate then usually it’s a sign of a design problem.

JME probably does at least need a bitwise tag for collideWith() but even that wouldn’t help you here.

Better to implement a data recursive (instead of code-recursive) traversal and then the sky is the limit. You could even dynamically prioritize different things, etc. for other general traversals. Extending THAT to add some extra data for the TRAVERSAL would totally make sense.

I’d call it a WeaponRay if you must know, which would make sense to differentiate it from all the mousepicking I do otherwise.

About the silly names though, that sounds like every java enterprise application I’ve heard of ever, with their AbstractSomethingSomethingRandomWordFactory classes.

Well I’d argue it’s more like this:

What I had:

What I needed:

http://universal-dsg.com/wp-content/uploads/2014/01/pubictears_ak-47.jpg

What I ended up with:

http://i.imgur.com/R8z4vRg.png

And while I wouldn’t exactly drive it into battle, it drives and shoots like a tank. Good enough :wink:

1 Like

It’s just weird to me to put data on a class that doesn’t need it because the built in process doesn’t support custom data. Especially when that built in process is only 4-5 lines of code and is easily replaced with something more robust. Even if you choose to use code-recursion and pass a context object, the code is really small.

The low level code of JME collisions is optimized for the specific collision classes like Ray. It can’t really be otherwise. So there is no way to add your own Ray class without adding special case code in a few places. And since the Ray doesn’t need the extra data. The collision code doesn’t need the extra data. Only your “Do I descend this branch” needs the extra data… it makes WAAAAY more sense to put the data in the traversal decision code instead of passing it all the way down to the “does this triangle intersect this ray” code.

class MySpecialTraverser {
    public void descend( Node node ) {
        ...check traversal constraints...
        for each child, descend to descend(node) or descend(geom)
    }
    public void descend( Geometry geom ) {
    }
}

The easily replaced part is the problem, mostly that it isn’t with the amout of custom and stock nodes I have scattered all around the project.

I know you guys wanted the Node class to be something that isn’t extended a lot, but alas that’s pretty much all I do hah. Every game object is a node of some kind since it’s just so convenient to have a stucture to attach stuff to.

So either I can spend the whole next week implementing a large and robust system (of questionable actual reliability) that I’ll use like twice in the next year…or I can add those two static lines.

That’s what controls and user data are for. Adding a few fields is not an excuse at all.

Anyway, everything I wrote works with node extensions unless you’ve been really crazy with it. instanceof Node will return true for all of your node subclasses.

Else, your argument breaks down to “I did the exact thing you guys recommended against and now I have problems.”

Haha, it’s cool that you think one can manage to make complicated game objects with only that and retain some sort of structure and organization.

I personally like to call my own update loops for transparency reasons and so I can easily switch where they’re called from and in which order. E.g. spatial transforms must be updated before their icons, ai before them and so on. Can’t really do that with an internally called control can you?

Although I get the use of controls in cases of say, BillboardControl or physics where the only thing it needs to do is a simple transform transfer and only a few lines of code that need to be repeated a lot otherwise and have little consequence in ordering.

But why I mostly why I like to extend Node: Say you have some sort of laser that shoots a constant beam for a few seconds. Wouldn’t it be great if you could just attach that beam to the laser and have it inherit all transforms and not mess up any other part of the scene graph? (and not to mention manage the reloads and attachment of the beam internally encapsulated in the laser’s update loop) But ohno the laser is a geometry that can’t have attachments! Not in this case :slight_smile:

I’d really hate to have different controls for laser rotation/seek, reload and an outside manager for effects for no bloody reason except to eliminate some node layers.

Also, since I don’t use an ECS the easiest way to classify and add functionality to stuff is with interfaces handled by a higher up manager (like a spaceship calling a throttle method on all nodes that implement engine). While you could do the same thing with geometries as well it would be odd to separate half the code into the control and half of it into the class itself, especially since they’re both intertwined.

The other option would be to implement stuff in controls themselves, but that just adds another level of access problems that I can simplify otherwise.

I know you like to call out people for having their mesh representation and update code together, saying it’s a beginner mistake but I say it’s the best way to guarantee with the utmost certainty that what you see in game is an actual game object and not just a geometry with its update controls detached because of some bug - shit I see in most games more often than not.

The only downside it brings that I need to deconstruct an object to data for saving to file and reconstructing it on loading instead of just saving the whole thing without issue.

But don’t let me keep you guys from knowing better.

Well if course it would work, it’s a sound concept and totally doable. Just I’m not sure which part of “infeasible to change a core engine mechanic used everywere” I can’t seem to explain to you.

And that you somehow have a core game mechanic spread all over.

Anyway… your game is already way too far to change anything now. So much like the many other things, you’ll have to go with something a little “distasteful” to you.

But when we suggest better architectures to folks, it’s exactly to prevent the kinds of corners you’ve painted yourself into.