当前位置: 代码迷 >> 综合 >> (五)Cube
  详细解决方案

(五)Cube

热度:31   发布时间:2023-11-26 15:15:53.0

文章目录

  • 1.概述
  • 2.基础版Cube
    • 2.1 基类
    • 2.2 Cube代码
  • 3.完善版Cube
    • 3.1 基础版Cube的问题
    • 3.2 完善版Cube顶点
    • 3.3 三角形数组
    • 3.4 法线数组
    • 3.5 完整代码
  • 4.结语

1.概述

Unity自带cube模型,但是此文实现,分基础版和完善版。基础版不进行顶点法线计算,完善版会进行法线计算,结果会跟自带cube比较接近。

2.基础版Cube

2.1 基类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]
public class CreateMeshBase : MonoBehaviour
{
    MeshFilter meshFilter;protected Mesh mesh;protected virtual Vector3[] Vertices {
     get; }protected virtual int[] Triangles {
     get; }protected virtual Vector3[] Normals {
     get; }protected virtual Vector2[] Uvs {
     get; }protected virtual string MeshName {
     get; }protected virtual void Start(){
    GetMeshFilter();}protected virtual void Reset(){
    GetMeshFilter();}protected virtual void OnValidate(){
    GetMeshFilter();}void GetMeshFilter(){
    if (meshFilter == null){
    meshFilter = GetComponent<MeshFilter>();mesh = new Mesh();            }mesh.triangles = null;mesh.uv = null;mesh.vertices = null;mesh.name = MeshName;mesh.vertices = Vertices;mesh.triangles = Triangles;mesh.uv = Uvs;meshFilter.mesh = mesh;}private void OnDrawGizmos(){
    if (Vertices == null) return;Gizmos.color = Color.red;Gizmos.DrawSphere(Vector3.zero, 0.5f);Gizmos.color = Color.blue;for (int i = 0; i < Vertices.Length; i++){
    Gizmos.DrawSphere(Vertices[i], 0.3f);}}
}

2.2 Cube代码

代码即为定义八个顶点,然后依次设置三角形即可。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CreateCube : CreateMeshBase
{
    public float halfLength = 5;protected override string MeshName{
    get{
    return "Cube Mesh";}}protected override Vector3[] Vertices{
    get{
    Vector3[] vertices = new Vector3[8];vertices[0] = new Vector3(-halfLength, -halfLength, -halfLength);vertices[1] = new Vector3(halfLength, -halfLength, -halfLength);vertices[2] = new Vector3(halfLength, -halfLength, halfLength);vertices[3] = new Vector3(-halfLength, -halfLength, halfLength);vertices[4] = new Vector3(-halfLength, halfLength, -halfLength);vertices[5] = new Vector3(halfLength, halfLength, -halfLength);vertices[6] = new Vector3(halfLength, halfLength, halfLength);vertices[7] = new Vector3(-halfLength, halfLength, halfLength);return vertices;}}protected override int[] Triangles{
    get{
    int[] triangles = new int[36]{
    0,1,3,3,1,2,4,6,5,4,7,6,1,6,2,1,5,6,0,3,4,4,3,7,0,4,1,1,4,5,3,2,6,3,6,7};return triangles;}}
}

3.完善版Cube

3.1 基础版Cube的问题

基础版Cube由于三个面公用一个顶点,导致此顶点处的法线和切线无法定义,所以需要分离顶点。这样顶点位置存在三个相互重合的点,每个点只跟自己对应的平面产生关系。

3.2 完善版Cube顶点

新Cube生成方法实在基础版基础上生成的,但是定点数由8个变成36个,即根据基础版的三角形数组生成。如下所示

    protected override Vector3[] Vertices{
    get{
    Vector3[] vertices = new Vector3[8];vertices[0] = new Vector3(-halfLength, -halfLength, -halfLength);vertices[1] = new Vector3(halfLength, -halfLength, -halfLength);vertices[2] = new Vector3(halfLength, -halfLength, halfLength);vertices[3] = new Vector3(-halfLength, -halfLength, halfLength);vertices[4] = new Vector3(-halfLength, halfLength, -halfLength);vertices[5] = new Vector3(halfLength, halfLength, -halfLength);vertices[6] = new Vector3(halfLength, halfLength, halfLength);vertices[7] = new Vector3(-halfLength, halfLength, halfLength);int[] triangles = new int[36]{
    0,3,1,3,2,1,4,5,6,4,6,7,1,2,6,1,6,5,0,4,3,4,7,3,0,1,4,1,5,4,3,6,2,3,7,6};cubeVertices = new Vector3[36];for (int i = 0; i < cubeVertices.Length; i++){
    cubeVertices[i] = vertices[triangles[i]];}return cubeVertices;}}

