When objects are reflected on a mirror from a perspective (the camera), then the light is leaving objects, hitting the mirror, reflecting off of it at the same angle it hit, and going to the eye. The object appears to the eye as if the ray had come from behind the mirror, at exactly the same angle. Here is a diagram:
Since the angle of reflection is always the the same in the opposite direction, the distance from the mirror stays the same but appears as in the opposite direction. What this means is that every object in 3D space is reflected about the plane of the mirror (mathematical reflection, not how we usually think of reflection). Every point’s position is changed by twice its distance from the plane along the normal of the plane. If we were to imagine the rotation vectors of the object, they too would be their reflections. However, doing this would make the vectors reversed, essentially converting between a left-hand and right-handed coordinate system (although this isn’t to say mirrors reverse left and right. They actually reverse forward and backward relative to the mirror. left-handed and right-handed coordinate systems is just a nod to the slightly different orthogonality in mirror space and doesn’t care which way is actually right or left). To change it back, we would have to reverse one of the axis. Since parts and spheres are symmetric around every axis, flipping one axis wont cause any issues. However it does become a problem for some axis with wedges and becomes even more complicated for meshes.
Here is the basic code to reflect a symmetric object:
local function reflectVector(v, n)
return v - 2 * n * n:Dot(v)
end
local function reflect(part, mirrorPos, mirrorNormal)
local p = mirrorPos + reflectVector(part.Position - mirrorPos, mirrorNormal)
local right = reflectVector(part.CFrame.RightVector, mirrorNormal)
local up = reflectVector(part.CFrame.UpVector, mirrorNormal)
local look = reflectVector(part.CFrame.LookVector, mirrorNormal)
right = -right -- I'm not sure how to choose which vector to invert
-- so I'll leave it to experimentation later if the thread author desires.
part.CFrame = CFrame.fromMatrix(p, right, up, look)
end
The way that mirrors have been done in the past is by projecting all the points of a part into the plane of the mirror and using right triangles to fill in the shapes.