118 lines
4.1 KiB
C#
118 lines
4.1 KiB
C#
#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 |