Jump to content

Mouse controlled 3D rotation


Recommended Posts

So I'm writing this model viewer for a friend and like in most model software I'm trying to implement an easy way to rotate the model with the mouse.

However I'm not getting it to work in a satisfying way, if you for example just rotate the cube a couple of times in different directions and then try to rotate it further the rotation gets weird.

Here's my code (I'm working with the IrrLicht plugin).

#include <IrrlichtPluginUtils.au3>
#include <GUIConstantsEx.au3>
#include <math.au3>
#include <SliderConstants.au3>
#include <misc.au3>
#include <winapi.au3>
#include <windowsconstants.au3>
Global Const $WM_MOUSEWHEEL = 0x020A 
Global $width = 800
Global $height = 500
Global $title = "Model"
Opt("GUIOnEventMode", 1)
Global $hwnd = GUICreate($title, $width, $height)

GUICtrlCreateMenu("Arkiv")



GUISetOnEvent($GUI_EVENT_CLOSE, "close")

CreateDeviceOnWindow($hwnd, $EDT_DIRECT3D9, 0, 0, $width - 150, $height - 20, 32, 0, 0);

GUISetState()






$cam = AddCameraSceneNode(0, 0, 0, -10, 0, 0, 0)

$Node = AddCubeSceneNode(2)
$Au3Texture = GetTexture("Examples\data\au3.bmp")
SetMaterialTexture($Node, 0, $Au3Texture)
SetMaterialFlag($Node, $EMF_LIGHTING, 0)
SetPosition($Node, 0, 0, 0)





$x = 0
$y=0
$xmod=0
$ymod=0
$scale=1
Global $pressed = True
Global $OldPos

GUIRegisterMsg($WM_MOUSEWHEEL, "_MouseWheel")

Do
    BeginScene(True, True, 255, 0, 0, 0)

    SetRotation($Node, $x, $y, 0)
    SetScale($Node,$scale,$scale,$scale)

    ConsoleWrite($x&@CRLF)
    If _IsPressed("01") Then
        If $pressed Then
            $tpos = MouseGetPos()
            $x +=   ($OldPos[1]-$tpos[1])*$xmod
            $y +=   ($OldPos[0]-$tpos[0])*$ymod
            $OldPos = $tpos
        Else
            $ymod=Sin(_Radian($x))
            $xmod=Cos(_Radian($y))*1
            $OldPos = MouseGetPos()
            $pressed = True
        EndIf
        
        
    Else
        $pressed = False
    EndIf
    

    
    SceneDraw()
    GuiDraw()
    
    EndScene()
    Sleep(10)
Until Not IrrRun()



Func _MouseWheel($hWndGUI, $MsgID, $WParam, $LParam)
    
    If _WinAPI_HiWord($WParam) > 0 Then
        $scale+=0.1
        
    Else
        $scale-=0.1
    EndIf

    Return $GUI_RUNDEFMSG
EndFunc  ;==>_MouseWheel


Func close()
    Exit
EndFunc  ;==>close

I also made a zip so you could test it without having to download irrlicht separately.

http://monoceres.se/Uploads/modelviewer.zip

Thanks.

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

What I found out is that the rotation is working only properly on the very 1st surface at the beginning.

E.g. if you turn to the right, so that the new surface is now in front of you, release mouse button, press mouse

button again and now when you try to rotate it again, the behavour is different.

If you move the cube back to start surface it will rotate again as "normal".

Currently, I don't know how to fix it. :)

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Why do I get the following error ?

...blahblah.au3 (22) : ==> Unknown function name.:

CreateDeviceOnWindow($hwnd, $EDT_DIRECT3D9, 0, 0, $width - 150, $height - 20, 32, 0, 0)

I have all the includes, I extracted the archive in my includes folder.

You need IrrlichtPluginUtils.au3

When the words fail... music speaks.

Link to comment
Share on other sites

I did it some time ago, its very very basic. To open a mesh press M. To open a texture press T. To control zoom, use A and Z keys. To move camera up, down, use D, C. Mouse control rotation.

I hope it helps you.

#Include <Misc.au3>
#include "IrrlichtPluginUtils.au3"

AutoItSetOption( "TrayIconHide", 1 )

