2D 3D Cube thingy....

Started by Dabz, February 08, 2021, 11:19:42

Previous topic - Next topic

Dabz


Framework BRL.D3D7Max2D

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


Little thing I made, draws a 3D cube in 2D and can be rotated etc etc Learnt a lot doing it, but could never get backface culling to work properly, when you rotate it you wil notice the clipping... Anyway, someone may find it interesting.

Dabz
Intel Core i5 6400 2.7GHz, NVIDIA GeForce GTX 1070 (8GB), 16Gig DDR4 RAM, 256GB SSD, 1TB HDD, Windows 10 64bit

iWasAdam

2 ways to do backface culling:
1. simple way is to use triangle rotation order. if the rotation is one direction it is facing, if it is the other way then it's hidden - you've got to make sure all your triangles are created with a single direction though...
2. normal calculation. if the normal is facing towards you - draw the triangle

I'll leave it up to others to get the code for these... But that's this way to do it ;)

Dabz

#2
WELL WHY DIDNT YOU TELL ME THAT TEN YEARS[plus] AGO!!!! \o/ OHHHHHHHHHHH MYYYYYYYYYYYYYYYYY GODDDDDDDDDDDDDDDDDDDDDD!!!!

;) hehehe

Dabz
Intel Core i5 6400 2.7GHz, NVIDIA GeForce GTX 1070 (8GB), 16Gig DDR4 RAM, 256GB SSD, 1TB HDD, Windows 10 64bit