A unique but simple camera problem

I’m working on a project with the game engine that involves doing some camera tracking with physical sensors on a physical tripod. It’s for doing virtual sets with Blender. I’m new to Python, but I still managed to get Blender working with pyserial to pull data in from the sensors.

I’ll spare you the “getdata()” function details, but here’s a snippit of my code:

currentdata = getdata()
print ('pan  ='), currentdata['pan']
print ('tilt ='), currentdata['tilt']
print ('zoom ='), currentdata['zoom']
print '
'

when this runs in Blender, the console outputs this:

pan  = 1.2448489011
tilt = 0.230082417582
zoom = 98.2646153846

So I have the data coming in correctly, but I don’t know how to get the Blender camera to be set to these numbers. It should be easy, but I’m too new to the game engine. Something about “setrot”…? help!

I have my logic set up like this, because I want the script to update the camera’s position every frame.
Sensor:always—>Controller:script(cartoni.py)–>Motion&Ipos.

Thanks for your help!

I’m getting somewhere…


myObj = Blender.Object.Get("Camera")
myObj.RotX = currentdata['tilt']
myObj.RotY = 0
myObj.RotZ = currentdata['pan']
Blender.Redraw()

Okay, this gets me somewhere. It seems I need to convert my numbers into radians.

Is there a better way to do this within the game engine? This method of setting things causes problems with the BGE. I mean, I need to set the camera’s rotation in the actuator to a specific value, not to change it by a certain value.

See the KX_GameObjects orientation property. you can modify this.
You can also use alignToVect() to align the objects axis to a vector you define.

Get the XYZ vector of the angle (I think you’ll have to do it manually with trig functions), then use myObj.alignAxisToVect(vector,axis)
where axis is the local axis you want to align (Z is forward)
I don’t think you need to use redraw, as blender does that automatically at the end of every frame. I have heard that redraw has compatibility issues, but I don’t know how true that info is.

you can use Mathutils.angleBetweenVecs(vec1, vec2)

angleBetweenVecs only gives you the angle between them, but doesn’t define the appropriate rotation required to orient the camera.

Commonly game engines usually work on a basis of allowing an object to be “oriented” via a matrix or other sort of transform. If what you get from your sensor data is tilt, pan, and zoom, then you have to orient the camera based on a transform that corresponds to those values.

Tilt is accomplished via an euler rotation along the Z (in GL, X in DX) axis. Panning is just a position offset. Zoom needs to be directed to the camera itself (usually zoom can be implemented by just varying the angle of view, given that zoom is usually a “factor” of some base focal length).

Not having that much experience in this particular engine, but there are most likely a few methods that allow you to either build an orientation matrix or just apply certain values directly - make sure to check over the development documents.

Sorry I can’t be more specific.

You can use an orientation matrix quite easily for pan and tilt, although for ease of use I’m going to refer to them as rotLeftRight and rotUpDown. The Mathutils module is very useful for matrices so import it:

import Mathutils

Now we have access to some awesome tools.

camera = GameLogic.getCurrentScene().getObjectList()['OBCamera']
camOrient = camera.getOrientation()
pan = Mathutils.RotationMatrix(rotLeftRight,3,'z')
tilt = Mathutils.RotationMatrix(rotUpDown,3,'x')

The rotation matrix function converts a degree value into a rotation matrix around the specified axis. By multiplying matrices, we get the desired effect:

camera.setOrientation(pan*camOrient*tilt)

This is assuming that you want to update the rotation each frame.
If you don’t, add this after camOrient:

camOrient = Mathutils.Matrix[[1,0,0],[0,1,0],[0,0,1]]
rotLeftRight = lastPan + pan #Where pan is the value of rotation for this 
#frame and lastPan is the total of all previous pans
rotUpDown = lastTilt + tilt #Same idea as above

If you are as confused as I usually am, check my example file. :wink:

Attachments

example.blend (180 KB)

Commonly game engines usually work on a basis of allowing an object to be “oriented” via a matrix or other sort of transform. If what you get from your sensor data is tilt, pan, and zoom, then you have to orient the camera based on a transform that corresponds to those values.

Tilt is accomplished via an euler rotation along the Z (in GL, X in DX) axis. Panning is just a position offset. Zoom needs to be directed to the camera itself (usually zoom can be implemented by just varying the angle of view, given that zoom is usually a “factor” of some base focal length).

clear and interesting… thanks

This information is super useful; thanks everybody. I’ll be trying this out later today.

Okay, pan/tilt is working well, but I’m having trouble setting the zoom to a specific value. I know I need to to something with IPOs, but I don’t quite understand this yet. Any help?

(I’ll be making a video to share about this project once its ready, by the way)

The easiest way to work with IPO’s (for me at least) is to select the lens channel, set one control point at 0,0 and another at 1,1 (you might need to use 1,0.1, depending on the scale used by the IPO). Set the interpolation type to linear and the extend mode to extrapolate, and you’ll have an infinite 1-1 line. Now in the GE you can set the frame number to whatever you want the lens number to be and it should work. (do that by using an IPO controller and setting the play type to prop. Assign a property and you can jsut modify that property directly in python)

actually, I found the answer here. the lens parameter works only if you give it a float. That was annoying.

camera.lens = currentdata['zoom']

case closed.