Community
Meshmixer
Welcome to Autodesk’s Meshmixer Forums. Share your knowledge, ask questions, and explore popular Meshmixer topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Camera Coordinate System

11 REPLIES 11
Reply
Message 1 of 12
simone.lodi.90
928 Views, 11 Replies

Camera Coordinate System

Hi all, 

i use meshmixer on win10 with SpaceMouse. I need to know how the coordinate system works between camera and object. When i rotate the view around the object with the spacemouse, i want to know exactly what is the camera position in the environment. If this info is not obtainable in meshmixer, there is some other software that can read stl files, interact with SpaceMouse and give info on the position of the camera/object?

11 REPLIES 11
Message 2 of 12
MagWeb
in reply to: simone.lodi.90

No way I know to get the current camera origin and direction in MM's GUI. 

Instead using the mmApi you can query the camera position and orientation. Some Python skills?



Gunter Weber
Triangle Artisan

Message 3 of 12
simone.lodi.90
in reply to: MagWeb

Not quite, i'm used to MATLAB thogh and i have some basics of programming. In fact, already come to my knowledge the existence of mmApi and i've already installed Python. Looking forward for this solution, even because the second step of my project involves "remote" use of MeshMixer (i have to get camera position, modify it and than update the mm view). If you have some tips for me, i'm glad to listen. 

Anyway, thanks for the kind and fast response, much appreciated!

Message 4 of 12
MagWeb
in reply to: simone.lodi.90

Here are two codes which might help.

The camera stuff isn't documented as it didn't find its way to the mm modules. No worries, you just need to call these functions directly.

This prints the current cam info and position to the Python shell. 

Note: Internally MM uses a "normalised" coordinates system. Therefor you may want to convert the output values to real World coordinates.

import mmapi
from mmRemote import *
import mm

remote = mmRemote()
remote.connect()

###Variables:
f = mmapi.frame3f()
target = mmapi.vec3f()
cam_info = mmapi.camera_info()
origin = mmapi.vec3f()
camTarget = mmapi.vec3f()

###Get camera data:
cmd2 = mmapi.StoredCommands()
cam_key = cmd2.CameraControl_QueryCamera()
remote.runCommand(cmd2)
cmd2.CameraControl_QueryCameraResult(cam_key,f,target,cam_info)
remote.runCommand(cmd2)

print "RAW OUTPUT of QueryCamera in MM's normalized Scene coordinates:"
print "Cam coordinates: ", [f.origin_x,f.origin_y,f.origin_z]
print "Cam normal direction: ", [f.normal_x,f.normal_y,f.normal_z]
print "Cam left direction: " , [f.tan1_x,f.tan1_y,f.tan1_z]
print "Cam up direction: ", [f.tan2_x,f.tan2_y,f.tan2_z]
print "Target of the cams center line: " , [target.x, target.y, target.z ]
print "Field of View angle: " , cam_info.horzFOVDegrees
print "Width of 3D scene (pixels): " , cam_info.width
print "Height of 3D scene (pixels): " , cam_info.height

###Conversion to real World coordinates:
origin.x = mm.toW(remote,f.origin_x)
origin.y = mm.toW(remote,f.origin_y)
origin.z = mm.toW(remote,f.origin_z)

camTarget.x = mm.toW(remote,target.x)
camTarget.y = mm.toW(remote,target.y)
camTarget.z = mm.toW(remote,target.z)

###Needed data to set the cam back to a stored position:
print "CONVERTED to World coordinates:"
print "Cam coordinates (World): ", [origin.x, origin.y, origin.z ]
print "Target coordinates (World): ", [camTarget.x, camTarget.y, camTarget.z ]
print "Up direction normal: ", [f.tan2_x, f.tan2_y, f.tan2_z]

remote.shutdown()

This code sets a new cam position:

Note: Setting a cam position works properly only if you are in perspective view mode (> View menu) so I force this mode at the beginning and switch to orthographic (you might comment that out) at the end.

import mmapi
from mmRemote import *
import mm

remote = mmRemote()
remote.connect()

