Jump to content

Positionning a calibration sight with Visualizer


photo

Recommended Posts

Hi,

I need to position a calibration sight for the player. This would be a small dot/sphere, located *relative* to the camera with an azimuth and elevation angle. Looks simple enough, just using a Visualizer solid sphere would do the trick, but I can't correctly write the transform matrix. I know I have to multiply somehow the player world transform, azimuth rotation around the vertical axis and elevation rotation around the right hand, but whatever the order I try, it's never right.

Please be my light in this math tunnel!

Link to comment

I'm not sure i correctly understood the problem, but here is some functions that might help you.


using namespace Unigine;
using namespace Math;

dvec3 get_relative_point(PlayerPtr p, float azimuth, float elevation,
                         float distance) {

  auto t = p->getWorldTransform() * rotateX(-90.0);
  quat rot = quat(elevation, 0, -azimuth);

  t = t * dmat4(rotate(rot));

  dvec3 v = dvec3_forward * Scalar(distance);

  v = t * v;
  return v;
}

dvec3 get_absolute_point(PlayerPtr player, float azimuth, float elevation,
                         float distance) {
  quat rot = quat(elevation, 0, azimuth);

  auto p = player->getWorldPosition();
  auto t = translate(p) * dmat4(rotate(rot));
  auto v = dvec3_forward * Scalar(distance);
  v = t * v;
  return v;
}

int AppWorldLogic::update() {
  auto p = Unigine::Game::getPlayer();
  float azimuth = 10.0f;
  float elevation = 5.0f;

  auto p1 = get_relative_point(p, azimuth, elevation, 5);
  Visualizer::setEnabled(true);
  Visualizer::renderSolidSphere(0.1f, translate(p1), vec4_blue);

  auto p2 = get_absolute_point(p, azimuth, elevation, 5);
  Visualizer::renderSolidSphere(0.1f, translate(p2), vec4_red);
  return 1;
}

image.png

Quote

azimuth rotation around the vertical axis and elevation rotation around the right hand

i'm not sure that i understood your problem correctly

 

Link to comment
Posted (edited)

Hi, I think we're almost there. Indeed, I was missing a crucial point with the camera basic orientation.

Yet, with your code, the sphere is not excatly at the correct coordinate (with the get_relative_point). Here is my code slghtly adapted and the result:

ConsoleVariableVec2 goniometer_steps{ "goniometer_steps", "\tGoniometer steps (azimuth,elevation)", false, {10,10} };
ConsoleVariableVec2 goniometer_target{ "goniometer_target", "\tGoniometer target position (azimuth,elevation)", false, {40,20} };

Vec3 get_relative_point(Mat4 transform, float azimuth, float elevation, float distance) {
	auto t = transform * rotateX(-90.0);
	quat rot = quat(elevation, 0, -azimuth);
	t = t * dmat4(rotate(rot));
	dvec3 v = dvec3_forward * Scalar(distance);
	v = t * v;
	return v;
}

void AppSystemLogic::goniometer()
{
	const double distance = 10;
	double step_azim = goniometer_steps.get().x;
	double step_elev = goniometer_steps.get().y;
	
	double target_azim = goniometer_target.get().x;
	double target_elev = goniometer_target.get().y;

	auto mat = p->getWorldTransform();

	auto d = -mat.getAxisZ() * .1;
	Mat4 m = translate(d);
		
	// Azimuth rings (red)
	Mat4 my = rotateY(90.);
	Visualizer::renderCircle(distance, mat * my, vec4_white, 0, false);
	for (int i = 1; i * step_azim <= 90; ++i) {
		Mat4 m0 = rotateY(i * step_azim);
		Visualizer::renderCircle(distance, mat * my * m0, vec4_red, 0, false);
		Mat4 m1 = rotateY(i * -step_azim);
		Visualizer::renderCircle(distance, mat * my * m1, vec4_red, 0, false);
	}

	// Elevation rings (green)
	Mat4 mx = rotateX(90.);
	Visualizer::renderCircle(distance, mat * mx, vec4_white, 0, false);
	for (int j = 1; j * step_elev <= 90; ++j) {
		Mat4 m0 = rotateX(j * step_elev);
		Visualizer::renderCircle(distance, mat * mx * m0, vec4_green, 0, false);
		Mat4 m1 = rotateX(j * -step_elev);
		Visualizer::renderCircle(distance, mat * mx * m1, vec4_green, 0, false);
	}

	// Calibration Target (white)
	auto p1 = get_relative_point(mat, target_azim, target_elev, distance);
	Visualizer::renderSolidSphere(0.1f, translate(p1), vec4_white, 0, false);
}

image.png.3d1308000f275c4577170e0a2f31c5a0.png

As you can see, the dot is not exactly on the azimuth=40, elevation=20 grid point.

What am I misunderstanding?

 

Edited by Amerio.Stephane
typo
Link to comment

Yes, we had a problem with calculation of rotation, here is the correct one:
 

dvec3 get_relative_point(Mat4 p, float azimuth, float elevation,
                         float distance) {

  auto t = p;

  auto rot = composeRotationZXY(vec3(elevation, 0, -azimuth));

  t = t * dmat4(rot);

  dvec3 v = dvec3_forward * static_cast<Scalar>(distance);

  v = t * v;
  return v;
}

My assumption is that you are using incorrect grid, here is what i think is correct one to use in this problem:

int AppWorldLogic::update() {
  const auto p = Game::getPlayer();
  constexpr float target_azim = 40.0f;
  constexpr float target_elev = 20.0f;

  const dmat4 transform = p->getWorldTransform() * rotateX(-90.0);
  constexpr float distance = 10.;

  constexpr float step_azim = 10.;
  constexpr float step_elev = 10.;

  for (int i = 0; static_cast<float>(i) * step_azim <= 90; ++i) {

    const float angle = static_cast<float>(i) * step_azim;
    Visualizer::renderSector(distance, 180.f,
                             transform * Mat4(rotateY(90.f) * rotateX(angle)),
                             vec4_blue);
    Visualizer::renderSector(distance, 180.f,
                             transform * Mat4(rotateY(90.f) * rotateX(-angle)),
                             vec4_blue);
  }

  for (int j = 1; static_cast<float>(j) * step_elev <= 90; ++j) {

    const float angle = static_cast<float>(j) * static_cast<float>(step_elev) *
                        static_cast<float>(j + 1);

    const float z = Math::sin(angle * Consts::DEG2RAD) * distance;
    const float r = Math::cos(angle * Consts::DEG2RAD) * distance;

    Visualizer::renderCircle(r, transform * Mat4(translate(vec3(0, 0, z))),
                             vec4_red);
    Visualizer::renderCircle(r, transform * Mat4(translate(vec3(0, 0, -z))),
                             vec4_red);
  }

  const dvec3 p1 = get_relative_point(transform, target_azim, target_elev, distance);
  Visualizer::renderSolidSphere(0.1f, translate(p1), vec4_white, 0, false);

  return 1;
}

Here is the result:

image.png

  • Like 2
Link to comment

Indeed, my lines were all wrong! Thanks a lot for the correct code and the insight in the math lib!

  • Like 2
Link to comment
×
×
  • Create New...