LineArray and QuadArray not playing nicely together

In my program here I have a LineArray displaying a simulation of a nice little Lorenz attractor. Also near the bottom is a blue box built by a QuadArray.

If I create the box with:
qa = new QuadArray(data.length * data[0].length * data[1].length,
QuadArray.COORDINATES | QuadArray.NORMALS | Primitive.ENABLE_GEOMETRY_PICKING);

and don’t give it any normals, I get the problem shown in the not-so-pretty image. If I create it with:
qa = new QuadArray(data.length * data[0].length * data[1].length,
QuadArray.COORDINATES | Primitive.ENABLE_GEOMETRY_PICKING);

then the problem is solved. However then I don’t get normals on my box.

Not so pretty image when using normals on the box:

http://www.gamelizard.com/images/temp/with_normals.png

Pretty image when NOT using normals on the box:

http://www.gamelizard.com/images/temp/without_normals.png

I’ve tried mucking with every number I can find to see if I could shorten or lengthen the breaks between vertices in my LineArray, but had no luck. It seems none of the inputs I’m giving to the constructors or methods have anything to do with it. I’ve tried messing with Appearance settings to see if there’s some default value causing problems that I don’t know about but I haven’t had any luck.

Does anyone recognize what’s going on? I’m hoping someone will see this and understand what this is. I’ve read all the documentation for QuadArray, LineArray and Appearance that I could find. I may have missed something due to lack of understanding but I’m posting here because I don’t know where to look or what else to try.

Thank you! Let me know if there’s any relevant code I need to share :slight_smile:

Malohkan, The flags of the QuadArray constructor should not use Primitive.ENABLE_GEOMETRY_PICKING. That flag is a capability indicator for Primitive subclasses (QuadArray is not a Primitive). The flags on the constructor are used to specify the information available for each vertex. When you specify QuadArray.NORMALS, you need to generate normals and assign them to the geometry. If you want to allow picking on the QuadArray, you will need to set the capability (Node.ALLOW_PICKABLE_…, and ENABLE_PICK_REPORTING) on the shape that uses the QuadArray for it’s geometry.

The alternative is to use a Box primitive.

Mike

Alrighty, fixed the picking thing (I think).

shape.setCapability(Node.ENABLE_PICK_REPORTING);
shape.setCapability(Node.ALLOW_PICKABLE_READ);

Is now what I use. Picking, however, worked before (sort of) and still works just as well. It seems if my mouse is on a vertex/edge it gives me an error so I ignore it but if the mouse is on a face it finds it. This hasn’t changed. Did I change enough?

OK and the next lines after my constructor are:


for (int i = 0, j = 0; j < data.length; j++) {
	qa.setCoordinate(i, data[j][0]);	qa.setNormal(i++, normals[j]);
	qa.setCoordinate(i, data[j][1]);	qa.setNormal(i++, normals[j]);
	qa.setCoordinate(i, data[j][2]);	qa.setNormal(i++, normals[j]);
	qa.setCoordinate(i, data[j][3]);	qa.setNormal(i++, normals[j]);
}

The data points and normals are all calculated elsewhere. The only reason I’m showing a box in this example is for simplicity but the actual class I’m working with is built to take any array of vertices and create a 3D object out of it and compute normals for it as well.

Thank you for your advice on the picking! I’ll do my best to make sure I didn’t mess that same thing up in other places. However I’m still getting the same problem as described in my original post.

EDIT: Since you mentioned the picking, perhaps I can ask a bit more about that too. My experience with picking, like I said, is that it won’t work on lines/vertices of my objects but instead only on the faces. Even then not so well. Here’s what I get when it doesn’t work:


javax.vecmath.SingularMatrixException: cannot invert matrix
at javax.media.j3d.Transform3D.invertAffine(Transform3D.java:2853)
at javax.media.j3d.Transform3D.invert(Transform3D.java:2707)
at javax.media.j3d.Shape3DRetained.intersect(Shape3DRetained.java:630)
at javax.media.j3d.Shape3DRetained.intersect(Shape3DRetained.java:726)
at javax.media.j3d.Shape3D.intersect(Shape3D.java:595)
at com.sun.j3d.utils.picking.PickTool.pickGeomAllSorted(PickTool.java:734)
at com.sun.j3d.utils.picking.PickTool.pickGeomClosest(PickTool.java:794)
at com.sun.j3d.utils.picking.PickTool.pickClosest(PickTool.java:576)

