Ruotare un cubo in una DrawingArea: differenze tra le versioni
Vai alla navigazione
Vai alla ricerca
Nessun oggetto della modifica |
Nessun oggetto della modifica |
||
| Riga 172: | Riga 172: | ||
Dim az As Float = Rad(angleZ) | Dim az As Float = Rad(angleZ) | ||
=== Vertici 3D del cubo === | === Vertici 3D del cubo === | ||
Dim vertices As New Float[][8] | Dim vertices As New Float[][8] | ||
vertices[0] = [-size, -size, -size] | vertices[0] = [-size, -size, -size] | ||
Versione delle 20:32, 19 lug 2025
Rotazione di un cubo intorno al suo asse Y
Mostriamo di seguito un possibile codice per ruotare un cubo in 3D intorno 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 = "Cubo che ruota intorno al suo asse Y" .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
Rotazione di un cubo intorno ai suoi assi X, Y e Z
' ===Variabili per gli angoli di rotazione su X, Y e Z === Private angleX As Float Private angleY As Float Private angleZ As Float Public Sub Form_Open() With Me .Title = "Cubo che ruota intorno ai suoi assi X, Y e Z" .Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight) .Arrangement = Arrange.Fill End With Timer1.Delay = 16 ' ~60 FPS Timer1.Start End Public Sub Timer1_Timer() angleX += 1.2 ' Incrementa angolo di rotazione su X angleY += 2.0 ' Rotazione su Y angleZ += 0.8 ' Rotazione su Z DrawingArea1.Refresh ' Richiede ridisegno della scena End ' === Disegno del cubo rotante === Public Sub DrawingArea1_Draw() ' Centro della DrawingArea: 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 Dim d As Float = 5.0 ' Distanza della "camera"(l'osservatore) Dim ax As Float = Rad(angleX) Dim ay As Float = Rad(angleY) Dim az As Float = Rad(angleZ) === Vertici 3D del cubo === 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[] = vertices[i] ' Applica rotazione X → Y → Z: p = RotateX(p, ax) p = RotateY(p, ay) p = RotateZ(p, az) ' Proiezione 3D → 2D: projected[i] = Project3D(p, d, cx, cy) Next ' Impostazioni di disegno: Paint.LineWidth = 2 Paint.Brush = Paint.Color(Color.Black) ' === Disegna i 12 spigoli del cubo === ' Faccia frontale: DrawEdge(projected, 0, 1) DrawEdge(projected, 1, 2) DrawEdge(projected, 2, 3) DrawEdge(projected, 3, 0) ' Faccia posteriore: DrawEdge(projected, 4, 5) DrawEdge(projected, 5, 6) DrawEdge(projected, 6, 7) DrawEdge(projected, 7, 4) ' Spigoli che collegano fronte e retro: DrawEdge(projected, 0, 4) DrawEdge(projected, 1, 5) DrawEdge(projected, 2, 6) DrawEdge(projected, 3, 7) End ' === ROTAZIONE attorno all'asse X === Private Function RotateX(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] ' Ruota y e z nel piano YZ: Dim yr As Float = y * Cos(angle) - z * Sin(angle) Dim zr As Float = y * Sin(angle) + z * Cos(angle) Return [x, yr, zr] End ' === 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] ' Ruota x e z 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 ' === ROTAZIONE attorno all'asse Z === Private Function RotateZ(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] ' Ruota x e y nel piano XY: Dim xr As Float = x * Cos(angle) - y * Sin(angle) Dim yr As Float = x * Sin(angle) + y * Cos(angle) Return [xr, yr, z] End ' === 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] ' Calcola il fattore di profondità: Dim factor As Float = d / (z + d + 0.001) ' +0.001 evita divisione per zero ' Applica il fattore e centra sulla DrawingArea: Dim x2D As Float = x * factor Dim y2D As Float = y * factor Return New PointF(cx + x2D * 100, cy - y2D * 100) End ' === Disegna una linea tra due punti proiettati === Private Procedure DrawEdge(points As PointF[], i1 As Integer, i2 As Integer) Paint.MoveTo(points[i1].X, points[i1].Y) Paint.LineTo(points[i2].X, points[i2].Y) Paint.Stroke() End