0
\$\begingroup\$

I'm attempting to parent a bullethole decal to a dynamic object. I've figured out how to set the correct position for the bullethole object so that it shows at the correct position of the dynamic object, but once that dynamic object is rotated, parenting new bulletholes are skewed because I'm not compensating for the rotation of the dynamic object (the child object, bullethole decal in this case, is translated relative to the parent, which is why I'm attempting to remove the initial rotation of the parent object to get the actual rotation for the child). I've probably done a terrible job of explaining this...so here is a video of what I'm working on (note that the bulletholes that are added to the barrel before it is moved stay where they should be, and it's only after the barrel is rotated that new bulletholes become skewed)

So I believe I know what needs to happen, I'm just not sure how to go about implementing it. I need to compensate for the rotation of the barrel at the time the bullethole is parented to it, setting the rotation of the bullethole to this value. Possibly an easy question to answer for someone with experience working with quaternions.

if (raycast.hasHit())
{
    auto hitPoint = vel::helpers::functions::bulletToGlmVec3(raycast.m_hitPointWorld);
    
    bulletObject->currentPositionFromScreen = hitPoint;
    bulletObject->disposeOnNextTick = true;

    auto normal = vel::helpers::functions::bulletToGlmVec3(raycast.m_hitNormalWorld);
    float nrmDot = glm::dot(normal, glm::vec3(0.0f, 1.0f, 0.0f));

    auto bulletHoleAdjustmentValue = this->currentBulletHoleIndex == 0 ? 0.00001f : 0.00001f + (0.00001f * this->currentBulletHoleIndex);
    auto bulletHolePosition = hitPoint + (normal * glm::vec3(bulletHoleAdjustmentValue, bulletHoleAdjustmentValue, bulletHoleAdjustmentValue));

    auto bulletHoleActor = this->bulletHoleQueue.at(this->currentBulletHoleIndex);

    if (this->currentBulletHoleIndex < (this->bulletHoleQueueSize - 1))
        this->currentBulletHoleIndex++;
    else
        this->currentBulletHoleIndex = 0;

    bulletHoleActor->getTransform().setTranslation(bulletHolePosition);

    if (nrmDot < 1.0f && nrmDot > -1.0f)
        bulletHoleActor->getTransform().setRotation(glm::toQuat(glm::transpose(glm::lookAt(hitPoint, bulletHolePosition, glm::vec3(0.0f, 1.0f, 0.0f)))));
    else
        bulletHoleActor->getTransform().setRotation(90.0f, glm::vec3(1.0f, 0.0f, 0.0f));

    bulletHoleActor->setVisible(true);      


    // if physics object has a user pointer, parent bullethole actor to the actor which that value represents
    if (raycast.m_collisionObject->getUserPointer() != nullptr)
    {
        auto dynamicActor = (vel::scene::stage::Actor*)raycast.m_collisionObject->getUserPointer();
        
        bulletHolePosition =  bulletHolePosition - dynamicActor->getTransform().getTranslation();
        bulletHoleActor->getTransform().setTranslation(bulletHolePosition);
        
        // Was thinking below would work, but it does not for some reason?
        //auto newRotation = bulletHoleActor->getTransform().getRotation() * glm::inverse(dynamicActor->getTransform().getRotation());
        //bulletHoleActor->getTransform().setRotation(newRotation);

        bulletHoleActor->setParentActor(dynamicActor);
    }

}
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Alright, figured this out. I needed to put the child object into the coordinate system of it's parent, before parenting it. This was accomplished by multiplying the inverse matrix of the parent by the matrix of the child, and applying the resulting matrix to the child. Below are the changes I made to my code to accomplish this:

// if physics object has a user pointer, parent bullethole actor to the actor which that value represents
if (raycast.m_collisionObject->getUserPointer() != nullptr)
{
    auto dynamicActor = (vel::scene::stage::Actor*)raycast.m_collisionObject->getUserPointer();
    
    // get inverse of dynamicActor transformation matrix
    glm::mat4 invDAM = glm::inverse(dynamicActor->getTransform().getMatrix());
    glm::mat4 newBulletHoleMatrix = invDAM * bulletHoleActor->getTransform().getMatrix();

    // now decompose and assign each element to bulletHoleActor since my Transform class generates matrix from the individual components
    // and i don't currently have functionality to assign a new matrix and have these elements automatically update
    glm::vec3       translation;
    glm::quat       rotation;
    glm::vec3       scale;
    glm::vec3       skew;
    glm::vec4       perspective;
    glm::decompose(newBulletHoleMatrix, scale, rotation, translation, skew, perspective);
    rotation = glm::conjugate(rotation);

    bulletHoleActor->getTransform().setScale(scale);
    bulletHoleActor->getTransform().setRotation(rotation);
    bulletHoleActor->getTransform().setTranslation(translation);

    bulletHoleActor->setParentActor(dynamicActor);
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .