Announcements
Due to scheduled maintenance, the Autodesk Community will be inaccessible from 10:00PM PDT on Oct 16th for approximately 1 hour. We appreciate your patience during this time.
Community
Inventor Programming - iLogic, Macros, AddIns & Apprentice
Inventor iLogic, Macros, AddIns & Apprentice Forum. Share your knowledge, ask questions, and explore popular Inventor topics related to programming, creating add-ins, macros, working with the API or creating iLogic tools.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Imitating Full Navigation Wheel orbit/pan/zoom through COM API and VB.NET

5 REPLIES 5
SOLVED
Reply
Message 1 of 6
jrowberg
2654 Views, 5 Replies

Imitating Full Navigation Wheel orbit/pan/zoom through COM API and VB.NET

Hey everyone!

 

I've been trying my best to get familiar with the Autodesk Inventor COM API for the purpose of integrating a new 3D input device (the Keyglove) for intuitive control. I have worked through the "My first plugin" example, and I have basic COM integration working using VB.NET in Visual Studio 2010. I've been able to rotate the camera's view around a single axis by applying a rotation matrix transform to the camera's UpVector property:

 

Dim Pi As Double = 3.14159265358979
Dim appInventor As Inventor.Application
Dim oCamera As Inventor.Camera
Dim oRotAxis As Inventor.Vector
Dim oRotMatrix As Inventor.Matrix
Dim oUpVector As Inventor.UnitVector

Try
appInventor = System.Runtime.InteropServices.Marshal.GetActiveObject("Inventor.Application")
oCamera = appInventor.ActiveView.Camera
oRotMatrix = appInventor.TransientGeometry.CreateMatrix
Catch ex As Exception
appInventor = Nothing
MsgBox("Unable to locate running Autodesk Inventor instance: " & ex.Message)
End Try

If Not appInventor Is Nothing Then
' apply rotation around camera's Z axis
oUpVector = oCamera.UpVector
oRotAxis = appInventor.TransientGeometry.CreateVector(oCamera.Target.X - oCamera.Eye.X, oCamera.Target.Y - oCamera.Eye.Y, oCamera.Target.Z - oCamera.Eye.Z)
Call oRotMatrix.SetToRotation(Pi / 4, oRotAxis, oCamera.Eye)
Call oUpVector.TransformBy(oRotMatrix)
oCamera.UpVector = oUpVector
oCamera.ApplyWithoutTransition()
End If

 

...and I've been able to rotate around the other two axes by using the Camera.ComputeWIthMouseInput() method:

 

' apply rotation around camera's X and Y axes
oCamera.ComputeWithMouseInput(appInventor.TransientGeometry.CreatePoint2d(0, 0), appInventor.TransientGeometry.CreatePoint2d(5, 5), 0, Inventor.ViewOperationTypeEnum.kRotateViewOperation)

But I cannot for the life of me figure out how to achieve what I'm really after: a programmatic equivalent to the "Orbit" action that is done on all three rotational axes at once. I would ultimately like to reproduce all aspects of the Full Navigation Wheel through the COM API, but right now I'll settle for 3D orbiting. The pan and zoom operations seem to be doable through the ComputeWithMouseInput() method, though I'd imagine there's a better, more direct way to do that with raw camera eye/target transformation as well.

 

When using the Orbit tool on the Full Navigation Wheel, the mouse X/Y axes control orientation about the Y and X axes respectively, centered around the pivot point. If you hold down shift to enable "roll" mode, the mouse Y axis is ignored, and the mouse X axis controls orientation about the Z axis. The Keyglove provides angular rotation data on all three axes at once, so there is no need to toggle between X/Y control and Z control; it should be easily possible to do them all at the same time. I can't figure out how though.

 

Has anyone done this kind of thing before, or can you provide any pointers? I feel like I'm really close, but lacking in familiarity with the COM API and/or the ability to visualize and code the correct spatial geometry calculations.

5 REPLIES 5
Message 2 of 6
jrowberg
in reply to: jrowberg

Reading some more of the API Help reference docs, I think I understand at least why my previous efforts at rotating the up vector by different axes didn't work right. As stated in the API Help, "Setting the up vector does not change the eye or target points, but rotates the camera about the vector defined by the eye and target points." So, it's totally impossible to do anything except rotate around the relative forward/backward Z axis of the camera by changing the up vector.

 

It seems then that the correct approach to mimic the Orbit tool would be to keep the camera target the same, keep the distance from the eye to the target the same, and rotate the eye around the target on all three axes. This is probably close enough to what I'm going for, but it isn't a true Orbit operation, since the Orbit tool rotates around a movable point that may not be the camera target. API control that is a true interface to the Orbit tool would be preferable.

 

