Archive 17/01/2023.

Relative Direction Billboards

Enhex

Currently the direction billboards only have world direction.
I tried updating their direction via AngelScript to be relative to their node, but it has frame(s) delay.

I suggest adding a new billboard facing mode for relative direction, which is relative to the BillboardSet’s node’s direction.

Implementation example, modifying BillboardSet::UpdateVertexBuffer()'s FC_DIRECTION code to be relative:

else // something like FC_RELATIVE_DIRECTION
{
	const auto node_rotation = node_->GetWorldRotation();

    for (unsigned i = 0; i < enabledBillboards; ++i)
    {
        Billboard& billboard = *sortedBillboards_[i];
		auto direction = node_rotation * billboard.direction_;

        Vector2 size(billboard.size_.x_ * billboardScale.x_, billboard.size_.y_ * billboardScale.y_);
        unsigned color = billboard.color_.ToUInt();
        if (fixedScreenSize_)
            size *= billboard.screenScaleFactor_;

        float rot2D[2][2];
        SinCos(billboard.rotation_, rot2D[0][1], rot2D[0][0]);
        rot2D[1][0] = -rot2D[0][1];
        rot2D[1][1] = rot2D[0][0];

        dest[0] = billboard.position_.x_;
        dest[1] = billboard.position_.y_;
        dest[2] = billboard.position_.z_;
        dest[3] = direction.x_;
        dest[4] = direction.y_;
        dest[5] = direction.z_;
        ((unsigned&)dest[6]) = color;
        dest[7] = billboard.uv_.min_.x_;
        dest[8] = billboard.uv_.min_.y_;
        dest[9] = -size.x_ * rot2D[0][0] + size.y_ * rot2D[0][1];
        dest[10] = -size.x_ * rot2D[1][0] + size.y_ * rot2D[1][1];

        dest[11] = billboard.position_.x_;
        dest[12] = billboard.position_.y_;
        dest[13] = billboard.position_.z_;
        dest[14] = direction.x_;
        dest[15] = direction.y_;
        dest[16] = direction.z_;
        ((unsigned&)dest[17]) = color;
        dest[18] = billboard.uv_.max_.x_;
        dest[19] = billboard.uv_.min_.y_;
        dest[20] = size.x_ * rot2D[0][0] + size.y_ * rot2D[0][1];
        dest[21] = size.x_ * rot2D[1][0] + size.y_ * rot2D[1][1];

        dest[22] = billboard.position_.x_;
        dest[23] = billboard.position_.y_;
        dest[24] = billboard.position_.z_;
        dest[25] = direction.x_;
        dest[26] = direction.y_;
        dest[27] = direction.z_;
        ((unsigned&)dest[28]) = color;
        dest[29] = billboard.uv_.max_.x_;
        dest[30] = billboard.uv_.max_.y_;
        dest[31] = size.x_ * rot2D[0][0] - size.y_ * rot2D[0][1];
        dest[32] = size.x_ * rot2D[1][0] - size.y_ * rot2D[1][1];

        dest[33] = billboard.position_.x_;
        dest[34] = billboard.position_.y_;
        dest[35] = billboard.position_.z_;
        dest[36] = direction.x_;
        dest[37] = direction.y_;
        dest[38] = direction.z_;
        ((unsigned&)dest[39]) = color;
        dest[40] = billboard.uv_.min_.x_;
        dest[41] = billboard.uv_.max_.y_;
        dest[42] = -size.x_ * rot2D[0][0] - size.y_ * rot2D[0][1];
        dest[43] = -size.x_ * rot2D[1][0] - size.y_ * rot2D[1][1];

        dest += 44;
    }

I think it’s quite obvious that it has use cases - prefabs, any direction billboard which is attached to a rotated node, …