如何通过鼠标移动进行3D旋转 [英] How to go about 3D rotation by mouse move
问题描述
我一直试图解决这个问题好几个月(如果不是一年)。我似乎无法在屏幕上获得相对于3D模型的旋转方向。我可以计算轴方向(作为角度)但不能让鼠标方向绕模型运行(就像Sketchup这样的建模软件)。
I添加了似乎很差的代码,但我尝试了很多不同的方法和它变得如此复杂。所以我把它简化为简单的骨头,开始理解什么是真正控制什么。我想放弃,但我想我需要寻求帮助。
我尝试使用谷歌搜索,但似乎没有什么比较合适或我可以申请。
轮换代码来自使用VB.NET和GDI +旋转实体立方体| codeNtronix [ ^ ]
我尝试过:
I have been try to work this problem out for months (If not a year). I can't seem to get the direction of rotation relative the 3D model on screen. I can work out the axis directions (as angles) but can't get the mouse direction to orbit the model(Just like a modelling software like Sketchup).
I have added code which seems to be poor but I have tried so many different ways & it has got so complex. So I have stripped it down to simple bones to start understanding what is really controlling what. I feel like giving up but I think I need to ask for help.
I have tried googling but nothing seems to quite fit or I can apply to the application.
The rotation code was from Rotating Solid Cube Using VB.NET and GDI+ | codeNtronix[^]
What I have tried:
Dim Distance_Between As Integer = 0 'How much rotation
Distance_Between = Math.Sqrt(((e.X - m_PanStartPoint.X) ^ 2) + ((e.Y - m_PanStartPoint.Y) ^ 2))
Dim X_Angle_Diff As Integer = Angle_Axis_X - Angle_Mouse
Dim Y_Angle_Diff As Integer = (Angle_Axis_Y) - Angle_Mouse
If X_Angle_Diff <> 0 Then
X_Rotate = Orig_X_Rot - (X_Angle_Diff * (Distance_Between / 2000))
End If
If Y_Angle_Diff <> 0 Then
Y_Rotate = Orig_Y_Rot + (Y_Angle_Diff * (Distance_Between / 2000))
End If
对不清楚感到抱歉。
你说的旋转点没有说明但是它会是正确的(直到我可以锻炼相对于不同旋转点的偏移,即从绘制零点和鼠标旋转的距离)绘制零点。通过Matrix Translate定位绘图零点(此时也完成了刻度)。
Sorry for not being clear.
You are correct the rotation point is not stated but it will be (until I can workout the shift relative to the different rotation point i.e. distance from drawn zero point & mouse rotation) the drawing zero point. The drawing zero point is positioned by Matrix Translate (& Scale is done also at this time).
Dim translateMatrix1 As New Matrix
translateMatrix1.Scale(Scale_Path, Scale_Path, MatrixOrder.Append)
translateMatrix1.Translate(Offset_X_Path, Offset_Y_Path, MatrixOrder.Append)
Temp_Path.Transform(translateMatrix1)
我现在在Ralf Meier的帮助下: -
Where I am now after help from Ralf Meier:-
Dim Correct_Speed_Factor As Decimal = Scale_Path * 0.5 ' set speed of rotation relative to scale
Dim Angle_Mouse As Decimal = Math.Atan2(Orbit_Start.Y - e.Y, Orbit_Start.X - e.X) * 180 / Math.PI
If Angle_Mouse < 0 Then
Angle_Mouse = 360 + Angle_Mouse
End If
Dim Distance_Between As Decimal = 0 ' To account how much rotation
'Get distance of coord from mousedown to mouse postion
Distance_Between = Math.Sqrt(((e.X - Orbit_Start.X) ^ 2) + ((e.Y - Orbit_Start.Y) ^ 2))
'Get Positive differance between mouse & axis direction
Dim X_Angle_Diff As Decimal = Calc_Angle_dif(Y_Direction_Angle, Angle_Mouse) 'Y_Direction_Angle - Angle_Mouse
Dim Y_Angle_Diff As Decimal = Calc_Angle_dif(X_Direction_Angle, Angle_Mouse)
Dim Z_Angle_Diff As Decimal = (Calc_Angle_dif(X_Direction_Angle, Angle_Mouse) + Calc_Angle_dif(Y_Direction_Angle, Angle_Mouse)) / 2
X_Rotate = Orig_X_Rot - ((Distance_Between * ((X_Angle_Diff - 90) / 90)) / Correct_Speed_Factor)
Y_Rotate = Orig_Y_Rot - ((Distance_Between * ((Y_Angle_Diff - 90) / 90)) / Correct_Speed_Factor)
Z_Rotate = Orig_Z_Rot - ((Distance_Between * ((Z_Angle_Diff - 90) / 90)) / Correct_Speed_Factor)
'Then redraw
带功能
With function
Private Function Calc_Angle_dif(ByVal firstAngle As Single, ByVal secondAngle As Single) As Decimal
Dim difference As Decimal = secondAngle - firstAngle
Select Case difference
Case Is < -180
difference += 360
Case Is > 180
difference -= 360
End Select
If secondAngle = firstAngle Then
Return 0
Else
Return (Math.Abs(difference))
End If
End
End Function
这很有效但我似乎X&时的旋转锁定Y在同一架飞机上。另一个问题是一段时间(并非总是颠倒过来)滚动方向反转。
很奇怪&我不太确定是什么原因。欢迎任何帮助,因为我的数学变得非常紧张。
我想我可能找到了错误的原因。 3D旋转公式在X旋转中工作但Y& Z处于屏幕旋转状态。这是矩阵计算,对我的数学专家来说可能有点远。也许需要一些帮助找到原因。
This works quite well but I seem to a rotation lock when the X & Y are on the same plane. The other problem is some time(not always when upside down) the roll direction is reversed.
Weird & I am not quite sure what is the cause. Any help is welcome as my math are getting very much stretched.
I think I may of found the reason for the errors. the 3D rotation formula works in X rotation but Y & Z are in screen rotation. This is matrices calculation which maybe a bit to far for my math expertices. Maybe need some help finding the reason.
Public Function RotateX(ByVal angle As Integer) As Point3D
Dim rad As Double, cosa As Double, sina As Double, yn As Double, zn As Double
rad = angle * Math.PI / 180
cosa = Math.Cos(rad)
sina = Math.Sin(rad)
yn = Me.Y * cosa - Me.Z * sina
zn = Me.Y * sina + Me.Z * cosa
Return New Point3D(Me.X, yn, zn)
End Function
Public Function RotateY(ByVal angle As Integer) As Point3D
Dim rad As Double, cosa As Double, sina As Double, Xn As Double, Zn As Double
rad = angle * Math.PI / 180
cosa = Math.Cos(rad)
sina = Math.Sin(rad)
Zn = Me.Z * cosa - Me.X * sina
Xn = Me.Z * sina + Me.X * cosa
Return New Point3D(Xn, Me.Y, Zn)
End Function
Public Function RotateZ(ByVal angle As Integer) As Point3D
Dim rad As Double, cosa As Double, sina As Double, Xn As Double, Yn As Double
rad = angle * Math.PI / 180
cosa = Math.Cos(rad)
sina = Math.Sin(rad)
Xn = Me.X * cosa - Me.Y * sina
Yn = Me.X * sina + Me.Y * cosa
Return New Point3D(Xn, Yn, Me.Z)
End Function
使用来自Ralf Meier的解决方案2
这是我通过捕捉点更改旋转点时遇到的问题。
更新在Ralf Meier评论之后。
Using Solution 2 from Ralf Meier
Here is the problem I am having with changing rotation point by snap point.
Updated after Ralf Meier comments.
Imports System.Drawing.Graphics
Public Class Form2
'Inherits Control
Protected m_vertices(8) As Point3D
Protected m_faces(6, 4) As Integer
Protected m_colors(6) As Color
Protected m_brushes(6) As Brush
Dim Offset_X As Integer
Dim Offset_Y As Integer
Dim Scale As Integer = 100
Sub New()
' Enable double-buffering to eliminate flickering.
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
' Create the cube vertices.
m_vertices = New Point3D() {
New Point3D(-1, 1, -1),
New Point3D(1, 1, -1),
New Point3D(1, -1, -1),
New Point3D(-1, -1, -1),
New Point3D(-1, 1, 1),
New Point3D(1, 1, 1),
New Point3D(1, -1, 1),
New Point3D(-1, -1, 1)}
' Create an array representing the 6 faces of a cube. Each face is composed by indices to the vertex array
' above.
m_faces = New Integer(,) {{0, 1, 2, 3}, {1, 5, 6, 2}, {5, 4, 7, 6}, {4, 0, 3, 7}, {0, 4, 5, 1}, {3, 2, 6, 7}}
' Define the colors of each face.
m_colors = New Color() {Color.BlueViolet, Color.Cyan, Color.Green, Color.Yellow, Color.Violet, Color.LightSkyBlue}
' Create the brushes to draw each face. Brushes are used to draw filled polygons.
For i = 0 To 5
m_brushes(i) = New SolidBrush(m_colors(i))
Next
End Sub
Property xAngle As Integer
Get
Return my_xAngle
End Get
Set(value As Integer)
my_xAngle = (value + 360) Mod 360
Me.Invalidate()
End Set
End Property
Private my_xAngle As Integer
Property yAngle As Integer
Get
Return my_yAngle
End Get
Set(value As Integer)
my_yAngle = (value + 360) Mod 360
Me.Invalidate()
End Set
End Property
Private my_yAngle As Integer
Property zAngle As Integer
Get
Return my_zAngle
End Get
Set(value As Integer)
my_zAngle = (value + 360) Mod 360
Me.Invalidate()
End Set
End Property
Private my_zAngle As Integer
Dim Shift_X As Integer 'Shift in X Pivot point
Dim Shift_Y As Integer 'Shift in Y Pivot point
Dim Shift_Z As Integer 'Shift in Z Pivot point
' Used for Panning
Dim Orig_X_Shift As Integer
Dim Orig_Y_Shift As Integer
Dim X_Zero_Track As Integer 'Track Origin point in X
Dim Y_Zero_Track As Integer 'Track Origin point in Y
Protected Overrides Sub OnMouseDown(e As System.Windows.Forms.MouseEventArgs)
If e.Button = Windows.Forms.MouseButtons.Left Then
MousePress = True
MousePosLast = e.Location
End If
'Pan
If e.Button = Windows.Forms.MouseButtons.Middle Then
MousePosLast = e.Location
Orig_X_Shift = Offset_X
Orig_Y_Shift = Offset_Y
End If
MyBase.OnMouseDown(e)
End Sub
Private MousePress As Boolean = False
Protected Overrides Sub OnMouseUp(e As System.Windows.Forms.MouseEventArgs)
MousePress = False
'Reset it back to position of Origin on No Snap
snap = False
Offset_X = X_Zero_Track
Offset_Y = Y_Zero_Track
Shift_X = 0 ' Zero Pivot point X
Shift_Y = 0 ' Zero Pivot point Y
Shift_Z = 0 'Zero Pivot point Z
MyBase.OnMouseUp(e)
End Sub
Private snap As Boolean = False
Protected Overrides Sub OnMouseMove(e As System.Windows.Forms.MouseEventArgs)
'Orbit
If MousePress Then
MouseMoveHorizontal = MousePosLast.X - e.X
MouseMoveVertical = MousePosLast.Y - e.Y
MousePosLast = e.Location
Dim Speed_Reducer As Integer = 5
Dim xxAngle As Integer = (xAngle + 360) Mod 180
Dim yyAngle As Integer = (yAngle + 360) Mod 180
If (yyAngle > 135) Or (yyAngle <= 45) Then
yAngle += MouseMoveHorizontal / Speed_Reducer
xAngle -= MouseMoveVertical / Speed_Reducer
Else
xxAngle = (xAngle + 360) Mod 180
If (xxAngle > 135) Or (xxAngle <= 45) Then
yAngle += MouseMoveHorizontal / Speed_Reducer
xAngle -= MouseMoveVertical / Speed_Reducer
Else
xAngle += MouseMoveHorizontal / Speed_Reducer
yAngle -= MouseMoveVertical / Speed_Reducer
End If
End If
Me.Invalidate()
End If
'Pan
If e.Button = Windows.Forms.MouseButtons.Middle Then
Offset_X = Orig_X_Shift + (e.X - MousePosLast.X)
Offset_Y = Orig_Y_Shift + (e.Y - MousePosLast.Y)
Me.Invalidate()
End If
MyBase.OnMouseMove(e)
End Sub
Private MouseMoveVertical As Integer = 0
Private MouseMoveHorizontal As Integer = 0
Private MousePosLast As Point
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
Dim t(8) As Point3D
Dim f(4) As Integer
Dim v As Point3D
Dim avgZ(6) As Double
Dim order(6) As Integer
Dim tmp As Double
Dim iMax As Integer
' Clear the window
e.Graphics.Clear(Color.LightBlue)
'Save to the original offset to set it back later
Dim Zero_Offset_X As Integer = Offset_X
Dim Zero_Offset_y As Integer = Offset_Y
'Reset offset (point of orgin) realitive to pivot point
Dim Pivot_Point As Point3D
Pivot_Point = New Point3D(Shift_X, Shift_Y, Shift_Z)
Pivot_Point = Pivot_Point.RotateX(xAngle).RotateY(yAngle).RotateZ(zAngle)
Offset_X -= ((Pivot_Point.X) * Scale)
Offset_Y -= ((Pivot_Point.Y) * Scale)
Dim Stringf As String = "SNAP ---- X" & Shift_X & " ------ Y" & Shift_X & " ------ Z" & Shift_Z
e.Graphics.DrawString(Stringf, New Font("Ariel", 12), New SolidBrush(Color.Black), 10, 10)
' Transform all the points and store them on the "t" array.
For i = 0 To 7
Dim b As Brush = New SolidBrush(Color.White)
v = m_vertices(i)
t(i) = v.RotateX(xAngle).RotateY(yAngle).RotateZ(zAngle)
't(i) = t(i).Project(Me.ClientSize.Width, Me.ClientSize.Height, 256, 10) 'Not Used
'Would do this as Transform Matrix to Graphicspath
'Scale
t(i).X *= Scale
t(i).Y *= Scale
'Shift Pivot Point for view
t(i).X += Offset_X
t(i).Y += Offset_Y
Next
' Compute the average Z value of each face.
For i = 0 To 5
avgZ(i) = (t(m_faces(i, 0)).Z + t(m_faces(i, 1)).Z + t(m_faces(i, 2)).Z + t(m_faces(i, 3)).Z) / 4.0
order(i) = i
Next
' Next we sort the faces in descending order based on the Z value.
' The objective is to draw distant faces first. This is called
' the PAINTERS ALGORITHM. So, the visible faces will hide the invisible ones.
' The sorting algorithm used is the SELECTION SORT.
For i = 0 To 4
iMax = i
For j = i + 1 To 5
If avgZ(j) > avgZ(iMax) Then
iMax = j
End If
Next
If iMax <> i Then
tmp = avgZ(i)
avgZ(i) = avgZ(iMax)
avgZ(iMax) = tmp
tmp = order(i)
order(i) = order(iMax)
order(iMax) = tmp
End If
Next
' Draw the faces using the PAINTERS ALGORITHM (distant faces first, closer faces last).
For i = 0 To 5
Dim points() As Point
Dim index As Integer = order(i)
points = New Point() {
New Point(CInt(t(m_faces(index, 0)).X), CInt(t(m_faces(index, 0)).Y)),
New Point(CInt(t(m_faces(index, 1)).X), CInt(t(m_faces(index, 1)).Y)),
New Point(CInt(t(m_faces(index, 2)).X), CInt(t(m_faces(index, 2)).Y)),
New Point(CInt(t(m_faces(index, 3)).X), CInt(t(m_faces(index, 3)).Y))
}
e.Graphics.FillPolygon(m_brushes(index), points)
Next
'Draw active pivot point
Pivot_Point = New Point3D(Shift_X, Shift_Y, Shift_Z)
Pivot_Point = Pivot_Point.RotateX(xAngle).RotateY(yAngle).RotateZ(zAngle)
e.Graphics.DrawString("X", New Font("Ariel", 12, FontStyle.Bold), New SolidBrush(Color.Red), ((Pivot_Point.X * Scale) + Offset_X) - 10, ((Pivot_Point.Y * Scale) + Offset_Y) - 10)
'Draw Orgin point
e.Graphics.DrawString("O", New Font("Ariel", 10), New SolidBrush(Color.Black), Offset_X - 8, Offset_Y - 8)
'Track Last place of Origin
X_Zero_Track = Offset_X ' (Zero.X * Scale) + Offset_X
Y_Zero_Track = Offset_Y ' (Zero.X * Scale) + Offset_X
'Reset Offset adjustments
Offset_X = Zero_Offset_X
Offset_Y = Zero_Offset_y
MyBase.OnPaint(e)
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.WindowState = FormWindowState.Maximized
'Set Offsets
Offset_X = Me.Width / 2
Offset_Y = Me.Height / 2
'Set Scale/Size
Scale = 100
End Sub
Private Sub Form2_MouseWheel(sender As Object, e As MouseEventArgs) Handles Me.MouseWheel
Dim scale_Factor As Decimal = 1.1
'Zoom
If e.Delta > 0 Then 'Zoom In
Scale *= scale_Factor
Else 'Zoom Out
If Scale / scale_Factor <= 0 Then 'Zoom to Small
Exit Sub
Else
Scale /= scale_Factor
End If
End If
Me.Invalidate()
End Sub
Private Sub Form2_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
isKeyDown = False
'Reset it back to position of Origin on No Snap
snap = False
Offset_X = X_Zero_Track
Offset_Y = Y_Zero_Track
Shift_X = 0 ' Zero Pivot point X
Shift_Y = 0 ' Zero Pivot point Y
Shift_Z = 0 'Zero Pivot point Z
Me.Invalidate()
End Sub
Dim isKeyDown As Boolean = False
Private Sub Form2_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
'Makesure there is only fire
If isKeyDown = True Then
Exit Sub
End If
Select Case e.KeyCode
Case Keys.NumPad1
snap = True
'Shift pivot to 1st point
Shift_X = m_vertices(0).X 'Shift in X Pivot point
Shift_Y = m_vertices(0).Y 'Shift in Y Pivot point
Shift_Z = m_vertices(0).Z 'Shift in Z Pivot point.
Case Keys.NumPad2
snap = True
'Shift pivot to 2nd point
Shift_X = m_vertices(1).X 'Shift in X Pivot point
Shift_Y = m_vertices(1).Y 'Shift in Y Pivot point
Shift_Z = m_vertices(1).Z 'Shift in Z Pivot point
Case Keys.NumPad3
snap = True
'Shift pivot to one 3rd point
Shift_X = m_vertices(2).X 'Shift in X Pivot point
Shift_Y = m_vertices(2).Y 'Shift in Y Pivot point
Shift_Z = m_vertices(2).Z 'Shift in Z Pivot point
Case Keys.NumPad4
snap = True
'Shift pivot to 4th point
Shift_X = m_vertices(3).X 'Shift in X Pivot point
Shift_Y = m_vertices(3).Y 'Shift in Y Pivot point
Shift_Z = m_vertices(3).Z 'Shift in Z Pivot point
Case Keys.NumPad5
snap = True
'Shift pivot to 5th point
Shift_X = m_vertices(4).X 'Shift in X Pivot point
Shift_Y = m_vertices(4).Y 'Shift in Y Pivot point
Shift_Z = m_vertices(4).Z 'Shift in Z Pivot point
Case Keys.NumPad6
snap = True
'Shift pivot to 6th point
Shift_X = m_vertices(5).X 'Shift in X Pivot point
Shift_Y = m_vertices(5).Y 'Shift in Y Pivot point
Shift_Z = m_vertices(5).Z 'Shift in Z Pivot point
Case Keys.NumPad7
snap = True
'Shift pivot to 7th point
Shift_X = m_vertices(6).X 'Shift in X Pivot point
Shift_Y = m_vertices(6).Y 'Shift in Y Pivot point
Shift_Z = m_vertices(6).Z 'Shift in Z Pivot point
Case Keys.NumPad8
snap = True
'Shift pivot to 8th point
Shift_X = m_vertices(7).X 'Shift in X Pivot point
Shift_Y = m_vertices(7).Y 'Shift in Y Pivot point
Shift_Z = m_vertices(7).Z 'Shift in Z Pivot point
Case Else
snap = False
'Shift point back to Zero/Origin
Shift_X = 0 ' Zero Pivot point X
Shift_Y = 0 ' Zero Pivot point Y
Shift_Z = 0 'Zero Pivot point Z
End Select
'Make adjustments offsets to compensate for new pivot point. Only once fire
Dim Pivot_Point As Point3D = New Point3D(Shift_X, Shift_Y, Shift_Z)
Pivot_Point = Pivot_Point.RotateX(xAngle).RotateY(yAngle).RotateZ(zAngle)
Offset_X += ((Pivot_Point.X) * Scale)
Offset_Y += ((Pivot_Point.Y) * Scale)
isKeyDown = True
Me.Invalidate()
End Sub
End Class
推荐答案
我请求道歉...但我忘记了我们所说的话关于...
根据我的建议,我修改了你所引用链接的代码。
这是我的解决方案:我构建一个具有行为的控件允许用/通过鼠标移动旋转立方体。
I beg for apologize ... but I have forgotten what we have spoken about ...
According to my suggestion I modified the code from the Link you are refering to.
Here is my Solution : I build a Control which has the Behaviour that allows to rotate a cube with/by the Mouse-Movement.
Imports System.Drawing.Graphics
Public Class RotatingCube
Inherits Control
Protected m_vertices(8) As Point3D
Protected m_faces(6, 4) As Integer
Protected m_colors(6) As Color
Protected m_brushes(6) As Brush
Sub New()
' Enable double-buffering to eliminate flickering.
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
' Create the cube vertices.
m_vertices = New Point3D() {
New Point3D(-1, 1, -1),
New Point3D(1, 1, -1),
New Point3D(1, -1, -1),
New Point3D(-1, -1, -1),
New Point3D(-1, 1, 1),
New Point3D(1, 1, 1),
New Point3D(1, -1, 1),
New Point3D(-1, -1, 1)}
' Create an array representing the 6 faces of a cube. Each face is composed by indices to the vertex array
' above.
m_faces = New Integer(,) {{0, 1, 2, 3}, {1, 5, 6, 2}, {5, 4, 7, 6}, {4, 0, 3, 7}, {0, 4, 5, 1}, {3, 2, 6, 7}}
' Define the colors of each face.
m_colors = New Color() {Color.BlueViolet, Color.Cyan, Color.Green, Color.Yellow, Color.Violet, Color.LightSkyBlue}
' Create the brushes to draw each face. Brushes are used to draw filled polygons.
For i = 0 To 5
m_brushes(i) = New SolidBrush(m_colors(i))
Next
End Sub
Property xAngle As Integer
Get
Return my_xAngle
End Get
Set(value As Integer)
my_xAngle = (value + 360) Mod 360
Me.Invalidate()
End Set
End Property
Private my_xAngle As Integer
Property yAngle As Integer
Get
Return my_yAngle
End Get
Set(value As Integer)
my_yAngle = (value + 360) Mod 360
Me.Invalidate()
End Set
End Property
Private my_yAngle As Integer
Property zAngle As Integer
Get
Return my_zAngle
End Get
Set(value As Integer)
my_zAngle = (value + 360) Mod 360
Me.Invalidate()
End Set
End Property
Private my_zAngle As Integer
Protected Overrides Sub OnMouseDown(e As System.Windows.Forms.MouseEventArgs)
If e.Button = Windows.Forms.MouseButtons.Left Then
MousePress = True
MousePosLast = e.Location
End If
MyBase.OnMouseDown(e)
End Sub
Private MousePress As Boolean = False
Protected Overrides Sub OnMouseUp(e As System.Windows.Forms.MouseEventArgs)
MousePress = False
MyBase.OnMouseUp(e)
End Sub
Protected Overrides Sub OnMouseMove(e As System.Windows.Forms.MouseEventArgs)
If MousePress Then
MouseMoveHorizontal = MousePosLast.X - e.X
MouseMoveVertical = MousePosLast.Y - e.Y
MousePosLast = e.Location
Dim xxAngle As Integer = (xAngle + 360) Mod 180
Dim yyAngle As Integer = (yAngle + 360) Mod 180
If (yyAngle > 135) Or (yyAngle <= 45) Then
yAngle += MouseMoveHorizontal
xAngle -= MouseMoveVertical
Else
xxAngle = (xAngle + 360) Mod 180
If (xxAngle > 135) Or (xxAngle <= 45) Then
yAngle += MouseMoveHorizontal
xAngle -= MouseMoveVertical
Else
xAngle += MouseMoveHorizontal
yAngle -= MouseMoveVertical
End If
End If
Me.Invalidate()
End If
MyBase.OnMouseMove(e)
End Sub
Private MouseMoveVertical As Integer = 0
Private MouseMoveHorizontal As Integer = 0
Private MousePosLast As Point
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
Dim t(8) As Point3D
Dim f(4) As Integer
Dim v As Point3D
Dim avgZ(6) As Double
Dim order(6) As Integer
Dim tmp As Double
Dim iMax As Integer
' Clear the window
e.Graphics.Clear(Color.LightBlue)
' Transform all the points and store them on the "t" array.
For i = 0 To 7
Dim b As Brush = New SolidBrush(Color.White)
v = m_vertices(i)
t(i) = v.RotateX(xAngle).RotateY(yAngle).RotateZ(zAngle)
t(i) = t(i).Project(Me.ClientSize.Width, Me.ClientSize.Height, 256, 4)
Next
' Compute the average Z value of each face.
For i = 0 To 5
avgZ(i) = (t(m_faces(i, 0)).Z + t(m_faces(i, 1)).Z + t(m_faces(i, 2)).Z + t(m_faces(i, 3)).Z) / 4.0
order(i) = i
Next
' Next we sort the faces in descending order based on the Z value.
' The objective is to draw distant faces first. This is called
' the PAINTERS ALGORITHM. So, the visible faces will hide the invisible ones.
' The sorting algorithm used is the SELECTION SORT.
For i = 0 To 4
iMax = i
For j = i + 1 To 5
If avgZ(j) > avgZ(iMax) Then
iMax = j
End If
Next
If iMax <> i Then
tmp = avgZ(i)
avgZ(i) = avgZ(iMax)
avgZ(iMax) = tmp
tmp = order(i)
order(i) = order(iMax)
order(iMax) = tmp
End If
Next
' Draw the faces using the PAINTERS ALGORITHM (distant faces first, closer faces last).
For i = 0 To 5
Dim points() As Point
Dim index As Integer = order(i)
points = New Point() {
New Point(CInt(t(m_faces(index, 0)).X), CInt(t(m_faces(index, 0)).Y)),
New Point(CInt(t(m_faces(index, 1)).X), CInt(t(m_faces(index, 1)).Y)),
New Point(CInt(t(m_faces(index, 2)).X), CInt(t(m_faces(index, 2)).Y)),
New Point(CInt(t(m_faces(index, 3)).X), CInt(t(m_faces(index, 3)).Y))
}
e.Graphics.FillPolygon(m_brushes(index), points)
Next
MyBase.OnPaint(e)
End Sub
End Class
Public Class Point3D
Protected m_x As Double, m_y As Double, m_z As Double
Public Sub New(ByVal x As Double, ByVal y As Double, ByVal z As Double)
Me.X = x
Me.Y = y
Me.Z = z
End Sub
Public Property X() As Double
Get
Return m_x
End Get
Set(ByVal value As Double)
m_x = value
End Set
End Property
Public Property Y() As Double
Get
Return m_y
End Get
Set(ByVal value As Double)
m_y = value
End Set
End Property
Public Property Z() As Double
Get
Return m_z
End Get
Set(ByVal value As Double)
m_z = value
End Set
End Property
Public Function RotateX(ByVal angle As Integer) As Point3D
Dim rad As Double, cosa As Double, sina As Double, yn As Double, zn As Double
rad = angle * Math.PI / 180
cosa = Math.Cos(rad)
sina = Math.Sin(rad)
yn = Me.Y * cosa - Me.Z * sina
zn = Me.Y * sina + Me.Z * cosa
Return New Point3D(Me.X, yn, zn)
End Function
Public Function RotateY(ByVal angle As Integer) As Point3D
Dim rad As Double, cosa As Double, sina As Double, Xn As Double, Zn As Double
rad = angle * Math.PI / 180
cosa = Math.Cos(rad)
sina = Math.Sin(rad)
Zn = Me.Z * cosa - Me.X * sina
Xn = Me.Z * sina + Me.X * cosa
Return New Point3D(Xn, Me.Y, Zn)
End Function
Public Function RotateZ(ByVal angle As Integer) As Point3D
Dim rad As Double, cosa As Double, sina As Double, Xn As Double, Yn As Double
rad = angle * Math.PI / 180
cosa = Math.Cos(rad)
sina = Math.Sin(rad)
Xn = Me.X * cosa - Me.Y * sina
Yn = Me.X * sina + Me.Y * cosa
Return New Point3D(Xn, Yn, Me.Z)
End Function
Public Function Project(ByVal viewWidth, ByVal viewHeight, ByVal fov, ByVal viewDistance)
Dim factor As Double, Xn As Double, Yn As Double
factor = fov / (viewDistance + Me.Z)
Xn = Me.X * factor + viewWidth / 2
Yn = Me.Y * factor + viewHeight / 2
Return New Point3D(Xn, Yn, Me.Z)
End Function
End Class
Sorry for not being clear.
You are correct the rotation point is not stated but it will be (until I can workout the shift relative to the different rotation point i.e. distance from drawn zero point & mouse rotation) the drawing zero point. The drawing zero point is positioned by Matrix Translate (& Scale is done also at this time).
<pre lang="vb">Dim translateMatrix1 As New Matrix
translateMatrix1.Scale(Scale_Path, Scale_Path, MatrixOrder.Append)
translateMatrix1.Translate(Offset_X_Path, Offset_Y_Path, MatrixOrder.Append)
Temp_Path.Transform(translateMatrix1)
I need to have the orbital roll relative to mouse move/gesture.
I need to have the orbital roll relative to mouse move/gesture.
这篇关于如何通过鼠标移动进行3D旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!