• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

3D Camera Implementation Troubles SDK

Engaged ,
Mar 22, 2023 Mar 22, 2023

Copy link to clipboard

Copied

Hi gang!

 

My colleague and I are working on a plugin which requires the implementation of After Effects' 3D camera.

 

We have been refereng this helpful thread: https://community.adobe.com/t5/after-effects-discussions/glator-for-dummies-and-from-dummy/m-p/69303... 

 

But unfortunately we are struggling to get it working. I don't think there's any sample project that shows how to do this. My colleague suggested I post some of the code we've developed to see if anyone can spot where our issues might be stemming from.

 

We have points in 3D space, in the range of -1.0 to 1.0 which we are trying to get to display correctly with the AE camera.

 

This is the LookAt function we have developed:

 

A_Matrix4 TransposeMat4(const A_Matrix4& m)
{
	A_Matrix4 r;
	for (int j = 0; j < 4; ++j) {
		for (int i = 0; i < 4; ++i) {
			r.mat[j][i] = m.mat[i][j];
		}
	}

	return r;
}


A_Matrix4 LookAt(
	Vector3<A_FpLong> eye, // camera pos
	Vector3<A_FpLong> target, // target position
	Vector3<A_FpLong> up // camera up direction
	)
{
	A_Matrix4 m;
	ZeroMemory(&m, sizeof(m));

	Vector3<A_FpLong> d{ target.x- eye.x, target.y- eye.y, target.z- eye.z };
	Vector3<A_FpLong> f = normalize(d);
	Vector3<A_FpLong> r = normalize(cross(up,f)); // right
	Vector3<A_FpLong> u = normalize(cross(f,r)); // up

	m.mat[0][0] = r.x;
	m.mat[0][1] = r.y;
	m.mat[0][2] = r.z;
	//m.mat[0][3] = -dot(r,eye);

	m.mat[1][0] = u.x;
	m.mat[1][1] = u.y;
	m.mat[1][2] = u.z;
	//m.mat[1][3] = -dot(u, eye);
	
	m.mat[2][0] = f.x;
	m.mat[2][1] = f.y;
	m.mat[2][2] = f.z;
	//m.mat[2][3] = dot(f,eye);

	m.mat[3][3] = 1.0;
	
	A_Matrix4 m2;
	ZeroMemory(&m2, sizeof(m2));

	m2.mat[0][0] = m2.mat[1][1] = m2.mat[2][2] = m2.mat[3][3];

	m2.mat[0][3] = -eye.x;
	m2.mat[1][3] = -eye.y;
	m2.mat[2][3] = -eye.z;
	
	return m;// MulMatrix4(m2, m);

	m.mat[0][0] = r.x;
	m.mat[0][1] = r.y;
	m.mat[0][2] = r.z;
	m.mat[0][3] = -dot(eye, r);

	m.mat[1][0] = u.x;
	m.mat[1][1] = u.y;
	m.mat[1][2] = u.z;
	m.mat[1][3] = -dot(eye, u);

	m.mat[2][0] = -f.x;
	m.mat[2][1] = -f.y;
	m.mat[2][2] = -f.z;
	m.mat[2][3] = dot(eye, f);

	m.mat[3][0] = 0.;
	m.mat[3][1] = 0.;
	m.mat[3][2] = 0.;
	m.mat[3][3] = 1.;

	m = TransposeMat4(m);
	return m;
}

 

