Setting Material (Displaying images on a cuboids surfaces)

Jul 8, 2010 at 6:00 PM


I have tried using numerous different images as the Material.DiffuseMap, but none seem to display correctly. For instance, the Jellyfish.jpg sample image supplied with Windows 7 shows in three horizontal segments, the two top segments showing the first half(ish) of the image and the bottom segment showing the bottom half but looks like it is inverted.

I used multiple other images of varying sizes, smaller images just show unglorious mashes of stretched pixels, a bigger one looked just as weird.

Is there that I am missing? Should the image be the exact size of the face onto which it is to be rendered? How to even determined the size of the face, since we use the Dimension property (not sure what units that is measuring in)?

Is there a more hands-on approach to manipulating the image rendering, since what I have so far is pretty much lifted from the sample browser (which works just fine, which is what I'm getting at :z).



Jul 8, 2010 at 9:00 PM


If I'm right, there is lacking an exception in Balder you should have seen for this. Balder does only accept textures with Width and Height being the power of 2. Meaning that the size should be 16x16, 32x32, 64x64, 128x128, 256x256, 512x512 and so forth, or combining like 16x256, 64x512, 512x128 and so on .. 


Jul 8, 2010 at 9:12 PM

Thanks for the information, I'll give it a go and let you know how it works out.

Just as a note, what do you mean by 'accept'? Am I correct in thinking that images ought to be a power of 2 in order to display correctly, but will still be displayed, albeit incorrectly?

Jul 8, 2010 at 10:25 PM
Edited Jul 9, 2010 at 10:07 AM

Great. That worked, thanks. I suppose my next question would be (considering documentation seems sparse at the moment) is how could I:


I. Prevent the image being shown upside down on some faces? (but you can kind of disregard this both in light of the next question and the fact that it just dawned on my that the picture isn't upside down, the face of the cuboid is, therefore it is up to me to rotate the 3D object accordingly).

II. Most importantly, how can I use a different image on each cuboid face? (This information I would be most grateful for).

Jul 9, 2010 at 5:04 AM

orientation is determined by the texture coordinates assigned to each vertex -- if you rotate the texture coordinates (move them all one vertex to the right or left around the plane) you can shift the image to any desired orientation. You dont need to rotate the entire object, just the texture coords of the face that is not oriented the way you want.

For a different image on each face, create a seperate material for each image, then assign the desired material to the desired target faces.

I would LOVE to see your code for getting ANY texture to show up on a face -- thats where I am stuck right now -- nothing I do seems to make the face do anything except reflect the light source.


Jul 9, 2010 at 5:34 AM

For a simple box, there is a method called SetMaterialOnSide() in which you can use to change the image/texture easily. 

There is a few higher level APIs missing for altering the texture coordinates, something I have wanted to do, so for now you have to do as Ascendion says, alter the texture coordinates within the FullDetailLevel instance of a Geometry directly. That means you need to have some understanding of how the box is created. If you have a look the Box.cs file in Balder.Core, you'll see how it works. 

Sorry about scarce documentation at this point. I'm scheduling a lot of time for working on the documentation soon. 

Jul 9, 2010 at 11:16 AM
Edited Jul 9, 2010 at 11:16 AM
Thanks to both of your for helping me out. I'm getting along now but just about to jump into fixing the image orientation issue in my case, it would be great, Ascendion, if you could elaborate in a slightly more specific sense relating to the usage of available functionality within this library to achieve what it is you propose. Initially I didn't see any balder specific properties exposed on the Material object which allows me to manipulate the coordinates, do I use the UIElement.Transform? Or should I look into the balder Face object to handle this? Going to look into it now but if you could help any that would be great.
Jul 9, 2010 at 2:20 PM

Texture coordinates are manipulated via IGeometryDetailLevel and requires some knowlege of how the mesh was constructed

            IGeometryContext gcontext = YourShape.GeometryContext;
            IGeometryDetailLevel context = gcontext.GetDetailLevel(Balder.Core.Rendering.DetailLevel.Full);

Please excuse that the IGDL instance is named "context"... the functionality in IGDL used to be in IGeometryContext and I just switched the code over :)

IGDL has methods to allocate and set texture coordinates at the geometry level, and to assign those texture coords to specific verticies on a face by setting indexes into the texture coordinate array.

Lets use my app for a specific example. I'm doing a sperical hex map where each hex is composed of 6 equilateral triangles. My textures are 256x256 (textures must have dimensions that are a power of 2) with the triangle mapped to the bottom edge of the texture image. I specifically want that bottom edge of the texture image to always be the outer edge of the hexagon when applied to the triangle slice, and the tip of the triangle to always be in the center of the hexagon. To achieve this, I allocated 3 texture coordinates and set them to { 0.5f, 0.0f }, { 0.0f, 1.0f }, and { 1.0f, 1.0f }  (Top center, bottom left, and bottom right, expressed as fractions of the texture size). Then, by knowing the order that the verticies are assigned to the face, I can figure out what order to use for the texture coordinates. My code specifically forces the vertex indices to be in Center, Bottom Right, Bottom Left order when looking at the face such that the 1st vertex is in the center of the hexagon. Since you are using an "off the shelf" geometry, you will have to dig into the code that generated the mesh to figure out the order of verticies assigned to each face, and what texture coordinates have already been created and assigned.

            context.SetTextureCoordinate(0, new TextureCoordinate(0.5f, 0.0f));
            context.SetTextureCoordinate(1, new TextureCoordinate(0.0f, 1.0f));
            context.SetTextureCoordinate(2, new TextureCoordinate(1.0f, 1.0f));

And then later in the code:

            context.SetFaceTextureCoordinateIndex(i, 0, 1, 2);

where (i) is the index of the face being assigned new texture coordinate indices.

For cube faces, you will need 4 texture coords, one for each corner, and assuming that :

1. each cube face is composed of 2 triangles
2. the seam between the triangles runs from the north-east to the south-west corner
3. your texture coords are numbered clockwise starting at the north-west corner
4. that the 1st vertex of the north-west triangle is the north-west corner
5. that the 1st vertex of the south-east triangle is the south-east corner

then your texture coords will be 0 (NW), 1 (NE), 3 (SW) for the north-west triangle, and 2 (SE) , 3 (SW) , 1 (NE) for the south-east triangle

That should give you enough to figure out how to set the texture mapping for the specific mesh that you are working with.

I hope that covers it :) I'm going to be gone for a few hours so it might be a bit if you have any more questions.

