Texture coordinates

Have jReality programming problems or questions? Post them here.
Post Reply
Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Texture coordinates

Post by Ronin » Thu 2. Feb 2012, 14:31

I am trying to add a texture to a geometry. The geometry is built up from 1 20-gon cylinder and 2 20-gon disks (top & bottom).

I manage to add the texture, but I can't for the life of me figure out what TextureCoordinates to use...
I've tried to use the coordinates gotten from the disk FaceSet, but then the texture is applied 4 times, not once like I want it too.

Posting an example code here to show what I've tried:

Code: Select all

public class CompassGeometry {

	private static Appearance diskAppearance;

	public static void main(String[] args)	{
		SceneGraphComponent myscene = SceneGraphUtility.createFullSceneGraphComponent("myscene");
		double zmin = 0;
		double zmax = 0.1;
		double radius = 1;
		
		IndexedFaceSet cylinder = Primitives.cylinder(20, radius, radius, zmin, zmax, Math.PI*2);
		SceneGraphComponent cylinderComponent = SceneGraphUtility.createFullSceneGraphComponent("compassCylinder");
		cylinderComponent.setGeometry(cylinder);
		
		SceneGraphComponent topDisk = createDisk("Top");
		SceneGraphComponent bottomDisk = createDisk("Bottom");
		MatrixBuilder.euclidean().translate(0,0,zmin).scale(radius,radius,1).assignTo(topDisk);
		MatrixBuilder.euclidean().translate(0,0,zmax).rotateX(Math.PI).scale(radius,radius,1).assignTo(bottomDisk);
		
		Appearance appearance = myscene.getAppearance();
		appearance.setAttribute(POLYGON_SHADER + "." + CommonAttributes.DIFFUSE_COLOR, Color.white);
		appearance.setAttribute(CommonAttributes.EDGE_DRAW, false);
		appearance.setAttribute(CommonAttributes.VERTEX_DRAW, false);

		myscene.addChildren(cylinderComponent, topDisk, bottomDisk);
		
		JRViewer.display(myscene);
	}
	
	private static SceneGraphComponent createDisk(String name) {
		SceneGraphComponent diskComponent = SceneGraphUtility.createFullSceneGraphComponent(name);
		IndexedFaceSetFactory disk = Primitives.regularPolygonFactory(20,0.0);
		
		double[][] coordinates = disk.getIndexedFaceSet().getVertexAttributes(Attribute.COORDINATES).toDoubleArrayArray(null);
		disk.setVertexTextureCoordinates(coordinates);
		disk.update();
		diskComponent.setGeometry(disk.getIndexedFaceSet());
		
		diskAppearance = diskComponent.getAppearance();
		URL imagePath = CompassGeometry.class.getResource("labels.png");
		applyTexture(imagePath);
		
		return diskComponent;
	}

	private static void applyTexture(URL imagePath) {
		Texture2D tex2d = (Texture2D) AttributeEntityUtility.createAttributeEntity(Texture2D.class, 
				POLYGON_SHADER + "." + TEXTURE_2D, diskAppearance, true);
		ImageData imageData = null;
		try {
			imageData = ImageData.load(new Input(imagePath));
		} catch (IOException ee) {
			ee.printStackTrace();
		}
	    tex2d.setImage(imageData);				
		
		Matrix textureMatrix = new Matrix();
		MatrixBuilder.euclidean().scale(1, 1, 1).assignTo(textureMatrix);
		tex2d.setTextureMatrix(textureMatrix);
	}
}
The result I get looks like:
Image

Andre
Posts: 226
Joined: Fri 18. Sep 2009, 11:30

Re: Texture coordinates

Post by Andre » Thu 2. Feb 2012, 15:40

Hi Ronin,

