Ruotare un cubo in una DrawingArea

Da Gambas-it.org - Wikipedia.
Versione del 19 lug 2025 alle 20:18 di Vuott (discussione | contributi) (Creata pagina con "Mostriamo di seguito un possibile codice per ruotare un cubo in 3D attorno al suo asse Y in una ''DrawingArea''. <FONT Color=gray>' ''=== Variabile per l’angolo di rotazion...")
(diff) ← Versione meno recente | Versione attuale (diff) | Versione più recente → (diff)
Vai alla navigazione Vai alla ricerca

Mostriamo di seguito un possibile codice per ruotare un cubo in 3D attorno al suo asse Y in una DrawingArea.

' === Variabile per l’angolo di rotazione attorno all’asse Y ===
Private angleY As Float


Public Sub Form_Open()

 With Me
   .Title = "Sfera che ruota in senso antiorario"
   .Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight)
   .Arrangement = Arrange.Fill
 End With

 Timer1.Delay = 16   ' ~60 FPS
 Timer1.Start

End


Public Sub Timer1_Timer()

 angleY += 2            ' Incrementa la rotazione Y (in gradi)
 DrawingArea1.Refresh    ' Richiede il ridisegno della scena

End


Public Sub DrawingArea1_Draw()

' === Centro dello schermo ===
 Dim cx As Float = DrawingArea1.Width / 2
 Dim cy As Float = DrawingArea1.Height / 2

' === Parametri del cubo ===
 Dim size As Float = 1.0         ' Metà lato del cubo (il cubo sarà 2×size)
 Dim d As Float = 5.0            ' Distanza simulata della "camera" (l'osservatore)
 Dim ay As Float = Rad(angleY)   ' Angolo Y convertito in radianti

' === Definizione dei vertici 3D del cubo ===
 ' Ordine: da 0 a 7 (8 vertici di un cubo centrato sull'origine):
 Dim vertices As New Float[][8]
 vertices[0] = [-size, -size, -size]
 vertices[1] = [ size, -size, -size]
 vertices[2] = [ size,  size, -size]
 vertices[3] = [-size,  size, -size]
 vertices[4] = [-size, -size,  size]
 vertices[5] = [ size, -size,  size]
 vertices[6] = [ size,  size,  size]
 vertices[7] = [-size,  size,  size]

' === Ruota e proietta ogni vertice ===
 Dim projected As New PointF[8]
 For i As Integer = 0 To 7
   Dim p As Float[] = RotateY(vertices[i], ay)    ' Rotazione Y
   projected[i] = Project3D(p, d, cx, cy)         ' Proiezione 3D → 2D
 Next

' === Impostazioni per disegno linee ===
 Paint.LineWidth = 2
 Paint.Brush = Paint.Color(Color.Black)

' === Disegna i lati del cubo ===

' Faccia frontale (quella visibile quando Z è negativo):
 DrawEdge(projected, 0, 1)
 DrawEdge(projected, 1, 2)
 DrawEdge(projected, 2, 3)
 DrawEdge(projected, 3, 0)

' Faccia posteriore (Z positivo):
 DrawEdge(projected, 4, 5)
 DrawEdge(projected, 5, 6)
 DrawEdge(projected, 6, 7)
 DrawEdge(projected, 7, 4)

' Collegamenti tra vertici corrispondenti frontali/posteriori:
 DrawEdge(projected, 0, 4)
 DrawEdge(projected, 1, 5)
 DrawEdge(projected, 2, 6)
 DrawEdge(projected, 3, 7)

End

' === Funzione: rotazione attorno all’asse Y ===
Private Function RotateY(v As Float[], angle As Float) As Float[]

 Dim x As Float = v[0]
 Dim y As Float = v[1]
 Dim z As Float = v[2]

' Formula di rotazione attorno all'asse Y:
' ruota il punto nel piano XZ:
 Dim xr As Float = x * Cos(angle) + z * Sin(angle)
 Dim zr As Float = -x * Sin(angle) + z * Cos(angle)

 Return [xr, y, zr]

End

' === Funzione: proiezione prospettica 3D → 2D ===
Private Function Project3D(v As Float[], d As Float, cx As Float, cy As Float) As PointF
 Dim x As Float = v[0]
 Dim y As Float = v[1]
 Dim z As Float = v[2]

' Fattore prospettico: maggiore Z → più vicino alla "camera" (l'osservatore):
 Dim factor As Float = d / (z + d + 0.001)  ' evita divisione per 0
 Dim x2D As Float = x * factor
 Dim y2D As Float = y * factor

' Trasla al centro della DrawingArea e scala:
 Return New PointF(cx + x2D * 100, cy - y2D * 100)

End


' === Procedura che disegna uno spigolo tra due vertici proiettati ===
Private Procedure DrawEdge(points As PointF[], i1 As Integer, i2 As Integer)

 Paint.MoveTo(points[i1].X, points[i1].Y)   ' Punto iniziale
 Paint.LineTo(points[i2].X, points[i2].Y)   ' Punto finale
 Paint.Stroke()                             ' Esegue il disegno della linea

End