/// btMotionState override. Called when Bullet wants to tell us the body's current transform void setWorldTransform(const btTransform &worldTrans) { /// \todo For a large scene, applying the changed transforms of rigid bodies is slow (slower than the physics simulation itself, /// or handling collisions) due to the large number of signals being fired. // Cannot modify server-authoritative physics object, rather get the transform changes through placeable attributes const bool hasAuthority = rigidBody->HasAuthority(); if (!hasAuthority && !clientExtrapolating) return; if (placeable.Expired()) return; Placeable* p = placeable; // Important: disconnect our own response to attribute changes to not create an endless loop! disconnected = true; AttributeChange::Type changeType = hasAuthority ? AttributeChange::Default : AttributeChange::LocalOnly; // Set transform float3 position = worldTrans.getOrigin(); Quat orientation = worldTrans.getRotation(); // Non-parented case if (p->parentRef.Get().IsEmpty()) { Transform newTrans = p->transform.Get(); newTrans.SetPos(position.x, position.y, position.z); newTrans.SetOrientation(orientation); p->transform.Set(newTrans, changeType); } else // The placeable has a parent itself { Urho3D::Node* parent = p->UrhoSceneNode()->GetParent(); if (parent) { position = parent->WorldToLocal(position); orientation = parent->GetWorldRotation().Inverse() * orientation; Transform newTrans = p->transform.Get(); newTrans.SetPos(position); newTrans.SetOrientation(orientation); p->transform.Set(newTrans, changeType); } } // Set linear & angular velocity if (body) { // Performance optimization: because applying each attribute causes signals to be fired, which is slow in a large scene // (and furthermore, on a server, causes each connection's sync state to be accessed), do not set the linear/angular // velocities if they haven't changed float3 linearVel = body->getLinearVelocity(); float3 angularVel = RadToDeg(body->getAngularVelocity()); if (!linearVel.Equals(rigidBody->linearVelocity.Get())) rigidBody->linearVelocity.Set(linearVel, changeType); if (!angularVel.Equals(rigidBody->angularVelocity.Get())) rigidBody->angularVelocity.Set(angularVel, changeType); } disconnected = false; }