I need some help understanding how rotation works with CFrames

I’ve been working on a world generation script for fun which uses 2d perlin noise to generate a heightmap, and then randomly places objects such as trees, rocks and cacti. To make things look a bit more natural, I am also slightly rotating each object so that it comes out of the ground at a slightly different angle and faces a slightly different direction.

The code to do so is pretty simple:

local rotation = CFrame.Angles(math.rad(math.random(0,10)), math.rad(math.random(0,10)), math.rad(math.random(0,360))) obj:SetPrimaryPartCFrame(obj.PrimaryPart.CFrame:ToWorldSpace(rotation))

I am rotating by 10 degrees on the x and y axis, which is what gives the objects a slightly different angle as they come out of the ground. The rotation around the Z axis determines which direction the object faces perpendicular to the ground. Here’s how it looks with some rocks and trees:

So far, so good. However I get some unexpected behaviour when I try it with this cactus model:

I tried changing the 360 degree rotation from around the Z axis to the Y axis, and now it works as expected for the cacti but I get the same problem with the other models:

So it seems that if I want to rotate the cactus perpendicular to the ground I have to do so around the Y axis, yet for every other model I have to do so around the Z axis. What I don’t understand is what determines which axis I should be rotating around, and how I can determine this for every model i’m using, preferably at runtime.

tl;dr: How can I consistently rotate an object perpendicular to the ground?

Remember that this all has to do with the PrimaryPart’s CFrame. Check each of these models’ PrimaryParts to ensure they’re facing the right way (both Front and Top faces!)

When you multiply CFrames, you’re composing them in a specific order, eg these are strictly different:

CFrame.new(0, 0, 10) * CFrame.Angles(0, math.rad(45), 0)
CFrame.Angles(0, math.rad(45), 0) * CFrame.new(0, 0, 10)
2 Likes

Thanks, I get it now. For anyone that has the same issue, make sure that the orientation property matches for the PrimaryParts of all your models.
worldgen4

2 Likes