Map a square texture image onto a non-square polygon without streaching

Hi folks,

I’m trying to convert a Java3D program to Jme3. I am stuck on textures for a month now. I read and copied so many suggestions I don’t know which end is up. This is as far as I got. I have a square texture image that I want to map onto a 5 sided polygon without stretching. What I get is a square section fine but the portion around the 5th vertex is stretched. Any way to map it without stretching?

Code Below:



[java]public void setMaterial()

{

Material material = new Material( assetManager, "Common/MatDefs/Misc/Unshaded.j3md" );

material.getAdditionalRenderState().setBlendMode( BlendMode.Alpha );

geometry.setQueueBucket( Bucket.Translucent );



Texture stone = assetManager.loadTexture( "Textures/stone.jpg" );

stone.setWrap( Texture.WrapMode.Repeat );

scaleTextureCoordinates( new Vector2f( 2.f, 2.f ));

material.setTexture( "ColorMap", stone );



geometry.setMaterial( material );

}



public void populatePositions()

{

position[0] = new Vector3f( 0,0,0 ); //lower left

position[1] = new Vector3f( 2,0,0 ); //lower right

position[2] = new Vector3f( 2,2,0 ); // upper right

position[3] = new Vector3f( 1,4,0 ); // upper middle

position[4] = new Vector3f( 0,2,0 ); // upper left

setBuffer( Type.Position, 3, BufferUtils.createFloatBuffer( position ) );

}



public void populateIndices()

{

indexes[0] = 0; // upper left

indexes[1] = 1; // lower left

indexes[2] = 2; // lower right



indexes[3] = 2; // lower right

indexes[4] = 4; // upper right

indexes[5] = 0; // upper left



indexes[6] = 2; // upper tri

indexes[7] = 3; // upper tri

indexes[8] = 4; // upper tri

setBuffer( Type.Index, 3, BufferUtils.createIntBuffer( indexes ) );

}



public void populateTextureCoords()

{

texCoord[0] = new Vector2f( 0, 0 ); // lower left corner of image maps to first vertex

texCoord[1] = new Vector2f( 1, 0 ); // lower right corner of image maps to second vertex

texCoord[2] = new Vector2f( 1, 1 ); // upper right



texCoord[3] = new Vector2f( 1, 1 ); // upper right

texCoord[4] = new Vector2f( 0, 1 ); // upper left

texCoord[5] = new Vector2f( 0, 0 ); // lower left



texCoord[6] = new Vector2f( 1, 0 ); // upper right

texCoord[7] = new Vector2f( .5f, 2 ); // top

texCoord[8] = new Vector2f( 0, 1 ); // upper left

setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));

}[/java]

Can you show us a picture of how you want to map the square texture to the 5 sided polygon? Or a picture of the problem you describe?



(Also, please put code in code boxes so our eyes don’t bleed… there’s a little “java” button you can use right at the top of the edit box)

Hi,

Thanks for your quick reply. As you can tell I’m new to the forum. Below is a snapshot of the application. Note the stone walled object. Note the stretching on top. Hope that helps with analysis.



http://www.relativitysimulation.com/Documents/stretchedTexture.jpg

Given the texture coordinates in the code, I can’t see how you get those results. However, it does look like you need to turn texture repeat on because it looks like it’s clamped right now.

[java][/java]Thanks again for your reply.



With regard to texture repeat;

I believe I have set it ON in the method “setMaterial()”



[java]Texture stones = assetManager.loadTexture( “Textures/stone.jpg” );

stones.setWrap( Texture.WrapMode.Repeat );[/java]



Isn’t that what the above code does? Am I missing something?

Please note that I call the method “setMaterial()” after the texture coordinates have been populated and the texture buffer created.

Does that make a difference?

Sorry, I missed that.



Somehow, these two vertexes:





…end up with the same texture coordinate.



Either I’m not seeing it in the code above or it’s in the code we can’t see… but it’s definitely true. Presuming that the wrap mode is in effect.

