Creating a cube from triangles

BlitzMax Forums/OpenGL Module/Creating a cube from triangles

Ferret(Posted 2011) [#1]
I'm trying to create a cube using triangles.

1: I created a front and back face but they seem to connect to eachoter creating another triangle?

2: For a cube with one texture, is 8 vertexes enough?

3: For a cube with a different texture for each face, i need 4 vertexes for each face?

4: How many vertexes do i need for a cube with correct lightning?


col(Posted 2011) [#2]
I'm surprised no one has answered already :P maybe the GL pros are away for the weekend :D

I'm more of a DirectX guy instead of GL but here are some things I'd look for :-

1: How are you drawing the triangles? each triangle separate with individual vertex data? index and vertex data? How are rendering - GL_TRIANGLES or GL_TRIANGLE_STRIP or other?
2: Kind of, but you may find some faces may be upside down, or reversed left to right
3: Yes, if using indices, otherwise 6 to define 2 Tris. Also you'll need UV data for each vertex.
4: The same as for 3, depending if you're using just vertex data or vertex and index data. Either way you'll need more information for each vertex - Normal Vector.


AdamRedwoods(Posted 2011) [#3]
There are many different ways to draw a cube in openGL.

- if using the immediate state glBegin()/glEnd(), you can use quads, triangles, triangle strips (beginners start here, i'm assuming you are starting here)
- if using the buffer method (vbo), then sending an array of vertices to the glDrawElements()

My advice would be to first create a Function() that creates a square or "quad", then rotate that quad in your app. Then you can see how a basic "quad" is built and how it works, how it lights, and how it is textured. Then you can use that function to accept x,y,z for positioning, size, and order (order is important for determining face direction) and you'll see how to create your own cube from that.
Once you do that it should answer all your questions, since a cube is just six squares pointing in different directions.

Last edited 2011


Ferret(Posted 2011) [#4]
I was drawing all triangles at once, drawing each one seperate seems to work.
But now i need 36 vertexes for a cube, wich seems allot.
I'm using GL_TRIANGLES.

I dont know what you mean with indices, index and vertex data.

What i do is create a mesh type with a list of surfaces, each surface has a vertex and a triangle list.
A vertex type stores position,color,uv and normals.
A triangle type points to 3 vertexes.
I draw the 3 vertexes for each triangle.


col(Posted 2011) [#5]
As it seems that you're a beginner, I'd advise you to go all through the Nehe Tutorials over at gamedev.net :P

They are on the right hand side of this page ( under Legacy Tutorials ) :-
http://nehe.gamedev.net/


Ferret(Posted 2011) [#6]
That obvious :p

I'm reading the red book and started playing to soon.

Is the red book a good start for a beginner or should i look at the Nehe Tutorials first?


AdamRedwoods(Posted 2011) [#7]
Both are good but I found Nehe to be more complete. The red book is good but I found it better for reference.

36 vertices is correct-- remember, if you are drawing PER TRIANGLE and not by an indices list, then you will be repeating vertices. 6 quads * 2 triangles per quad * 3 vertices per triangle = 36.

If you're creating classes and trying to create an engine, I'd advise learning about glDrawElements:
http://www.songho.ca/opengl/gl_vertexarray.html


Ferret(Posted 2011) [#8]
I read about gl arays last night, if i understand correctly vertices can be shared.

Had a quick look at the link, verry interesting, especialy using buffers to speed things up.

Going to play with those arays first and learn about buffers and display lists.

Thx for the advise!


Ferret(Posted 2011) [#9]
I got glArrayElement() working but can't get glDrawElements() to work.
Here is a test app to show what i'm doing.



Last edited 2011


AdamRedwoods(Posted 2011) [#10]
I think I had problems with glDrawElements using GL_INT, too.

Try using GL_UNSIGNED_SHORT, and remember you will have to cast your array differently (Global indices:Short[]).


OH! NOTE: I see you've place glbegin() glend()-- you DO NOT use these when using glDrawElements. glDrawElements is your drawing command.


Ferret(Posted 2011) [#11]
It works now :), thx.
Also added added normal and texture coords arrays.


Dabhand(Posted 2012) [#12]
A bit late for the party, but I wrote this a good few years ago:-

[bbcode]
Type vector
Field x:Float
Field y:Float
Field z:Float
Field xp:Float
Field yp:Float
End Type

Type Triangle
Field p1:Long
Field p2:Long
Field p3:Long
Field dotProduct:Float
End Type

Global P:vector[9] 'We need eight vectors and 12 triangles, but adding
Global T:Triangle[13] 'But I'm adding one more so we can index them them
'from 1, instead of 0... Just to ease readibility.
For loop = 0 To 12
If loop< 9
P[loop] = New vector
End If
T[loop] = New Triangle
Next

Const CULL_BACK_FACES = True
Const PERSPECTIVE_MODE = True


Global Offset:Float = 300
Global turnRate:Float = 1
Global pointOfView:Float
Init(200)

Graphics 800,600

Repeat
Cls

If KeyDown(KEY_LEFT)
RotateCubeZ(-turnRate)
End If

If KeyDown(KEY_RIGHT)
RotateCubeZ(turnRate)
End If

If KeyDown(KEY_UP)
RotateCubeX(-turnRate)
End If

If KeyDown(KEY_DOWN)
RotateCubeX(turnRate)
End If

If KeyDown(KEY_S)
RotateCubeY(-turnRate)
End If

If KeyDown(KEY_A)
RotateCubeY(turnRate)
End If

If CULL_BACK_FACES = True
CullBackFaces()
End If

If PERSPECTIVE_MODE = True
CalculatevectorProjections()
End If



DrawCube()
Flip(1)
Until KeyDown(KEY_ESCAPE)

Function CullBackFaces()
Local loop:Int
For loop = 1 To 12
CalculateCrossProduct(loop)
T[loop].dotProduct = CalculateDotProduct()
Next
End Function

Function CalculatevectorProjections()
Local loop:Int
For loop = 1 To 8
P[loop].xp = P[loop].X * pointOfView / (pointOfView + P[loop].Z) + Offset
P[loop].yp = P[loop].Y * pointOfView / (pointOfView + P[loop].Z) + Offset
Next
End Function

Function CalculateCrossProduct(triangleIndex:Long)
Local x1:Float, y1:Float, z1:Float, x2:Float, y2:Float, z2:Float
x1 = P[T[triangleIndex].p2].X - P[T[triangleIndex].p1].X
y1 = P[T[triangleIndex].p2].Y - P[T[triangleIndex].p1].Y
z1 = P[T[triangleIndex].p2].Z - P[T[triangleIndex].p1].Z

x2 = P[T[triangleIndex].p3].X - P[T[triangleIndex].p1].X
y2 = P[T[triangleIndex].p3].Y - P[T[triangleIndex].p1].Y
z2 = P[T[triangleIndex].p3].Z - P[T[triangleIndex].p1].Z

P[0].X = y1 * z2 - y2 * z1
P[0].Y = x2 * z1 - x1 * z2
P[0].Z = x1 * y2 - x2 * y1
End Function

Function CalculateDotProduct:Float()
Return(0 * P(0).X + 0 * P(0).Y + (pointOfView * P(0).Z))
End Function

Function RotateCubeX(angle:Float)
Local NewY:Float, NewZ:Float,loop:Int
For loop = 1 To 8
NewY = P[loop].Y * Cos(angle) - P[loop].Z * Sin(angle)
NewZ = P[loop].Y * Sin(angle) + P[loop].Z * Cos(angle)
P[loop].Y = NewY
P[loop].Z = NewZ
Next
End Function

Function RotateCubeZ(angle:Float)
Local newX:Float,newY:Float,loop:Int
For loop = 1 To 8
NewX = P[loop].X * Cos(angle) - P[loop].Y * Sin(angle)
NewY = P[loop].X * Sin(angle) + P[loop].Y * Cos(angle)
P[loop].X = NewX
P[loop].Y = NewY
Next
End Function

Function RotateCubeY(angle:Float)
Local loop:Int,NewX:Float, NewZ:Float
For loop = 1 To 8
NewX = P[loop].Z * Sin(angle) + P[loop].X * Cos(angle)
NewZ = P[loop].Z * Cos(angle) - P[loop].X * Sin(angle)
P[loop].X = NewX
P[loop].Z = NewZ
Next
End Function

Function DrawCube()
Local loop:Int, draw:Byte

If CULL_BACK_FACES = True Then draw = True

For loop = 1 To 12
If (draw = True And T[loop].dotProduct > 0.5) Or draw = False
DrawColouredLine(T(loop).p1,T(loop).p2)
DrawColouredLine(T(loop).p2,T(loop).p3)
DrawColouredLine(T(loop).p3,T(loop).p1)
End If
Next
End Function

Function Init(size:Float)
If CULL_BACK_FACES = False
pointOfView = 1000
Else
pointOfView = 5000
End If

P[1].x = -size; P[1].y = -size; P[1].z = -size
P[2].x = -size; P[2].y = size; P[2].z = -size
P[3].x = size; P[3].y = size; P[3].z = -size
P[4].x = size; P[4].y = -size; P[4].z = -size
P[5].x = -size; P[5].y = -size; P[5].z = size
P[6].x = -size; P[6].y = size; P[6].z = size
P[7].x = size; P[7].y = size; P[7].z = size
P[8].x = size; P[8].y = -size; P[8].z = size

T[1].p1 = 1; T[1].p2 = 4; T[1].p3 = 3
T[2].p1 = 1; T[2].p2 = 3; T[2].p3 = 2
T[3].p1 = 5; T[3].p2 = 1; T[3].p3 = 2
T[4].p1 = 5; T[4].p2 = 2; T[4].p3 = 6
T[5].p1 = 8; T[5].p2 = 5; T[5].p3 = 6
T[6].p1 = 8; T[6].p2 = 6; T[6].p3 = 7
T[7].p1 = 4; T[7].p2 = 8; T[7].p3 = 7
T[8].p1 = 4; T[8].p2 = 7; T[8].p3 = 3
T[9].p1 = 3; T[9].p2 = 7; T[9].p3 = 6
T[10].p1 = 3; T[10].p2 = 6; T[10].p3 = 2
T[11].p1 = 4; T[11].p2 = 1; T[11].p3 = 5
T[12].p1 = 4; T[12].p2 = 5; T[12].p3 = 8
End Function

Function DrawColouredLine(p1:Long,p2:Long,r:Byte =255,g:Byte = 255,b:Byte = 255)
Local x1:Float, y1:Float,x2:Float,y2:Float

If PERSPECTIVE_MODE = True
x1 = P[p1].X * pointOfView / (pointOfView + P[p1].Z) + Offset
y1 = P[p1].Y * pointOfView / (pointOfView + P[p1].Z) + Offset
x2 = P[p2].X * pointOfView / (pointOfView + P[p2].Z) + Offset
y2 = P[p2].Y * pointOfView / (pointOfView + P[p2].Z) + Offset
Else
x1 = P(p1).x + offset
y1 = P(p1).y + offset
x2 = P(p2).x + offset
y2 = P(p2).y + offset
End If
SetColor r,g,b
DrawLine x1,y1,x2,y2
SetColor 255,255,255
End Function
[/bbcode]

Just for anyone who's passing and might be interested, back fall culling is a bit 'meh', but overall, it looks nice! :D

Check code for controls.

Dabz