How to change Decal's rotation at runtime relative to the floor or wall? C++

What do you mean when you say “into”? Could you elaborate further please? If possible.

I think the question is which vector should be the “basis” and which vector should be the “in the plane.” I’m of the belief that the normal is perpendicular to the surface, and should be the Z vector, and the other vector should be in the surface, and should be the X vector (or could be the Y vector,) because the basis should be oriented so that U == X and V == Y. E g, the question here is: which axis does an applied normal map apply along?

I think the reason for this confusion comes from the decal actor – by default, it doesn’t actually orient its decal texture such that the coordinate system of the decal is the same as the local coordinate system of the actor. Flipping the cooridnates around like that, essentially counter-rotates the rotation that the decal actor will apply.

So, what my answer said, was “you want the texture coordinate space to be this.” And, then, if you just create a decal actor with that coordinate space as orientation, it won’t work, because the decal actor rotates whatever coordinate space IT uses by 90 degrees, because, why wouldn’t it? Doing so gives us all something to talk about on the forums! And, thus, when spawning that actor, you need to counter-rotate it, and one way of doing that, is simply flipping the vectors around a bit (because that’s what a 90-degree rotation ends up doing, in the matrix.)

Note that this newly placed Decal actor, which is placed on a normal-oriented floor, with “Z up,” is actually rotated 90 degrees around Y:

1 Like

I appreciate the in-depth explanation. I feel more enlightened on the topic at hand.

With this function you are trying to get the absolute value of the impactNormal’s Z axis and checking if that absolute value is greater then 0.8? Then you change the basis vector’s X axis based on that. You are checking to see if the Z axis of the vector is greater then 0.80. But why 0.80 in particular? Please correct me in anything that I am saying.

The point is to detect normals that are largely “up or down” compared to “sideways.”
The “Z” coordinate value can be used to test “how much up is this normalized vector.” Absolute “Z” tests “how much straight up or straight down is this normalized vector”
The “perfect value” to use for this (45 degrees off the ground plane) is Sqrt(0.5) or about 0.707. I picked 0.80 because I wanted to bias slightly towards “don’t change the basis.”
The reason the basis needs to change at all, is that if the basis is “Z” and the normal is also “close to Z” then the math degenerates and becomes unstable, or even singular (zero and division by zero) which ends up rendering poorly or not at all. You could use a value like 0.99 and still have a stable solution, if you wanted.

1 Like

So you are using the if statement to prevent the calculation from becoming unstable before building a matrix with the X and Z axis.
Using this function:

FMatrix rotation = FRotationMatrix::MakeFromZX(impactNormal, basis);

Correct.

Would I in fact disregard using both cross products and creating a matrix based on both cross products in lieu of this new information? In favor of using this function.

They do the same thing, essentially. One just shows what’s going on on the inside of the other :slight_smile:

1 Like

Thank you for the help jwatte and jamsh.