Weil ich selbst ein grosser Fan von Rubikwürfeln (auch gern Zauberwürfel genannt) bin, habe ich einen solchen in Blitz umgesetzt.
Da mir die normale Ausführung mit nur 3x3x3 Feldern zu langweilig wurde, kann man auch andere Grössen wählen.
BlitzBasic: [AUSKLAPPEN] [EINKLAPPEN] Graphics3D 800, 600, 0, 2 SetBuffer BackBuffer()
Const DIMENSION = 3 Const GRIDSIZE# = 5
Const WHITE = 0 Const BLUE = 1 Const ORANGE = 2 Const GREEN = 3 Const RED = 4 Const YELLOW = 5
Dim ColorTable( 5, 2 ) Dim RubicsCube.TCube( DIMENSION - 1, DIMENSION - 1, DIMENSION - 1 ) Dim TempCube.TCube( DIMENSION - 1, DIMENSION - 1, DIMENSION - 1 )
Global RubicMesh
Type TCube Field X Field Y Field Z Field Surface Field Side[ 5 ] End Type
Cam = CreateCamera() PositionEntity Cam, DIMENSION/2*GRIDSIZE, DIMENSION/2*GRIDSIZE, -DIMENSION*GRIDSIZE
CameraRange Cam, 0.1, 1000
Light = CreateLight() PositionEntity Light, 50, 0, 0
AmbientLight 255, 255, 255
Timer = CreateTimer( 60 )
MouseXSpeed() MouseYSpeed()
InitColorTable() InitCube()
Global AxisTurn[ 2 ]
While Not KeyHit( 1 ) RenderWorld TurnEntity Cam, MouseYSpeed(), -MouseXSpeed(), 0 MoveMouse 400, 300 MoveEntity Cam, ( KeyDown( 205 ) - KeyDown( 203 ) )*0.5, KeyDown( 57 )*0.1, ( KeyDown( 200 ) - KeyDown( 208 ) )*0.5 If Not Turning Then Axis = Rand( 0, 2 ) Slice = Rand( 0, DIMENSION - 1 ) AxisTurn[ 0 ] = -1 AxisTurn[ 1 ] = -1 AxisTurn[ 2 ] = -1 AxisTurn[ Axis ] = Slice Turning = True Else TurnSlice( AxisTurn[ 0 ], AxisTurn[ 1 ], AxisTurn[ 2 ], 1 ) Angle = Angle + 1 If Angle = 90 Then Angle = 0 Turning = False SwapSlice( AxisTurn[ 0 ], AxisTurn[ 1 ], AxisTurn[ 2 ], 1 ) EndIf EndIf Text 0, 0, TrisRendered() Flip 0 WaitTimer Timer Wend
ShowPointer()
End
Function InitColorTable() ColorTable( WHITE, 0 ) = 255 ColorTable( WHITE, 1 ) = 255 ColorTable( WHITE, 2 ) = 255 ColorTable( BLUE, 0 ) = 0 ColorTable( BLUE, 1 ) = 0 ColorTable( BLUE, 2 ) = 255 ColorTable( ORANGE, 0 ) = 225 ColorTable( ORANGE, 1 ) = 100 ColorTable( ORANGE, 2 ) = 6 ColorTable( GREEN, 0 ) = 0 ColorTable( GREEN, 1 ) = 255 ColorTable( GREEN, 2 ) = 0 ColorTable( RED, 0 ) = 225 ColorTable( RED, 1 ) = 0 ColorTable( RED, 2 ) = 0 ColorTable( YELLOW, 0 ) = 255 ColorTable( YELLOW, 1 ) = 255 ColorTable( YELLOW, 2 ) = 0 End Function
Function InitCube() RubicMesh = CreateMesh() EntityFX RubicMesh, 2 RubicSurface = CreateSurface( RubicMesh ) For X = 0 To DIMENSION - 1 For Y = 0 To DIMENSION - 1 For Z = 0 To DIMENSION - 1 If CountVertices( RubicSurface ) + 24 >= 65536 Then RubicSurface = CreateSurface( RubicMesh ) Cube.TCube = New TCube Cube\X# = X*GRIDSIZE# Cube\Y# = Y*GRIDSIZE# Cube\Z# = Z*GRIDSIZE# Cube\Surface = RubicSurface Cube\Side[ 0 ] = AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddTriangle( RubicSurface, Cube\Side[ 0 ] + 0, Cube\Side[ 0 ] + 2, Cube\Side[ 0 ] + 1 ) AddTriangle( RubicSurface, Cube\Side[ 0 ] + 0, Cube\Side[ 0 ] + 3, Cube\Side[ 0 ] + 2 ) Cube\Side[ 1 ] = AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddTriangle( RubicSurface, Cube\Side[ 1 ] + 0, Cube\Side[ 1 ] + 2, Cube\Side[ 1 ] + 1 ) AddTriangle( RubicSurface, Cube\Side[ 1 ] + 0, Cube\Side[ 1 ] + 3, Cube\Side[ 1 ] + 2 ) Cube\Side[ 2 ] = AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddTriangle( RubicSurface, Cube\Side[ 2 ] + 0, Cube\Side[ 2 ] + 2, Cube\Side[ 2 ] + 1 ) AddTriangle( RubicSurface, Cube\Side[ 2 ] + 0, Cube\Side[ 2 ] + 3, Cube\Side[ 2 ] + 2 ) Cube\Side[ 3 ] = AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddTriangle( RubicSurface, Cube\Side[ 3 ] + 0, Cube\Side[ 3 ] + 2, Cube\Side[ 3 ] + 1 ) AddTriangle( RubicSurface, Cube\Side[ 3 ] + 0, Cube\Side[ 3 ] + 3, Cube\Side[ 3 ] + 2 ) Cube\Side[ 4 ] = AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 1 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddTriangle( RubicSurface, Cube\Side[ 4 ] + 0, Cube\Side[ 4 ] + 2, Cube\Side[ 4 ] + 1 ) AddTriangle( RubicSurface, Cube\Side[ 4 ] + 0, Cube\Side[ 4 ] + 3, Cube\Side[ 4 ] + 2 ) Cube\Side[ 5 ] = AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 1 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 1 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddVertex( RubicSurface, ( X + 0 )*GRIDSIZE#, ( Y + 0 )*GRIDSIZE#, ( Z + 0 )*GRIDSIZE# ) AddTriangle( RubicSurface, Cube\Side[ 5 ] + 0, Cube\Side[ 5 ] + 2, Cube\Side[ 5 ] + 1 ) AddTriangle( RubicSurface, Cube\Side[ 5 ] + 0, Cube\Side[ 5 ] + 3, Cube\Side[ 5 ] + 2 ) RubicsCube( X, Y, Z ) = Cube For i = 0 To 23 VertexColor RubicSurface, Cube\Side[ 0 ] + i, 100, 100, 100 Next If X = 0 Then For i = 0 To 3 VertexColor RubicSurface, Cube\Side[ 4 ] + i, ColorTable( 4, 0 ), ColorTable( 4, 1 ), ColorTable( 4, 2 ) Next EndIf If Y = 0 Then For i = 0 To 3 VertexColor RubicSurface, Cube\Side[ 5 ] + i, ColorTable( 5, 0 ), ColorTable( 5, 1 ), ColorTable( 5, 2 ) Next EndIf If Z = 0 Then For i = 0 To 3 VertexColor RubicSurface, Cube\Side[ 1 ] + i, ColorTable( 1, 0 ), ColorTable( 1, 1 ), ColorTable( 1, 2 ) Next EndIf If X = DIMENSION - 1 Then For i = 0 To 3 VertexColor RubicSurface, Cube\Side[ 2 ] + i, ColorTable( 2, 0 ), ColorTable( 2, 1 ), ColorTable( 2, 2 ) Next EndIf If Y = DIMENSION - 1 Then For i = 0 To 3 VertexColor RubicSurface, Cube\Side[ 0 ] + i, ColorTable( 0, 0 ), ColorTable( 0, 1 ), ColorTable( 0, 2 ) Next EndIf If Z = DIMENSION - 1 Then For i = 0 To 3 VertexColor RubicSurface, Cube\Side[ 3 ] + i, ColorTable( 3, 0 ), ColorTable( 3, 1 ), ColorTable( 3, 2 ) Next EndIf Next Next Next UpdateNormalsEx RubicSurface End Function
Function TurnSlice( X, Y, Z, Angle# ) Local XStart, YStart, ZStart, XEnd = DIMENSION - 1, YEnd = DIMENSION - 1, ZEnd = DIMENSION - 1 If X >= 0 Then XStart = X XEnd = X ElseIf Y >= 0 Then YStart = Y YEnd = Y ElseIf Z >= 0 Then ZStart = Z ZEnd = Z EndIf For GridX = XStart To XEnd For GridY = YStart To YEnd For GridZ = ZStart To ZEnd Additions = Additions + 1 CenterX# = CenterX# + ( RubicsCube( GridX, GridY, GridZ )\X# + GRIDSIZE#/2 ) CenterY# = CenterY# + ( RubicsCube( GridX, GridY, GridZ )\Y# + GRIDSIZE#/2 ) CenterZ# = CenterZ# + ( RubicsCube( GridX, GridY, GridZ )\Z# + GRIDSIZE#/2 ) Next Next Next CenterX# = CenterX#/Additions CenterY# = CenterY#/Additions CenterZ# = CenterZ#/Additions Local SurfacesToUpdate[ 10 ] For GridX = XStart To XEnd For GridY = YStart To YEnd For GridZ = ZStart To ZEnd RubicSurface = RubicsCube( GridX, GridY, GridZ )\Surface For i = 0 To 10 If RubicSurface = SurfacesToUpdate[ i ] Then Exit If SurfacesToUpdate[ i ] = 0 Then SurfacesToUpdate[ i ] = RubicSurface Exit EndIf Next For i = 0 To 23 DiffX# = VertexX( RubicSurface, RubicsCube( GridX, GridY, GridZ )\Side[ 0 ] + i ) - CenterX# DiffY# = VertexY( RubicSurface, RubicsCube( GridX, GridY, GridZ )\Side[ 0 ] + i ) - CenterY# DiffZ# = VertexZ( RubicSurface, RubicsCube( GridX, GridY, GridZ )\Side[ 0 ] + i ) - CenterZ# If X >= 0 Then DiffX# = 0 ElseIf Y >= 0 Then DiffY# = 0 ElseIf Z >= 0 Then DiffZ# = 0 EndIf Radius# = Sqr( DiffX#*DiffX# + DiffY#*DiffY# + DiffZ#*DiffZ# ) If X >= 0 Then Angle2# = ATan2( DiffY#, DiffZ# ) NewX# = VertexX( RubicSurface, RubicsCube( GridX, GridY, GridZ )\Side[ 0 ] + i ) NewY# = Radius#*Sin( Angle2# - Angle# ) + CenterY# NewZ# = Radius#*Cos( Angle2# - Angle# ) + CenterZ# ElseIf Y >= 0 Then Angle2# = ATan2( DiffZ#, DiffX# ) NewX# = Radius#*Cos( Angle2# + Angle# ) + CenterX# NewY# = VertexY( RubicSurface, RubicsCube( GridX, GridY, GridZ )\Side[ 0 ] + i ) NewZ# = Radius#*Sin( Angle2# + Angle# ) + CenterZ# ElseIf Z >= 0 Then Angle2# = ATan2( DiffY#, DiffX# ) NewX# = Radius#*Cos( Angle2# + Angle# ) + CenterX# NewY# = Radius#*Sin( Angle2# + Angle# ) + CenterY# NewZ# = VertexZ( RubicSurface, RubicsCube( GridX, GridY, GridZ )\Side[ 0 ] + i ) EndIf VertexCoords RubicSurface, RubicsCube( GridX, GridY, GridZ )\Side[ 0 ] + i, NewX#, NewY#, NewZ# Next Next Next Next For i = 0 To 10 If SurfacesToUpdate[ i ] Then UpdateNormalsEx SurfacesToUpdate[ i ] Else Exit Next End Function
Function UpdateNormalsEx( Surface ) TriangleCount = CountTriangles( Surface ) For Triangle = 0 To TriangleCount - 1 V1 = TriangleVertex( Surface, Triangle, 0 ) V2 = TriangleVertex( Surface, Triangle, 1 ) V3 = TriangleVertex( Surface, Triangle, 2 ) VX1# = VertexX( Surface, V2 ) - VertexX( Surface, V1 ) VY1# = VertexY( Surface, V2 ) - VertexY( Surface, V1 ) VZ1# = VertexZ( Surface, V2 ) - VertexZ( Surface, V1 ) VX2# = VertexX( Surface, V3 ) - VertexX( Surface, V1 ) VY2# = VertexY( Surface, V3 ) - VertexY( Surface, V1 ) VZ2# = VertexZ( Surface, V3 ) - VertexZ( Surface, V1 ) VX3# = VY1*VZ2 - VZ1*VY2 VY3# = VZ1*VX2 - VX1*VZ2 VZ3# = VX1*VY2 - VY1*VX2 TFormNormal VX3, VY3, VZ3, 0, 0 VertexNormal Surface, V1, TFormedX(), TFormedY(), TFormedZ() VertexNormal Surface, V2, TFormedX(), TFormedY(), TFormedZ() VertexNormal Surface, V3, TFormedX(), TFormedY(), TFormedZ() Next End Function
Function SwapSlice( X, Y, Z, Times ) Local XStart, YStart, ZStart, XEnd = DIMENSION - 1, YEnd = DIMENSION - 1, ZEnd = DIMENSION - 1 If X >= 0 Then XStart = X XEnd = X ElseIf Y >= 0 Then YStart = Y YEnd = Y ElseIf Z >= 0 Then ZStart = Z ZEnd = Z EndIf For GridX = XStart To XEnd For GridY = YStart To YEnd For GridZ = ZStart To ZEnd Additions = Additions + 1 CenterX# = CenterX# + GridX CenterY# = CenterY# + GridY CenterZ# = CenterZ# + GridZ Next Next Next CenterX# = CenterX#/Additions CenterY# = CenterY#/Additions CenterZ# = CenterZ#/Additions For GridX = 0 To DIMENSION - 1 For GridY = 0 To DIMENSION - 1 For GridZ = 0 To DIMENSION - 1 TempCube( GridX, GridY, GridZ ) = RubicsCube( GridX, GridY, GridZ ) Next Next Next For GridX = XStart To XEnd For GridY = YStart To YEnd For GridZ = ZStart To ZEnd DiffX# = GridX - CenterX# DiffY# = GridY - CenterY# DiffZ# = GridZ - CenterZ# Radius# = Sqr( DiffX#*DiffX# + DiffY#*DiffY# + DiffZ#*DiffZ# ) If X >= 0 Then Angle2# = ATan2( DiffY#, DiffZ# ) NewX = GridX NewY = Radius#*Sin( Angle2# - Times*90 ) + CenterY# NewZ = Radius#*Cos( Angle2# - Times*90 ) + CenterZ# ElseIf Y >= 0 Then Angle2# = ATan2( DiffZ#, DiffX# ) NewX = Radius#*Cos( Angle2# + Times*90 ) + CenterX# NewY = GridY NewZ = Radius#*Sin( Angle2# + Times*90 ) + CenterZ# ElseIf Z >= 0 Then Angle2# = ATan2( DiffY#, DiffX# ) NewX = Radius#*Cos( Angle2# + Times*90 ) + CenterX# NewY = Radius#*Sin( Angle2# + Times*90 ) + CenterY# NewZ = GridZ EndIf TempCube( NewX, NewY, NewZ ) = RubicsCube( GridX, GridY, GridZ ) Next Next Next For GridX = 0 To DIMENSION - 1 For GridY = 0 To DIMENSION - 1 For GridZ = 0 To DIMENSION - 1 RubicsCube( GridX, GridY, GridZ ) = TempCube( GridX, GridY, GridZ ) RubicsCube( GridX, GridY, GridZ )\X# = GridX*GRIDSIZE# RubicsCube( GridX, GridY, GridZ )\Y# = GridY*GRIDSIZE# RubicsCube( GridX, GridY, GridZ )\Z# = GridZ*GRIDSIZE# Next Next Next End Function
Zur Erklärung:
Die Konstante DIMENSION legt die Anzahl Felder pro Seite fest, GRIDSIZE bestimmt, wie gross die Felder in 3D - Einheiten sind.
InitCube und InitColorTable bereiten den Würfel vor, TurnSlice dreht die Vertices einer Reihe um eine angegebene Anzahl Grad und SwapSlice dreht eine Reihe im Array, das den Rubikwürfel darstellt.
UpdateNormalsEx ist einfach noch eine simplere UpdateNormals - Funktion, die die Triangles einzeln betrachtet.
Würde man UpdateNormals benutzen, würde der Rubikwürfel unschön flackern, wenn sich eine Reihe dreht.
|