Upvector Drift?

I am creating a system that can map plants in patches around a sphere, which is a planet. It works very well, but as the system keeps going, it starts changing the lookvector, idk why, and the plants start hovering off of the planet. This is bad.


You can see hovering on the grass if you look closely at the edges. Can someone help?

Code:

local function patch(amount)

		local lastPosition = nil
		local rightVector = nil
		local upVector = nil

		for i = 1, amount do

			throttle += 1

			if throttle == 20 then
				task.wait()
				throttle = 0
			end

			local phi = math.random() * math.pi
			local theta = math.random() * 2 * math.pi

			local x = Variables.Radius * math.sin(phi) * math.cos(theta)
			local y = Variables.Radius * math.sin(phi) * math.sin(theta)
			local z = Variables.Radius * math.cos(phi)

			local myModel = createAlienPlant(height, density):Clone()

			-- Adjust the Y component to spawn above the planet based on the distance
			local position = Variables.Center + Vector3.new(x, y, z)

			if lastPosition == nil then
				rightVector = myModel.PrimaryPart.CFrame.RightVector
				upVector = myModel.PrimaryPart.CFrame.UpVector
				lastPosition = position
			else
				position = lastPosition + (rightVector * math.random(-100, 100)) + (upVector * math.random(-100, 100))
				lastPosition = position
			end

			myModel.Parent = game.ReplicatedStorage.UnloadedPlants

			myModel:PivotTo(CFrame.new(position, Variables.Center))

			rightVector = myModel.PrimaryPart.CFrame.RightVector
			upVector = myModel.PrimaryPart.CFrame.UpVector

			--myModel:ScaleTo(ScaleFactor)

		end
	end
3 Likes

Still can’t figure this out… I tried doing one or the other, but the drift still occurs???

2 Likes

I am not sure of the method that you’ve used is valid for this usage but if I were to randomize the position of trees in a sphere, I would do it with Vector Addition methods such as Triangle or Parallelogram method, ( Polygon method wont work here since sphere doesn’t have vertices ).

This is a rough method that I did while reading your issue. The image is of 2 dimensional only so in order to make it 3D, you can count in the k vector i.e z-axis and find the Resultant Vector ( R ). With the help of all three vectors, you should be able to place the trees within that boundary.

[NOTE : using this method will leave some gaps which cannot be altered or changed so as to fill them up with plants or etc. ]

I am pretty sure if you use this method and combine it otherwise you can use the formula
|a||b| = (a.b) / (cos theta) where |a| and |b| represent magnitude of vectors A and B. (a.b) is dot product of the two vectors. cos theta is the angle between two vectors.

once you get the magnitudes, you can randomize them from lowest to maximum, clone the plant and place it there with the common Y-axis of all three vectors.

2 Likes

Yes, but the problem is not with random placement, its with placing random patches of foliage. My code works fine to place objects at random locations on the sphere. Also, math is not my best subject, so I dont really know how to implement your system.

2 Likes

If you’re really sure that your method is an apt way to go with this problem then one of the magnitude of a coordinate axis is being wrongly calculated in the script. Maybe print all the values and then have a dry run of it to see where possibly your code is going incorrect.

Otherwise, you can use my method as it only involves finding magnitude of 2 vectors and resultant vector.

try this

local function randomPointOnSphere(center, radius)
	local randomX = (math.random()*2)-1
	local randomY = (math.random()*2)-1
	local randomZ = (math.random()*2)-1

	local randomVector = Vector3.new(randomX, randomY, randomZ)
	local randomDirection = randomVector.Unit
	local randomDirectionWithRadius = randomDirection * radius
	local randomPointOnSurface = center + randomDirectionWithRadius

	-- Adjust the randomPointOnSurface to prevent clipping inside the planet
	local distanceToSurface = (randomPointOnSurface - center).Magnitude - radius
	randomPointOnSurface = randomPointOnSurface - randomDirectionWithRadius.Unit * distanceToSurface

	return randomPointOnSurface, randomDirection -- Return the random direction as well
end

local function spawnPartsAroundSphere(spherePart, numParts)
	local radius = spherePart.Size.X / 2
	local center = spherePart.Position

	for i = 1, numParts do
		local randomPoint, randomDirection = randomPointOnSphere(center, radius) -- Get the random direction from the randomPointOnSphere function

		local part = game.ReplicatedStorage.Core:Clone()
		part.Position = randomPoint
		part.Parent = workspace
		

		-- Rotate the part to face towards the center of the sphere
		
		part.CFrame = CFrame.lookAt(part.Position, center) 
		
	end
end
while true do
	wait(20)
	spawnPartsAroundSphere(script.Parent, 5)
end

a nice and simple solution is to simply use raycast to set their height relative to the sphere

@sussy_bacoo and @Super_pro322222, this is not the problem. I can easily spawn the plants randomly around the planet. That works perfectly. The problem is spawning them in clumps, and still have them relative to the sphere. Raycasting is difficult, because I can’t just change the y value down a bit.

1 Like