;~ $Hwnd = CreateLayeredDevice( "Model Viewer", 0, 0, @DesktopWidth, @DesktopHeight, 255, 0, 128, 1 )
CreateDevice( $EDT_OPENGL, @DesktopWidth, @DesktopHeight, 32, 1, 0, 0 )
SetWindowCaption( "Model Viewer" )

;Add Light
$Light1 = AddLightSceneNode( 0, -1000, 1000, -1000, 0, 0, 0, 0 )
$SLight = AddNewSLight( 1, 50, 1, 500, 3000, $ELT_POINT )
SetLightSpecularColor( $SLight, 0.1, 0.1, 0.1 )
SetLightData( $Light1, $SLight )

$Light2 = AddLightSceneNode( 0, 1000, 1000, 1000, 0, 0, 0, 0 )
SetLightData( $Light2, $SLight )

;Add Camera
$Camera = AddCameraSceneNode( 0, 0, 15, -400, 0, 0, 0 )
SetTarget( $Camera, 0, 15, 0 )

Global $Node

$CurrDir = @ScriptDir
$MouseLastPos = MouseGetPos( )

HotKeySet( "m", "OpenMesh" )
HotKeySet( "t", "OpenTexture" )

$Z = -400
$Y = 15
While IrrRun( )

    BeginScene( true, true, 0, 128, 128, 128 )
    SceneDraw( )
    EndScene( )
    
    If _IsPressed( "41" ) Then
        $Z += 10
        SetPosition( $Camera, 0, $Y, $Z )
    EndIf
    If _IsPressed( "5A" ) Then
        $Z -= 10
        SetPosition( $Camera, 0, $Y, $Z )
    EndIf
    
    If _IsPressed( "44" ) Then
        $Y += 5
        SetPosition( $Camera, 0, $Y, $Z )
        SetTarget( $Camera, 0, $Y, 0 )
    EndIf
    If _IsPressed( "43" ) Then
        $Y -= 5
        SetPosition( $Camera, 0, $Y, $Z )
        SetTarget( $Camera, 0, $Y, 0 )
    EndIf
    
    SetNodeRotationByMouse( $Camera, $Node, $MouseLastPos )

    sleep( 20 )
Wend

Func OpenMesh( )
    $File = FileOpenDialog( "Select a mesh", $CurrDir, "All (*.*)" )
    If @error = 0 Then
        $Max = StringLen( $File ) - 1
        For $i = $Max to 0 step -1
            If StringMid( $File, $i, 1 ) = "\" Then
                $CurrDir = StringLeft( $File, $i - 1 )
                ExitLoop
            EndIf
        Next
        SetVisible( $Node, 0 )
        $Node = AddAnimatedMeshSceneNode( GetMesh( $File ) )
        SetMaterialFlag( $Node, $EMF_BACK_FACE_CULLING, 0 )
        $Y = 15
        $Z = -400
        SetPosition( $Camera, 0, $Y, $Z )
        SetTarget( $Camera, 0, $Y, 0 )
    EndIf
EndFunc

Func OpenTexture( )
    $File = FileOpenDialog( "Select a texture", $CurrDir, "All (*.*)" )
    If @error = 0 Then
        $Max = StringLen( $File ) - 1
        For $i = $Max to 0 step -1
            If StringMid( $File, $i, 1 ) = "\" Then
                $CurrDir = StringLeft( $File, $i - 1 )
                ExitLoop
            EndIf
        Next
        SetMaterialTexture( $Node, 0, GetTexture( $File ) )
    EndIf
EndFunc

Func SetNodeRotationByMouse( $Camera, $Node, ByRef $MouseLastPos )
    Local $DegToRad = ( $PI / 180 )
    Local $Mouse = MouseGetPos( )
    
    If _IsPressed( "01" ) Then
        Local $CameraYRot = GetRotation( $Node, "Y" )
        Local $Movement = ( $Mouse[0] - $MouseLastPos[0] )
        $CameraYRot -= ( $Movement * 900 ) / 3600
        SetRotationByAxis( $Node, "Y", $CameraYRot )
        
        Local $CameraXRot = GetRotation( $Node, "X" )
        $Movement = ( $Mouse[1] - $MouseLastPos[1] )
        $CameraXRot -= ( $Movement * 900 ) / 3600
        SetRotationByAxis( $Node, "X", $CameraXRot )
    EndIf
    $MouseLastPos = $Mouse