you can't use closed surfaces for 2dtexture in jReality. If you want to draw a 2dtexture you need an open surface. Check out the torus example of the primitives class de.jreality.geometry.Primitives . There you get some vertices twice (the starting and the end vertices) and you're able to draw a boundary. The same should be possible for the normal "cylinder" example of the primitives class and also for the closedCylinder, which is pretty much the same you want!

You can call them by using:

Code: Select all

SceneGraphComponent sgc = Primitives.closedCylinder(n, r, zmin, zmax, thetamax);

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Texture coordinates

Post by Ronin » Thu 2. Feb 2012, 15:50

Andre wrote:Hi Ronin,

you can't use closed surfaces for 2dtexture in jReality. If you want to draw a 2dtexture you need an open surface. Check out the torus example of the primitives class de.jreality.geometry.Primitives . There you get some vertices twice (the starting and the end vertices) and you're able to draw a boundary. The same should be possible for the normal "cylinder" example of the primitives class, but not for the closedCylinder.

You can call them by using:

Code: Select all

SceneGraphComponent sgc = Primitives.closedCylinder(n, r, zmin, zmax, thetamax);
I'm not sure I follow what you're trying to say here, but that can be just me ofc :p
I am using two IndexedFaceSets constructed with constructPolygonFactory in IndexedFaceSetUtility, and as far as i can see that's not a closed surface(I might have misunderstood the concept behind closed surfaces tho :p)?

And don't that example create a closed surface?

Andre
Posts: 226
Joined: Fri 18. Sep 2009, 11:30

Re: Texture coordinates

Post by Andre » Thu 2. Feb 2012, 16:00

Ronin wrote:
Andre wrote:Hi Ronin,

you can't use closed surfaces for 2dtexture in jReality. If you want to draw a 2dtexture you need an open surface. Check out the torus example of the primitives class de.jreality.geometry.Primitives . There you get some vertices twice (the starting and the end vertices) and you're able to draw a boundary. The same should be possible for the normal "cylinder" example of the primitives class, but not for the closedCylinder.

You can call them by using:

Code: Select all

SceneGraphComponent sgc = Primitives.closedCylinder(n, r, zmin, zmax, thetamax);
I'm not sure I follow what you're trying to say here, but that can be just me ofc :p
I am using two IndexedFaceSets constructed with constructPolygonFactory in IndexedFaceSetUtility, and as far as i can see that's not a closed surface(I might have misunderstood the concept behind closed surfaces tho :p)?

And don't that example create a closed surface?
first of all I corrected my post, it should also work for the closedCylinder example.

closed in this case means not visually closed.
If you create a cylinder with 3 vertices at the top and the bottom, we got 6 vertices in total. This surface is closed.
But if you add two further vertices at the same vertexpositions like the first have and declare them as your "endpoints" your cylinder is still on a base of a triangle and looks visually closed but isn't. It is cutted!

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Texture coordinates

Post by Ronin » Thu 2. Feb 2012, 16:06

I tried using the closedcylinder at first, but I couldn't find a way to apply the texture to the disk polygons instead of the cylinder surface. Any suggestions on that?

Really appreciate your help :)

Andre
Posts: 226
Joined: Fri 18. Sep 2009, 11:30

Re: Texture coordinates

Post by Andre » Thu 2. Feb 2012, 16:09

Sorry my fault. I see right now, that you just applied the texture to the disks and not to the cylinder itself, so forget about my answer ;)

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Texture coordinates

Post by Ronin » Thu 2. Feb 2012, 16:12

Andre wrote:Sorry my fault. I see right now, that you just applied the texture to the disks and not to the cylinder itself, so forget about my answer ;)
Hehe okay, that clear's up my confusion too :P

Andre
Posts: 226
Joined: Fri 18. Sep 2009, 11:30

Re: Texture coordinates

Post by Andre » Thu 2. Feb 2012, 16:50

Try

Code: Select all

	      Matrix textureMatrix = new Matrix();
	      MatrixBuilder.euclidean().scale(1, 1, 1).assignTo(textureMatrix);
	      MatrixBuilder.euclidean().translate(0.5, 0.5, 0.).assignTo(textureMatrix);
	      tex2d.setTextureMatrix(textureMatrix);