Right now I just ignore the exception and act as if I just didn’t find anything. It’s alright, I can still pick objects, but sometimes you have to wiggle the mouse around on an object to find a spot it’ll actually pick.

EDIT 2: Actually this problem is easiest seen when I create a circle out of a TriangleFanArray and stick it inside an OrientedShape3D to make it face the camera billboard style. I did my best to follow the example used in PickText.java in the Java3D examples set which also uses a TriangleFanArray but it appears I’m still missing something that I can’t figure out from their example. It DOES give me picking results, but it just misses most of the points. I have to move my mouse all over the object before I can get a spot where it detects the shape. Perhaps an issue with OrientedShape3D? The center always works, however.

Help me understand something. When you use QuadArray.NORMALS but don’t give it normals it looks bad, right? But your code in the most recent post shows the same normal being applied to the four vertices within the loop. Assuming your are using NORMALS and you are assigning the coordinates and normals (and you are certain the normals are unit vectors in the right direction) then the all white box might be related to appearance and lights. Just to be certain, I would simplify the geometry down to a single quad to make sure that works.

What type of lights are you using and have you assigned an appearance/material to the shape?

Mike

P.S I don’t know much about the picking API, so I can’t really help much more there.

Well as for the 4 of the same normal… that appears to be a typo! Thanks for catching that :wink:

For clarification, what I was testing was in the GOOD image, I DON’T use QuadArray.NORMALS and I DON’T make any qa.setNormal() calls. In the BAD image, I DO use QuadArray.NORMALS and I DO make qa.setNormal() calls. The box is acting fine. I turn on normals, and the normals are correct. I turn off normals, and there are no normals. No problem. The problem I’m having is with half of my LineArray disappearing in chunks when I alter the box. I have no idea why changing the QuadArray would affect the LineArray.

So I don’t need to muck with how the box looks. It’s doing everything I want. I just need to fix my LineArray.

Thanks for the clarification. I certainly did not understand the problem. Changing the quad should have no affect on the line array unless… Are you applying the line array to an oriented shape? I wonder if it has to do with rendering settings (sorting issues perhaps?) rather than geometry. I would try using a Shape3D and also try changing the line attributes to make the line 2 or more pixels instead of one. I realize your requirements might need billboarding this may help isolate the issue.

Are you using an early version of J3D or a released version? Perhaps a webstart demo or download would help verify it is not a video card driver.

This is a strange problem. Sorry I don’t have anything concrete answers.

Mike

The OrientedShape3D is in a different scenario. I referred to it when I mentioned picking problems. I’m not using it in this scene. I’ll try the line thickness thing, that’s a good idea I hadn’t thought of. If this has to do with sorting issues, where could I find more information about how to tweak how Java3D does its sorting? I assume there are some flags related to this.

I’m using Java3D version 1.4.0_01 and Java JRE & SDK version 1.5.0_07.

Do you think it would be worth my while to test with the new Java3D 1.5 releases?

EDIT:
I tried changing the line thickness, and flipped on and off line antialiasing. I even tried never giving either object an Appearance, meaning they’re both null. None of these attempts changed the result. I remove the NORMALS code from the box and my line shows up properly then like always. I’m going to try one of the new Java3D releases now and see what happens.

EDIT2:
Java3D 1.5.0_build4 didn’t make a difference. Guess it’s back to the drawing board.

I believe the J3D sorting stuff primarily deals with how transparent objects are sorted relative to opaque objects. Check out the View class. When using transparent objects that need to be sorted with opaque objects, I use:


canvas3D.getView().setTransparencySortingPolicy(View.TRANSPARENCY_SORT_GEOMETRY);

However, this is on a geometry basis (not vertex) so I doubt this is it.

If the box normal code is the only thing that seems to make the problem show up, could you post that code (assuming there’s more). Is there anything the two shapes might share? Is it possible that the LineArray has normals assigned (that could make segments disappear)?

Edit: If you change the view position (using a keyboard behavior for example) does the nature of the problem change with the view?

Mike

I tried that line of code you suggested, no change. I wish there was something related between the two objects but nothing is shared at all. Those lines of code I showed you with the normals are the ONLY things that change between those two pictures. Nowhere else do I ask for any information from those objects which might effect other code. When I spin the camera around nothing changes. I can zoom in and out and spin all around and get the camera between things and nothing changes. It’s as if I removed certain segments from the scene altogether.