EndFunc
Edited by A. Percy

Só o que posso lhe dizer, bom é quando faz mal!My work:Au3Irrlicht - Irrlicht for AutoItMsAgentLib - An UDF for MSAgentAu3GlPlugin T2 - A 3D plugin for AutoIt...OpenGl Plugin - The old version of Au3GlPlugin.MAC Address Changer - Changes the MAC AddressItCopter - A dragonfly R/C helicopter simulator

VW Bug user

Pinheiral (Pinewood) city:

http://pt.wikipedia.org/wiki/Pinheiral

Link to comment
Share on other sites

So I tried Percy's version, but it suffers from the same thing as mine, that is, the rotatation gets off when you have already rotated the box.

The simpliest way to reproduce is to first rotate the model 90 degrees to the left/right and then dragging the mouse upwards (the model should rotate up, but instead spins around the z-axis).

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

So I tried Percy's version, but it suffers from the same thing as mine, that is, the rotatation gets off when you have already rotated the box.

The simpliest way to reproduce is to first rotate the model 90 degrees to the left/right and then dragging the mouse upwards (the model should rotate up, but instead spins around the z-axis).

I have an idea... I'll try later in my house. Do the rotation on X as example, do it on Z axis too, but both multiplied by sin( Y ) on X and cos( Y ) on Z...

Edited by A. Percy

Só o que posso lhe dizer, bom é quando faz mal!My work:Au3Irrlicht - Irrlicht for AutoItMsAgentLib - An UDF for MSAgentAu3GlPlugin T2 - A 3D plugin for AutoIt...OpenGl Plugin - The old version of Au3GlPlugin.MAC Address Changer - Changes the MAC AddressItCopter - A dragonfly R/C helicopter simulator

VW Bug user

Pinheiral (Pinewood) city:

http://pt.wikipedia.org/wiki/Pinheiral

Link to comment
Share on other sites

I have an idea... I'll try later in my house. Do the rotation on X as example, do it on Z axis too, but both multiplied by sin( Y ) on X and cos( Y ) on Z...

Yeah, sounds good. I've already failed with the trig stuff so hopefully you crack this one :)

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Ok, I did:

#Include <Misc.au3>
#include "IrrlichtPluginUtils.au3"

AutoItSetOption( "TrayIconHide", 1 )

;~ $Hwnd = CreateLayeredDevice( "Model Viewer", 0, 0, @DesktopWidth, @DesktopHeight, 255, 0, 128, 1 )
CreateDevice( $EDT_OPENGL, @DesktopWidth, @DesktopHeight, 32, 1, 0, 0 )
SetWindowCaption( "Model Viewer" )

;Add Light
$Light1 = AddLightSceneNode( 0, -1000, 1000, -1000, 0, 0, 0, 0 )
$SLight = AddNewSLight( 1, 50, 1, 500, 3000, $ELT_POINT )
SetLightSpecularColor( $SLight, 0.1, 0.1, 0.1 )
SetLightData( $Light1, $SLight )

$Light2 = AddLightSceneNode( 0, 1000, 1000, 1000, 0, 0, 0, 0 )
SetLightData( $Light2, $SLight )

;Add Camera
$Camera = AddCameraSceneNode( 0, 0, 15, -400, 0, 0, 0 )
SetTarget( $Camera, 0, 15, 0 )

Global $Node
Global $Parent

$CurrDir = @ScriptDir
$MouseLastPos = MouseGetPos( )

HotKeySet( "m", "OpenMesh" )
HotKeySet( "t", "OpenTexture" )

$Z = -400
$Y = 15
While IrrRun( )

    BeginScene( true, true, 0, 128, 128, 128 )
    SceneDraw( )
    EndScene( )
    
    If _IsPressed( "41" ) Then
        $Z += 10
        SetPosition( $Camera, 0, $Y, $Z )
    EndIf
    If _IsPressed( "5A" ) Then
        $Z -= 10
        SetPosition( $Camera, 0, $Y, $Z )
    EndIf
    
    If _IsPressed( "44" ) Then
        $Y += 5
        SetPosition( $Camera, 0, $Y, $Z )
        SetTarget( $Camera, 0, $Y, 0 )
    EndIf
    If _IsPressed( "43" ) Then
        $Y -= 5
        SetPosition( $Camera, 0, $Y, $Z )
        SetTarget( $Camera, 0, $Y, 0 )
    EndIf
    
    SetNodeRotationByMouse( $Camera, $Node, $MouseLastPos )

    sleep( 20 )
