Skip to main content

A "canonical" way to create Polygons?

4 replies [Last post]
jaume_aau
Offline
Joined: 2009-10-19

Hi, I'm using Java3D as the 3D engine in my research. I'm writing a loader that reads a CityGML-like model into a scene and among many other things, I have to create lots of Polygons. To do so, each time a parse the coordinates of the polygons I call this static method where the first matrix is the outer boundary of the polygon and the list of matrices is the same but for the internal holes. The matrix are N+3 dimensional. Other parameters just contain paths for textures or if the coordinates have to be read in forward or reverse order.

public static Geometry createPolygon(double[][] outer, ArrayList holes, int coordReadMode, TextureInfo textureInfo) {
if (coordReadMode != Constants.COORDINATE_READ &&
coordReadMode != Constants.COORDINATE_READ_REVERSE) {
throw new IllegalArgumentException("coordReadMode can only be Constants.COORDINATE_READ or Constants.COORDINATE_READ_REVERSE.");
}

boolean clockWise = coordReadMode == Constants.COORDINATE_READ;
int vertexCount = outer.length * outer[0].length;

if (holes != null && holes.size() > 0 && holes.get(0) != null) {
for (double[][] hole : holes) {
vertexCount += hole.length * hole[0].length;
}
}

double[] m_VertexArray = new double[vertexCount];

int vertexIndex = 0;
try {

if (clockWise) {
for (int i = 0; i < outer.length; i++) {
m_VertexArray[vertexIndex++] = outer[i][0];
m_VertexArray[vertexIndex++] = outer[i][1];
m_VertexArray[vertexIndex++] = outer[i][2];
}
} else {
for (int i = outer.length-1; i >= 0 ; i--) {
m_VertexArray[vertexIndex++] = outer[i][0];
m_VertexArray[vertexIndex++] = outer[i][1];
m_VertexArray[vertexIndex++] = outer[i][2];
}
}
} catch (Exception e) {
e.printStackTrace();
}
int[] stripCountArray = null;
if (holes != null && holes.size() > 0 && holes.get(0) != null) {
stripCountArray = new int[holes.size()+1];
stripCountArray[0] = vertexIndex / 3; // divide by 3???
for (int i = 0; i < holes.size(); i++) {
double[][] hole = holes.get(i);
stripCountArray[i+1] = (hole.length * hole[0].length) / 3; // divide by 3???

if (!clockWise) {
for (int j = 0; j < hole.length; j++) {
m_VertexArray[vertexIndex++] = hole[j][0];
m_VertexArray[vertexIndex++] = hole[j][1];
m_VertexArray[vertexIndex++] = hole[j][2];
}
} else {
for (int j = hole.length-1; j >= 0; j--) {
m_VertexArray[vertexIndex++] = hole[j][0];
m_VertexArray[vertexIndex++] = hole[j][1];
m_VertexArray[vertexIndex++] = hole[j][2];
}
}
}
}

// triangulate the polygon
GeometryInfo gi = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);

gi.setCoordinates(m_VertexArray);

int[] contourCountArray = null;
if (stripCountArray == null) {
// means that we don't have holes
stripCountArray = new int[] { m_VertexArray.length / 3 };
} else {
contourCountArray = new int[] { stripCountArray.length };
}

gi.setContourCounts(contourCountArray);
gi.setStripCounts(stripCountArray);

// apply the texture
if (textureInfo != null) {
float[][] texCoordArray = textureInfo.texCoordArray;
int dim = texCoordArray[0].length; // <- should always be 2
float[] coords = new float[texCoordArray.length*dim];
for (int i = 0; i < texCoordArray.length; i++) {
for (int j = 0; j < dim; j++) {
coords[dim*i+j] = texCoordArray[i][j];
}
}
gi.setTextureCoordinates2(coords);
// gi.setTextureCoordinates(0 /* ? */, coords);
}

NormalGenerator normalGenerator = new NormalGenerator();
normalGenerator.generateNormals(gi);

return gi.getGeometryArray();

}

The "funny" thing is that geometry that is built sometimes is correct, sometimes there is something wrong that I can't explain. I have quite complex models that look great when I load them. But I have some others in which the polygons don't have the shape they were supposed to have. They look strange, "irregular", and when I orbit the scene I see the buildings shaking... changing the geometry.

I wonder why the same function creates perfect buildings in some cases and extremely bad buildings in other. Is it incorrect? After debugging I saw that the triangulator sometimes falls into the "Desperate" triangulation. Is this the cause? Why is that? How is it avoided?

By the way, just a sight.. I read that messages sent from and to the forum are reflected in the interest mailing list, but I don't receive anything there. Does this happen to everyone?

Thanks a lot.
Jaume

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
jaume dominguez faus