This sounds to me like the data within the line array is being compromised somehow. Is the LineArray created with INTERLEAVED and/or BY_REFERENCE by chance? If so, what is the source of the by reference data?

Is the data created before being rendered or is the attractor an animation (updating the geometry over time)?

Are the two geometries (line array and quad array) assigned to different Shape3Ds, or shared by a single Shape3D? (I realize you stated that there is nothing in common, but I wanted to double check this scenario.)

I would try assigning a sequence of colors to the line segments to see if there is a pattern to the missing segments.

Mike

Hmmm I think the easiest way to answer these questions without giving a bad answer is to just show you the two classes :slight_smile: They’re not very long.

The ElementTrail IS created BY_REFERENCE and it’s created over time in an animation. Every tick I use the GeometryUpdater interface to update the line. The ElementBox is created once unless someone throws a method asking it to change properties about it in which case it would recreate the QuadArray but in my examples that doesn’t happen.

I also have another example I use where I took the ElementTrail and modified it to create a spring shape. I create it once at the beginning and never change it and still have this problem.

ElementTrail.java
ElementBox.java

As for the sequence of colors idea… what exactly do you mean? What would I be trying to find there? I’ve definitely noticed the length is constant. Or rather, the length of the broken pieces is the same all throughout. In my first post I mentioned I tried to change every number in my class to try and see if I could change the length of the breaks but I couldn’t. So it’s aparantly controlled by something else. Is there a line property that draws broken lines perhaps? I think there is in Java2D.

I will look at ElementTrail in detail later, but here are a few observations. There appears to be OpenGL code in the class. Are you using Java3D for rendering? The reason I ask is there appears to be OpenGL line drawing code in your class and you are having problems drawing the line. The Element superclass seems to take care of the Appearance. This is where the LineAttributes can be set (solid line, dashed line, etc) if Java3D is doing the rendering.

I see that init() replaces the LineArray and that init() is called elsewhere. When using by reference, I cannot think of a reason why the LineArray would need to be replaced. Generally speaking, the valid vertex count does not need to be set if you are rendering all of the vertices (unless perhaps the by reference array size is changing?). If you are rendering only a subset of the vertices, perhaps that is part of the problem?

In ElementBox, there is a flag from Primitive that is being used incorrectly as a vertex format flag:


qa = new QuadArray(data.length * data[0].length * data[1].length,
					QuadArray.COORDINATES | Primitive.ENABLE_GEOMETRY_PICKING);

This has a value of 32, which J3D interprets to mean that you will be supplying texture coordinates (TEXTURE_COORDINATE_2).

When you create the geometry, you can also specify that you will supply vertex colors (another vertex format flag). If you set the lines to be a sequence of colors (red, yellow, blue, green, purple, … repeat) you would be able to see that the red segment is there, the yellow segment is there… oh the blue one is missing (for example). Knowing the pattern of missing segments may help in isolating the problem.

Mike

init() isn’t called outside of this class. I’ve changed it to “private void init()” for clarity. It is called in the addPoint() method. If the number of points exceeds the length of the array, I have to resize the array and recreating the LineArray is the only way I’ve figured out how to successfully change the array. I create a larger array, copy the whole thing in, and reset the LineArray. I changed the initial size and the size step when resizing to see if this changed the length of the breaks in the picture and it didn’t. So I figure that means this isn’t the cause of the problem. Is there a better way to change the size of the reference array?

The OpenGL code is all commented out. This class was ported over from a working JOGL version of the same simulation. OpenGL code is so much easier than Java3D :stuck_out_tongue:

“QuadArray.COORDINATES | Primitive.ENABLE_GEOMETRY_PICKING”
I fixed that, certainly might have caused problems. However that’s from the working portion haha. I removed that so now it’s just:
QuadArray.COORDINATES and that portion of the code still works just fine. I haven’t tested picking but I can deal with that later.

I’ll play with the colors idea now and let you know what I find out.

EDIT: OK I set colors one after the other following in this array:


private float[] colors = new float[] {
		0, 0, 0, 1,
		0, 0, 1, 1,
		0, 1, 0, 1,
		0, 1, 1, 1,
		1, 0, 0, 1,
		1, 0, 1, 1,
		1, 1, 0, 1,
		1, 1, 1, 1
};

Here’s the result with the camera turned to face it head on:

http://www.gamelizard.com/images/temp/colors.PNG

I am stumped. There are a huge number of missing vertices and yet it seems to pick up where it should. Would it be possible to share the Element source? Or better yet a full example?