Wend

Func OpenMesh( )
    $File = FileOpenDialog( "Select a mesh", $CurrDir, "All (*.*)" )
    If @error = 0 Then
        $Max = StringLen( $File ) - 1
        For $i = $Max to 0 step -1
            If StringMid( $File, $i, 1 ) = "\" Then
                $CurrDir = StringLeft( $File, $i - 1 )
                ExitLoop
            EndIf
        Next
        SetVisible( $Parent, 0 )
        
        $Parent = AddEmptySceneNode( )
        $Node = AddAnimatedMeshSceneNode( GetMesh( $File ) )
        AddChild( $Parent, $Node )
        SetMaterialFlag( $Node, $EMF_BACK_FACE_CULLING, 0 )
        $Y = 15
        $Z = -400
        SetPosition( $Camera, 0, $Y, $Z )
        SetTarget( $Camera, 0, $Y, 0 )
    EndIf
EndFunc

Func OpenTexture( )
    $File = FileOpenDialog( "Select a texture", $CurrDir, "All (*.*)" )
    If @error = 0 Then
        $Max = StringLen( $File ) - 1
        For $i = $Max to 0 step -1
            If StringMid( $File, $i, 1 ) = "\" Then
                $CurrDir = StringLeft( $File, $i - 1 )
                ExitLoop
            EndIf
        Next
        SetMaterialTexture( $Node, 0, GetTexture( $File ) )
    EndIf
EndFunc

Func SetNodeRotationByMouse( $Camera, $Node, ByRef $MouseLastPos )
    Local $DegToRad = ( $PI / 180 )
    Local $Mouse = MouseGetPos( )
    Local $PiRad = $PI / 180
    
    If _IsPressed( "01" ) Then
        Local $YRot = GetRotation( $Parent, "Y" )
        Local $Movement = ( $Mouse[0] - $MouseLastPos[0] )
        $YRot -= ( $Movement * 900 ) / 3600
        SetRotationByAxis( $Parent, "Y", $YRot )
        
        Local $XRot = GetRotation( $Node, "X" )
        $Movement = ( $Mouse[1] - $MouseLastPos[1] ) * sin( ( GetRotation( $Parent, "Y" ) + 90 ) * $PiRad )
        $XRot -= ( $Movement * 900 ) / 3600
        SetRotationByAxis( $Node, "X", $XRot )
        ;ConsoleWrite( "X: " & $Movement & " " )
        
        Local $ZRot = GetRotation( $Node, "Z" )
        $Movement = ( $Mouse[1] - $MouseLastPos[1] ) * cos( ( GetRotation( $Parent, "Y" ) + 90 ) * $PiRad )
        $ZRot += ( $Movement * 900 ) / 3600
        SetRotationByAxis( $Node, "Z", $ZRot )
        ;ConsoleWrite( "Z: " & $Movement & @CRLF )
    EndIf
    $MouseLastPos = $Mouse
EndFunc
Edited by A. Percy

Só o que posso lhe dizer, bom é quando faz mal!My work:Au3Irrlicht - Irrlicht for AutoItMsAgentLib - An UDF for MSAgentAu3GlPlugin T2 - A 3D plugin for AutoIt...OpenGl Plugin - The old version of Au3GlPlugin.MAC Address Changer - Changes the MAC AddressItCopter - A dragonfly R/C helicopter simulator

VW Bug user

Pinheiral (Pinewood) city:

http://pt.wikipedia.org/wiki/Pinheiral

Link to comment
Share on other sites

Any news?

Só o que posso lhe dizer, bom é quando faz mal!My work:Au3Irrlicht - Irrlicht for AutoItMsAgentLib - An UDF for MSAgentAu3GlPlugin T2 - A 3D plugin for AutoIt...OpenGl Plugin - The old version of Au3GlPlugin.MAC Address Changer - Changes the MAC AddressItCopter - A dragonfly R/C helicopter simulator

VW Bug user

Pinheiral (Pinewood) city:

http://pt.wikipedia.org/wiki/Pinheiral

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...