Cube 3D + inclinaison

Rykudos - 4 oct. 2014 à 16:04
 Rykudos - 13 oct. 2014 à 18:19
Bonjour,
je développe en vb.net une application qui permet de déplacer une forme 3D (dans un 1er temps un cube) sur les axes X Y, effectuer une rotation, effectuer une inclinaison.
mon problème et que lorsque que j'incline ma forme vers le haut ça position en Y diminue et lorsque j'incline vers le bas ça position en Y augmente.



Private Sub rotationinclinaison()
If CheckBox1.Checked = True Then 'selection de la forme (carré/cube)

'position point d'origine de la forme
Dim X As Integer = Label2.Text
Dim Y As Integer = Label4.Text

Dim ray As Integer = TextBox1.Text 'rayon

'calcule des angles des 4 point de la base
Dim phi = Label8.Text 'interval rotation
Dim phi1 = Label8.Text + 1.6
Dim phi2 = Label8.Text + 3.2
Dim phi3 = Label8.Text + 4.7

'calcue de la position X et Y des 4 point de la base
Dim cs = (Math.Cos(phi))
Dim sn = (Math.Sin(-phi))
Dim cs1 = (Math.Cos(phi1))
Dim sn1 = (Math.Sin(-phi1))
Dim cs2 = (Math.Cos(phi2))
Dim sn2 = (Math.Sin(-phi2))
Dim cs3 = (Math.Cos(phi3))
Dim sn3 = (Math.Sin(-phi3))

Dim xpc = ray * cs
Dim ypc = ray * sn
Dim xpc1 = ray * cs1
Dim ypc1 = ray * sn1
Dim xpc2 = ray * cs2
Dim ypc2 = ray * sn2
Dim xpc3 = ray * cs3
Dim ypc3 = ray * sn3

Dim xp As Integer = xpc + X
Dim yp As Integer = ypc + Y
Dim xp1 As Integer = xpc1 + X
Dim yp1 As Integer = ypc1 + Y
Dim xp2 As Integer = xpc2 + X
Dim yp2 As Integer = ypc2 + Y
Dim xp3 As Integer = xpc3 + X
Dim yp3 As Integer = ypc3 + Y


If RadioButton2.Checked = True Then '(3D) transforme la base en cube

Dim ie = Label12.Text 'interval inclinaison
Dim rayE = (ray / 2) + ie 'Rayon ellipse
yp = yp * (rayE / ray)
yp1 = yp1 * (rayE / ray)
yp2 = yp2 * (rayE / ray)
yp3 = yp3 * (rayE / ray)

'image des point de la base pour former le cube
Dim ypp As Integer = yp - ray
Dim ypp1 As Integer = yp1 - ray
Dim ypp2 As Integer = yp2 - ray
Dim ypp3 As Integer = yp3 - ray

'dessine la partie supérieure du cube
Dim NewPoint1 As New Point(10, 10)
Dim NewGraphic1 As Graphics = PictureBox1.CreateGraphics()
NewGraphic1.DrawRectangle(Pens.Red, xp, ypp, (1), (1))
NewGraphic1.DrawRectangle(Pens.Red, xp1, ypp1, (1), (1))
NewGraphic1.DrawRectangle(Pens.Red, xp2, ypp2, (1), (1))
NewGraphic1.DrawRectangle(Pens.Red, xp3, ypp3, (1), (1))

NewGraphic1.DrawLine(Pens.Red, xp, yp, xp, ypp)
NewGraphic1.DrawLine(Pens.Red, xp1, yp1, xp1, ypp1)
NewGraphic1.DrawLine(Pens.Red, xp2, yp2, xp2, ypp2)
NewGraphic1.DrawLine(Pens.Red, xp3, yp3, xp3, ypp3)
NewGraphic1.DrawLine(Pens.Red, xp, ypp, xp1, ypp1)
NewGraphic1.DrawLine(Pens.Red, xp1, ypp1, xp2, ypp2)
NewGraphic1.DrawLine(Pens.Red, xp2, ypp2, xp3, ypp3)
NewGraphic1.DrawLine(Pens.Red, xp3, ypp3, xp, ypp)
NewGraphic1.Dispose()
End If


''''''''''''''
'dessine la base du cube
Dim NewPoint As New Point(10, 10)
Dim NewGraphic As Graphics = PictureBox1.CreateGraphics()

