Creating a triangle from 3 points

I have 3 points But I want to have a triangle part that is created from these 3 Points so i could make “Shards” from it The triangle is not in 2d space but can be represented in 2d space.

2 Likes

What are you using to create the triangle? EditableMeshes?

1 Like

I want to use the triangle as a shard so i would need to cut it from a part

2 Likes

So, by using the CSG API? Specifically :SubtractAsync()?

1 Like

You want to make triangle out of 2 wedges? If yes, I can give you code to do so.

1 Like

yes but how would i get the Shape out of it because when i tried to sub the lines creating that pieceit obviously as expected Only cut the outer lines

2 Likes

Yeah sure thats what i originally thought to do im just not that good with trigo to be able to do it

2 Likes
local wedge = Instance.new("WedgePart");
wedge.Anchored = true;
wedge.TopSurface = Enum.SurfaceType.Smooth;
wedge.BottomSurface = Enum.SurfaceType.Smooth;
 
local function draw3dTriangle(a, b, c)
    local ab, ac, bc = b - a, c - a, c - b;
    local abd, acd, bcd = ab:Dot(ab), ac:Dot(ac), bc:Dot(bc);
    
    if (abd > acd and abd > bcd) then
        c, a = a, c;
    elseif (acd > bcd and acd > abd) then
        a, b = b, a;
    end
    
    ab, ac, bc = b - a, c - a, c - b;
    
    local right = ac:Cross(ab).unit;
    local up = bc:Cross(right).unit;
    local back = bc.unit;
    
    local height = math.abs(ab:Dot(up));
    
    local w1 = wedge:Clone();
    w1.Size = Vector3.new(0, height, math.abs(ab:Dot(back)));
    w1.CFrame = CFrame.fromMatrix((a + b)/2, right, up, back);
    w1.Parent = workspace;
    
    local w2 = wedge:Clone();
    w2.Size = Vector3.new(0, height, math.abs(ac:Dot(back)));
    w2.CFrame = CFrame.fromMatrix((a + c)/2, -right, up, -back);
    w2.Parent = workspace;
    
    return w1, w2;
end

Use that function.

Run it by just passing your three vector 3 points.

Could you explain how this works? Maybe if you know

It’s just maths. I don’t know what I can explain about maths.

This is from EgoMoose, he wrote an article on it here: Articles/3d triangles/3D triangles.md at master · EgoMoose/Articles · GitHub

1 Like

Here it is:

local function CalculateTriangle(a,b,c)
	local ax,ay,az=a.x,a.y,a.z
	local bx,by,bz=b.x,b.y,b.z
	local cx,cy,cz=c.x,c.y,c.z
	local px,py,pz=ax,ay,az
	local tx,ty,tz=cx,cy,cz
	local v0x,v0y,v0z=bx-ax,by-ay,bz-az
	local v1x,v1y,v1z=cx-ax,cy-ay,cz-az
	local d01=v0x*v1x+v0y*v1y+v0z*v1z--In case of case 2 triangle. Speeds it up a lot
	local d=d01/(v0x*v0x+v0y*v0y+v0z*v0z)
	if d>0 then
		if d>1 then--Case 2 triangle
			tx,ty,tz=bx,by,bz
			v0x,v0y,v0z,v1x,v1y,v1z=v1x,v1y,v1z,v0x,v0y,v0z
			d=d01/(v0x*v0x+v0y*v0y+v0z*v0z)
			--		else Case 1 triangle			
		end
	else--Case 3 triangle. Don't get a case 3 triangle lol. Slowest of them all.
		px,py,pz=cx,cy,cz
		tx,ty,tz=ax,ay,az
		v0x,v0y,v0z=bx-cx,by-cy,bz-cz
		v1x,v1y,v1z=-v1x,-v1y,-v1z
		d=(v0x*v1x+v0y*v1y+v0z*v1z)/(v0x*v0x+v0y*v0y+v0z*v0z)
	end
	local y0x,y0y,y0z=tx-px-d*v0x,ty-py-d*v0y,tz-pz-d*v0z
	local l0,l1=(v0x*v0x+v0y*v0y+v0z*v0z)^0.5, (y0x*y0x+y0y*y0y+y0z*y0z)^0.5
	local hy0x,hy0y,hy0z,hd=y0x*0.5,y0y*0.5,y0z*0.5,d*0.5
	local tf=0.5+hd
	local oyx,oyy,oyz,ozx,ozy,ozz=y0x/l1,y0y/l1,y0z/l1,v0x/l0,v0y/l0,v0z/l0
	local oxx,oxy,oxz=oyy*ozz-oyz*ozy,oyz*ozx-oyx*ozz,oyx*ozy-oyy*ozx
	local Tris1CF = CFrame.new(v0x*hd+hy0x+px,v0y*hd+hy0y+py,v0z*hd+hy0z+pz, oxx,oyx,ozx,oxy,oyy,ozy,oxz,oyz,ozz)
	local Tris2CF = CFrame.new(v0x*tf+hy0x+px,v0y*tf+hy0y+py,v0z*tf+hy0z+pz,-oxx,oyx,-ozx,-oxy,oyy,-ozy,-oxz,oyz,-ozz)
	local Size1 = Vector3.new(0.001,l1,d*l0)
	local Size2 = Vector3.new(0.001,l1,(1-d)*l0)
	return Tris1CF, Size1, Tris2CF, Size2
end

I’m not owner of this code though, and this complex math as I know is the most optimized, cuz only basic math operations used.

1 Like

First, let us visualize 3 points a, b, c in space. It should look something like this:

Now, lets focus on the first line of the function.

local ab, ac, bc = b - a, c - a, c - b

Lets say you take two points in space, a, b. Now, if you do (b - a), it simply returns a vector that starts off at point a, and ends at point b. We call this vector AB. Here is an image.
image

The first line of code just gets the vectors AB, AC, BC.

Next, lets take a look at the second line.

local abd, acd, bcd = ab:Dot(ab), ac:Dot(ac), bc:Dot(bc)

Assume you have a vector called AB. When you dot AB with itself, you get the magnitude squared, also known as the length of the vector but SQUARED. What the code does is simply get the squared lengths of the vectors AB, AC, and BC. Learn more about dot products here.

Moving onto the next few lines of code.

    if (abd > acd and abd > bcd) then
        c, a = a, c
    elseif (acd > bcd and acd > abd) then
        a, b = b, a
    end

What this does is simply swap the a and c coordinates if the squared length of AB is greater than AC and BC. If the first if statement doesn’t hold true, it swaps the a and b coordinates if the squared length of AC is greater than BC and AB.

 ab, ac, bc = b - a, c - a, c - b

This line simply recalculates the vectors (look above for explanation), since the coordinates might have been swapped.

Let us now look at the next few lines of code.

    local right = ac:Cross(ab).Unit
    local up = bc:Cross(right).Unit
    local back = bc.Unit

The first line returns a unit vector facing the right (the black arrow) like this:
image

The second line returns a unit vector that faces up like this:
image

Finally, the third line simply returns the normalized version (has a length of 1) of the vector BC like this:


Learn more about cross products here.

Moving onto the next line.

local height = math.abs(ab:Dot(up))

This line returns the height of the triangle, and the math.abs is to ensure the height is always positive. Look at the image below for a visual (the black line).

Now, the next line.

w1.Size = Vector3.new(0, height, math.abs(ab:Dot(back)))

When you dot AB with back, you get the length of the base of the triangle.

Next line.

w1.CFrame = CFrame.fromMatrix((a + b) / 2, right, up, back)

This line simply constructs a new CFrame. The first parameter is the mid point of our two vectors a and b, the second parameter is our right vector, the third parameter is our up vector, and the last parameter is the back vector. Look above if you want visuals for right, up, and back vectors.

Lets look at our next line of code.

w2.Size = Vector3.new(0, height, math.abs(ac:Dot(back)))

This also returns the length of the triangle base.

Our final line of code.

w2.CFrame = CFrame.fromMatrix((a + c) / 2, -right, up, -back)

This line also constructs a new CFrame, but our parameters are a bit different this time. The first parameter is the mid point of our two vectors a and c, the second parameter is our left vector (if you add a negative to a vector, it flips the direction), the third parameter is our up vector, and the last parameter is the forward vector.

Hopefully this helped you understand the code. If you have any further questions, feel free to ask me.

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