Quad Tessellation 3.1 Alpha Problem

I’m currently trying to both develop a game and in the process learn something about tessellation. In relation to this I got JME3.1 alpha to check out if I could make sense of the tessellation.

I like to get something simple working from an example, and then twiddle with it as I go along, however I’m having problems with the tessellation sample supplied with JME3.1 alpha.

I have based both my triangles and quad tessellation on the example source from:

The vertex and fragment shader I will leave out since they are the same as from the above link.

First, a screenshot of my problem (left triangle, right quad)

As shown above I seem to be having some problems with the quad tessellation. The source code for adding the two cubes is as follow:
Node models = (Node) assetManager.loadModel(“Models/dice_simple.blend”);

Node triModel = (Node) models.getChild("d6").deepClone();
triModel.setLocalTranslation(-2, 2, 0);

Geometry triGeom = (Geometry) triModel.getChild("d6Geometry1");

Material triMaterial = new Material(getAssetManager(), "Materials/TriTess.j3md");
triMaterial.setInt("TessellationFactor", 5);


Node quadModel = (Node) models.getChild("d6").deepClone();
quadModel.setLocalTranslation(2, 2, 0);

Geometry quadGeom = (Geometry) quadModel.getChild("d6Geometry1");

Material quadMaterial = new Material(getAssetManager(), "Materials/QuadTess.j3md");
quadMaterial.setInt("TessellationFactor", 5);


Below are the two eval and control shaders for triangles and quads.

layout(vertices=3) out;

uniform int m_TessellationFactor;

void main(void)
	if (gl_InvocationID == 0)
		gl_TessLevelInner[0] = m_TessellationFactor;
		gl_TessLevelOuter[0] = m_TessellationFactor;
		gl_TessLevelOuter[1] = m_TessellationFactor;
		gl_TessLevelOuter[2] = m_TessellationFactor;

	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

layout (triangles) in;

uniform mat4 g_WorldViewProjectionMatrix;

