I am trying with no avail to create a camera path that follows a lemniscate shape as shown in the figure.
I do it in 3D but just set the vertical dimension (y) to a fixed number so really is 2D. the x and z coordinates are generated with a closed form function. I calculated the derivative of the function and that should give me the normal at each point. With the normal and a world UP axis I estimate the lookat direction and build a lookat matrix. However, this is not working for me. The camera does not turn properly at the lemniscate curves. Is there any other way to do this?
I have the 3D points of the lemniscate and I know world coordinates are X-Right, Y-Down and Z-Forward.
This is the code:
# Parameters
a = 0.2 # Scale of the lemniscate
# Create theta values
theta1 = np.linspace(0.5*np.pi, 0.75*np.pi, 25)
theta2 = np.linspace(0.75*np.pi, 1.25*np.pi, 80)
theta3 = np.linspace(1.25*np.pi, 1.75*np.pi, 45)
theta4 = np.linspace(1.75*np.pi, 2.25*np.pi, 80)
theta5 = np.linspace(2.25*np.pi, 2.5*np.pi, 25)
theta = np.concatenate((theta1, theta2, theta3, theta4, theta5))
# Convert to Cartesian coordinates
x = a * np.cos(theta) / (np.sin(theta)**2 + 1)
z = a * np.cos(theta) * np.sin(theta) / (np.sin(theta)**2 + 1)
y = a * 0.2 * np.cos(4*theta)
Cs = np.stack((x, y, z)).T
dx_dtheta = -a*(np.sin(theta) * (np.sin(theta) ** 2 + 2*np.cos(theta)**2 + 1)) / (np.sin(theta)**2 + 1)**2
dz_dtheta = -a*(np.sin(theta)**4 + np.sin(theta)**2 + (np.sin(theta)**2-1)*np.cos(theta)**2) / (np.sin(theta)**2 + 1)**2
dy_dtheta = - 4 * a * 0.2 * np.sin(4*theta) # If I use this, it gets worse
normal = np.stack((dx_dtheta, np.zeros_like(x), dz_dtheta)).T
normal = normal / np.linalg.norm(normal, axis=1, keepdims=True)
UP = np.array([0, -1, 0])[None, :]
lookat = np.cross(normal, UP)
lookat = lookat / np.linalg.norm(lookat, axis=1, keepdims=True)
right = normal
up = np.cross(right, lookat)
up /= np.linalg.norm(up, axis=1, keepdims=True)
Rs = np.concatenate((right, up, lookat), axis=1).reshape(-1, 3, 3).transpose(0, 2, 1)
y
related totheta
, when you saybut just set the vertical dimension (y) to a fixed number
? (2) It seems that you are using Lemniscate of Bernoulli, and you present the curve in its parametric equation form. So, lets say if it is 2D. Taking the derivative oftheta
will end up in tangent vector on the x-z plane. If I understand it correctly, this should be the look-at vector (after normalization). $\endgroup$y
related totheta
. What I want is the lookat vector to be corresponding to the one in 2D, i.e. tangent vector on the x-z plane. Regardless ify
is zero or not. That why in my normal I sety
to zeronormal = np.stack((dx_dtheta, np.zeros_like(x), dz_dtheta)).T
. $\endgroup$