# Drawing 3D cubes with xna

I managed to draw a 3d cube using triangles like this:

    protected override void LoadContent()
{
basicEffect = new BasicEffect(GraphicsDevice);
VertexPositionColor[] vertices = new VertexPositionColor[8];
short[] indices = new short[36];
vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), vertices.Length, BufferUsage.WriteOnly);
indexBuffer = new IndexBuffer(graphics.GraphicsDevice, typeof(short), indices.Length, BufferUsage.WriteOnly);
Color Color1 = Color.DarkRed;
Color Color2 = Color.Pink;
float width = 2;
float height = 1;
float depth = 0.5f;

vertices[0] = new VertexPositionColor(new Vector3(0, 0, 0), Color1);
vertices[1] = new VertexPositionColor(new Vector3(width, 0, 0), Color1);
vertices[2] = new VertexPositionColor(new Vector3(width, -height, 0), Color1);
vertices[3] = new VertexPositionColor(new Vector3(0, -height, 0), Color1);
vertices[4] = new VertexPositionColor(new Vector3(0, 0, depth), Color1);
vertices[5] = new VertexPositionColor(new Vector3(width, 0, depth), Color1);
vertices[6] = new VertexPositionColor(new Vector3(width, -height, depth), Color1);
vertices[7] = new VertexPositionColor(new Vector3(0, -height, depth), Color1);

indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 0; indices[4] = 3; indices[5] = 2;
indices[6] = 4; indices[7] = 0; indices[8] = 3;
indices[9] = 4; indices[10] = 7; indices[11] = 3;
indices[12] = 3; indices[13] = 7; indices[14] = 6;
indices[15] = 3; indices[16] = 6; indices[17] = 2;
indices[18] = 1; indices[19] = 5; indices[20] = 6;
indices[21] = 1; indices[22] = 5; indices[23] = 2;
indices[24] = 4; indices[25] = 5; indices[26] = 6;
indices[27] = 4; indices[28] = 7; indices[29] = 6;
indices[30] = 0; indices[31] = 1; indices[32] = 5;
indices[33] = 0; indices[34] = 4; indices[35] = 5;

vertexBuffer.SetData<VertexPositionColor>(vertices);
indexBuffer.SetData(indices);
}


I have two questions:

• As you can see i am using float width = 2; float height = 1; float depth = 0.5f; but why "width = 2" looks like 80 pixels instead of 2? I want the cubes to be 72x24x12, i can't figure out how to calculate the pixels from the field of view / aspect ratio. To draw the cube on different positions i am using world = Matrix.CreateTranslation(10.0f, 10.0f, 0.0f);, is that the correct way to do this ?
• How can i draw each face of the cube a different color? (Right now i know how to give color to each vertice, see Color1 variable). Right now i am using 2 different BasicEffects, is there any better way perhaps ?

So , as already was sad there are no pixels in 3D spcae at all. There are usints that dont have any relations with 2D pixels. Pixel are also units, but they have fixed size couse screen have have fixed resolution. For example if your monitor is 12 inches in width and 9 inches in height and resolutins is set to 800x600 one pixel will have real size 0.015x0.015 inches^2.

But 3D's units is not pixels. Theare are no relations with hardvare and screen resolution. If you want create rectahgle with size 72x24x12 than do it. Next you need to create camera with distance, aspect rations and angle of view that allows you see all you scene. If scene if too big than move camera farther, or scale down the scene.

You can do tree types of transformation with matrices: translation, rotation, scaling. Most important thing you should now that if you apply few transformatins that every next will be applyind for all that was applyid before. For example if you do

transform = translate(10,8,10) * scale(2,3,5) * translate(4, 5, 10)


it means that you translate your first model at(10,8,10) units, but then scale ALL distances to (2,3,5). So, your model's size will be scaled, as far as distance of applyed translation and translate(10,8,10) will means translate(20,24,50). Then you translate model again at translate(4, 5, 10), and this translations will NOT be scaled. So, you can create all scene withoud scaling and then just scale it before drawing.

This article was very helpfull for me. If you don't understand russian click at "часть 1, часть 2, часть 3 и часть 4" links int top of article.

• so you are saying there is no way to tell if with 45 degrees camera angle, (0,0,100f) camera position, and (1,1,1) cube model, to calculate the expected width in pixels of the model on screen ? there has to be an analogy to be able to calculate it Jan 29 '15 at 13:42
• if you place camera at point (0,0,100f) ant direct it to (0,0,0) with 45 degrees field of view you will see 100 units, in width at (0,0,50), 200 units in (0,0,0), 300 units in (0,0,-50) and so on: W = 2*D*tg(A), where A is angle, D - camera distance. But it's not exactly screen width, it's width of plane for witch vector of distance is a normal. You should not bind to pixels couse they are only 2D. In 3D operate units, texels and voxels.
– user52551
Jan 29 '15 at 14:22

Like dustin said, the size of a 3d object isnt measured in pixels. But if you wish to scale it, change "world = Matrix.CreateTranslation(10.0f, 10.0f, 0.0f);" to "world = Matrix.CreateScale(2) * Matrix.CreateTranslation(10.0f, 10.0f, 0.0f);". Notice that I put the scale factor matrix BEFORE the translation. Otherwise, the translation would also get scaled. Matrix multiplying works from left to right.

And for your second question: if you want all faces to have a different color, you will have to place differently colored vertices at every point of the cube/block. This is because as you said, you can assign one color per vertex.

• in spritebatch.Begin method you can add a scale matrix. how can i do the same with 3d models ? the method you showed wouldn't have exactly the same effect with adding a scale matrix on Begin() function. because if i had 2 models side by side, and increased each ones scale individually those objects would overlap. but on the other example they wouldn't Jan 28 '15 at 20:26
• so if i had to use your method to increase every single object scale individually, that wouldn't be enough. i would also have to change their position, by a proper amount. how would i calculate that amount ? Jan 28 '15 at 20:31
• In that case, first translate, and then scale. That will scale the translation as well, causing the distance between them to scale as well."world = Matrix.CreateTranslation(10.0f, 10.0f, 0.0f) * Matrix.CreateScale(2);". Jan 29 '15 at 4:35
• but the translation is related to the screen. how would that work ? I wouldn't want to scale Matrix.CreateTranslation(-1000.0f, 1000.0f, 0.0f) by 2, which is what i am using now Jan 29 '15 at 10:21
• Both the translation and the scale are related to the game world, not to screen coordinates or sizes. I'm not really sure what you mean right now. Have you tried the code? What does it do/not do that you don't like? Jan 29 '15 at 11:27

For: why "width = 2" looks like 80 pixels instead of 2?

Pixels are gone in 3d space, but you still use them in your UI canvas.

Your distances are in "units". How large something looks depends on if you put the camera 1 unit away from the object or 20, 100, etc.

• right now its 38f away, in the Z axis, how you calculate the cube's size ? Vector3 cameraPosition = new Vector3(0.0f, 0.0f, 38f) Jan 24 '15 at 17:33
• how could i at least rescale what i am drawing ? lets say make it x2 bigger ? what is the pattern ? do you know ? Jan 24 '15 at 17:41
• Those aren't things I ever did. I put a bunch of triangles on the screen and came up with a min/max distance and let the user adjust the cam distance as they wanted. Jan 24 '15 at 17:49