Rotation relative to surface normal

Heya, so i’m making the build tool for my game: Build a killing machine! ™
The question is, I don’t know how to make the rotation relative to the plane you’re building a block on.
Like this:

As you can see, you can rotate the block on another block either on the X direction or the Y direction.
This is my attempt, using the normal of each face of the block:

As seen, it doesn’t rotate properly. I don’t know why. This is the relevant piece of code.

function getPlacementCFrame(primaryPart: BasePart): CFrame
	assert(raycastResult, "raycastResult is nil!") 
	local target: Part = raycastResult.Instance
	local hitPosition: Vector3 = raycastResult.Position
	
	local _rotation: CFrame = rotation
	if relativeRotation then
		local tempCFrame1: CFrame = CFrame.lookAt(Vector3.new(), raycastResult.Normal) 
		tempCFrame1 = (tempCFrame1 - tempCFrame1.Position)
		local tempCFrame2: CFrame = tempCFrame1:ToObjectSpace(rotation)
		_rotation = (tempCFrame2 - tempCFrame2.Position)
	end
	--CFrame.new(raycastResult.Position) * _rotation * 
	local resolvedCFrame: CFrame = CFrame.new(raycastResult.Position) * _rotation
        ...

I think you are looking for CFrame.fromAxisAngle

How would you use this? Especially with two axes? (X,Y) I think I have to use :cross somewhere but I do not know the other value of cross other than normal vector.

Hey, I saw your gridplacer module. Is that the thing I need to place my blocks? I want to make a build a boat-esque building tool.

Gridplacer will do some of the things you are trying to do, the main thing it doesn’t have is collision detection. Also I think this place is uncopylocked and has an example of how to use GridPlacer in ProtoFabriz tool:

Bump. Sorry, I just cannot for the life of me figure out how to do this. Even with the CFrame.fromAxisAngle tip from azqjanna
Let me rephrase: How can we achieve what we saw in the build a boat clip without relying on the rotation of the part itself (only the surface normal)

Sorry I’m not the best at CFrames but maybe you can use CFrame.fromMatrix() and set the UpVector to the surface normal.

1 Like

Okay, but what should I set the other Vectors to? I think I might need to use the part’s rotation.

The UpVector to the surface normal, what I mean is the vector which represents the front face (I hope you get what I mean).

I’m pretty sure there’s one other vector you need to specify (rightvector or lookvector) and then you could just use cross to fill in the other one

but i don’t know what to specify

Oh sorry for being confusing, I understand now. But how do you set the upvector

What I mean by UpVector is the vector which represents the front face. It is probably Y vector but you can just see it by clicking on the part, if the axis of front face is green, it’s Y vector. Sorry but I’m myself learning about CFrames.

Oh. Yes i know that, i’m just wondering how to set the upvector to the surfacenormal
it seems to be read-only

CFrame.fromMatrix(part.Position, part.XVector, the_normal, part.ZVector) – the part is the part you want to place

1 Like

I’m not sure about that sorry. I’ll do some research

I meant that you cant set it directly (have to use frommatrix)
Also i didn’t notice that the parameters for .fromMatrix were vectors :sweat_smile:

1 Like

Oh, no problem. I think that’s something fromMatrix() can be used for. I need to do more research though

(EDIT: Ok so I found out that CFrame.lookAt is similar to CFrame.fromMatrix but lookAt is slightly better for the work you want)

I’ve tested this, and this only works on one side (since the normal is different depending on which side you’re raycasting from, it isn’t perpindicular to the other two vectors unless the normal is on the top side)

Uhh, can you post a screenshot of this? I did something similar to this but it worked well so

Sorry I’m being too dumb and you’re just trying to explain everything to this dumb man

Oh! Can you show me the code? And ok, i’m going to make a gif of it. Hold on

1 Like