Let’s see.
-- our centroid position
local centroidPosition = Vector3.new(0,0,0)
-- our facing vector (x-z plane for this example)
local facing = Vector3.new(1, 0, 0).Unit
-- up vector (straight up for this example)
local up = Vector3.new(0,1,0).Unit
-- values for our equilateral triangle
local side_length = 10
local half_base = side_length / 2
local height = half_base * math.sqrt(3) -- dist from point to opp side
-- vector displacement from centroid to "top" vertex
local facing_point_disp = 2/3 * height * facing
-- vector displacement from centroid to center of base of eq triangle
local baseline_disp = 1/3 * height * (-facing)
-- vector displacement from center of base to bottom points
local right_disp = half_base * facing:Cross(up)
-- find the points
local point1 = centroidPosition + facing_point_disp
local point2 = centroidPosition + baseline_disp + right_disp
local point3 = centroidPosition + baseline_disp - right_disp
Something like that, maybe.
Storing the magnitude calc from centroid to a vertex ( mag = 2/3 * side_len/2 * math.sqrt(3) or based on a radius like you did) and angle offsets from facing vect to the other two points (should always be same 120 deg relative to facing), then just offset points from centroid along the 3 vectors by that magnitude amount. What you did seems like a fine approach. The CFrame has all the facing/up/right vectors built in for full 3D support.
-- side len of equilateral triangle
local sideLength = 10
-- position of triangle centroid
local centroidPosition = Vector3.new(4,5,10)
-- facing and up vectors (constrain facing to xz plane with y-up
-- so we don't have to keep track of a rotated up vector)
local up = Vector3.new(0,1,0).Unit
local facing = Vector3.new(2,0,2).Unit
facing *= sideLength*math.sqrt(3)/3
-- rotate vert 120 deg around centroid (y-axis) to find other verts
local angle = 120
local function qConvertToVect3(q)
return Vector3.new(q[2], q[3], q[4])
end
local function qProduct(a, b)
return {
a[1]*b[1]-a[2]*b[2]-a[3]*b[3]-a[4]*b[4],
a[1]*b[2]+a[2]*b[1]+a[3]*b[4]-a[4]*b[3],
a[1]*b[3]-a[2]*b[4]+a[3]*b[1]+a[4]*b[2],
a[1]*b[4]+a[2]*b[3]-a[3]*b[2]+a[4]*b[1]
}
end
local function qRotate(axis, vect, angle)
-- get cos & sin of angle/2
local cos_a = math.cos(math.rad(angle/2))
local sin_a = math.sin(math.rad(angle/2))
-- build quaternion
local u = {0, vect.X, vect.Y, vect.Z}
local q = {cos_a, axis.X*sin_a, axis.Y*sin_a, axis.Z*sin_a}
local q_star = {cos_a, -q[2], -q[3], -q[4]}
-- u_prime = q*u*q_star
return qProduct(qProduct(q, u), q_star)
end
Test code
-- TEST
local part = Instance.new("Part")
part.Parent = workspace
part.Shape = Enum.PartType.Ball
part.Material = Enum.Material.SmoothPlastic
part.Size = Vector3.new(1,1,1)
part.Anchored = true
part.Position += centroidPosition
local part1 = part:Clone()
part1.Parent = workspace
part1.Position = facing + centroidPosition
part1.Name = "tip"
local q = qRotate(up, facing, angle)
local part2 = part:Clone()
part2.Parent = workspace
part2.Position = qConvertToVect3(q) + centroidPosition
part2.Name = "first"
local r = qRotate(up, qConvertToVect3(q), angle)
local part3 = part:Clone()
part3.Parent = workspace
part3.Position = qConvertToVect3(r) + centroidPosition
part3.Name = "second"
print("mag", (part3.Position - part2.Position).Magnitude)
print("mag", (part2.Position - part1.Position).Magnitude)
print("mag", (part1.Position - part3.Position).Magnitude)
Anyway…looks like you have a soln so just goofing around.