Ruotare un cubo in una DrawingArea: differenze tra le versioni

Da Gambas-it.org - Wikipedia.
Vai alla navigazione Vai alla ricerca
Nessun oggetto della modifica
Nessun oggetto della modifica
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 cubo in 3D attorno al suo asse Y in una ''DrawingArea''.
Mostriamo di seguito un possibile codice per ruotare un cubo in 3D intorno al suo asse Y in una ''DrawingArea''.
  <FONT Color=gray>' ''=== Variabile per l’angolo di rotazione attorno all’asse Y ===''</font>
  <FONT Color=gray>' ''=== Variabile per l’angolo di rotazione attorno all’asse Y ===''</font>
  Private angleY As Float
  Private angleY As Float
Riga 8: Riga 8:
   
   
   With Me
   With Me
     .Title = "Sfera che ruota in senso antiorario"
     .Title = "Cubo che ruota intorno al suo asse Y"
     .Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight)
     .Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight)
     .Arrangement = Arrange.Fill
     .Arrangement = Arrange.Fill
Riga 122: Riga 122:
   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
==Rotazione di un cubo intorno ai suoi assi X, Y e Z==
<FONT Color=gray>' ''===Variabili per gli angoli di rotazione su X, Y e Z ===''</font>
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  <FONT Color=gray>' ''~60 FPS''</font>
  Timer1.Start
End
Public Sub Timer1_Timer()
 
  angleX += 1.2          <FONT Color=gray>' ''Incrementa angolo di rotazione su X''</font>
  angleY += 2.0          <FONT Color=gray>' ''Rotazione su Y''</font>
  angleZ += 0.8          <FONT Color=gray>' ''Rotazione su Z''</font>
  DrawingArea1.Refresh    <FONT Color=gray>' ''Richiede ridisegno della scena''</font>
End
<FONT Color=gray>' ''=== Disegno del cubo rotante ===''</font>
Public Sub DrawingArea1_Draw()
<FONT Color=gray>' ''Centro della DrawingArea:''</font>
  Dim cx As Float = DrawingArea1.Width / 2
  Dim cy As Float = DrawingArea1.Height / 2
<FONT Color=gray>' ''Parametri del cubo:''</font>
  Dim size As Float = 1.0          <FONT Color=gray>' ''Metà lato''</font>
  Dim d As Float = 5.0              <FONT Color=gray>' ''Distanza della "camera"(l'osservatore)''</font>
  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]
<FONT Color=gray>' ''=== Ruota e proietta ogni vertice ===''</font>
  Dim projected As New PointF[8]
  For i As Integer = 0 To 7
    Dim p As Float[] = vertices[i]
<FONT Color=gray>' ''Applica rotazione X → Y → Z:''</font>
    p = RotateX(p, ax)
    p = RotateY(p, ay)
    p = RotateZ(p, az)
<FONT Color=gray>' ''Proiezione 3D → 2D:''</font>
    projected[i] = Project3D(p, d, cx, cy)
  Next
<FONT Color=gray>' ''Impostazioni di disegno:''</font>
  Paint.LineWidth = 2
  Paint.Brush = Paint.Color(Color.Black)
<FONT Color=gray>' ''=== Disegna i 12 spigoli del cubo ===''</font>
<FONT Color=gray>' ''Faccia frontale:''</font>
  DrawEdge(projected, 0, 1)
  DrawEdge(projected, 1, 2)
  DrawEdge(projected, 2, 3)
  DrawEdge(projected, 3, 0)
<FONT Color=gray>' ''Faccia posteriore:''</font>
  DrawEdge(projected, 4, 5)
  DrawEdge(projected, 5, 6)
  DrawEdge(projected, 6, 7)
  DrawEdge(projected, 7, 4)
<FONT Color=gray>' ''Spigoli che collegano fronte e retro:''</font>
  DrawEdge(projected, 0, 4)
  DrawEdge(projected, 1, 5)
  DrawEdge(projected, 2, 6)
  DrawEdge(projected, 3, 7)
End
<FONT Color=gray>' ''=== ROTAZIONE attorno all'asse X ===''</font>
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]
<FONT Color=gray>' ''Ruota y e z nel piano YZ:''</font>
  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
<FONT Color=gray>' ''=== ROTAZIONE attorno all'asse Y ===''</font>
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]
<FONT Color=gray>' ''Ruota x e z nel piano XZ:''</font>
  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
<FONT Color=gray>' ''=== ROTAZIONE attorno all'asse Z ===''</font>
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]
<FONT Color=gray>' ''Ruota x e y nel piano XY:''</font>
  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
<FONT Color=gray>' ''=== PROIEZIONE prospettica 3D → 2D ===''</font>
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]
<FONT Color=gray>' ''Calcola il fattore di profondità:''</font>
  Dim factor As Float = d / (z + d + 0.001)  <FONT Color=gray>' ''+0.001 evita divisione per zero''</font>
<FONT Color=gray>' ''Applica il fattore e centra sulla DrawingArea:''</font>
  Dim x2D As Float = x * factor
  Dim y2D As Float = y * factor
  Return New PointF(cx + x2D * 100, cy - y2D * 100)
End
<FONT Color=gray>' ''=== Disegna una linea tra due punti proiettati ===
Private Procedure DrawEdge(points As PointF[], i1 As Integer, i2 As Integer)''</font>
  Paint.MoveTo(points[i1].X, points[i1].Y)
  Paint.LineTo(points[i2].X, points[i2].Y)
  Paint.Stroke()
   
   
  End
  End

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