Jul 11, 2010 at 7:42 PM

Phew! Finally got this sorted, your input certainly helped - although with the simplicity of my object and requirement for textured to be embedded means it was even slightly less work than you have above.


Don't suppose you have a quick way of determining the objects size in pixels? Or even simply the width and height of a face - not sure how to do it with the dimension property values.


Thanks again.

Jul 11, 2010 at 8:09 PM

its really not relevant -- textures are applied proportionatly, hence the texture coordinates always being fractional (except when you really want to tile a face, using texture coords above 1 will cause the texture to repeat)

Or to look at it another way - my hexagon sphere uses 256x256 textures at the moment (probably a bit overkill)... when I zoom out really far, the triangles are a few pixels across.. when I zoom in tight. a triangle can cover half the screen (1920px wide)... worse -- if you are looking at the face at an angle, one end is likely to be bigger in pixels than the other -- thats why the proportional mapping is needed -- because there is no fixed pixel arrangement once the mesh is projected to screen coords. I could just as well be using 128x128 or 1024x1024 textures and so long as the image used is a scaled up or scaled down version of the 256x256 texture, it would look pretty much identical.

The size of an object is in world space coordinates and has no direct relationship to any size in pixels. Again to look at my sphere.. All the math is based on the assumption that I'm working inside a unit radius sphere, so all my coords are between -1 and 1... To get the size I want, I scale as needed.

As to the size of a face, you have the 3 coordinates of the verticies, solve L = sqrt(deltax^2 + deltay^2 + deltaz^2) for each side, which gives you all the information that you need to solve for the angles, area, and perimeter of the triangle -- all in world coordinates of course :)

Jul 12, 2010 at 11:25 PM

Got this nailed yesterday, thanks for your help in giving things such clarity - real size is still kind of relevant in my situation, but I won't go into that; your input gave me enough to merge and digest both perspectives of my implementation, that is, I can now have my object rotate, and at a single certain point, 'plant' a given face in Flatland, momentarily.

Thanks again. Sure I'll be back ;)