NewGraphic.DrawRectangle(Pens.Red, xp, yp, (1), (1))
NewGraphic.DrawRectangle(Pens.Red, xp1, yp1, (1), (1))
NewGraphic.DrawRectangle(Pens.Red, xp2, yp2, (1), (1))
NewGraphic.DrawRectangle(Pens.Red, xp3, yp3, (1), (1))
NewGraphic.DrawLine(Pens.Red, xp, yp, xp1, yp1)
NewGraphic.DrawLine(Pens.Red, xp1, yp1, xp2, yp2)
NewGraphic.DrawLine(Pens.Red, xp2, yp2, xp3, yp3)
NewGraphic.DrawLine(Pens.Red, xp3, yp3, xp, yp)
NewGraphic.Dispose()


End If

End Sub

5 réponses

Salut,

Il y a la possibilité de travailler avec les matrices. Avec ceci, il est très facile de déplacer des objets.
Un petit exemple d'un cube qui tourne sur lui même à tester dans un projet vierge:

Public Class Form1
'declaration d'un timer
Dim tmr As New Timers.Timer(10)
'angle
Dim angle As Single

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'abonnement événement elapsed
AddHandler tmr.Elapsed, AddressOf tmr_Elapsed
'démarrage du timer
tmr.Start()
End Sub

Private Sub tmr_Elapsed(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs)
'changement de l'angle de rotation
angle += 1
'déclenchement de l'événement paint
Me.InvokePaint(Me, New PaintEventArgs(Me.CreateGraphics, Me.Bounds))
End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
'effacement
e.Graphics.Clear(Color.White)

'translation du cube
e.Graphics.TranslateTransform(100, 100)

'changement de l'angle de rotation
e.Graphics.RotateTransform(angle)

'dessin du cube
e.Graphics.DrawRectangle(New Pen(Brushes.Blue), New Rectangle(0, 0, 50, 50))
e.Graphics.DrawRectangle(New Pen(Brushes.Magenta), New Rectangle(25, -25, 50, 50))
e.Graphics.DrawLine(New Pen(Brushes.Red), New Point(0, 0), New Point(25, -25))
e.Graphics.DrawLine(New Pen(Brushes.Yellow), New Point(50, 0), New Point(75, -25))
e.Graphics.DrawLine(New Pen(Brushes.Green), New Point(0, 50), New Point(25, 25))
e.Graphics.DrawLine(New Pen(Brushes.Cyan), New Point(50, 50), New Point(75, 25))
End Sub
End Class

Ici, j'ai utilisé l'objet Graphics mais il est fort possible d'utiliser la classe Drawing2D.Matrix qui fait le job de la même manière.

Dim MaMatrice As Drawing2D.Matrix

Bonne prog.
1
CGSI3 Messages postés 416 Date d'inscription vendredi 22 février 2008 Statut Membre Dernière intervention 7 janvier 2018 1
Modifié par CGSI3 le 4/10/2014 à 18:12
Bonjour Rycudos,

Difficile de trouver l'erreur de cette liste d'opération mathématique, je vais regarder vite fait si je trouve mais je ne promet rien.

Personnellement, tu va très vite saturer de cette manière des que tes formes vont atteindre 10 points ou + ,avec des faces carrés, triangulaires etc ...

Il te faut a mon avis définir tes objets sous formes "objet" et donc de class.

Par hypothèse je t'explique rapidement ce que serait cette classe que je nomme Objet3D

- elle comprend des coordonnés de base (ou point 3d) sur les 3 axes (x,y,z) bref les points

- elle donne selon
- L'échelle
- La translation
- La rotation
les coordonnés de chaque points. Ces différentes actions appliquées sur les coordonnées de départ pour les transcrire en 2D avec une matrice d'affichage . ( ou matrice de projection )

- elle comprend les arêtes (ou segments ) a dessiner ( dessine un segment du point 1 au point 4 ) etc
...

Bref un gros travail de réflexion sinon tu va très vite arriver a un gros tas de lignes inextricables ..

Voici une chose a étudier en parallèle si tu te lance sur cette voie
http://codes-sources.commentcamarche.net/source/53580-matrice-de-rotation-quaternion-et-3d

L'avantage des matrices est qu'elles intègrent dans ton calcul 3 types d'opérations pour l'affichage ( en 3D ):
- L'échelle
- La translation
- La rotation

Si tu as besoin d'aide pour comprendre, je peux détailler l'ensemble.

Bonne prog
CGSI3
--
0
merci pour ta réponse rapide, je vais regarder le lien que tu ma fourni
0
Salut CGSI3,

Désolé, je n'avais pas vu ta réponse.

A bientôt.
0
CGSI3 Messages postés 416 Date d'inscription vendredi 22 février 2008 Statut Membre Dernière intervention 7 janvier 2018 1
Modifié par CGSI3 le 4/10/2014 à 22:01
Bonsoir banana32