In the mean time, I'll see if I can make any headway on these rotations. I am guessing that the calculations will go something like this:

 

  1. Get vector between camera eye and camera target (a.k.a. relative Z axis).
  2. Get camera up vector.
  3. Compute relative Y axis from up vector (Y axis must run through camera target point).
  4. Compute relative orthoganal X axis from Y and Z axes (X axis runs through camera target point).
  5. Rotate camera eye around X, Y, and Z axes based on appropriate 3D gyroscopic input.
  6. Apply updates and bask in 3D input glory!

Something like that. I may have missed something. As always, any help is appreciated.

Message 3 of 6
jrowberg
in reply to: jrowberg

Okay, so I've got ALMOST what I'm after, but it's missing a key feature. I got the camera to orbit around all three axes as described in my previous post, but while it mimics the mouse-controlled orbit feature, it's missing an intuitive advantage of a true 3D input device, namely this:

 

While orbiting with the mouse (not in "Roll" mode, i.e. without holding down Shift), moving the mouse left and right ALWAYS rotates around the vertical axis through the pivot point, and moving the mouse up and down ALWAYS rotates around the horizontal axis through the pivot point perpendicular to the camera's Up vector. So, it rolls "forward" or "backward" relative to the direction you are looking.

 

So, while orbiting with all three dimensions using gyro rotational values using a wearable device (not just a rotating, spinnable trackball or something), the axes themselves should maintain their rotations as long as the orbit is active. That is to say, tilting "forward" from the initial state should do as the regular orbit tool does (roll the object "forward"), but rotating around the Y axis 90 degrees and THEN tilting the Keyglove forward should actually rotate the object left (since the relative "front" of the object will have been rotated to face left). I cannot figure out how to adjust the rotational axes correctly to make that happen.

 

Here is my current code. The x/y/zPersistTransform matrices are what I am attempting to use to maintain the right rotation. Notice that when rotating around the X axis, the Y and Z axes are themselves rotated, and a simliar thing happens when rotating around the Y and Z axes. This almost seems to work, but it isn't right. If you take out the x/y/zPersistTransform stuff, it works like the regular Orbit tool...but that's not what I need.

 

Any pointers?

 

Dim oCamera As Inventor.Camera = appInventor.ActiveView.Camera
Dim oEye As Inventor.Point = oCamera.Eye

Dim axisTransform As Inventor.Matrix

If xPersistTransform Is Nothing Then
xPersistTransform = appInventor.TransientGeometry.CreateMatrix
yPersistTransform = appInventor.TransientGeometry.CreateMatrix
zPersistTransform = appInventor.TransientGeometry.CreateMatrix
End If

' setup Z axis (from camera eye to camera target)
Dim zAxis As Inventor.Vector = oCamera.Target.VectorTo(oEye)

' setup Y axis (through camera target, vertically perpendicular to Z axis)
axisTransform = appInventor.TransientGeometry.CreateMatrix
Call axisTransform.SetTranslation(zAxis)
Dim yAxis As Inventor.UnitVector = oCamera.UpVector
Call yAxis.TransformBy(axisTransform)

' setup X axis (through camera target, horizontally perpendicular to Z axis)
Dim xAxis As Inventor.UnitVector = oCamera.UpVector
Call xAxis.TransformBy(axisTransform)
axisTransform = appInventor.TransientGeometry.CreateMatrix
Call axisTransform.SetToRotation(Pi / 2, zAxis, oEye)
Call xAxis.TransformBy(axisTransform)

' rotate to maintain our existing rotation
Call xAxis.TransformBy(xPersistTransform)
Call xAxis.TransformBy(yPersistTransform)
Call xAxis.TransformBy(zPersistTransform)
Call yAxis.TransformBy(xPersistTransform)
Call yAxis.TransformBy(yPersistTransform)
Call yAxis.TransformBy(zPersistTransform)
Call zAxis.TransformBy(xPersistTransform)
Call zAxis.TransformBy(yPersistTransform)
Call zAxis.TransformBy(zPersistTransform)

Dim oRotMatrix As Inventor.Matrix

' rotate camera "up" vector around Z axis (position stays the same, but camera rotates)
oRotMatrix = appInventor.TransientGeometry.CreateMatrix
Dim oUpVector As Inventor.UnitVector = oCamera.UpVector
Call oRotMatrix.SetToRotation(gyroZ * Pi / 7200, zAxis, oCamera.Target)
Call oUpVector.TransformBy(oRotMatrix)
Call oRotMatrix.SetToRotation(-gyroZ * Pi / 7200, zAxis, oCamera.Target)
Call xAxis.TransformBy(oRotMatrix)
Call xPersistTransform.TransformBy(oRotMatrix)
Call yAxis.TransformBy(oRotMatrix)
Call yPersistTransform.TransformBy(oRotMatrix)
oCamera.UpVector = oUpVector

