Orientating a tree model to fit the generated terrain

I’ve been recently working in a terrain generation script, and I want to make it so trees spawn on top of the terrain without them floating or looking weird.
For that, I’ve used RayCasting and CFrame:fromMatrix(), but I don’t really understand how this two work together, so any help will be kindly appreciated :slight_smile:

Code:

local hit, intersection, surfaceNormal, surfaceMaterial, normal = workspace:FindPartOnRayWithWhitelist(ray, whitelist, ignoreWater) --Raycast
local tree = trees[math.random(1, 2)]:Clone() -- 2 different type of trees
tree.Parent = workspace.Trees -- "Trees" is a folder in workspace
tree:SetPrimaryPartCFrame(CFrame.fromMatrix()) -- I have no clue what to do now, lol
-- // NOTE: Trees have a primary part, it should be obvious since I am using ":SetPrimaryPartCFrame()"

All you need to not make them float is the Y coordinate from your ray cast, apply that to whatever location you shot the ray from.

Essentially just replace the Y coordinate.

tree:SetPrimaryPartCFrame(CFrame.new(x, y, z))

I unederstand what you are trying to say here, but the problem is that what I am looking to do is to make the tree kind of addapt to the terrain so it’s not just standing vertically, but it also rotates acordingly to the terrain. Here is an example:
Capture2
:white_check_mark:
Capture
:x:

1 Like

Alright so in that case you want to take the normal and multiply it to where you want it.
That should do the trick

Can you make an example? I would really appreciate it.

Absolutely but I won’t be able to do so until later tonight, not home right now.
I’ll post the solution then.

1 Like

Amazing! No problem, I can wait as much time as you need

1 Like

First, both :FindPartOnRayWithWhitelist() and :SetPrimaryPartCFrame() are deprecated, so use :Raycast() and :PivotTo() instead.

A raycast returns the position where it hit (raycastResult.Position), and the direction that points directly outward from the surface it hit (raycastResult.Normal). We can use CFrame.lookAt() to create a CFrame which is at that position, and pointing in the direction of the normal:

-- Set up the params that will be used in the raycast
local raycastParams = RaycastParams.new() 
	raycastParams.IgnoreWater = ignoreWater
	raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
	raycastParams.FilterDescendantsInstances = whitelist

-- Make the raycast and pivot the tree based on its result
local raycastResult = workspace:Raycast(origin, direction, raycastParams)
local tree = trees[math.random(1, 2)]:Clone()
tree:PivotTo(CFrame.lookAt(raycastResult.Position, raycastResult.Position + raycastResult.Normal))
tree.Parent = workspace.Trees

This should put the tree’s PrimaryPart at the position, and aligned with the surface. The tree might be rotated in some direction by 90 degrees, depending on what the Orientation of the PrimaryPart is relative to the rest of the tree. To fix this, you could either manually rotate that part in the model until the tree lines up, or you could rotate the CFrame in the script by 90 degrees in whichever direction it needs.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.