• Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

# Creating cubes with XNA primitives

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

3 replies to this topic

### #1Negão  Members   -  Reputation: 100

Like
0Likes
Like

Posted 26 November 2011 - 03:50 AM

Hi guys, i'm trying to create cubes using XNA primitives, but i don't understand how to use triangle to make then. Help?
I made the first face, but i don't know how i can do the rest.

[source lang="cs"][/size][/size][/font][/color][color="#666666"][font="Arial"][size="3"][size="2"][size="3"][size="2"][color="blue"]this[/color].triangleStrip = [color="blue"]new[/color] [color="#2B91AF"]VertexPositionColor[/color][4]; [/size][size="2"] triangleStrip[0].Position = [color="blue"]new[/color] [color="#2B91AF"]Vector[/color][color="#2B91AF"]3[/color](450, 400, 0);[/size][size="2"] triangleStrip[1].Position = [color="blue"]new[/color] [color="#2B91AF"]Vector[/color][color="#2B91AF"]3[/color](550, 400, 0);[/size][size="2"] triangleStrip[2].Position = [color="blue"]new[/color] [color="#2B91AF"]Vector[/color][color="#2B91AF"]3[/color](450, 500, 0);[/size][size="2"] triangleStrip[3].Position = [color="blue"]new[/color] [color="#2B91AF"]Vector[/color][color="#2B91AF"]3[/color](550, 500, 0);[/size] [/size][/size][/size][/font][/color][color="#666666"][font="Arial"][size="3"][size="2"][/source]

### #2Starnick  Members   -  Reputation: 553

Like
1Likes
Like

Posted 26 November 2011 - 05:11 PM

An easy way of considering a cube is to have it axis-aligned (each face is aligned with the x, y, z axes). So you write your cube creation function/class/etc, pass in a center point and a size (in the example code I use extents, or half lengths - the length from the center to a face on each respective axis) so then you can programmatically create a cube without hardcoding anything. Note, the following explanation and code uses triangle list, not triangle strip.

A cube has 8 corner vertices, but generally your cube will require 36 vertices in order to account for uniqueness - like UV coordinates and normals (or vertex colors in your case). By using indexed geometry, you can cut this down to 24 unique vertices since vertices can be shared by the triangles that make up each face (so no need to replicate that data). Following code is largely based on a Box class I wrote that can be found here.

[source lang=csharp]private Vector3 XAxis = new Vector3(1, 0, 0);private Vector3 YAxis = new Vector3(0, 1, 0);private Vector3 ZAxis = new Vector3(0, 0, 1);...//Center is usually the origin, and X, Y, Z values of extents correspond to the half-length along each axis.public void ComputeBox(Vector3 center, Vector3 extents) { Vector3[] exAxes = new Vector3[3]; exAxes[0] = XAxis * extents.X; exAxes[1] = YAxis * extents.Y; exAxes[2] = ZAxis * extents.Z; Vector3[] vertices = new Vector3[8]; //Use the scaled axes to compute the 8 corners vertices[0] = ((center - exAxes[0]) + exAxes[1]) + exAxes[2]; vertices[1] = ((center + exAxes[0]) + exAxes[1]) + exAxes[2]; vertices[2] = ((center + exAxes[0]) - exAxes[1]) + exAxes[2]; vertices[3] = ((center - exAxes[0]) - exAxes[1]) + exAxes[2]; vertices[4] = ((center + exAxes[0]) + exAxes[1]) - exAxes[2]; vertices[5] = ((center - exAxes[0]) + xAxes[1]) - exAxes[2]; vertices[6] = ((center - exAxes[0]) - exAxes[1]) - exAxes[2]; vertices[7] = ((center + exAxes[0]) - exAxes[1]) - exAxes[2]; //Set position data Vector3[] positions = new Vector3[24]; //Front face (facing +Z axis) positions[0] = vertices[0]; positions[1] = vertices[1]; positions[2] = vertices[2]; positions[3] = vertices[3]; //Back face (facing -Z axis) positions[4] = vertices[4]; positions[5] = vertices[5]; positions[6] = vertices[6]; positions[7] = vertices[7]; //Left face (facing -X axis) positions[8] = vertices[5]; positions[9] = vertices[0]; positions[10] = vertices[3]; positions[11] = vertices[6]; //Right face (facing +X axis) positions[12] = vertices[1]; positions[13] = vertices[4]; positions[14] = vertices[7]; positions[15] = vertices[2]; //Top face (facing +Y axis) positions[16] = vertices[5]; positions[17] = vertices[4]; positions[18] = vertices[1]; positions[19] = vertices[0]; //Bottom face (facing -Y axis) positions[20] = vertices[7]; positions[21] = vertices[6]; positions[22] = vertices[3]; positions[23] = vertices[2]; //Set normals, colors, UV coordinates, etc //Normals can be the above directions for each face, or could have a crease, or inverted if you want an inside out box, //need to swap the winding order of your indices to do that though (or use a rasterizer state) //UV coordinates could be (0,0) (1,0) (1,1) (0,1) for each face //Set indices int[] indices = new int[36]; //Set indices for each triangle per face (two triangles, 6 faces). This should be CCW ordering for XNA. for(int i = 0, j = 0; i < 24; i += 4) { indices[j++] = i + 2; indices[j++] = i + 1; indices[j++] = i; indices[j++] = i + 3; indices[j++] = i + 2; indices[j++] = i; } //Set geometry data to hardware buffers}[/source]