' rotate camera eye around X axis (camera eye moves around target point)
oRotMatrix = appInventor.TransientGeometry.CreateMatrix
Call oRotMatrix.SetToRotation(gyroX * Pi / 7200, xAxis.AsVector, oCamera.Target)
Call oEye.TransformBy(oRotMatrix)
Call oRotMatrix.SetToRotation(-gyroX * Pi / 7200, xAxis.AsVector, oCamera.Target)
Call yAxis.TransformBy(oRotMatrix)
Call yPersistTransform.TransformBy(oRotMatrix)
Call zAxis.TransformBy(oRotMatrix)
Call zPersistTransform.TransformBy(oRotMatrix)

' rotate camera eye around Y axis (camera eye moves around target point)
oRotMatrix = appInventor.TransientGeometry.CreateMatrix
Call oRotMatrix.SetToRotation(gyroY * Pi / 7200, yAxis.AsVector, oCamera.Target)
Call oEye.TransformBy(oRotMatrix)
Call oRotMatrix.SetToRotation(-gyroY * Pi / 7200, yAxis.AsVector, oCamera.Target)
Call xAxis.TransformBy(oRotMatrix)
Call xPersistTransform.TransformBy(oRotMatrix)
Call zAxis.TransformBy(oRotMatrix)
Call zPersistTransform.TransformBy(oRotMatrix)

oCamera.Eye = oEye
oCamera.ApplyWithoutTransition()
Tags (4)
Message 4 of 6
adam.nagy
in reply to: jrowberg

Hi there,

 

I think this is what you are trying to do. When you start rotating then you want to rotate round the screen X, Y and Z, and you want to keep rotating around those even if the model got transformed by the rotation.

So I think you just need to store the screen axes:

<code>

PublicClass Form1

 

  PrivateConst unit AsDouble = 0.1

 

  Private Sub left_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles left.Click

    ChangeView(unit, 0, 0)

  EndSub

 

  Private Sub up_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles up.Click

    ChangeView(0, unit, 0)

  EndSub

 

  Private Sub right_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles right.Click

    ChangeView(-unit, 0, 0)

  EndSub

 

  Private Sub down_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles down.Click

    ChangeView(0, -unit, 0)

  EndSub

 

  Private Sub rotate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rotate.Click

    ChangeView(0, 0, unit)

  EndSub

 

  Private screenX As Inventor.Vector

  Private screenY As Inventor.Vector

  Private screenZ As Inventor.Vector

 

  PrivateSub ChangeView(ByVal gyroY AsDouble, ByVal gyroX AsDouble, ByVal gyroZ AsDouble)

 

    Dim appInventor As Inventor.Application = System.Runtime.InteropServices.Marshal.GetActiveObject("Inventor.Application")

    Dim oCamera As Inventor.Camera = appInventor.ActiveView.Camera

    Dim oGeom As Inventor.TransientGeometry = appInventor.TransientGeometry 

 

    ' Get screen vectors

 

    If screenX IsNothingThen

      screenZ = oCamera.Target.VectorTo(oCamera.Eye)

      screenZ.Normalize 

 

      screenY = oCamera.UpVector.AsVector 

 

      screenX = screenY.CrossProduct(screenZ) 

    EndIf

 

    ' Transform around those axes

 

    Dim rotX As Inventor.Matrix = oGeom.CreateMatrix 

    rotX.SetToRotation(gyroX, screenX, oCamera.Target)

 

    Dim rotY As Inventor.Matrix = oGeom.CreateMatrix 

    rotY.SetToRotation(gyroY, screenY, oCamera.Target)

 

    Dim rotZ As Inventor.Matrix = oGeom.CreateMatrix 

    rotZ.SetToRotation(gyroZ, screenZ, oCamera.Target)

 

    Dim rot As Inventor.Matrix = oGeom.CreateMatrix

    rot = rotX

    rot.PostMultiplyBy(rotY)

    rot.PostMultiplyBy(rotZ) 

 

    Dim newEye As Inventor.Point = oCamera.Eye 

    newEye.TransformBy(rot)  

 

    Dim newUp As Inventor.UnitVector = oCamera.UpVector

    newUp.TransformBy(rot)  

 

    oCamera.Eye = newEye 

    oCamera.UpVector = newUp  

    oCamera.ApplyWithoutTransition()

 

  EndSub

 

  Private Sub clear_Click( ByVal sender As System.Object,  ByVal e As System.EventArgs) Handles clear.Click

    screenX = Nothing

    screenY = Nothing

    screenZ = Nothing

  EndSub

 

EndClass

</code>

 

In this sample you click "Clear" once the rotation is finished.

 

I hope this helps.

 

______________________________________________________________

If my post answers your question, please click the "Accept as Solution"

button. This helps everyone find answers more quickly!



Adam Nagy
Autodesk Platform Services
Message 5 of 6
jrowberg
in reply to: adam.nagy

Brilliant solution, Adam! Far simpler than mine, and it actually works (now that I've had a chance to implement it two weeks later). I really appreciate your expertise. Thanks!

Message 6 of 6
adam.nagy
in reply to: jrowberg

You're welcome!

I'm glad you liked it 🙂



Adam Nagy
Autodesk Platform Services

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report