I'm happy to say that I finally found the problem. The code is correct
(although I have improved the method), the problem lies in the nature of
the CityGML files with cartographic CRS that give quite often huge
values for the coordinates. When the values are in a small range, say
less than 1000, it is fine. But in my case I was loading models with
coordinates around 6.500.000 and 4.000.000. In such cases, it seems like
triangulation has difficulties or simply there is not enough floating
point resolution in the CPU to scale without loss (or maybe what happens
is that I'm amplifying tiny errors by a factor of 6... who knows).

So, if I move everything in the range from -1000 to 1000 everything goes
again perfect.

Hope this will help to anyone in the same situation than me. It was a
really blocking issue for my research and I was thinking to change to
other engine since several weeks ago because I was quite desperated.

Regards,
jaume

java3d-interest@javadesktop.org wrote:
> Hi, I'm using Java3D as the 3D engine in my research. I'm writing a loader that reads a CityGML-like model into a scene and among many other things, I have to create lots of Polygons. To do so, each time a parse the coordinates of the polygons I call this static method where the first matrix is the outer boundary of the polygon and the list of matrices is the same but for the internal holes. The matrix are N+3 dimensional. Other parameters just contain paths for textures or if the coordinates have to be read in forward or reverse order.
>
> public static Geometry createPolygon(double[][] outer, ArrayList holes, int coordReadMode, TextureInfo textureInfo) {
> if (coordReadMode != Constants.COORDINATE_READ &&
> coordReadMode != Constants.COORDINATE_READ_REVERSE) {
> throw new IllegalArgumentException("coordReadMode can only be Constants.COORDINATE_READ or Constants.COORDINATE_READ_REVERSE.");
> }
>
> boolean clockWise = coordReadMode == Constants.COORDINATE_READ;
> int vertexCount = outer.length * outer[0].length;
>
> if (holes != null && holes.size() > 0 && holes.get(0) != null) {
> for (double[][] hole : holes) {
> vertexCount += hole.length * hole[0].length;
> }
> }
>
> double[] m_VertexArray = new double[vertexCount];
>
> int vertexIndex = 0;
> try {
>
> if (clockWise) {
> for (int i = 0; i < outer.length; i++) {
> m_VertexArray[vertexIndex++] = outer[i][0];
> m_VertexArray[vertexIndex++] = outer[i][1];
> m_VertexArray[vertexIndex++] = outer[i][2];
> }
> } else {
> for (int i = outer.length-1; i >= 0 ; i--) {
> m_VertexArray[vertexIndex++] = outer[i][0];
> m_VertexArray[vertexIndex++] = outer[i][1];
> m_VertexArray[vertexIndex++] = outer[i][2];
> }
> }
> } catch (Exception e) {
> e.printStackTrace();
> }
> int[] stripCountArray = null;
> if (holes != null && holes.size() > 0 && holes.get(0) != null) {
> stripCountArray = new int[holes.size()+1];
> stripCountArray[0] = vertexIndex / 3; // divide by 3???
> for (int i = 0; i < holes.size(); i++) {
> double[][] hole = holes.get(i);
> stripCountArray[i+1] = (hole.length * hole[0].length) / 3; // divide by 3???
>
> if (!clockWise) {
> for (int j = 0; j < hole.length; j++) {
> m_VertexArray[vertexIndex++] = hole[j][0];
> m_VertexArray[vertexIndex++] = hole[j][1];
> m_VertexArray[vertexIndex++] = hole[j][2];
> }
> } else {
> for (int j = hole.length-1; j >= 0; j--) {
> m_VertexArray[vertexIndex++] = hole[j][0];
> m_VertexArray[vertexIndex++] = hole[j][1];
> m_VertexArray[vertexIndex++] = hole[j][2];
> }
> }
> }
> }
>
> // triangulate the polygon
> GeometryInfo gi = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
>
> gi.setCoordinates(m_VertexArray);
>
> int[] contourCountArray = null;
> if (stripCountArray == null) {
> // means that we don't have holes
> stripCountArray = new int[] { m_VertexArray.length / 3 };
> } else {
> contourCountArray = new int[] { stripCountArray.length };
> }
>
> gi.setContourCounts(contourCountArray);
> gi.setStripCounts(stripCountArray);
>
> // apply the texture
> if (textureInfo != null) {
> float[][] texCoordArray = textureInfo.texCoordArray;
> int dim = texCoordArray[0].length; // <- should always be 2
> float[] coords = new float[texCoordArray.length*dim];
> for (int i = 0; i < texCoordArray.length; i++) {
> for (int j = 0; j < dim; j++) {
> coords[dim*i+j] = texCoordArray[i][j];
> }
> }
> gi.setTextureCoordinates2(coords);
> // gi.setTextureCoordinates(0 /* ? */, coords);
> }
>
> NormalGenerator normalGenerator = new NormalGenerator();
> normalGenerator.generateNormals(gi);
>
> return gi.getGeometryArray();
>
> }
>
> The "funny" thing is that geometry that is built sometimes is correct, sometimes there is something wrong that I can't explain. I have quite complex models that look great when I load them. But I have some others in which the polygons don't have the shape they were supposed to have. They look strange, "irregular", and when I orbit the scene I see the buildings shaking... changing the geometry.
>
> I wonder why the same function creates perfect buildings in some cases and extremely bad buildings in other. Is it incorrect? After debugging I saw that the triangulator sometimes falls into the "Desperate" triangulation. Is this the cause? Why is that? How is it avoided?
>
>
>
> By the way, just a sight.. I read that messages sent from and to the forum are reflected in the interest mailing list, but I don't receive anything there. Does this happen to everyone?
>
> Thanks a lot.
> Jaume
> [Message sent by forum member 'jaume_aau' (jaume@plan.aau.dk)]
>
> http://forums.java.net/jive/thread.jspa?messageID=387868
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
> For additional commands, e-mail: interest-help@java3d.dev.java.net
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

darwinjob
Offline
Joined: 2004-11-16

>when I orbit the scene I see the buildings shaking...
I guess this is Z-fighting...

http://en.wikipedia.org/wiki/Z-fighting

>So, if I move everything in the range from -1000 to 1000 everything goes
again perfect.

You might want to play with front/back clip distances. Then you probably can keep your coordinates intact.

http://download.java.net/media/java3d/javadoc/1.5.2/javax/media/j3d/View...

jaume dominguez faus

java3d-interest@javadesktop.org wrote:
>> when I orbit the scene I see the buildings shaking...
>>
> I guess this is Z-fighting...
>
> http://en.wikipedia.org/wiki/Z-fighting
>
>
Well, I'm not such an expert. But from comparing what I saw to what
Wikipedia explains about z-fighting I would say that my problem wasn't
the z-fighting since I happened either with shapes made of double or
single faced polygon. Even more, also with only one single-faced
polygon. It happened as well in windows 32 bit as in linux 32 and 64
bit. So, it seems to point to may graphic card's GPU's lack of precision
(or better said not precise enough for such huge values). It is an
NVidia Quadro F770 (or something like that).

Maybe this is a common problem in this world. But since I'm a beginner
and I'm teaching myself I have very hard time solving
well-known-to-anybody-else issues.

Thanks for your link. Now I know another concept.

Now I have this issue solved, I would like to ask what is the way to
free the memory once the scene and the canvas and so on is no needed
anymore.

This is the code I use.

public void dispose() {
remove(canvas);
new Thread(new Runnable() {

@Override
public void run() {
System.out.println("Universe clean up start.");
universe.cleanup();
universe = null;
canvas = null;
System.out.println("Universe clean up finished.");
System.gc();
}
}, "Close 3D view thread").start();

}

My application is a desktop application and uses JPanel (it is not an
Applet) and when I close the internal frame with the scene this method
is called. It starts a separate thread for cleaning up so the user can
do other things while this happens in background. But after the cleanup
finishes I don't see any freed memory. The memory consumed remains the
same and after creating 2 o 3 big models I always run out of memory.

The question are:

1) Is this the correct way to do it?