Merci pour ton complément
La solution ci dessous peut en effet également donner de bon résultats.
Elle est simple et efficace.

Bref Rykudos peux choisir l'outil le plus adapté a ce qu'il veut faire.

J'ajoute également une troisième solution qui s'approche du WPF
System.Windows.Media.Media3D
http://msdn.microsoft.com/en-us/library/system.windows.media.media3d.matrix3d(v=vs.110).aspx

Qui travaille avec les matrices ...
Mais je n'ai pas encore utilisé pour le moment.

Merci et Bonne soirée a vous deux.
0
merci a vous pour vos réponse je vais regarder ça de plus prés =)
0
résolu, un détail a corriger dans ma formule pour éviter le déplacement inopiné dans l'axe y, en tous cas merci pour votre aide =)
je pense refaire sous forme de matrice ça semble bien plus simple.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
CGSI3 Messages postés 416 Date d'inscription vendredi 22 février 2008 Statut Membre Dernière intervention 7 janvier 2018 1
Modifié par CGSI3 le 13/10/2014 à 02:16
Re

J'ai juste essayé de refaire un début de travail sur le sujet en reprenant System.Windows.Media.Media3D qui est compris dans les frameworks récent.

Cette classe permet de modifier les coordonnées de ton point selon les 3 critères:
Translation, échelle, rotation.

J'ai juste un pb avec les matrices d'affichage sinon le reste semble fonctionner.

Comme je n'ai pas trop le temps en ce moment, je te laisse ce brouillon pour terminer les réglages et nettoyer ce qui doit l'être mais l'essentiel est la.

Tiens nous au courant.

Bonne prog CGSI3


' Ajouter référence  C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\PresentationCore.dll
Imports System.Windows.Media.Media3D
Public Class M3D
Private _Translate As System.Windows.Media.Media3D.Vector3D
Private _Rotate As System.Windows.Media.Media3D.Vector3D
Private _Scale As System.Windows.Media.Media3D.Vector3D
Private _Mat As System.Windows.Media.Media3D.Matrix3D

' _Mat comprend déjà les 3 opérations de bases, pour obtenir une matrice final il faut la multiplier a une matrice de projection.
Public Camera As System.Windows.Media.Media3D.Matrix3D
Private Final As System.Windows.Media.Media3D.Matrix3D = Nothing

Public Sub New()
_Scale.X = 1 : _Scale.Y = 1 : _Scale.Z = 1

' essai d'une camera perso
Camera.M11 = 2.414213
Camera.M22 = 2.414213
Camera.M33 = 1
Camera.M34 = -1
Camera.OffsetZ = -0.2

' Sinon voici une fonction trouvé sur le net
'Camera = Matrix3D.Identity
Dim cam2 As New PerspectiveCamera
cam2.FieldOfView = 0.005
cam2.FarPlaneDistance = 10000
cam2.NearPlaneDistance = 0.01
'myViewport.Camera = cam

Camera = Projectioncam(cam2, 1)
Maj()
End Sub

Public Function OrthographicCamera(ByRef camera As OrthographicCamera, ByRef aspectRatio As Double) As Matrix3D
' This math is identical to what you find documented for
' D3DXMatrixOrthoRH with the exception that in WPF only
' the camera's width is specified. Height is calculated
' from width and the aspect ratio.
Dim w As Double = camera.Width
Dim h As Double = w / aspectRatio
Dim zn As Double = camera.NearPlaneDistance
Dim zf As Double = camera.FarPlaneDistance
Dim m33 As Double = 1 / (zn - zf)
Dim m43 As Double = zn * m33
Return New Matrix3D(
2 / w, 0, 0, 0,
0, 2 / h, 0, 0,
0, 0, m33, 0,
0, 0, m43, 1)
End Function

Public Function Projectioncam(ByRef camera As PerspectiveCamera, ByRef aspectRatio As Double) As Matrix3D
' This math is identical to what you find documented for
' D3DXMatrixPerspectiveFovRH with the exception that in
' WPF the camera's horizontal rather the vertical
' field-of-view is specified.
Dim hFoV As Double = camera.FieldOfView
Dim zn As Double = camera.NearPlaneDistance
Dim zf As Double = camera.FarPlaneDistance
Dim xScale As Double = 1 / Math.Tan(hFoV / 2)
Dim yScale As Double = aspectRatio * xScale
Dim m33 As Double = (zf / (zn - zf))
'If zf>Double.= (zf == double.PositiveInfinity) ? -1 :
Dim m43 As Double = zn * m33
Return New Matrix3D(
xScale, 0, 0, 0,
0, yScale, 0, 0,
0, 0, m33, -1,
0, 0, m43, 0)
End Function