Thanks again. Please stay with me on this. I’m desperate. I tried changing the values for the last 3 texture coordinates, the ones that map the upper triangle. No difference. I even commented them out. No difference. It’s almost like jme is saying “you gave me an image with 4 corners and that’s all I’ll map!”



I created a new game project in the SDK with just this mesh. Below is the code to the entire program (except the image file which you can get from the URL above) If any reader would like to paste this into their SDK and try it, please let me know if you get anything different.



[java]

public class Main extends SimpleApplication {



public static void main(String[] args) {

Main app = new Main();

app.start();

}



@Override

public void simpleInitApp() {

DirectionalLight sun = new DirectionalLight();

sun.setDirection(new Vector3f( 0f, 1f ,1f ).normalizeLocal());

sun.setColor(ColorRGBA.White);

rootNode.addLight( sun );



AmbientLight al = new AmbientLight();

al.setColor( ColorRGBA.White.mult( .6f ) );

rootNode.addLight( al );



Geometry stoneWall = new Geometry();

Mesh mesh = new Mesh();

stoneWall.setMesh( mesh );



Vector3f[] position = new Vector3f[5];

position[0] = new Vector3f( 0,0,0 ); //lower left

position[1] = new Vector3f( 2,0,0 ); //lower right

position[2] = new Vector3f( 2,2,0 ); // upper right

position[3] = new Vector3f( 1,4,0 ); // upper middle

position[4] = new Vector3f( 0,2,0 ); // upper left

mesh.setBuffer( Type.Position, 3, BufferUtils.createFloatBuffer( position ) );



int[] indexes = new int[9];

indexes[0] = 0; // upper left

indexes[1] = 1; // lower left

indexes[2] = 2; // lower right



indexes[3] = 2; // lower right

indexes[4] = 4; // upper right

indexes[5] = 0; // upper left



indexes[6] = 2; // upper tri

indexes[7] = 3; // upper tri

indexes[8] = 4; // upper tri

mesh.setBuffer( Type.Index, 3, BufferUtils.createIntBuffer( indexes ) );



Vector2f[] texCoord = new Vector2f[9];

texCoord[0] = new Vector2f( 0, 0 ); // lower left corner of image maps to first vertex

texCoord[1] = new Vector2f( 1, 0 ); // lower right corner of image maps to second vertex

texCoord[2] = new Vector2f( 1, 1 ); // upper right



texCoord[3] = new Vector2f( 1, 1 ); // upper right

texCoord[4] = new Vector2f( 0, 1 ); // upper left

texCoord[5] = new Vector2f( 0, 0 ); // lower left



texCoord[6] = new Vector2f( 1, 1 ); // upper right

texCoord[7] = new Vector2f( .5f, 2 ); // top

texCoord[8] = new Vector2f( 0, 1 ); // upper left

mesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));



Texture stone = assetManager.loadTexture( “Textures/stone.jpg” );

stone.setWrap( Texture.WrapMode.Repeat );

mesh.scaleTextureCoordinates( new Vector2f( 2.f, 2.f ));

Material material = new Material( assetManager, “Common/MatDefs/Misc/Unshaded.j3md” );

material.setTexture( “ColorMap”, stone );

stoneWall.setMaterial( material );

rootNode.attachChild( stoneWall );

}



@Override

public void simpleUpdate(float tpf) {

//TODO: add update code

}



@Override

public void simpleRender(RenderManager rm) {

//TODO: add render code

}

}

[/java]

Oh… heheh… I just noticed you have too many texture coordinates. You only need one per vertex. The rest are getting ignored.



You only have 5 vertexes so you only need 5 texture coordinates. The index buffer says how to make triangles out of them… it is the only thing that needs 9 entries.

2 Likes

That was it! :slight_smile:

I want to say I tried that days ago but obviously not.

This was a BIG help. Thank you,

If there is anything I can do to return the favor (I’m obviously not a good programmer) please let me know.