평소랑 똑같이 만들어놓고
변환 행렬 (Transformation Matrix)
출처 https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Introduction
유틸리티 C#을 만들고
아무런 상속도 받징낳게 합니다.
당연히 유니티에서는 기본적으로 만들수있게 제공 해주지만
Vector의 이해를위해 직접 만들어보자
우선
public static Mesh CreateMeshQuad(string _name = "Deafult")
{
Mesh mesh = new Mesh();
mesh.name = _name;
//0--1
//l l
//2--3
//Vertex / Vertex Buffer
Vector3[] vertices = new Vector3[4]
{
new Vector3(-0.5f, 0.5f, 0f),
new Vector3(.5f, .5f, 0f),
new Vector3(-0.5f , -0.5f, 0f),
new Vector3(0.5f, -0.5f, 0f)
};
mesh.vertices = vertices;
//Index / Index Buffer
int[] indices = new int[6]
{
0,1,2,
1,2,3
};
mesh.triangles = indices;
//UV Coordinate
// Texture / Texture Mapping
Vector2[] uvs = new Vector2[4]
{
new Vector2(0f, 0f),
new Vector2(1f, 0f),
new Vector2(0f, 1f),
new Vector2(1f, 1f)
};
mesh.uv = uvs;
//Normal Vector
Vector3[] normals = new Vector3[4]
{
new Vector3(0f, 0f, -1f),
new Vector3(0f, 0f,-1f),
new Vector3(0f, 0f, -1f),
new Vector3(0f, 0f, -1f)
};
mesh.normals = normals;
return mesh;
}
이렇게 만들어 놓은 다음
하나 더 만들어서
빈 프로젝트로 만들고 transformain 으로 이름지정하고 스크립트를 넣어줍니다 .
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UIElements;
[RequireComponent(typeof(MeshFilter))]
public class Transformation : MonoBehaviour
{
//Serializable : 데이터 직렬화
[System.Serializable]
private struct MyTransform
{
public Vector3 pos;
public Vector3 rot;
public Vector3 scale;
}
//Mesh Filter
//Mesh Renderer
private MeshFilter mf = null;
private MeshRenderer mr = null;
[SerializeField] private MyTransform tr;
// T: Translate
private Matrix4x4 T = Matrix4x4.identity;
private void Update()
{
ResetMesh();
TRS();
}
private void Awake()
{
mf = GetComponent<MeshFilter>(); // 없으면 NULL이 나오고
//반드세 오브젝트가 있어야한다
mr = gameObject.AddComponent<MeshRenderer>(); // 있으면 NULL 이 나온다
if (mr == null) mr = GetComponent<MeshRenderer>();
tr.scale.x = 1f;
tr.scale.y = 1f;
tr.scale.z = 1f;
}
public void Start()
{
mf.mesh = Utillity.CreateMeshQuad();
//Meterial / Shader
Material mat = new Material(Shader.Find("Standard"));
Texture2D tex = Resources.Load("Textures\\T_Kriby") as Texture2D;
mat.mainTexture = tex;
mr.material = mat;
}
private void ResetMesh()
{
Mesh mesh = mf.mesh;
Vector3[] vertices = new Vector3[4]
{
new Vector3(-0.5f, 0.5f, 0f),
new Vector3(.5f, .5f, 0f),
new Vector3(-0.5f , -0.5f, 0f),
new Vector3(0.5f, -0.5f, 0f)
};
mesh.vertices = vertices;
}
private void LocalToWorld(Matrix4x4 _world)
{
Vector3[] verices = mf.mesh.vertices;
for (int i = 0; i < verices.Length; ++i)
{
verices[i] = _world.MultiplyPoint(verices[i]);
}
mf.mesh.vertices = verices;
}
private Matrix4x4 TRS()
{
Matrix4x4 world = Matrix4x4.identity;
// T: Translate
Matrix4x4 T = Matrix4x4.identity;
T.m03 = tr.pos.x;
T.m13 = tr.pos.y;
T.m23 = tr.pos.x;
// R : Rotation
Matrix4x4 Rx = Matrix4x4.identity;
Rx.m11 = Mathf.Cos(tr.rot.x);
Rx.m12 = Mathf.Sin(tr.rot.x);
Rx.m21 = Mathf.Sin(tr.rot.x);
Rx.m22 = Mathf.Cos(tr.rot.x);
// C 0 S 0
// 0 1 1 1
// -s 0 C 0
// 0 0 0 1
Matrix4x4 Ry = Matrix4x4.identity;
Ry.m00 = Mathf.Cos(tr.rot.y);
Ry.m02 = Mathf.Sin(tr.rot.y);
Ry.m20 = Mathf.Sin(tr.rot.y) * 1f;
Ry.m22 = Mathf.Cos(tr.rot.y);
// C -s 0 0
// S C 0 0
// 0 0 1 0
// 0 0 0 1
Matrix4x4 Rz = Matrix4x4.identity;
Rz.m00 = Mathf.Cos(tr.rot.z);
Rz.m01 = Mathf.Sin(tr.rot.z) - 1f;
Rz.m10 = Mathf.Sin(tr.rot.z);
Rz.m11 = Mathf.Cos(tr.rot.z);
//S : Scale
Matrix4x4 S = Matrix4x4.identity;
S[0, 0] = tr.scale.x;
S[1, 1] = tr.scale.y;
S[2, 2] = tr.scale.z;
//TRS 순
world = T * Rx * Ry * Rz * S;
//world = S * Rz * Ry * Rx * T;
return world;
}
}
이렇게 하면 유니티에서 제공하는 기본기능들이 구현됩니다.
Utillity.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Transformtion Metrix
// Liner Transformation
// Liner
public class Utillity
{
public static Mesh CreateMeshQuad(string _name = "Deafult")
{
Mesh mesh = new Mesh();
mesh.name = _name;
//0--1
//l l
//2--3
//Vertex / Vertex Buffer
Vector3[] vertices = new Vector3[4]
{
new Vector3(-0.5f, 0.5f, 0f),
new Vector3(.5f, .5f, 0f),
new Vector3(-0.5f , -0.5f, 0f),
new Vector3(0.5f, -0.5f, 0f)
};
mesh.vertices = vertices;
//Index / Index Buffer
//CW(시계방향 , 앞면) / CCW(반 시계방향, 뒷면)
//Backface Culling(은면 제거)
int[] indices = new int[6]
{
0,1,2,
1,3,2
};
mesh.triangles = indices;
//UV Coordinate
// Texture / Texture Mapping
Vector2[] uvs = new Vector2[4]
{
new Vector2(0f, 1f), //LU
new Vector2(1f, 1f), //RU
new Vector2(0f, 0f), //LD
new Vector2(1f, 0f) //RD
};
mesh.uv = uvs;
//Normal Vector
Vector3[] normals = new Vector3[4]
{
new Vector3(0f, 0f, -1f),
new Vector3(0f, 0f,-1f),
new Vector3(0f, 0f, -1f),
new Vector3(0f, 0f, -1f)
};
mesh.normals = normals;
//마젠타가 보이면 쉐이더가 깨진거임
return mesh;
}
}