And this is our projection matrix:

 

	A_long		width, height, fullWidth, fullHeight;
	width = output_worldP->width;
	height = output_worldP->height;
	fullWidth = width * in_data->downsample_x.den;
	fullHeight = height * in_data->downsample_y.den;
	float aspect = (float)width / (float)height;

	float camx = matrix.mat[3][0];// (2.0 * matrix.mat[3][0] - fullWidth) / fullHeight; //<-Trans X
	float camy = matrix.mat[3][1];// (2.0 * matrix.mat[3][1] - fullHeight) / fullHeight; //<-Trans Y
	float camz = matrix.mat[3][2];// (2.0 * matrix.mat[3][2] - fullHeight) / fullHeight; //<-Trans Z

	// calc projection matrix
	PF_FpLong fovy = 2.0 * atan(fullHeight / (2.0 * cameraZoom)) / PF_RAD_PER_DEGREE;
	PF_FpLong tanfov2 = tan(fovy * PF_PI/360.0);


	A_Matrix4 proj_matrix;

	PF_FpLong zfar = 1000., znear = 0.05;

	PF_FpLong halfh = tanfov2 * znear;
	PF_FpLong halfw = halfh * aspect;
	PF_FpLong l = -halfw;
	PF_FpLong r = halfw;
	PF_FpLong b = -halfh;
	PF_FpLong t = halfh;

	proj_matrix.mat[0][0] = 2.0 * znear / (r-l);
	proj_matrix.mat[0][1] = 0.0;
	proj_matrix.mat[0][2] = (r+l)/(r-l);
	proj_matrix.mat[0][3] = 0.0;

	proj_matrix.mat[1][0] = 0.;
	proj_matrix.mat[1][1] = 2.0 * znear / (t - b);
	proj_matrix.mat[1][2] = (t + b) / (t - b);
	proj_matrix.mat[1][3] = 0.0;

	proj_matrix.mat[2][0] = 0.0;
	proj_matrix.mat[2][1] = 0.0;
	proj_matrix.mat[2][2] = (zfar + znear) / (zfar - znear);
	proj_matrix.mat[2][3] = -(2. * zfar * znear) / (zfar - znear);

	proj_matrix.mat[3][0] = 0.0;
	proj_matrix.mat[3][1] = 0.0;
	proj_matrix.mat[3][2] = 1.0;
	proj_matrix.mat[3][3] = 1.0;

	// Calc lookat matrix

	Vector3<A_FpLong> origin, target;
	origin.x = camx;
	origin.y = camy;
	origin.z = camz;

	float distCam = magnitude(matrix.mat[3][0] - fullWidth * .5,
		matrix.mat[3][1] - fullHeight * .5,
		matrix.mat[3][2]);

	target.x = matrix.mat[2][0] * distCam + camx;
	target.y = matrix.mat[2][1] * distCam + camy;
	target.z = matrix.mat[2][2] * distCam + camz;

	A_Matrix4 invMat = matrix;
	A_Matrix4 invMat2;
	InvertMatrix((A_FpLong*)invMat.mat, (A_FpLong*)invMat2.mat);

	Vector3<A_FpLong> orientation_vector = { 0,1,0 };
	orientation_vector.x = invMat2.mat[0][1];
	orientation_vector.y = invMat2.mat[1][1];
	orientation_vector.z = invMat2.mat[2][1];

	A_Matrix4 view_matrix = LookAt(origin, target, orientation_vector);
	A_Matrix4 vp_matrix = MulMatrix4(view_matrix, proj_matrix); // view-projection matrix

 

And finally, the invert matrix and a few other used functions:

 

bool InvertMatrix(A_FpLong m[16], A_FpLong invOut[16])
{
	A_FpLong inv[16], det;
	int i;

	inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15]
		+ m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];
	inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15]
		- m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];
	inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15]
		+ m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9];
	inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14]
		- m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9];
	inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15]
		- m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];
	inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15]
		+ m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];
	inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15]
		- m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9];
	inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14]
		+ m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9];
	inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15]
		+ m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6];
	inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15]
		- m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6];
	inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15]
		+ m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5];
	inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14]
		- m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5];
	inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11]
		- m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6];
	inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11]
		+ m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6];
	inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11]
		- m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5];
	inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10]
		+ m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5];

	det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
	if (det == 0)
		return false;

	det = 1.0 / det;

	for (i = 0; i < 16; i++)
		invOut[i] = inv[i] * det;

	return true;
}

template <typename T> struct Vector3 { T x, y, z; };

template <typename T> Vector3<T> cross(const Vector3<T>& v1, const Vector3<T>& v2) {
	return Vector3<T>{
		v1.y*v2.z - v1.z*v2.y,
		v1.z*v2.x - v1.x*v2.z,
		v1.x*v2.y - v1.y*v2.x
	};
}

template <typename T> T dot(const Vector3<T>& v1, const Vector3<T>& v2) {
	return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}

template <typename T> T magnitude(const Vector3<T>& v) {
	return sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}

template <typename T> T magnitude(T vx, T vy, T vz) {
	return sqrt(vx * vx + vy * vy + vz * vz);
}

// this could be optimized with Q_rsqrt or instrinsics later
template <typename T> Vector3<T> normalize(const Vector3<T>& v) {
	T len = sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
	return Vector3<T>{
		v.x / len,
		v.y / len,
		v.z / len
	};
}

I understand getting a solution from all of this is unlikely but I'm posting it on behalf of my colleague to see if anyone here has experience in this and could let us know what we are doing wrong. Or maybe you can spot something that doesn't look right - it might not be the fix but it might lead us in the right direction. If I mistakenly left out any functions, please let me know and I can add them.

 

It would be helpful if AE SDK provided with a project example but it seems it does not.

 

Thanks so much in advance for any help.

 

Regards,

-Richard

TOPICS
SDK

Views

139

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 22, 2023 Mar 22, 2023

Copy link to clipboard

Copied

LATEST

a basic question: are you trying to match AE's comp active camera? if so, you can get the camera matrix directly using AEGP_GetEffectCameraMatrix(). you'll need to concat with the perspective matrix, but all of the transforamation will be handed to you ready made.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines