Here's my atc version of CD3DArcBall :)



D3DXQuaternionAxisToAxis proto :DWORD,:DWORD,:DWORD

.data
iCurMouseX dd 0
iCurMouseY dd 0
s_vDown D3DXVECTOR3 <0.0f,-1.0f,0.0f>
s_vCur D3DXVECTOR3 <NULL>
fp0 FLOAT 0.0f
fp2 FLOAT 2.0f
fp5 FLOAT 5.0f
fp0pt85 FLOAT 0.85
.code

class CD3DArcBall, ,C++ compatible
virtual ScreenToVector:sx,sy
virtual HandleMouseMessages:hwin,uint,wparam,lparam
virtual GetRotationMatrix
virtual GetRotationDeltaMatrix
virtual GetTranslationMatrix
virtual GetTranslationDeltaMatrix
virtual IsBeingDragged
virtual SetRadius
virtual SetWindow:iWidth, iHeight, fRadius
virtual SetRightHanded:bRightHanded
virtual Init

long iWidth ; // ArcBall's window width
long iHeight ; // ArcBall's window height
float fRadius ; // ArcBall's radius in screen coords
float fRadiusTranslation; // ArcBall's radius for translating the target
des qDown D3DXQUATERNION ; // Quaternion before button down
des qNow D3DXQUATERNION ; // Composite quaternion for current drag
Mat matRotation ; // Matrix for arcball's orientation
Mat matRotationDelta ; // Matrix for arcball's orientation
Mat matTranslation ; // Matrix for arcball's position
Mat matTranslationDelta ; // Matrix for arcball's position
bool bDrag ; // Whether user is dragging arcball
bool bRightHanded ; // Whether to use RH coordinate system
endclass

CD3DArcBall_CD3DArcBall proc
icall ecx, CD3DArcBall, Init
ret
CD3DArcBall_CD3DArcBall endp

CD3DArcBall_$CD3DArcBall proc
ret
CD3DArcBall_$CD3DArcBall endp

CD3DArcBall_Init proc
local me:DWORD
mov me,ecx
invoke D3DXQuaternionIdentity, addr [ecx].CD3DArcBall.qDown
mov ecx,me
invoke D3DXQuaternionIdentity,addr [ecx].CD3DArcBall.qNow
mov ecx,me
invoke D3DXMatrixIdentity,addr [ecx].CD3DArcBall.matRotation
mov ecx,me
invoke D3DXMatrixIdentity,addr [ecx].CD3DArcBall.matRotationDelta
mov ecx,me
invoke D3DXMatrixIdentity,addr [ecx].CD3DArcBall.matTranslation
mov ecx,me
invoke D3DXMatrixIdentity,addr [ecx].CD3DArcBall.matTranslationDelta
mov ecx,me
mov [ecx].CD3DArcBall.bDrag , FALSE
m2m [ecx].CD3DArcBall.fRadiusTranslation , fp1
mov [ecx].CD3DArcBall.bRightHanded , FALSE
ret
CD3DArcBall_Init endp

CD3DArcBall_SetWindow proc iWidth:DWORD, iHeight:DWORD, fRadius:FLOAT
; // Set ArcBall info
m2m [ecx].CD3DArcBall.iWidth , iWidth
m2m [ecx].CD3DArcBall.iHeight , iHeight
m2m [ecx].CD3DArcBall.fRadius , fRadius
ret
CD3DArcBall_SetWindow endp

CD3DArcBall_ScreenToVector proc sx, sy
local fx
local fy
local fz
local fmag
local scale:FLOAT


; // Scale to screen
fild sx
fild [ecx].CD3DArcBall.iWidth
fdiv fp2
fsub
fld [ecx].CD3DArcBall.fRadius
fild [ecx].CD3DArcBall.iWidth
fdiv fp2
fmul
fdiv
fchs
fstp fx ;fx = -(sx - m_iWidth/2) / (m_fRadius*m_iWidth/2);

fild sy
fild [ecx].CD3DArcBall.iHeight
fdiv fp2
fsub
fld [ecx].CD3DArcBall.fRadius
fild [ecx].CD3DArcBall.iHeight
fdiv fp2
fmul
fdiv
fstp fy ;fy = (sy - m_iHeight/2) / (m_fRadius*m_iHeight/2);

.if [ecx].CD3DArcBall.bRightHanded
fld fx
fchs
fstp fx
fld fy
fchs
fstp fy
.endif

mov fz,0
fld fx
fmul fx
fld fy
fmul fy
fadd
fstp fmag; fmag = x*x + y*y;

fld fmag
fcomp fp1
__FJLE @F
; if( mag > 1.0f )
; FLOAT scale = 1.0f/sqrtf(mag);
fld fp1
fld fmag
fsqrt
fdiv
fst scale
fmul fx
fstp fx
fld scale
fmul fy
fstp fy
jmp cya
@@:
; else
fld fp1
fsub fmag
fsqrt
fstp fz ; fz = sqrtf( 1.0f - mag );
; endif

; // Return ptr to vector
cya: lea eax,fx
ret ; return D3DXVECTOR3( x, y, z );
CD3DArcBall_ScreenToVector endp


CD3DArcBall_SetRadius proc fRadius
m2m [ecx].CD3DArcBall.fRadiusTranslation , fRadius
ret
CD3DArcBall_SetRadius endp


CD3DArcBall_HandleMouseMessages proc hWnd, uMsg, wParam, lParam
local iMouseX
local iMouseY
local ftemp1
local ftemp2
local me
local fDeltaX
local fDeltaY
local vCur:D3DXVECTOR3
local qAxisToAxis:D3DXQUATERNION

mov me,ecx
; UNREFERENCED_PARAMETER( hWnd );

; // Current mouse position
; int iMouseX = GET_X_LPARAM(lParam);
; int iMouseY = GET_Y_LPARAM(lParam);
mov ebx,lParam
mov eax,ebx
and eax,0FFFFh
mov iMouseX,eax
mov eax,ebx
shr eax,16
mov iMouseY,eax

.if uMsg==WM_RBUTTONDOWN
.elseif uMsg==WM_MBUTTONDOWN
; // Store off the position of the cursor when the button is pressed
m2m iCurMouseX , iMouseX
m2m iCurMouseY , iMouseY
return TRUE

.elseif uMsg==WM_LBUTTONDOWN
; // Start drag mode
mov ecx,me
mov [ecx].CD3DArcBall.bDrag , TRUE
icall me, CD3DArcBall, ScreenToVector, iMouseX, iMouseY ;returns ptr to temp 3dvector - grab values now !!
m2m s_vDown.x, [eax].D3DVECTOR.x
m2m s_vDown.y, [eax].D3DVECTOR.y
m2m s_vDown.y, [eax].D3DVECTOR.z
mov ecx,me
invoke RtlMoveMemory,addr [ecx].CD3DArcBall.qDown,addr [ecx].CD3DArcBall.qNow,sizeof D3DXQUATERNION
return TRUE

.elseif uMsg==WM_LBUTTONUP
; // End drag mode
mov ecx,me
mov [ecx].CD3DArcBall.bDrag , FALSE
return TRUE

.elseif uMsg==WM_MOUSEMOVE
; // Drag object
mov eax,wParam
.if eax & MK_LBUTTON
mov ecx,me
.if [ecx].CD3DArcBall.bDrag
; // recompute m_qNow
icall me, CD3DArcBall, ScreenToVector, iMouseX, iMouseY
m2m s_vCur.x, [eax].D3DVECTOR.x
m2m s_vCur.y, [eax].D3DVECTOR.y
m2m s_vCur.y, [eax].D3DVECTOR.z

