用来可视化了解各种矩阵变换的代码。直接创建即可用。代码注释完整
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class CoordinateSystem : MonoBehaviour
{
public Transform RedPoint;
public Transform BluePoint;
public Camera ccamera;
public Transform transformCamera;
public Transform transformModel;
public Transform transformWorld;
public Color[] cameraSystemColor;
public Color[] worldSystemColor;
public Color[] modelSystemColor;
public void OnDrawGizmos()
{
//世界空间坐标系
DrawACoordinate(transformWorld, worldSystemColor);
//摄像机空间坐标系
DrawACoordinate(transformCamera,cameraSystemColor);
//模型空间坐标系
DrawACoordinate(transformModel, modelSystemColor);
}
private void DrawACoordinate(Transform inT,Color[] DrawColor)
{
Gizmos.color = DrawColor[0];
Gizmos.DrawLine(inT.position, inT.position + inT.forward);
Gizmos.color = DrawColor[1];
Gizmos.DrawLine(inT.position, inT.position + inT.up);
Gizmos.color = DrawColor[2];
Gizmos.DrawLine(inT.position, inT.position + inT.right);
}
public void CreateModelToWorldMatrix()
{
Matrix4x4 mMatrix = Matrix4x4.TRS(transformModel.position, transformModel.rotation, transformModel.lossyScale);
Debug.Log(transformModel.localToWorldMatrix.ToString() + "\n\n"+mMatrix.ToString());
//取模型空间的原点,转移到世界坐标系中
RedPoint.position = mMatrix *new Vector4(0, 0, 0, 1);
}
public void CreateWorldToCameraMatrix()
{
//将世界坐标的摄像机信息构建一个变换矩阵
//需要注意的是,Z方向的轴向是反的,这是因为
//camera space matches OpenGL convention: camera's forward is the negative Z axis.
//This is different from Unity's convention, where forward is the positive Z axis.
//OpenGL和unity在Z轴的正方定义是相反的
Matrix4x4 cMatrix = Matrix4x4.TRS(transformCamera.position,transformCamera.rotation,new Vector3(1,1,-1));
//计算这个摄像机的逆
cMatrix = Matrix4x4.Inverse(cMatrix);
Debug.Log(ccamera.worldToCameraMatrix.ToString() + "\n\n" + cMatrix.ToString());
Vector3 cameraPosition = cMatrix * new Vector4(RedPoint.position.x, RedPoint.position.y, RedPoint.position.z, 1.0f);
BluePoint.localPosition = new Vector3(cameraPosition.x, cameraPosition.y,cameraPosition.z*-1);
Debug.Log("红点在摄像机空间的坐标为" + BluePoint.localPosition.ToString());
}
public void CreateProjectionMatrix()
{
//Debug.Log(ccamera.projectionMatrix.ToString() + "\n\n"
Matrix4x4 pMatrix = Matrix4x4.Perspective(ccamera.fieldOfView, ccamera.aspect, ccamera.nearClipPlane, ccamera.farClipPlane);
Vector3 bl = BluePoint.localPosition;
Vector3 screenPosition = pMatrix * new Vector4(bl.x, bl.y, bl.z, 1.0f);
screenPosition.Normalize();
Vector2 v2ScreenPosition = new Vector2(screenPosition.x*0.5f+0.5f, screenPosition.y*0.5f+0.5f);
Debug.Log(ccamera.projectionMatrix + "\n\n" + pMatrix.ToString());
Debug.Log("红点在投影后的坐标为" + v2ScreenPosition.ToString());
Debug.Log(ccamera.WorldToViewportPoint(BluePoint.position));
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(CoordinateSystem))]
public class CoordinateSystemEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
CoordinateSystem myScript = (CoordinateSystem)target;
if (GUILayout.Button("重置"))
{
myScript.RedPoint.position = Vector3.zero;
myScript.BluePoint.localPosition = Vector3.zero;
}
if (GUILayout.Button("将一个顶点从本地坐标系转换到世界坐标系"))
{
myScript.CreateModelToWorldMatrix();
}
if (GUILayout.Button("将一个顶点从世界坐标系转换到视空间坐标系"))
{
myScript.CreateWorldToCameraMatrix();
}
if (GUILayout.Button("将一个视空间坐标系的内容投影到2D平面上"))
{
myScript.CreateProjectionMatrix();
}
}
}
#endif
领取专属 10元无门槛券
私享最新 技术干货