#Region "############## Property #################"

Public ReadOnly Property Matrix As System.Windows.Media.Media3D.Matrix3D
Get
Return _Mat
End Get
End Property

''' <summary>
''' Translation
''' </summary>
Public Property Translate() As System.Windows.Media.Media3D.Vector3D
Get
Return _Translate
End Get
Set(ByVal value As System.Windows.Media.Media3D.Vector3D)
_Translate = value
Maj()
End Set
End Property

''' <summary>
''' Rotation
''' </summary>
Public Property Rotate() As System.Windows.Media.Media3D.Vector3D
Get
Return _Rotate
End Get
Set(ByVal value As System.Windows.Media.Media3D.Vector3D)
_Rotate = value
Maj()
End Set
End Property

''' <summary>
''' Scale
''' </summary>
Public Property Scale() As System.Windows.Media.Media3D.Vector3D
Get
Return _Scale
End Get
Set(ByVal value As System.Windows.Media.Media3D.Vector3D)
_Scale = value
Maj()
End Set
End Property

''' <summary>
''' Renvoi la Matrice en Single(0..3,0..3)
''' </summary>
Public ReadOnly Property MatrixSingle() As Single(,)
Get
Dim M As Single(,)
ReDim M(3, 3)
M(0, 0) = _Mat.M11
M(0, 1) = _Mat.M12
M(0, 2) = _Mat.M13
M(0, 3) = _Mat.M14
M(1, 0) = _Mat.M21
M(1, 1) = _Mat.M22
M(1, 2) = _Mat.M23
M(1, 3) = _Mat.M24
M(2, 0) = _Mat.M31
M(2, 1) = _Mat.M32
M(2, 2) = _Mat.M33
M(2, 3) = _Mat.M34
M(3, 0) = _Mat.OffsetX
M(3, 1) = _Mat.OffsetY
M(3, 2) = _Mat.OffsetZ
M(3, 3) = _Mat.M44
Return M
End Get
End Property

#End Region

' Nouvelles coordonnées du point sans appliquer de Matrice d'Affichage en Perspective
Public Function Projection(ByRef P As System.Windows.Media.Media3D.Point3D) As System.Windows.Media.Media3D.Point3D
Return _Mat.Transform(P)
End Function

' Nouvelles coordonnées du point après avoir appliqué une Matrice d'Affichage en Perspective
Public Function Affichage(ByRef P As List(Of System.Windows.Media.Media3D.Point3D)) As List(Of System.Drawing.PointF)
Affichage = New List(Of System.Drawing.PointF)
For Each Pt In P
Dim retour As System.Windows.Media.Media3D.Point3D
retour = Final.Transform(Pt)
' applique ce code au dessous si ca ne fonctionne pas au dessus en jouant avec retour.z pour obtenir une perspective si tu veux faire simple
'retour.X = retour.X + 200
'retour.Y = retour.Y + 200
Affichage.Add(New System.Drawing.PointF(retour.X, retour.Y))
Next
End Function

Private Sub Maj()
Dim Matr As System.Windows.Media.Media3D.Matrix3D
Matr = CalculateRotationMatrix(Rotate.X, Rotate.Y, Rotate.Z)
' Pour retrouver les différents angles appliqués mais ca ne marche pas bien.
'Dim rotationX As Double = Vector3D.AngleBetween(New Vector3D(1, 0, 0), Matr.Transform(New Vector3D(1, 0, 0)))
'Dim rotationY As Double = Vector3D.AngleBetween(New Vector3D(0, 1, 0), Matr.Transform(New Vector3D(0, 1, 0)))
'Dim rotationZ As Double = Vector3D.AngleBetween(New Vector3D(0, 0, 1), Matr.Transform(New Vector3D(0, 0, 1)))
Matr.Translate(Translate)
Matr.Scale(Scale)
_Mat = Matr
Final = System.Windows.Media.Media3D.Matrix3D.Multiply(_Mat, Camera)
End Sub

Private Function CalculateRotationMatrix(ByRef x As Double, ByRef y As Double, ByRef z As Double) As Matrix3D
Dim Matrix As New Matrix3D
Matrix.Rotate(New Quaternion(New Vector3D(1, 0, 0), x))
Matrix.Rotate(New Quaternion(New Vector3D(0, 1, 0) * Matrix, y))
Matrix.Rotate(New Quaternion(New Vector3D(0, 0, 1) * Matrix, z))
Return Matrix
End Function

End Class


--
0
bonjour et merci pour ton exemple je vais y regarder
0
Rejoignez-nous