invoke D3DXQuaternionAxisToAxis,addr qAxisToAxis, addr s_vDown, addr vCur
mov ecx,me
invoke RtlMoveMemory,addr [ecx].CD3DArcBall.qNow,addr [ecx].CD3DArcBall.qDown,sizeof D3DXQUATERNION ; m_qNow = m_qDown;
mov ecx,me
invoke D3DXQuaternionMultiply,addr [ecx].CD3DArcBall.qNow, addr [ecx].CD3DArcBall.qNow, addr qAxisToAxis
mov ecx,me
invoke D3DXMatrixRotationQuaternion,addr [ecx].CD3DArcBall.matRotationDelta, addr qAxisToAxis
.else
invoke D3DXMatrixIdentity,addr [ecx].CD3DArcBall.matRotationDelta
invoke D3DXMatrixRotationQuaternion,addr [ecx].CD3DArcBall.matRotation, addr [ecx].CD3DArcBall.qNow
mov ecx,me
mov [ecx].CD3DArcBall.bDrag , TRUE
.endif

.elseif (eax & MK_RBUTTON) || (eax & MK_MBUTTON)
; // Normalize based on size of window and bounding sphere radius
; FLOAT fDeltaX = ( iCurMouseX-iMouseX ) * m_fRadiusTranslation / m_iWidth;
fild iCurMouseX
fisub iMouseX
fld [ecx].CD3DArcBall.fRadiusTranslation
fidiv [ecx].CD3DArcBall.iWidth
fmul
fstp fDeltaX
; FLOAT fDeltaY = ( iCurMouseY-iMouseY ) * m_fRadiusTranslation / m_iHeight;
fild iCurMouseY
fisub iMouseY
fld [ecx].CD3DArcBall.fRadiusTranslation
fidiv [ecx].CD3DArcBall.iHeight
fmul
fstp fDeltaY

.if( wParam & MK_RBUTTON )
fld fDeltaX
fmul fp2
fchs
fstp ftemp1 ; -2*fDeltaX
fld fDeltaY
fmul fp2
fstp ftemp2 ; 2*fDeltaY
mov ecx,me
invoke D3DXMatrixTranslation, addr [ecx].CD3DArcBall.matTranslationDelta,ftemp1, ftemp2, fp0
mov ecx,me
invoke D3DXMatrixMultiply, addr [ecx].CD3DArcBall.matTranslation, addr [ecx].CD3DArcBall.matTranslation, addr [ecx].CD3DArcBall.matTranslationDelta
.else ; // wParam & MK_MBUTTON
fld fDeltaY
fmul fp5
fstp ftemp2 ; 5*fDeltaY
mov ecx,me
invoke D3DXMatrixTranslation, addr [ecx].CD3DArcBall.matTranslationDelta, fp0, fp0, ftemp2
mov ecx,me
invoke D3DXMatrixMultiply, addr [ecx].CD3DArcBall.matTranslation, addr [ecx].CD3DArcBall.matTranslation, addr [ecx].CD3DArcBall.matTranslationDelta
.endif

; // Store mouse coordinate
m2m iCurMouseX , iMouseX
m2m iCurMouseY , iMouseY
.endif
return TRUE
.endif

return FALSE
CD3DArcBall_HandleMouseMessages endp

CD3DArcBall_IsBeingDragged proc
return [ecx].CD3DArcBall.bDrag
CD3DArcBall_IsBeingDragged endp

CD3DArcBall_GetTranslationDeltaMatrix proc
lea eax, [ecx].CD3DArcBall.matTranslationDelta
ret
CD3DArcBall_GetTranslationDeltaMatrix endp

CD3DArcBall_GetTranslationMatrix proc
lea eax, [ecx].CD3DArcBall.matTranslation
ret
CD3DArcBall_GetTranslationMatrix endp

CD3DArcBall_GetRotationDeltaMatrix proc
lea eax, [ecx].CD3DArcBall.matRotationDelta
ret
CD3DArcBall_GetRotationDeltaMatrix endp

CD3DArcBall_GetRotationMatrix proc
lea eax, [ecx].CD3DArcBall.matRotation
ret
CD3DArcBall_GetRotationMatrix endp

CD3DArcBall_SetRightHanded proc bRightHanded:DWORD
m2m [ecx].CD3DArcBall.bRightHanded, bRightHanded
ret
CD3DArcBall_SetRightHanded endp
Posted on 2004-07-01 01:47:07 by Homer