Guest User

Untitled

a guest
Apr 14th, 2023
3
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.90 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using System;
  3. using System.IO;
  4. using UnityEngine;
  5. using CrystalFrost.Assets.Mesh;
  6.  
  7.  
  8. public class AvatarLadLoad : MonoBehaviour
  9. {
  10.  
  11.     public string fileName;
  12.     public bool isLOD;
  13.     public SkeletonLoad skeleton;
  14.  
  15.     void Start()
  16.     {
  17.         string _fileName = @$"{Application.dataPath}/character/{fileName}.llm";
  18.         Mesh mesh = new Mesh();
  19.         FileStream stream = new FileStream(_fileName, FileMode.Open);
  20.         BinaryReader reader = new BinaryReader(stream);
  21.         SkinnedMeshRenderer renderer = gameObject.GetComponent<SkinnedMeshRenderer>();
  22.         // Read header information
  23.         string header = new string(reader.ReadChars(24));
  24.         bool hasWeights = (reader.ReadByte() != 0); Debug.Log($"hasWeights = {hasWeights}");
  25.         bool hasDetailTexCoords = (reader.ReadByte() != 0); Debug.Log($"hasDetailTexCoords = {hasDetailTexCoords}");
  26.         Vector3 position = LindenMeshLoader.ReadVector3(reader);
  27.         Vector3 rotationAngles = LindenMeshLoader.ReadVector3(reader);
  28.         byte rotationOrder = reader.ReadByte();
  29.         Vector3 scale = LindenMeshLoader.ReadVector3(reader);
  30.         ushort numVertices = reader.ReadUInt16();
  31.  
  32.         // Read vertex data
  33.         Vector3[] vertices = new Vector3[numVertices];
  34.         Vertices = new Vertex[numVertices];
  35.         Vector3[] normals = new Vector3[numVertices];
  36.         Vector2[] uvs = new Vector2[numVertices];
  37.         Vector3[] tangents = new Vector3[numVertices];
  38.         Vector2[] detailUVs = new Vector2[numVertices];
  39.         byte[] bonesPerVertex = new byte[numVertices];
  40.        
  41.  
  42.         float[] weights = new float[numVertices];
  43.         int[] faces;
  44.         string[] skinJoints;
  45.  
  46.         for (int i = 0; i < numVertices; i++)
  47.         {
  48.             vertices[i] = LindenMeshLoader.ReadVector3(reader);
  49.             bonesPerVertex[i] = 1;
  50.         }
  51.  
  52.         for (int i = 0; i < numVertices; i++)
  53.         {
  54.             normals[i] = LindenMeshLoader.ReadVector3(reader);
  55.         }
  56.         for (int i = 0; i < numVertices; i++)
  57.         {
  58.             tangents[i] = LindenMeshLoader.ReadVector3(reader);
  59.         }
  60.         for (int i = 0; i < numVertices; i++)
  61.         {
  62.             uvs[i] = new Vector2(reader.ReadSingle(), reader.ReadSingle());
  63.         }
  64.  
  65.         if (hasDetailTexCoords)
  66.         {
  67.             for (int i = 0; i < numVertices; i++)
  68.             {
  69.                 detailUVs[i] = LindenMeshLoader.ReadVector2(reader);
  70.             }
  71.         }
  72.  
  73.         BoneWeight1[] boneWeights = new BoneWeight1[numVertices];
  74.         if (hasWeights)
  75.         {
  76.             for (int i = 0; i < numVertices; i++)
  77.             {
  78.                 boneWeights[i].weight = reader.ReadSingle();
  79.             }
  80.         }
  81.  
  82.         ushort numFaces = reader.ReadUInt16();
  83.         //Debug.Log($"{fileName} {numVertices} vertices, {numFaces} faces");
  84.         faces = new int[numFaces * 3];
  85.         List<int> _faces = new List<int>();
  86.         int v1, v2, v3;
  87.  
  88.         int counter = 0;
  89.         for(int i = 0; i < numFaces; i++)
  90.         {
  91.             v1 = reader.ReadUInt16();
  92.             v2 = reader.ReadUInt16();
  93.             v3 = reader.ReadUInt16();
  94.             if (v1 == v2 || v1 == v2 || v2 == v3) continue;
  95.             _faces.Add(v1);
  96.             _faces.Add(v2);
  97.             _faces.Add(v3);
  98.             counter++;
  99.         }
  100.  
  101.  
  102.         faces = _faces.ToArray();
  103.  
  104.         List<Line> bonelines = new List<Line>();
  105.  
  106.         Debug.Log($"{fileName} {counter} faces");
  107.         if (hasWeights)
  108.         {
  109.             UInt16 numSkinJoints = reader.ReadUInt16();
  110.             Debug.Log($"{fileName} {numVertices} vertices, {numSkinJoints} skinJoints");
  111.             skinJoints = new string[numSkinJoints];
  112.             char[] chars;// = new char[64];
  113.             string skinJoint = string.Empty;
  114.             int count = 0;
  115.             Matrix4x4[] bindPoses = new Matrix4x4[numSkinJoints];
  116.  
  117.             for (int i = 0; i < numSkinJoints; i++)
  118.             {
  119.                 chars = reader.ReadChars(64);
  120.                 skinJoint = chars[0].ToString();
  121.                 count = 1;
  122.                 while (chars[count]!='\0')
  123.                 {
  124.                     skinJoint += chars[count].ToString();
  125.                     count++;
  126.                 }
  127.                 skinJoints[i] = skinJoint;
  128.                 Debug.Log($"\"{skinJoints[i]}\"");
  129.  
  130.                 bonelines.Add(new Line(skinJoint, skeleton.llmBones[skinJoint].position, skeleton.llmBones[skinJoint].position + skeleton.llmBones[skinJoint].end));
  131.  
  132.                 bindPoses[i] = skeleton.llmBones[skinJoint].transform.worldToLocalMatrix * transform.worldToLocalMatrix;
  133.                 //These probably don't match up since there's more weights than skinJoints;
  134.                 //skeleton.Bones is a dictionary that converts names to bone indices
  135.                 //however the skeleton isn't completely ready for use either.
  136.                 //as as far as I know, I still need to actually go and add the transforms
  137.                 //for the bones to an array to for the mesh to know which indice is which bone
  138.                 //boneWeights[i].boneIndex = skeleton.boneIndices[skinJoints[i]];
  139.             }
  140.            
  141.             mesh.bindposes = bindPoses;
  142.  
  143.             for (int i = 0; i < numVertices; i++)
  144.             {
  145.                 if (bonelines == null) Debug.Log("bonelines null");
  146.                 string boneName = FindNearestLineName(bonelines, vertices[i]);
  147.                 if (boneName == null) Debug.Log("boneName null");
  148.                 boneWeights[i].boneIndex = skeleton.boneIndices[boneName];
  149.                 Vertices[i] = new Vertex(boneName, vertices[i]);
  150.             }
  151.  
  152.         }
  153.  
  154.         Unity.Collections.NativeArray<BoneWeight1> _boneWeights = new Unity.Collections.NativeArray<BoneWeight1>(boneWeights, Unity.Collections.Allocator.Temp);
  155.         Unity.Collections.NativeArray<byte> _bonesPerVertex = new Unity.Collections.NativeArray<byte>(bonesPerVertex, Unity.Collections.Allocator.Temp);
  156.  
  157.         // Create mesh
  158.         mesh.vertices = vertices;
  159.         mesh.normals = normals;
  160.         mesh.uv = uvs;
  161.         mesh.SetTriangles(faces,0);
  162.         mesh.ReverseWind();
  163.         mesh.RecalculateBounds();
  164.         mesh.SetBoneWeights(_bonesPerVertex, _boneWeights); //no idea how to do this
  165.  
  166.         renderer.bones = skeleton.boneTransforms;
  167.  
  168.         //bw.
  169.         // Set LOD group settings if applicable
  170.         if (isLOD)
  171.         {
  172.             MeshFilter meshFilter = GetComponent<MeshFilter>();
  173.             meshFilter.mesh = mesh;
  174.             //SkinnedMeshRenderer meshRenderer = GetComponent<SkinnedMeshRenderer>();
  175.             renderer.enabled = false;
  176.         }
  177.         else
  178.         {
  179.             //SkinnedMeshRenderer renderer = GetComponent<SkinnedMeshRenderer>();
  180.             renderer.sharedMesh = mesh;
  181.             renderer.ResetBounds();
  182.  
  183.             GetComponent<MeshFilter>().mesh = mesh;
  184.         }
  185.  
  186.         reader.Close();
  187.         stream.Close();
  188.     }
  189.  
  190.     public class Line
  191.     {
  192.         public string lineName;
  193.         public Vector3 lineStart;
  194.         public Vector3 lineEnd;
  195.  
  196.         public Line(string lineName,  Vector3 lineStart, Vector3 lineEnd)
  197.         {
  198.             this.lineName = lineName;
  199.             this.lineStart = lineStart;
  200.             this.lineEnd = lineEnd;
  201.         }
  202.     }
  203.  
  204.     class Vertex
  205.     {
  206.         public Color color;
  207.         public Vector3 position;
  208.  
  209.         public Vertex(string name, Vector3 position)
  210.         {
  211.             color = SkeletonLoad.GetColorFromStringHash(name);
  212.             this.position = position;
  213.         }
  214.     }
  215.  
  216.     Vertex[] Vertices;
  217.  
  218.     bool visualizeOriginalVertexPositions = true;
  219.     private void Update()
  220.     {
  221.         float dotSize = 0.001f;
  222.         //Vector3[] vertices = gameObject.GetComponent<SkinnedMeshRenderer>().sharedMesh.vertices;
  223.         Vector3 vertex;
  224.         //Vector3 skinnedVertexPosition;// = skinnedMeshRenderer.localToWorldMatrix.MultiplyPoint(skinnedMesh.vertices[vertexIndex])
  225.         if (Input.GetKeyDown(KeyCode.Space))
  226.         {
  227.             visualizeOriginalVertexPositions = !visualizeOriginalVertexPositions;
  228.         }
  229.         else
  230.         {
  231.  
  232.             if (visualizeOriginalVertexPositions)
  233.             {
  234.                 //Debug.Log("original");
  235.                 for (int i = 0; i < Vertices.Length; i++)
  236.                 {
  237.                     vertex = transform.TransformPoint(Vertices[i].position);
  238.                     Debug.DrawLine(vertex - Vector3.up * dotSize, vertex + Vector3.up * dotSize, Vertices[i].color);
  239.                     Debug.DrawLine(vertex - Vector3.left * dotSize, vertex + Vector3.left * dotSize, Vertices[i].color);
  240.                     Debug.DrawLine(vertex - Vector3.forward * dotSize, vertex + Vector3.forward * dotSize, Vertices[i].color);
  241.                 }
  242.             }
  243.             else
  244.             {
  245.                 //Debug.Log("not original");
  246.                 SkinnedMeshRenderer skinnedMeshRenderer = gameObject.GetComponent<SkinnedMeshRenderer>();
  247.                 Mesh bakedMesh = new Mesh();
  248.                 skinnedMeshRenderer.BakeMesh(bakedMesh);
  249.  
  250.                 for (int i = 0; i < Vertices.Length; i++)
  251.                 {
  252.                     vertex = skinnedMeshRenderer.transform.TransformPoint(bakedMesh.vertices[i]);
  253.                     Debug.DrawLine(vertex - Vector3.up * dotSize, vertex + Vector3.up * dotSize, Vertices[i].color);
  254.                     Debug.DrawLine(vertex - Vector3.left * dotSize, vertex + Vector3.left * dotSize, Vertices[i].color);
  255.                     Debug.DrawLine(vertex - Vector3.forward * dotSize, vertex + Vector3.forward * dotSize, Vertices[i].color);
  256.                 }
  257.             }
  258.         }
  259.     }
  260.  
  261.     List<Line> lines = new List<Line>();
  262.  
  263.     public string FindNearestLineName(List<Line> lines, Vector3 point)
  264.     {
  265.         float shortestDistance = float.MaxValue;
  266.         string nearestLineName = "";
  267.  
  268.         foreach (Line line in lines)
  269.         {
  270.             Vector3 closestPoint = GetClosestPointOnFiniteLine(line.lineStart, line.lineEnd, point);
  271.             float distance = Vector3.Distance(closestPoint, point);
  272.  
  273.             if (distance < shortestDistance)
  274.             {
  275.                 shortestDistance = distance;
  276.                 nearestLineName = line.lineName;
  277.             }
  278.         }
  279.  
  280.         return nearestLineName;
  281.     }
  282.  
  283.     Vector3 GetClosestPointOnFiniteLine(Vector3 lineStart, Vector3 lineEnd, Vector3 point)
  284.     {
  285.         Vector3 line_direction = lineEnd - lineStart;
  286.         float line_length = line_direction.magnitude;
  287.         line_direction.Normalize();
  288.         float project_length = Mathf.Clamp(Vector3.Dot(point - lineStart, line_direction), 0f, line_length);
  289.         return lineStart + line_direction * project_length;
  290.     }
  291. }
  292.  
Advertisement
Add Comment
Please, Sign In to add comment