### Force perspective view.
cmd2 = mmapi.StoredCommands()
cmd2.CameraControl_SetPerspectiveView()
remote.runCommand(cmd2)

### Just some values to set World coordinates:
o = [205.0062713623047, 196.65916442871094, 205.0062713623047]
t = [2.7823712825775146, -5.564741611480713, 2.7823712825775146]
### normal vector:
u = [-0.40824830532073975, 0.8164966106414795, -0.40824830532073975]

### Variables:
origin = mmapi.vec3f()
target = mmapi.vec3f()
up = mmapi.vec3f()

### Converting World coordinates to MM's scene coordinates:
origin.x = mm.toS(remote, float(o[0]))
origin.y = mm.toS(remote, float(o[1]))
origin.z = mm.toS(remote, float(o[2]))

target.x = mm.toS(remote,float(t[0]))
target.y = mm.toS(remote,float(t[1]))
target.z = mm.toS(remote, float(t[2]))

up.x = float(u[0])
up.y = float(u[1])
up.z = float(u[2])

### Set camera:
cmd2 = mmapi.StoredCommands()
cmd2.CameraControl_SetSpecificView(origin,target,up)
remote.runCommand(cmd2)

### Optional: Switch to orthographic view:
cmd2 = mmapi.StoredCommands()
cmd2.CameraControl_SetOrthographicView()
remote.runCommand(cmd2)

remote.shutdown()

 



Gunter Weber
Triangle Artisan

Message 5 of 12
simone.lodi.90
in reply to: MagWeb

Thanks alot for the response!

I'm trying the code but i have trouble with the proper installation of mmapi.

I've installed the following:

- Python 3.7.4

- Visual Studio 2019

- Anaconda 3 / Spider 3.3.6

- Meshmixer 3.5.474

Then i've downloaded mmapi from github, run build_python_distrib.bat from the main folder (no error here). 

I've added to the windows path the address of the folder containing mmapi.py and mmRemote.py (namely ***\mm-api-master\distrib\python).

Lastly, opened Windows Powershell and tryed to setup the thing, typing:

cd  ***\mm-api-master\distrib\python

python setup.py install

but it broke at:

c1xx: fatal error C1083: Cannot open source file: 'mmapi.cpp': No such file or directory.

 

How do i fix it? 😞

 

Message 6 of 12

UPDATE:

with the help of a collegue i've finally done it: 

i've moved mm folder and mmRemote.py to the script folder than updated all mm folder .py files, modifying "import thing" in "import mm.thing". Now it works! 

Message 7 of 12

Looking at the coordinates, a new question came to my mind:
how evaluate normalized scene coordinates and how these are related to World Coordinates? 

I guess scene coordinates are related to the scene frame of reference that i can "inspect" with View/Show Grid option, but what about world coordinates?

Message 8 of 12
MagWeb
in reply to: simone.lodi.90

There's no fix ratio of MM's internal scene coordinates to world coordinates.

Internally MM takes the very first object (let's say its World size is 78x54x67) you load to a fresh scene as a internal unit. Objects added later on are handled in ratio to that very first object.

Calling scene coordinates of the very first object MM always returns  scene coordinates in the range of -1 to +1. Means the biggest dimension (in upper case 78) owns the length of 2. 

At the same time MM remembers the real world length and its center and uses the ratio of realWorldLength/sceneLength (78/2) to convert scene to-world coordinates.

Editing that object (e.g. scaling it along X by factor 2 = 156) and calling scene coordinates will return a length (X_max - X_Min) of 4. Multiplied by 78/2 will give the world length.

 

Hint: In case the very first object is 2x2x2 (BB_Min = -1,-1,-1  and BB_Max is 1,1,1 so it is centred at the origin) MM's scene coordinates are equal to world coordinates.



Gunter Weber
Triangle Artisan

Message 9 of 12
hfcandrew
in reply to: MagWeb

My work around to normalize this for repetitive use of an API script has been to:

1) Start MM and load a primitive such as a the Bunny

2) Make it not visible.

3) Create my API workflow based on that scene

4) Save that scene as a .mix.

5) Then anytime I know I want to use my script I load my new .stl into that saved .mix scene and run it from there.