2) Are there any considerations to keep in mind when it comes to memory
management when loading and unloading a scene graph?

Tusen takk.
Jaume

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@java3d.dev.java.net
For additional commands, e-mail: interest-help@java3d.dev.java.net

jaume_aau
Offline
Joined: 2009-10-19

Sorry, it seems like the formatter of the forum gets confused with some source code characters and the is not correctly shown. I will put the same message with no code, and I will link to the code instead

> Hi, I'm using Java3D as the 3D engine in my
> research. I'm writing a loader that reads a
> CityGML-like model into a scene and among many other
> things, I have to create lots of Polygons. To do so,
> each time a parse the coordinates of the polygons I
> call this static method where the first matrix is the
> outer boundary of the polygon and the list of
> matrices is the same but for the internal holes. The
> matrix are N+3 dimensional. Other parameters just
> contain paths for textures or if the coordinates have
> to be read in forward or reverse order.
>

The code I use is here -> http://superbumbot.sytes.net/CreatePolygon.txt
>
> The "funny" thing is that geometry that is built
> sometimes is correct, sometimes there is something
> wrong that I can't explain. I have quite complex
> models that look great when I load them. But I have
> some others in which the polygons don't have the
> shape they were supposed to have. They look strange,
> "irregular", and when I orbit the scene I see the
> buildings shaking... changing the geometry.
>
> I wonder why the same function creates perfect
> buildings in some cases and extremely bad buildings
> in other. Is it incorrect? After debugging I saw that
> the triangulator sometimes falls into the "Desperate"
> triangulation. Is this the cause? Why is that? How is
> it avoided?
>
>
>
> By the way, just a sight.. I read that messages sent
> from and to the forum are reflected in the interest
> mailing list, but I don't receive anything there.
> Does this happen to everyone?
>
> Thanks a lot.
> Jaume