Ruotare un cubo in una DrawingArea
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