instead of

Code: Select all

	      Matrix textureMatrix = new Matrix();
	      MatrixBuilder.euclidean().scale(1, 1, 1).assignTo(textureMatrix);
	      tex2d.setTextureMatrix(textureMatrix);
maybe you also have to lower the scale to 0.5

Code: Select all

	      MatrixBuilder.euclidean().scale(0.5, 0.5, 0.).assignTo(textureMatrix);
I couldn't try it with your "lable.png" but with my black_cross it is working...

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Texture coordinates

Post by Ronin » Thu 2. Feb 2012, 17:01

Hmmm, looks like you're unto something there.
With 0.5 scale and translate I got this:

Image

Gonna try tweak the values some and see if I can get it to align correctly.

Andre
Posts: 226
Joined: Fri 18. Sep 2009, 11:30

Re: Texture coordinates

Post by Andre » Thu 2. Feb 2012, 17:04

Sorry, I made again a small mistake. You have to apply the translate and scale function at each other. It is implortant to apply the translate function first!

Code: Select all

	    
              Matrix textureMatrix = new Matrix();
	      MatrixBuilder.euclidean().translate(0.5, 0.5, 0.).scale(0.5, 0.5, 1).assignTo(textureMatrix);
	      tex2d.setTextureMatrix(textureMatrix);
instead of

Code: Select all

	    
              Matrix textureMatrix = new Matrix();
	      MatrixBuilder.euclidean().scale(1, 1, 1).assignTo(textureMatrix);
	      tex2d.setTextureMatrix(textureMatrix);
I've attached an example.png which shows the difference in my case.
left the translate.scale example
right the normal one
Attachments
example.png
example.png (22.58 KiB) Viewed 2599 times

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Texture coordinates

Post by Ronin » Thu 2. Feb 2012, 17:55

That did it! Perfect!
Thank you :D

What's the reason that these values had to be set like that anyway?
I'm not too good with textures :P

Andre
Posts: 226
Joined: Fri 18. Sep 2009, 11:30

Re: Texture coordinates

Post by Andre » Thu 2. Feb 2012, 18:16

Ronin wrote:That did it! Perfect!
Thank you :D

What's the reason that these values had to be set like that anyway?
I'm not too good with textures :P
Im not really sure about that aswell. I first looked into the 2dtexture stuff, then I found an example.png file and got the same result like you with the 4 copies. gambling around with the Matrixbuilder made some things more clearly.

First it seems that each texture png. is shrinked down to a quad with vertexcoords ([0.0, 0.0], [0.0, 0.5], [0.5,0.5], [0.5,0.0]) and than translated by 0.5 in +/- x/y direction.
These are global coordinates!

Our Cylinder has the following global "coordinates-range" radius 1 around the origin [x=0 /y= 0] -> x: [-0.5 : 0.5] y: [-0.5: 0.5]

The goal now is to move the midpoint of the texture at the origin, or multiples of the translation applied at the texture. (We moved the texture eg at the point [x=1/y=1]) You already got the result for just applying the tranlation (the circle in the middle with the for circle parts around)

After the tranlation we have to scale its size:
The size of our texture is between 0/ 0.5, -> 0.5
The size of our cylinderdisk is between -0.5 / 0.5 -> 1

Unfortunate it seems, that the scalingfactor is reversed. I first tryed to scale it with 2, but then I got smaller textures. Reversing it to 0.5 -> voila ;)

Finally you have to apply this translation and scaling at your 2dTexture. Applying one after the other will override your first choice.

Ronin
Posts: 50
Joined: Wed 9. Nov 2011, 17:22

Re: Texture coordinates

Post by Ronin » Mon 6. Feb 2012, 09:59

Many thanks for your observations, it makes working with textures a bit more clear in the future :)

Post Reply