3.3 三角形数组

根据3.2生成的新的顶点数组,此时三角形数组值即为其索引,如下所示:

   protected override int[] Triangles{
    get{
    /*int[] triangles = new int[36]{0,1,3,3,1,2,4,6,5,4,7,6,1,6,2,1,5,6,0,3,4,4,3,7,0,4,1,1,4,5,3,2,6,3,6,7};*/int[] triangles = new int[36];for (int i = 0; i < triangles.Length; i++){
    triangles[i] = i;}return triangles;}}

3.4 法线数组

基础版cube看起来与unity自带的相比比较奇怪,这是因为没有设置顶点的法向。由于基础版公用顶点,所以法线无法定义,所以新版本法线则比较容易。如下所示:

    protected override Vector3[] Normals{
    get{
    Vector3[] normals = new Vector3[36];for (int i = 0; i < normals.Length - 2; i+=3){
    Vector3 normal = Vector3.Cross(cubeVertices[i + 1] - cubeVertices[i], cubeVertices[i + 2] - cubeVertices[i]);for (int j = 0; j < 3; j++){
    normals[i + j] = normal;}}return normals;}}

3.5 完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CreateNewCube : CreateMeshBase
{
    public float halfLength = 5;private Vector3[] cubeVertices = new Vector3[36];protected override string MeshName{
    get{
    return "Cube Mesh";}}protected override Vector3[] Vertices{
    get{
    Vector3[] vertices = new Vector3[8];vertices[0] = new Vector3(-halfLength, -halfLength, -halfLength);vertices[1] = new Vector3(halfLength, -halfLength, -halfLength);vertices[2] = new Vector3(halfLength, -halfLength, halfLength);vertices[3] = new Vector3(-halfLength, -halfLength, halfLength);vertices[4] = new Vector3(-halfLength, halfLength, -halfLength);vertices[5] = new Vector3(halfLength, halfLength, -halfLength);vertices[6] = new Vector3(halfLength, halfLength, halfLength);vertices[7] = new Vector3(-halfLength, halfLength, halfLength);int[] triangles = new int[36]{
    0,3,1,3,2,1,4,5,6,4,6,7,1,2,6,1,6,5,0,4,3,4,7,3,0,1,4,1,5,4,3,6,2,3,7,6};cubeVertices = new Vector3[36];for (int i = 0; i < cubeVertices.Length; i++){
    cubeVertices[i] = vertices[triangles[i]];}return cubeVertices;}}protected override int[] Triangles{
    get{
    /*int[] triangles = new int[36]{0,1,3,3,1,2,4,6,5,4,7,6,1,6,2,1,5,6,0,3,4,4,3,7,0,4,1,1,4,5,3,2,6,3,6,7};*/int[] triangles = new int[36];for (int i = 0; i < triangles.Length; i++){
    triangles[i] = i;}return triangles;}}protected override Vector3[] Normals{
    get{
    Vector3[] normals = new Vector3[36];for (int i = 0; i < normals.Length - 2; i+=3){
    Vector3 normal = Vector3.Cross(cubeVertices[i + 1] - cubeVertices[i], cubeVertices[i + 2] - cubeVertices[i]);for (int j = 0; j < 3; j++){
    normals[i + j] = normal;}}return normals;}}//override 
}

4.结语

即使完善版cube也未进行uv定义以及切线定义。切线一般均为Vector4类型,值为相应切向或者(-1,0,0,-1)。至于uv问题不考虑是因为比较负责,涉及每个面都相同还是不同的uv,对于cube贴图问题一般使用自带或者cube贴图shader来实现,所以在此不做展开,如果需要可以参考如下。

  相关解决方案