I'm trying to use SetWorldTransform to build and rotate a 3d object. I'm having a difficult time getting the side to rotate around the center point and still maintain it's position with respect to the front panel. I cannot seem to get the math right for the second Transform, I thought about using the CombineTransform to do a second transform but all effort has failed. Also any clue to how to get the perspective to have that 3d affect would be nice. I have posted the test project, so it may be a bit messy. You'll need a timer, 3 command buttons and a picturebox.
My goal here is to take existing panel objects, which already contain all the properties, Angle, Width, Height, Cutouts, even their own dc's for output to emf files, etc. and creating a 3-d image with them all combined into a unit object. This object would then be displayed with the ability to rotate from side to side.
Option Explicit
Private Declare Function CreateSolidBrush Lib "gdi32" _
(ByVal crColor As Long) As Long
Private Declare Function BitBlt Lib "gdi32" _
(ByVal hDestDC As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long, _
ByVal hSrcDC As Long, _
ByVal xSrc As Long, _
ByVal ySrc As Long, _
ByVal dwRop As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" _
(ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" _
(ByVal lDC As Long) As Long
Private Declare Function CombineTransform Lib "gdi32" ( _
lpxformResult As XForm, lpxform1 As XForm, _
lpxform2 As XForm) As Long
Private Declare Function SetWorldTransform Lib "gdi32" ( _
ByVal hdc As Long, ByRef lpXform As XForm) As Long
Private Declare Function SetGraphicsMode Lib "gdi32" ( _
ByVal hdc As Long, ByVal iMode As Long) As Long
Private Declare Function GetWorldTransform Lib "gdi32" ( _
ByVal hdc As Long, ByRef lpXform As XForm) As Long
Private Declare Function SetViewportOrgEx Lib "gdi32" ( _
ByVal hdc As Long, ByVal nX As Long, ByVal nY As Long, _
ByRef lpPoint As Any) As Long
Private Declare Function Ellipse Lib "gdi32" ( _
ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, _
ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function SelectObject Lib "gdi32" ( _
ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function GetStockObject Lib "gdi32" ( _
ByVal nIndex As Long) As Long
Private Declare Function MoveToEx Lib "gdi32" ( _
ByVal hdc As Long, ByVal x As Long, ByVal y As Long, _
ByRef lpPoint As Any) As Long
Private Declare Function LineTo Lib "gdi32" ( _
ByVal hdc As Long, ByVal x As Long, _
ByVal y As Long) As Long
Private Declare Function GetSysColor Lib "user32" ( _
ByVal nIndex As Long) As Long
Private Declare Function CreatePen Lib "gdi32" ( _
ByVal nPenStyle As Long, ByVal nWidth As Long, _
ByVal crColor As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" ( _
ByVal hObject As Long) As Long
Private Declare Function Polygon Lib "gdi32" _
(ByVal hdc As Long, lpPoint As PointAPI, _
ByVal nCount As Long) As Long
Private Declare Function CreatePolygonRgn Lib "gdi32" _
(lpPoint As PointAPI, ByVal nCount As Long, _
ByVal nPolyFillMode As Long) As Long
Private Type XForm
eM11 As Single
eM12 As Single
eM21 As Single
eM22 As Single
eDx As Single
eDy As Single
End Type
Dim CenterPoint As Single
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type PointAPI
x As Long
y As Long
End Type
Private RotAmt As Single
Const Pi As Single = 3.14159
Private RotRad As Single
Private Const GM_ADVANCED As Long = &H2
Private Const COLOR_BTNSHADOW As Long = &H10
Private Const NULL_BRUSH As Long = &H5
Private Const BLACK_PEN As Long = &H7
Private Const PS_DOT As Long = &H2
Private Const PS_SOLID As Long = &H0
Private Sub Command1_Click()
Picture1.Cls
RotAmt = RotAmt + 5
RotRad = (RotAmt / 180) * Pi
If RotAmt <= 90 Or RotAmt >= 270 Then
CreatePanelDC
CreateDoorDC
Else
CreateDoorDC
CreatePanelDC
End If
End Sub
Private Sub Command2_Click()
Picture1.Cls
RotAmt = RotAmt - 5
RotRad = (RotAmt / 180) * Pi
If RotAmt <= 90 Or RotAmt >= 270 Then
CreatePanelDC
CreateDoorDC
Else
CreateDoorDC
CreatePanelDC
End If
End Sub
Private Function CreateDoorDC() As Long
Dim TransMatrix As XForm
Dim OldMatrix As XForm
Dim OldMode As Long
Dim OldBrush As Long, OldPen As Long
Dim OldOrg As PointAPI
Dim EdgePens As Long
Dim i As Integer
' Create z-axis transformation matrix
With TransMatrix
.eM11 = Cos(RotRad)
.eM12 = Sin(RotRad)
.eM21 = 0 '-Sin(RotRad)
.eM22 = 1 'Cos(RotRad)
.eDx = 325 - Cos(RotRad) * 325 + Sin(RotRad) * 0
.eDy = 0 - Cos(RotRad) * 0 - Sin(RotRad) * 325
End With
' Set the graphics mode to advanced mode
OldMode = SetGraphicsMode(Picture1.hdc, GM_ADVANCED)
' Create pens (edges)
EdgePens = CreatePen(PS_SOLID, 1, vbBlack)
' Disable brush (fill), and set dotted 'faded' pen
OldBrush = SelectObject(Picture1.hdc, GetStockObject(NULL_BRUSH))
' Select black pen
Call SelectObject(Picture1.hdc, EdgePens)
' Get the current transformation matrix and set new one
Call GetWorldTransform(Picture1.hdc, OldMatrix)
Call SetWorldTransform(Picture1.hdc, TransMatrix)
' Draw the transformed geometry
'------------------------------------------------------------------------
DrawSquare Picture1.hdc, 250, 250
'------------------------------------------------------------------------
' Clean up
Call SetViewportOrgEx(Picture1.hdc, OldOrg.x, OldOrg.y, ByVal 0&)
Call SetWorldTransform(Picture1.hdc, OldMatrix)
Call SetGraphicsMode(Picture1.hdc, OldMode)
Call SelectObject(Picture1.hdc, OldBrush)
Call SelectObject(Picture1.hdc, OldPen)
Call DeleteObject(EdgePens)
End Function
Private Function CreatePanelDC() As Long
Dim TransMatrix1 As XForm, TransMatrix2 As XForm
Dim OldMatrix As XForm
Dim OldMode As Long
Dim OldBrush As Long, OldPen As Long
Dim OldOrg As PointAPI
Dim EdgePens As Long
Dim i As Integer
Dim sngAngle As Single
Dim sngRad As Single
sngAngle = 45
sngRad = (sngAngle / 180) * Pi
With TransMatrix1
.eM11 = Cos(RotRad + sngRad)
.eM12 = Sin(RotRad + sngRad)
.eM21 = 0
.eM22 = 1
.eDx = 325 - Cos(RotRad + sngRad) * 325 + Sin(RotRad + sngRad) * 0
.eDy = 0 - Cos(RotRad + sngRad) * 0 - Sin(RotRad + sngRad) * 325
End With
' CombineTransform TransMatrix1, TransMatrix1, TransMatrix2
' Set the graphics mode to advanced mode
OldMode = SetGraphicsMode(Picture1.hdc, GM_ADVANCED)
' Create pens (edges)
EdgePens = CreatePen(PS_SOLID, 1, vbBlack)
' Disable brush (fill), and set dotted 'faded' pen
OldBrush = SelectObject(Picture1.hdc, GetStockObject(NULL_BRUSH))
' Select black pen
Call SelectObject(Picture1.hdc, EdgePens)
' Get the current transformation matrix and set new one
Call GetWorldTransform(Picture1.hdc, OldMatrix)
Call SetWorldTransform(Picture1.hdc, TransMatrix1)
' Draw the transformed geometry
'------------------------------------------------------------------------
DrawSquare Picture1.hdc, 100, 250
'------------------------------------------------------------------------
' Clean up
Call SetViewportOrgEx(Picture1.hdc, OldOrg.x, OldOrg.y, ByVal 0&)
Call SetWorldTransform(Picture1.hdc, OldMatrix)
Call SetGraphicsMode(Picture1.hdc, OldMode)
Call SelectObject(Picture1.hdc, OldBrush)
Call SelectObject(Picture1.hdc, OldPen)
Call DeleteObject(EdgePens)
End Function
Private Sub DrawSquare(hdc As Long, lngLeftX As Long, lngTopY As Long)
Dim hBrush As Long, hRgn As Long
Dim mBrush As Long
mBrush = CreateSolidBrush(&HFFFFD0)
SelectObject hdc, mBrush
Dim poly(1 To 4) As PointAPI
hRgn = CreatePolygonRgn(poly(1), 4, 1)
DeleteObject hRgn
poly(1).x = lngLeftX
poly(1).y = lngTopY
poly(2).x = lngLeftX
poly(2).y = lngTopY + 150
poly(3).x = lngLeftX + 150
poly(3).y = lngTopY + 150
poly(4).x = lngLeftX + 150
poly(4).y = lngTopY
SelectObject hdc, mBrush
Polygon hdc, poly(1), 4
hRgn = CreatePolygonRgn(poly(1), 4, 1)
DeleteObject mBrush
DeleteObject hRgn
End Sub
Private Sub Command3_Click()
If Timer1.Enabled = True Then
Timer1.Enabled = False
Else
Timer1.Enabled = True
End If
End Sub
Private Sub Timer1_Timer()
Picture1.Cls
RotAmt = RotAmt + 5
RotRad = (RotAmt / 180) * Pi
If RotAmt <= 90 Or RotAmt >= 270 Then
CreatePanelDC
CreateDoorDC
Else
CreateDoorDC
CreatePanelDC
End If
End Sub
"Two strings walk into a bar. The first string says to the bartender: 'Bartender, I'll have a beer. u.5n$x5t?*&4ru!2[sACC~ErJ'. The second string says: 'Pardon my friend, he isn't NULL terminated'."
My goal here is to take existing panel objects, which already contain all the properties, Angle, Width, Height, Cutouts, even their own dc's for output to emf files, etc. and creating a 3-d image with them all combined into a unit object. This object would then be displayed with the ability to rotate from side to side.
Option Explicit
Private Declare Function CreateSolidBrush Lib "gdi32" _
(ByVal crColor As Long) As Long
Private Declare Function BitBlt Lib "gdi32" _
(ByVal hDestDC As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long, _
ByVal hSrcDC As Long, _
ByVal xSrc As Long, _
ByVal ySrc As Long, _
ByVal dwRop As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" _
(ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" _
(ByVal lDC As Long) As Long
Private Declare Function CombineTransform Lib "gdi32" ( _
lpxformResult As XForm, lpxform1 As XForm, _
lpxform2 As XForm) As Long
Private Declare Function SetWorldTransform Lib "gdi32" ( _
ByVal hdc As Long, ByRef lpXform As XForm) As Long
Private Declare Function SetGraphicsMode Lib "gdi32" ( _
ByVal hdc As Long, ByVal iMode As Long) As Long
Private Declare Function GetWorldTransform Lib "gdi32" ( _
ByVal hdc As Long, ByRef lpXform As XForm) As Long
Private Declare Function SetViewportOrgEx Lib "gdi32" ( _
ByVal hdc As Long, ByVal nX As Long, ByVal nY As Long, _
ByRef lpPoint As Any) As Long
Private Declare Function Ellipse Lib "gdi32" ( _
ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, _
ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function SelectObject Lib "gdi32" ( _
ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function GetStockObject Lib "gdi32" ( _
ByVal nIndex As Long) As Long
Private Declare Function MoveToEx Lib "gdi32" ( _
ByVal hdc As Long, ByVal x As Long, ByVal y As Long, _
ByRef lpPoint As Any) As Long
Private Declare Function LineTo Lib "gdi32" ( _
ByVal hdc As Long, ByVal x As Long, _
ByVal y As Long) As Long
Private Declare Function GetSysColor Lib "user32" ( _
ByVal nIndex As Long) As Long
Private Declare Function CreatePen Lib "gdi32" ( _
ByVal nPenStyle As Long, ByVal nWidth As Long, _
ByVal crColor As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" ( _
ByVal hObject As Long) As Long
Private Declare Function Polygon Lib "gdi32" _
(ByVal hdc As Long, lpPoint As PointAPI, _
ByVal nCount As Long) As Long
Private Declare Function CreatePolygonRgn Lib "gdi32" _
(lpPoint As PointAPI, ByVal nCount As Long, _
ByVal nPolyFillMode As Long) As Long
Private Type XForm
eM11 As Single
eM12 As Single
eM21 As Single
eM22 As Single
eDx As Single
eDy As Single
End Type
Dim CenterPoint As Single
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type PointAPI
x As Long
y As Long
End Type
Private RotAmt As Single
Const Pi As Single = 3.14159
Private RotRad As Single
Private Const GM_ADVANCED As Long = &H2
Private Const COLOR_BTNSHADOW As Long = &H10
Private Const NULL_BRUSH As Long = &H5
Private Const BLACK_PEN As Long = &H7
Private Const PS_DOT As Long = &H2
Private Const PS_SOLID As Long = &H0
Private Sub Command1_Click()
Picture1.Cls
RotAmt = RotAmt + 5
RotRad = (RotAmt / 180) * Pi
If RotAmt <= 90 Or RotAmt >= 270 Then
CreatePanelDC
CreateDoorDC
Else
CreateDoorDC
CreatePanelDC
End If
End Sub
Private Sub Command2_Click()
Picture1.Cls
RotAmt = RotAmt - 5
RotRad = (RotAmt / 180) * Pi
If RotAmt <= 90 Or RotAmt >= 270 Then
CreatePanelDC
CreateDoorDC
Else
CreateDoorDC
CreatePanelDC
End If
End Sub
Private Function CreateDoorDC() As Long
Dim TransMatrix As XForm
Dim OldMatrix As XForm
Dim OldMode As Long
Dim OldBrush As Long, OldPen As Long
Dim OldOrg As PointAPI
Dim EdgePens As Long
Dim i As Integer
' Create z-axis transformation matrix
With TransMatrix
.eM11 = Cos(RotRad)
.eM12 = Sin(RotRad)
.eM21 = 0 '-Sin(RotRad)
.eM22 = 1 'Cos(RotRad)
.eDx = 325 - Cos(RotRad) * 325 + Sin(RotRad) * 0
.eDy = 0 - Cos(RotRad) * 0 - Sin(RotRad) * 325
End With
' Set the graphics mode to advanced mode
OldMode = SetGraphicsMode(Picture1.hdc, GM_ADVANCED)
' Create pens (edges)
EdgePens = CreatePen(PS_SOLID, 1, vbBlack)
' Disable brush (fill), and set dotted 'faded' pen
OldBrush = SelectObject(Picture1.hdc, GetStockObject(NULL_BRUSH))
' Select black pen
Call SelectObject(Picture1.hdc, EdgePens)
' Get the current transformation matrix and set new one
Call GetWorldTransform(Picture1.hdc, OldMatrix)
Call SetWorldTransform(Picture1.hdc, TransMatrix)
' Draw the transformed geometry
'------------------------------------------------------------------------
DrawSquare Picture1.hdc, 250, 250
'------------------------------------------------------------------------
' Clean up
Call SetViewportOrgEx(Picture1.hdc, OldOrg.x, OldOrg.y, ByVal 0&)
Call SetWorldTransform(Picture1.hdc, OldMatrix)
Call SetGraphicsMode(Picture1.hdc, OldMode)
Call SelectObject(Picture1.hdc, OldBrush)
Call SelectObject(Picture1.hdc, OldPen)
Call DeleteObject(EdgePens)
End Function
Private Function CreatePanelDC() As Long
Dim TransMatrix1 As XForm, TransMatrix2 As XForm
Dim OldMatrix As XForm
Dim OldMode As Long
Dim OldBrush As Long, OldPen As Long
Dim OldOrg As PointAPI
Dim EdgePens As Long
Dim i As Integer
Dim sngAngle As Single
Dim sngRad As Single
sngAngle = 45
sngRad = (sngAngle / 180) * Pi
With TransMatrix1
.eM11 = Cos(RotRad + sngRad)
.eM12 = Sin(RotRad + sngRad)
.eM21 = 0
.eM22 = 1
.eDx = 325 - Cos(RotRad + sngRad) * 325 + Sin(RotRad + sngRad) * 0
.eDy = 0 - Cos(RotRad + sngRad) * 0 - Sin(RotRad + sngRad) * 325
End With
' CombineTransform TransMatrix1, TransMatrix1, TransMatrix2
' Set the graphics mode to advanced mode
OldMode = SetGraphicsMode(Picture1.hdc, GM_ADVANCED)
' Create pens (edges)
EdgePens = CreatePen(PS_SOLID, 1, vbBlack)
' Disable brush (fill), and set dotted 'faded' pen
OldBrush = SelectObject(Picture1.hdc, GetStockObject(NULL_BRUSH))
' Select black pen
Call SelectObject(Picture1.hdc, EdgePens)
' Get the current transformation matrix and set new one
Call GetWorldTransform(Picture1.hdc, OldMatrix)
Call SetWorldTransform(Picture1.hdc, TransMatrix1)
' Draw the transformed geometry
'------------------------------------------------------------------------
DrawSquare Picture1.hdc, 100, 250
'------------------------------------------------------------------------
' Clean up
Call SetViewportOrgEx(Picture1.hdc, OldOrg.x, OldOrg.y, ByVal 0&)
Call SetWorldTransform(Picture1.hdc, OldMatrix)
Call SetGraphicsMode(Picture1.hdc, OldMode)
Call SelectObject(Picture1.hdc, OldBrush)
Call SelectObject(Picture1.hdc, OldPen)
Call DeleteObject(EdgePens)
End Function
Private Sub DrawSquare(hdc As Long, lngLeftX As Long, lngTopY As Long)
Dim hBrush As Long, hRgn As Long
Dim mBrush As Long
mBrush = CreateSolidBrush(&HFFFFD0)
SelectObject hdc, mBrush
Dim poly(1 To 4) As PointAPI
hRgn = CreatePolygonRgn(poly(1), 4, 1)
DeleteObject hRgn
poly(1).x = lngLeftX
poly(1).y = lngTopY
poly(2).x = lngLeftX
poly(2).y = lngTopY + 150
poly(3).x = lngLeftX + 150
poly(3).y = lngTopY + 150
poly(4).x = lngLeftX + 150
poly(4).y = lngTopY
SelectObject hdc, mBrush
Polygon hdc, poly(1), 4
hRgn = CreatePolygonRgn(poly(1), 4, 1)
DeleteObject mBrush
DeleteObject hRgn
End Sub
Private Sub Command3_Click()
If Timer1.Enabled = True Then
Timer1.Enabled = False
Else
Timer1.Enabled = True
End If
End Sub
Private Sub Timer1_Timer()
Picture1.Cls
RotAmt = RotAmt + 5
RotRad = (RotAmt / 180) * Pi
If RotAmt <= 90 Or RotAmt >= 270 Then
CreatePanelDC
CreateDoorDC
Else
CreateDoorDC
CreatePanelDC
End If
End Sub
"Two strings walk into a bar. The first string says to the bartender: 'Bartender, I'll have a beer. u.5n$x5t?*&4ru!2[sACC~ErJ'. The second string says: 'Pardon my friend, he isn't NULL terminated'."