http://www.gamelizard.com/com/DrawingPanel3D.java
http://www.gamelizard.com/com/Element.java
http://www.gamelizard.com/com/Style.java

These are the last of the classes that have any affect on any of these things. If the answers are anywhere it’s within here and the other classes I shared with you. I REALLY appreciate the help you’ve given me so far. I hope you can help me figure out what I’ve done wrong here once and for all :slight_smile:

I don’t have the code that uses the ElementTrail, but I assume that there is a behavior that wakes up (every frame or every x milliseconds) calculates the next point for the attractor and then uses addPoint() on the ElementTrail. Is that right?

It looks like when the by reference data reaches capacity in addPoint(), a new array is allocated with twice the old capacity, the old data is copied and the new array is intended to be the new by reference array with a new shape. Is the old shape ever removed from the scene? I assume it is no longer of use since the old data is copied to the new array.

I don’t understand what’s going on in the updateData() method when (length == maximumPoints*2) but I am not sure that is relevant.

I notice in updateData(), the code manually replicates the previous vertex if the length > 1. If the next point is always going to be a segment formed with the previous vertex, I suggest you switch to a LineStripArray with a single strip. This is will substantially reduce the memory used. It will also completely change the length and reallocation logic.

I suspect the issue is related to the maximum number of vertices being reached and the array replication and shape replacement. Is there a way to use the ElementTrail so that it is initially allocated with a large enough number of vertices so that the reallocation code is not run? This may help isolate the problem to this area.

Check the points array contents. I suspect the gaps grow (perhaps doubles) and are all zeros.

Mike

Well it’s not done in a behavior… It’s just in another Thread. There’s a Thread.sleep() between the calls to addPoint(). Yes, I remove the old Shape from the scene. if I don’t, it goes crazy and I get the shape made really dense and it bogs down the framerate like crazy. Yeah right now all the points connect… I think that might not always be true so this structure sort of leaves room for the option of allowing breaks in the line. However I honestly don’t know how to do it with a LineStripArray. I gave it my best shot reading the docs but I couldn’t figure out how to make it work :stuck_out_tongue:

I checked the point array contents. The data is exactly the same in both the buggy and non-buggy versions :stuck_out_tongue: There are no 0’s in the data. I also can’t predict how big I’ll need the array to be. It can grow as long as the scene is active.

I tried doubling the grow rate, but the breaks in the line occur in the exact same places regardless. I even started the array at 10 times the original size, and the breaks still don’t change.

I believe Java3D has a few problems (namely geometry locking: https://java3d.dev.java.net/issues/show_bug.cgi?id=39) with rendering if the updates are done in a separate thread like that. If all the thread does is sleep, compute the next point and add it, I would suggest moving that function to a behavior.

I have run out of ideas. This problem is very strange. The fact that the geometry data is the same between the working and failing scenarios leads me to think it is rendering related. I think the last idea I have is to ensure you have the latest drivers for your video card.

BTW, The LineStripArray uses vertices like this: V1-------V2-------V3 which implicity defines two segments: V1 to V2 and V2 to V3. The V2 instance is shared enabling the creation of a long sequence of connected segments. The strips define where a new series of connected vertices starts.

Mike

Whelp I guess it’s time I start learning about Behaviors. I gave em a shot before but had bad luck. I think the problem I was hitting was unrelated to Behaviors however, or at least I hope that was the case :slight_smile: I’ll check that out and also give LineStripArray another shot. I’ll let you know if I hit any other snags. Thanks again for your help so far :slight_smile:

Well I think I have Behaviors implemented. Now every single change I do happens inside the processChanges() when a wakeup criterion has been met. Namely this one:
wakeupOn(new WakeupOnElapsedFrames(1));

I call it every time and check a flag to see if I need changes. I tried 0, and found that when I was doing frequen changes the whole app would basically hang. I could rotate freely, but the actual results of my changes would take over 5 seconds to happen.

Then I changed it to 1, and I could actually rather quickly see the scene being built. I have an example with the Spring in it which has the same problem as the line loopy thing in my original post. In it is a wire-frame box with a block in the middle and a spring attached with a ball at the end of the spring. When I start the app I see the box and the spring in there correctly. Then I see the ball at the end of it and the spring moved to the correct position. Then I see the block appear in the screen. When that happens, the middle of the spring disappears… GRRR

It seems Behaviors have not solved my problem. However they have managed to make my application incredibly difficult to interact with.