void main(){	
	gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +
			(gl_TessCoord.y * gl_in[1].gl_Position) +
			(gl_TessCoord.z * gl_in[2].gl_Position);
	gl_Position = g_WorldViewProjectionMatrix * gl_Position;


layout(vertices=4) out;

uniform int m_TessellationFactor;

void main(void)
	if (gl_InvocationID == 0)
		gl_TessLevelInner[0] = m_TessellationFactor;
		gl_TessLevelInner[1] = m_TessellationFactor;
		gl_TessLevelOuter[0] = m_TessellationFactor;
		gl_TessLevelOuter[1] = m_TessellationFactor;
		gl_TessLevelOuter[2] = m_TessellationFactor;
		gl_TessLevelOuter[3] = m_TessellationFactor;

	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

layout (quads) in;

uniform mat4 g_WorldViewProjectionMatrix;

void main(){	
	vec3 p0 = mix(gl_in[0].gl_Position.xyz, gl_in[3].gl_Position.xyz, gl_TessCoord.x);
	// interpolate in horizontal direction between vert. 1 and 2
	vec3 p1 = mix(gl_in[1].gl_Position.xyz, gl_in[2].gl_Position.xyz, gl_TessCoord.x);
	// interpolate in vert direction
	vec3 tePosition = mix(p0, p1, gl_TessCoord.y);
	gl_Position = g_WorldViewProjectionMatrix * vec4(tePosition, 1);

Any help or guidance would be appreciated, even if it is just a link to some place I can read up on why I might be doing something wrong.
You might be able to notice that I have tried to keep the quad tessellation as close to the source material from JME3.1alpha just to try and get something working.

If needed I can provide more sourcecode or information regarding the model (which is just a cube made in blender).

I hope someone has some insight to give in regards to my problem.

Cloning a mesh and setting its patch count to 4 will not produce a correct mesh.
You have to update also your index buffer to the new geometry model.

A triangle based quad has 4 vertices, and a index buffer with lenght 6.
A quad based quad has the same 4 vertices but a indexbuffer with lenght 4.

Having read what you said I looked into how a simple cube was made in blender. As far as I can see (I might be wrong), blender creates my cube as quads. However when I import it into blender, it seems to automatically be stored as a triangle formed cube.

From what I could find, this is the only way that jme3 stores its meshes?

Having gone from that assumption I tried really dissecting what you wrote and thoughg I might be able to adjust the index buffer in the mesh after I had loaded it, for example with the following code:

    ShortBuffer newIndexBuffer = BufferUtils.createShortBuffer(
            (short) 0, (short) 1, (short) 2, (short) 3,
            (short) 4, (short) 5, (short) 6, (short) 7,
            (short) 8, (short) 9, (short) 10, (short) 11,
            (short) 12, (short) 13, (short) 14, (short) 15,
            (short) 16, (short) 17, (short) 18, (short) 19,
            (short) 20, (short) 21, (short) 22, (short) 23
    VertexBuffer indexBuffer = quadGeom.getMesh().getBuffer(VertexBuffer.Type.Index);

This did not really do anything different… the model appeares just as broken as my original post. I am not sure if it is because what I’m trying to do is just really silly (which might be the case since I’m still learning), or if it is simply because I’m going about it in a wrong way.

I guess my real questions are, would I be able to load a blender model that is created as quads and stored as quads, and render fine with my quad tessellation shader? If so how?

In the case that the above is no, you seem to have pointed me in the direction of updating my index buffer, however I seem to have failed miserably. You might be seeing a mistake in the way I’m trying to modify it?

This topic is too advanced for me but atleast by default the blender importer is doing a “triangulation”, to feed in triangle data into the mesh

Did you try the ogre xml importer, what it does?
I guess by using a custom Mesh you could also render from a quad buffer instead of a triangle buffer (There are types like GL_QUADS and TRIANGLE_STRIP etc), atleast in the fixed pipeline of openGL, so there might be different types in JME aswell.

However, since the BlenderImporter triangulates, you maybe have to modifiy or pass some params to it, or the data will be “lost” before it’s in your Custom Mesh

If this doesn’t work, it should work in theory to reassemble quads from triangles, however since your Mesh won’t be all-quads, it’s impossible to tell where the regular tris or even n-gons start.

I guess this is the reason jme triangulates, because you would have several buffers and hence seperate objects/meshes which would lead to performance loss.

Other than that, draw a Quad and Triangulate it manually:
The first three Indices are three edges of the quad, The next three Indices denote the other triangle (of which you simply need to drop two indices, namely the ones of the diagonal line) whereas the last one is the fourth edge.

Now this information is so vague, because I don’t know in which order indices are adressed, I guess counter-clockwise (Either one or the other, depends on culling) and it’s important where the second triangle will start again.

I’d say when treating them counter clockwise, that the first and second index match the fourth and sixth.
Anyway: Simply print out the index buffer to find and remove the duplicates.

Again: This method shouldn’t be used, rather a custom importer or something

Darkchaos is right. As far as i know there is no way to import a quad based mesh into jme. But it is possible to store and load generated meshes. I have to say that i used the quad tessellation only on self generated meshes in code so i have 0 experience with the loader and how it works internally.

I am not at the pc currently but i can try to give you an example in the evening. First would be to check how jme actually triangulates the cube. Since i am not 100% sure on the ordering of the vertices.

However, in general, quad tessellation does not give you any advantage over triangle tessellation. AFAIK the most used model is a patch size of 16 to have all the control points for a bezier interpolation and actually gaining smoothness when tessellating. Its on my todo for a long time, but its to low priority for now. (And a complex topic since there is no importer to support stuff like that)

Well if you do happen to come up with some example code, it would always be welcome :smile:

I think living with the triangle tessellation will have to do for now. My main concern was really that what I thought should be working, wasn’t really working for me. Having a slightly better understanding as to why, has somewhat put my mind at ease.

The fun game project I’m doing really only needs high detailed dice with vertex displacement, so let’s see how high I can set the count without killing the game.

Thanks so far, both of you, for the insight you have provided.