Message 10 of 12

 
Hello,
I am looking for a solution to achieve this task of saving the focus and view point within meshmixer in a scene, I have read that you have achieved it. I would like to ask you if you could share your development, I wouldn't mind paying for the achievement... or I don't know if you could give me some indication to achieve it, I would be very grateful.... I await your response. Thank you very much for your attention. Greetings
Message 11 of 12

Hi man! Glad to help! 
Disclaimer: i moved away from the project because i actually changed job, and moreover in later iterations i was actually moving to cv2. 

Anyway i digged out what i recall SHOULD be the latest working script i was up to. I based that upon what the real masters told me just in this post, so i'm just glad to help! 

Let me know if something is not working, i can try to give you some more code if needed (this script was part of a more complex project, and frankly i dont remember well if this would be a stand alone).

 

# -*- coding: utf-8 -*-
"""
Created on Mon Nov 25 09:43:06 2019

@author: Simone Lodi
"""

import mmapi
### from mmRemote import *
from mmRemote import mmRemote
import mm
import numpy as np

def GetCamCoord(continuos=False, FileName='default_output', verbose=False, world=False):
    remote = mmRemote()
    if continuos:
        remote.connect()
        while True:
            ###Variables:
            f = mmapi.frame3f()
            w = mmapi.frame3f()
            target = mmapi.vec3f()
            cam_info = mmapi.camera_info()
            origin = mmapi.vec3f()
            camTarget = mmapi.vec3f()
            
            ###Get camera data:
            cmd2 = mmapi.StoredCommands()
            cam_key = cmd2.CameraControl_QueryCamera()
            remote.runCommand(cmd2)
            cmd2.CameraControl_QueryCameraResult(cam_key,f,target,cam_info)
            remote.runCommand(cmd2)
            
            # Converting tangents to degree angles
            Tans = (f.tan2_x,f.tan2_y,f.tan2_z)
            Angle_Rad = np.arctan2(Tans)
            Angle_Deg = Angle_Rad*180/np.pi
            
            ###Output data:
            # DirOut = INSERT YOUR DIRECTORY;
            if world:
                ### Conversion to 'real' World coordinates:
                WoX = mm.toW(remote,f.origin_x)
                WoY = mm.toW(remote,f.origin_y)
                WoZ = mm.toW(remote,f.origin_z)
                
                WtX = mm.toW(remote,target.x)
                WtY = mm.toW(remote,target.y)
                WtZ = mm.toW(remote,target.z)
                Coord =  [(WoX,WoY,WoZ),
                          (WtX,WtY,WtZ),
                          Angle_Deg]
            else:
                Coord =  [(f.origin_x,f.origin_y,f.origin_z),
                          (target.x, target.y, target.z),
                          Angle_Deg]
            if verbose:
                print("RAW OUTPUT of QueryCamera in MM's normalized Scene coordinates:")
                print("Cam coordinates: ", [f.origin_x,f.origin_y,f.origin_z])
                print("Cam normal direction: ", [f.normal_x,f.normal_y,f.normal_z])
                print("Cam left direction: " , [f.tan1_x,f.tan1_y,f.tan1_z])
                print("Cam up direction: ", [f.tan2_x,f.tan2_y,f.tan2_z])
                print("Target of the cams center line: " , [target.x, target.y, target.z ])
                print("Field of View angle: " , cam_info.horzFOVDegrees)
                print("Width of 3D scene (pixels): " , cam_info.width)
                print("Height of 3D scene (pixels): " , cam_info.height)
                
                ##Needed data to set the cam back to a stored position:
                print("CONVERTED to World coordinates:")
                print("Cam coordinates (World): ", [origin.x, origin.y, origin.z ])
                print("Target coordinates (World): ", [camTarget.x, camTarget.y, camTarget.z ])
                print("Up direction normal: ", [f.tan2_x, f.tan2_y, f.tan2_z])
            print(Coord)
        remote.shutdown()
    else:
        remote.connect()
        ###Variables:
        f = mmapi.frame3f()
        w = mmapi.frame3f()
        target = mmapi.vec3f()
        cam_info = mmapi.camera_info()
        origin = mmapi.vec3f()
        camTarget = mmapi.vec3f()
        
        ###Get camera data:
        cmd2 = mmapi.StoredCommands()
        cam_key = cmd2.CameraControl_QueryCamera()
        remote.runCommand(cmd2)
        cmd2.CameraControl_QueryCameraResult(cam_key,f,target,cam_info)
        remote.runCommand(cmd2)
             
        ###Output data:
        DirOut = INSERT YOUR DIRECTORY;
        # Coord = (Cam coordinates, Target coordinates, Cam up direction)
        
        # Converting tangents to degree angles
        Tans = (f.tan2_x,f.tan2_y,f.tan2_z)
        Angle_Rad_xy = np.arctan2(f.tan2_x,f.tan2_y)
        Angle_Rad_xz = np.arctan2(f.tan2_x,f.tan2_z)
        Angle_Rad_yz = np.arctan2(f.tan2_y,f.tan2_z)
        
        Angle_Deg_xy = Angle_Rad_xy*180/np.pi
        Angle_Deg_xz = Angle_Rad_xz*180/np.pi
        Angle_Deg_yz = Angle_Rad_yz*180/np.pi
        Angle_Deg = [Angle_Deg_xy, Angle_Deg_xz, Angle_Deg_yz]
        
        if world:
            ### Conversion to 'real' World coordinates:
#            w.origin.x = mm.toW(remote,f.origin_x)
#            w.origin.y = mm.toW(remote,f.origin_y)
#            w.origin.z = mm.toW(remote,f.origin_z)
#            
#            w.target.x = mm.toW(remote,target.x)
#            w.target.y = mm.toW(remote,target.y)
#            w.target.z = mm.toW(remote,target.z)
            WoX = mm.toW(remote,f.origin_x)
            WoY = mm.toW(remote,f.origin_y)
            WoZ = mm.toW(remote,f.origin_z)
            
            WtX = mm.toW(remote,target.x)
            WtY = mm.toW(remote,target.y)
            WtZ = mm.toW(remote,target.z)
            Coord =  [(WoX,WoY,WoZ),
                      (WtX,WtY,WtZ),
                      Angle_Deg]
        else:
            Coord =  [(f.origin_x,f.origin_y,f.origin_z),
                      (target.x, target.y, target.z),
                      Angle_Deg]
        if verbose:
            print("RAW OUTPUT of QueryCamera in MM's normalized Scene coordinates:")
            print("Cam coordinates: ", [f.origin_x,f.origin_y,f.origin_z])
            print("Cam normal direction: ", [f.normal_x,f.normal_y,f.normal_z])
            print("Cam left direction: " , [f.tan1_x,f.tan1_y,f.tan1_z])
            print("Cam up direction: ", [f.tan2_x,f.tan2_y,f.tan2_z])
            print("Target of the cams center line: " , [target.x, target.y, target.z ])
            print("Field of View angle: " , cam_info.horzFOVDegrees)
            print("Width of 3D scene (pixels): " , cam_info.width)
            print("Height of 3D scene (pixels): " , cam_info.height)
        
            ##Needed data to set the cam back to a stored position:
            print("CONVERTED to World coordinates:")
            print("Cam coordinates (World): ", [origin.x, origin.y, origin.z ])
            print("Target coordinates (World): ", [camTarget.x, camTarget.y, camTarget.z ])
            print("Up direction normal: ", [f.tan2_x, f.tan2_y, f.tan2_z])
            
        CoordStr = str(Coord[0])+"\n"+str(Coord[1])+"\n"+str(Coord[2])+"\n"
        Outfile = open(DirOut+FileName+'.txt','a+')
        Outfile.write(CoordStr+'\n')
        Outfile.close()
        
        # Closing connectin to MeshMixer
        remote.shutdown()
        ACoord = np.around(Coord)
    return Coord, ACoord

#[Coord,ACoord] = GetCamCoord(continuos=False, verbose=False, world=True)
#print(ACoord)

 

Message 12 of 12

Muchas gracias por la respuesta, seguire probando...gracias¡¡

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

Post to forums