@ferdinand
Thanks, that is exactly correct - in fact I did not need to make the orthonormal vector, all one needs do is set the objects Y-axis equal to the camera, and get the x-axis by cross product .
I think I correctly handle the pathological situation after looking at the limiting cases.
The modified function is below.
Randy
EPSILON = 1E-5 # The floating point precision we are going to assume, i.e., 0.00001
# This is based on the python Look at Camera example
# https://github.com/PluginCafe/cinema4d_py_sdk_extended/tree/master/plugins/py-look_at_camera_r13
def GetLookAtTransform(host: c4d.Matrix, target: c4d.Matrix, reverseZ=True) -> c4d.Matrix:
"""Returns a transform which orients its z/k/v3 component from #host to #target.
"""
# Get the position of both transforms.
p: c4d.Vector = host.off
q: c4d.Vector = target.off
# The normalized offset vector between 'host' (object to be reoriented) and 'target' (the camera)
# will become the z-axis of the modified frame for the object .
#
# If reverseZ = True, the new z-axis is points from camera toward object, if False the reverse
# I turn reverseZ on by default, as my initial application is to text splines, which are meant to be
# viewed looking down the object z-axis.
# In the original implementation
# (https://github.com/PluginCafe/cinema4d_py_sdk_extended/tree/master/plugins/py-look_at_camera_r13 )
# the modified y-axisis computed using the global y-axis, and this does not consistently
# keep the text upright in the view of the camera. Instead, simply take the object y-axis same as camera y.
#
# In the pathological case of new object z-axis parallel to camera y :
# If reverseZ : set object z = camera y , object y = -camera Z
# else : set object z = -camera y, object y = -camera z
#
if reverseZ :
z: c4d.Vector = ~(p - q)
if 1. - abs(z * target.v2) > EPSILON :
y = target.v2
else :
z = target.v2
y = -target.v3
else :
z: c4d.Vector = ~(q - p)
if 1. - abs(z * target.v2) > EPSILON :
y = target.v2
else :
z = -target.v2
y = -target.v3
# get x using cross product
x: c4d.Vector = ~(y % z)
# Return the frame (x, y, z) plus the offset of #host as the look-at transform.
return c4d.Matrix(off=p, v1=x, v2=y, v3=z)