Starnick

### #3Negão  Members   -  Reputation: 100

Like
0Likes
Like

Posted 29 November 2011 - 04:42 AM

An easy way of considering a cube is to have it axis-aligned (each face is aligned with the x, y, z axes). So you write your cube creation function/class/etc, pass in a center point and a size (in the example code I use extents, or half lengths - the length from the center to a face on each respective axis) so then you can programmatically create a cube without hardcoding anything. Note, the following explanation and code uses triangle list, not triangle strip.

A cube has 8 corner vertices, but generally your cube will require 36 vertices in order to account for uniqueness - like UV coordinates and normals (or vertex colors in your case). By using indexed geometry, you can cut this down to 24 unique vertices since vertices can be shared by the triangles that make up each face (so no need to replicate that data). Following code is largely based on a Box class I wrote that can be found here.

[source lang=csharp]private Vector3 XAxis = new Vector3(1, 0, 0);private Vector3 YAxis = new Vector3(0, 1, 0);private Vector3 ZAxis = new Vector3(0, 0, 1);...//Center is usually the origin, and X, Y, Z values of extents correspond to the half-length along each axis.public void ComputeBox(Vector3 center, Vector3 extents) { Vector3[] exAxes = new exAxes[3]; exAxes[0] = XAxis * extents.X; exAxes[1] = YAxis * extents.Y; exAxes[2] = ZAxis * extents.Z; Vector3[] vertices = new Vector3[8]; //Use the scaled axes to compute the 8 corners vertices[0] = ((center - exAxes[0]) + exAxes[1]) + exAxes[2]; vertices[1] = ((center + exAxes[0]) + exAxes[1]) + exAxes[2]; vertices[2] = ((center + exAxes[0]) - exAxes[1]) + exAxes[2]; vertices[3] = ((center - exAxes[0]) - exAxes[1]) + exAxes[2]; vertices[4] = ((center + exAxes[0]) + exAxes[1]) - exAxes[2]; vertices[5] = ((center - exAxes[0]) + xAxes[1]) - exAxes[2]; vertices[6] = ((center - exAxes[0]) - exAxes[1]) - exAxes[2]; vertices[7] = ((center + exAxes[0]) - exAxes[1]) - exAxes[2]; //Set position data Vector3[] positions = new Vector3[24]; //Front face (facing +Z axis) positions[vertices[0]]; positions[vertices[1]]; positions[vertices[2]]; positions[vertices[3]]; //Back face (facing -Z axis) positions[vertices[4]]; positions[vertices[5]]; positions[vertices[6]]; positions[vertices[7]]; //Left face (facing -X axis) positions[vertices[5]]; positions[vertices[0]]; positions[vertices[3]]; positions[vertices[6]]; //Right face (facing +X axis) positions[vertices[1]]; positions[vertices[4]]; positions[vertices[7]]; positions[vertices[2]]; //Top face (facing +Y axis) positions[vertices[5]]; positions[vertices[4]]; positions[vertices[1]]; positions[vertices[0]]; //Bottom face (facing -Y axis) positions[vertices[7]]; positions[vertices[6]]; positions[vertices[3]]; positions[vertices[2]]; //Set normals, colors, UV coordinates, etc //Normals can be the above directions for each face, or could have a crease, or inverted if you want an inside out box, //need to swap the winding order of your indices to do that though (or use a rasterizer state) //UV coordinates could be (0,0) (1,0) (1,1) (0,1) for each face //Set indices int[] indices = new int[36]; //Set indices for each triangle per face (two triangles, 6 faces). This should be CCW ordering for XNA. for(int i = 0, j = 0; i < 24; i += 4) { indices[j++] = i + 2; indices[j++] = i + 1; indices[j++] = i; indices[j++] = i + 3; indices[j++] = i + 2; indices[j++] = i; } //Set geometry data to hardware buffers}[/source]

Hi, thanks for the explanation, but, i've tryed to test your code, but i found some problems.. in [source lang=csharp] Vector3[] exAxes = new exAxes[3];[/source]

On line: [source lang=csharp][font="Consolas,"] positions[vertices[0]];[/font][font="Consolas,"][/source][/font]
i got the problem:
Only assignment, call, increment, decrement, and new object expressions can be used as a statement

Is your code working fine with you?

### #4Starnick  Members   -  Reputation: 553

Like
1Likes
Like

Posted 29 November 2011 - 06:59 AM

Well that was a gigantic embarrassing mistake . In my original code (the Box class link) I wrap arrays in something called a DataBuffer, so if you have a DataBuffer<Vector3> you can use Set(Vector3), which adds the value to the underlying array at the current position (index) and increments the position. But I replaced all that with a regular old array, but forgot to add in the indices! The original code snippet is corrected now.

Starnick

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS