BITFALL/Assets/GSpawn - Level Designer/Scripts/Math/Symmetry.cs

118 lines
4.1 KiB
C#
Raw Normal View History

2024-01-27 04:09:57 +08:00
#if UNITY_EDITOR
using UnityEngine;
namespace GSpawn
{
public static class Symmetry
{
public struct MirroredRotation
{
public Quaternion rotation;
public Vector3 axesScaleSign;
public MirroredRotation(Quaternion rotation, Vector3 axesScaleSign)
{
this.rotation = rotation;
this.axesScaleSign = axesScaleSign;
}
public static MirroredRotation identity { get { return new MirroredRotation() { rotation = Quaternion.identity, axesScaleSign = Vector3.one }; } }
}
public struct MirroredOBB
{
public OBB obb;
public MirroredRotation mirroredRotation;
public MirroredOBB(OBB obb, MirroredRotation mirroredRotation)
{
this.obb = obb;
this.mirroredRotation = mirroredRotation;
}
}
public static Vector3Int mirror3DGridCell(Vector3Int cell, Vector3Int mirrorCell, PlaneId mirrorPlaneId)
{
Vector3Int toMirrorPos = mirrorCell - cell;
switch (mirrorPlaneId)
{
case PlaneId.XY:
return new Vector3Int(cell.x, cell.y, cell.z + toMirrorPos.z * 2);
case PlaneId.YZ:
return new Vector3Int(cell.x + toMirrorPos.x * 2, cell.y, cell.z);
case PlaneId.ZX:
return new Vector3Int(cell.x, cell.y + toMirrorPos.y * 2, cell.z);
}
return cell;
}
public static Vector3 mirrorPosition(Vector3 position, Plane mirrorPlane)
{
float distanceToPt = mirrorPlane.GetDistanceToPoint(position);
return position - mirrorPlane.normal * distanceToPt * 2.0f;
}
public static Vector3 mirrorNormal(Vector3 normal, Plane mirrorPlane)
{
Plane mirrorPlaneAtOrigin = new Plane(mirrorPlane.normal, 0.0f);
Vector3 mirroredNormal = mirrorPosition(normal, mirrorPlaneAtOrigin).normalized;
return mirroredNormal;
}
public static OBB mirrorOBB(OBB obb, bool mirrorRotation, Plane mirrorPlane)
{
OBB mirroredOBB = new OBB(obb);
mirroredOBB.center = mirrorPosition(mirroredOBB.center, mirrorPlane);
if (mirrorRotation)
{
MirroredRotation mirroredRotation = Symmetry.mirrorRotation(mirroredOBB.rotationMatrix, Vector3.one, mirrorPlane);
mirroredOBB.rotation = mirroredRotation.rotation;
}
return mirroredOBB;
}
public static MirroredOBB mirrorOBB(MirroredOBB obb, bool mirrorRotation, Plane mirrorPlane)
{
MirroredOBB mirroredOBB = obb;
mirroredOBB.obb.center = mirrorPosition(obb.obb.center, mirrorPlane);
if (mirrorRotation)
{
mirroredOBB.mirroredRotation = Symmetry.mirrorRotation(mirroredOBB.obb.rotationMatrix, obb.mirroredRotation.axesScaleSign, mirrorPlane);
mirroredOBB.obb.rotation = mirroredOBB.mirroredRotation.rotation;
}
return mirroredOBB;
}
public static MirroredRotation mirrorRotation(Matrix4x4 rotationMtx, Vector3 axesSigns, Plane mirrorPlane)
{
Vector3 right = rotationMtx.getNormalizedAxis(0) * axesSigns.x;
Vector3 up = rotationMtx.getNormalizedAxis(1) * axesSigns.y;
Vector3 look = rotationMtx.getNormalizedAxis(2) * axesSigns.z;
right = mirrorNormal(right, mirrorPlane);
up = mirrorNormal(up, mirrorPlane);
look = mirrorNormal(look, mirrorPlane);
Quaternion newRotation = Quaternion.LookRotation(look, up);
Vector3 resultRightAxis = Vector3.Cross(up, look);
Vector3 axesScaleSign = Vector3.one;
float dot = Vector3.Dot(resultRightAxis, right);
if (dot <= 0.0f) axesScaleSign[0] = -1.0f;
return new MirroredRotation(newRotation, axesScaleSign);
}
}
}
#endif