Antoine.YVAN Posted April 30, 2021 Share Posted April 30, 2021 Hi all ! I am trying to compute the velocity of an entity within a SendPacketCallback (using the addSendPacketCallback added in 2.14) Configs: Unigine SDK 2.14 Windows 10 IG / Host Setup: A host which updates the entity's rotation every frame (1 host frame is 100ms) The Unigine IG sim with a callback for LOS extended response opcode The CIGI connection is asynchronous Entity smoothing is enabled Here is the code I am using : int AppWorldLogic::init() { // init systems, do some optimizations for IG Game::setEnabled(1); Physics::setEnabled(0); Render::setMotionBlur(0); Render::setLightsLensFlares(0); Render::setWhiteBalance(false); Render::setExposureMode(0); Render::setExposure(1.0f); // clamp framerate to 60 if VSync is off if ((App::getFlags() & App::VSYNC) == 0 || (App::getFlags() & App::FULLSCREEN) == 0) Render::setMaxFPS(60.0f); int index = Engine::get()->findPlugin("CIGIConnector"); // check CIGIConnector plugin load if (index != -1) { // getting the CIGI interface _cigi = IG::CIGI::Connector::get(); _cigi->addSendPacketCallback(IG::CIGI::CIGI_OPCODE_LOS_EXT_RESPONSE, MakeCallback(this, &AppWorldLogic::on_speed_packet_required)); } return 1; } void AppWorldLogic::on_speed_packet_required(bool &ret, IG::CIGI::CigiIGPacket *response, IG::CIGI::CigiHostPacket *request, IG::IGIntersection *intersection) { if(intersection) { ObjectPtr object = intersection->object; // Log::message("\tHIT Object => %s\n", intersection->object->getName()); Math::Vec3 point_world = intersection->point; Math::Vec3 prev_point_world = point_world * Math::inverse(object->getWorldTransform()) * object->getOldWorldTransform(); Math::Vec3 point_velocity = (point_world - prev_point_world) / Game::getIFps(); Log::message("velocity = {%f,%f,%f}\n\n", point_velocity.x, point_velocity.y, point_velocity.z); } } The callback is called every ~100ms. What I expect : Whenever I enter this callback, the velocity is computed based on the entity previous world transform I know that the velocity is moving so it should not be equal to (0,0,0) Problem is : - When I enter the callback, "object->getOldWorldTransform()" is always equals to "object->GetWorldTransform()" which will set the velocity to (0,0,0). - A callback has to compute the velocity independently, meaning I cannot save the position to compute the velocity on the next callback. If you need any more infos feel free to ask. Best regards, Antoine Link to comment
cash-metall Posted April 30, 2021 Share Posted April 30, 2021 the order of the matrix multiplication matters. Vec3 prev_point_world = (object-> getOldWorldTransform () * inverse (object-> getWorldTransform ())) * point_world; I checked it works correctly for simple cases. however, getOldTransform may be updated due to the update of the spatial tree.https://drive.google.com/file/d/1V5axIYmJbNvvjwajF1tykvEeHfXMZINj/view?usp=sharing tell me more about the scene - what is the object for which you need to get velocity? who moves it, where (update / post_update) does this movement take place? Sphere.node Link to comment
Antoine.YVAN Posted April 30, 2021 Author Share Posted April 30, 2021 Hi cash-metall, thank you for your reply. The object is a cylinder which just rotates on the Z axis. It is my CIGI Host who creates it via a CIGIEntityCtrl packet and updates its rotation every 100 milliseconds, increasing it by 30 until 360°. I don't know -in the Unigine Side- where the movement takes place as I don't control that part, Unigine does so after receiving the packet I send and computing the next position with interpolation. Do you need to know anything more ? spinner.node Link to comment
Antoine.YVAN Posted May 3, 2021 Author Share Posted May 3, 2021 Hello again ! So I downloaded your sphere.node to see if I could make it work. I tried to use your sphere with a Cigi Communication using Unigine's IG Host. I enabled the interpolation to have a smooth movement and not a direct teleportation. Here is the result : As you can see, the pink trail supposed to trace the sphere's movement using the OldWorldTransform is not shown. This means that when using a Cigi Communication, the OldWorldTransform is not updated correctly and is not usable. Is there a way for your team to solve this problem ? Thank you for your time and your help ! Best Regards, Antoine 1 Link to comment
cash-metall Posted May 11, 2021 Share Posted May 11, 2021 yes, interpolation happens in the post-update, but callbacks are processed in the update. As a result, in the update of the current frame, the position of the entity has not yet been applied. there are two ways: 1. fast but not universal: make a simple component class VelocityControl : public ComponentBase { COMPONENT(VelocityControl, ComponentBase) COMPONENT_UPDATE(update) PROP_NAME("VelocityControl") void update() { auto c_transform = node->getWorldTransform(); delta = inverse(old_transform) * c_transform; linear_velocity = vec3(delta.getTranslate()) / Game::getIFps(); angular_velocity = Math::decomposeRotationZXY(mat3(delta)) / Game::getIFps(); old_transform = c_transform; } Unigine::Math::Mat4 old_transform; Unigine::Math::vec3 linear_velocity; Unigine::Math::vec3 angular_velocity; Unigine::Math::Mat4 delta; }; which to assign to those objects whose velocities are of interest to us (landing pads ?) and in the callback it is easy to take auto vc = ComponentSystem::get()->getComponent<VelocityControl>(object); if (vc) { linear = vc->delta * point_world; } 2. universal, but may slow: manual control the previous transformation - in update, bypass all nodes and save the transformations of all object meshes. (maybe some mask optimize to reduce the number of matrix copies) // each update Vector<NodePtr> nodes; World::getNodes(nodes); for (const auto & node : nodes) { if (node->getType() == Node::OBJECT_MESH_STATIC) world_transforms[node->getID()] = node->getWorldTransform(); } // and take in the callback inverse(world_transforms[object->getID()]) * object->getWorldTransform(); Link to comment
Recommended Posts