Ruotare un cubo in una DrawingArea: differenze tra le versioni
Vai alla navigazione
Vai alla ricerca
Nessun oggetto della modifica |
Nessun oggetto della modifica |
||
| (3 versioni intermedie di uno stesso utente non sono mostrate) | |||
| Riga 1: | Riga 1: | ||
==Rotazione di un cubo intorno al suo asse Y== | ==Rotazione di un cubo intorno al suo asse Y== | ||
Mostriamo di seguito un possibile codice per ruotare un | Mostriamo di seguito un possibile codice per ruotare un Cubo in 3D intorno al suo asse Y in una ''DrawingArea''. | ||
<FONT Color=gray>' '' | |||
Nell'esempio che segue sarà possibile aumentare o diminuire la dimensione del disegno del Cubo, cliccando rispettivamente sui tasti "+" e "-" della tastiera. | |||
<FONT Color=gray>' ''Variabile per l’angolo di rotazione attorno all’asse Y:''</font> | |||
Private angleY As Float | Private angleY As Float | ||
<FONT Color=gray>' ''Fattore di zoom (valore più alto = oggetto più grande):''</font> | |||
Private Zoom As Float = 150 | |||
| Riga 111: | Riga 115: | ||
<FONT Color=gray>' ''Trasla al centro della DrawingArea e scala:''</font> | <FONT Color=gray>' ''Trasla al centro della DrawingArea e scala:''</font> | ||
Return New PointF(cx + x2D * | Return New PointF(cx + x2D * Zoom, cy - y2D * Zoom) | ||
End | End | ||
| Riga 122: | Riga 126: | ||
Paint.LineTo(points[i2].X, points[i2].Y) <FONT Color=gray>' ''Punto finale''</font> | Paint.LineTo(points[i2].X, points[i2].Y) <FONT Color=gray>' ''Punto finale''</font> | ||
Paint.Stroke() <FONT Color=gray>' ''Esegue il disegno della linea''</font> | Paint.Stroke() <FONT Color=gray>' ''Esegue il disegno della linea''</font> | ||
End | |||
Public Sub Form_KeyPress() <FONT Color=gray>' ''Gestione della tastiera per controllare lo zoom''</font> | |||
Select Case Key.Code | |||
Case Key["+"] | |||
Zoom = Min(Zoom + 25, 1000) | |||
Case Key["-"] | |||
Zoom = Max(Zoom - 25, 25) | |||
End Select | |||
DrawingArea1.Refresh | |||
End | End | ||
| Riga 127: | Riga 145: | ||
==Rotazione di un cubo intorno ai suoi assi X, Y e Z== | ==Rotazione di un cubo intorno ai suoi assi X, Y e Z== | ||
<FONT Color=gray>' '' | <FONT Color=gray>' ''Variabili per gli angoli di rotazione su X, Y e Z:''</font> | ||
Private angleX As Float | Private angleX As Float | ||
Private angleY As Float | Private angleY As Float | ||
Private angleZ As Float | Private angleZ As Float | ||
<FONT Color=gray>' ''Fattore di zoom (valore più alto = oggetto più grande):''</font> | |||
Private Zoom As Float = 150 | |||
| Riga 172: | Riga 192: | ||
Dim az As Float = Rad(angleZ) | Dim az As Float = Rad(angleZ) | ||
=== Vertici 3D del cubo === | <FONT Color=gray>' ''=== Vertici 3D del cubo ===''</font> | ||
Dim vertices As New Float[][8] | Dim vertices As New Float[][8] | ||
vertices[0] = [-size, -size, -size] | vertices[0] = [-size, -size, -size] | ||
| Riga 286: | Riga 306: | ||
Dim y2D As Float = y * factor | Dim y2D As Float = y * factor | ||
Return New PointF(cx + x2D * | Return New PointF(cx + x2D * Zoom, cy - y2D * Zoom) | ||
End | End | ||
<FONT Color=gray>' ''=== Disegna una linea tra due punti proiettati === | <FONT Color=gray>' ''=== Disegna una linea tra due punti proiettati ===''</font> | ||
Private Procedure DrawEdge(points As PointF[], i1 As Integer, i2 As Integer) | Private Procedure DrawEdge(points As PointF[], i1 As Integer, i2 As Integer) | ||
Paint.MoveTo(points[i1].X, points[i1].Y) | Paint.MoveTo(points[i1].X, points[i1].Y) | ||
Paint.LineTo(points[i2].X, points[i2].Y) | Paint.LineTo(points[i2].X, points[i2].Y) | ||
Paint.Stroke() | Paint.Stroke() | ||
End | |||
Public Sub Form_KeyPress() <FONT Color=gray>' ''Gestione della tastiera per controllare lo zoom''</font> | |||
Select Case Key.Code | |||
Case Key["+"] | |||
Zoom = Min(Zoom + 25, 1000) | |||
Case Key["-"] | |||
Zoom = Max(Zoom - 25, 25) | |||
End Select | |||
DrawingArea1.Refresh | |||
End | End | ||
Versione attuale delle 14:37, 21 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.
Nell'esempio che segue sarà possibile aumentare o diminuire la dimensione del disegno del Cubo, cliccando rispettivamente sui tasti "+" e "-" della tastiera.
' Variabile per l’angolo di rotazione attorno all’asse Y:
Private angleY As Float
' Fattore di zoom (valore più alto = oggetto più grande):
Private Zoom As Float = 150
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 * Zoom, cy - y2D * Zoom)
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
Public Sub Form_KeyPress() ' Gestione della tastiera per controllare lo zoom
Select Case Key.Code
Case Key["+"]
Zoom = Min(Zoom + 25, 1000)
Case Key["-"]
Zoom = Max(Zoom - 25, 25)
End Select
DrawingArea1.Refresh
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
' Fattore di zoom (valore più alto = oggetto più grande):
Private Zoom As Float = 150
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 * Zoom, cy - y2D * Zoom)
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
Public Sub Form_KeyPress() ' Gestione della tastiera per controllare lo zoom
Select Case Key.Code
Case Key["+"]
Zoom = Min(Zoom + 25, 1000)
Case Key["-"]
Zoom = Max(Zoom - 25, 25)
End Select
DrawingArea1.Refresh
End