Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using System;
- using System.IO;
- using UnityEngine;
- using CrystalFrost.Assets.Mesh;
- public class AvatarLadLoad : MonoBehaviour
- {
- public string fileName;
- public bool isLOD;
- public SkeletonLoad skeleton;
- void Start()
- {
- string _fileName = @$"{Application.dataPath}/character/{fileName}.llm";
- Mesh mesh = new Mesh();
- FileStream stream = new FileStream(_fileName, FileMode.Open);
- BinaryReader reader = new BinaryReader(stream);
- SkinnedMeshRenderer renderer = gameObject.GetComponent<SkinnedMeshRenderer>();
- // Read header information
- string header = new string(reader.ReadChars(24));
- bool hasWeights = (reader.ReadByte() != 0); Debug.Log($"hasWeights = {hasWeights}");
- bool hasDetailTexCoords = (reader.ReadByte() != 0); Debug.Log($"hasDetailTexCoords = {hasDetailTexCoords}");
- Vector3 position = LindenMeshLoader.ReadVector3(reader);
- Vector3 rotationAngles = LindenMeshLoader.ReadVector3(reader);
- byte rotationOrder = reader.ReadByte();
- Vector3 scale = LindenMeshLoader.ReadVector3(reader);
- ushort numVertices = reader.ReadUInt16();
- // Read vertex data
- Vector3[] vertices = new Vector3[numVertices];
- Vertices = new Vertex[numVertices];
- Vector3[] normals = new Vector3[numVertices];
- Vector2[] uvs = new Vector2[numVertices];
- Vector3[] tangents = new Vector3[numVertices];
- Vector2[] detailUVs = new Vector2[numVertices];
- byte[] bonesPerVertex = new byte[numVertices];
- float[] weights = new float[numVertices];
- int[] faces;
- string[] skinJoints;
- for (int i = 0; i < numVertices; i++)
- {
- vertices[i] = LindenMeshLoader.ReadVector3(reader);
- bonesPerVertex[i] = 1;
- }
- for (int i = 0; i < numVertices; i++)
- {
- normals[i] = LindenMeshLoader.ReadVector3(reader);
- }
- for (int i = 0; i < numVertices; i++)
- {
- tangents[i] = LindenMeshLoader.ReadVector3(reader);
- }
- for (int i = 0; i < numVertices; i++)
- {
- uvs[i] = new Vector2(reader.ReadSingle(), reader.ReadSingle());
- }
- if (hasDetailTexCoords)
- {
- for (int i = 0; i < numVertices; i++)
- {
- detailUVs[i] = LindenMeshLoader.ReadVector2(reader);
- }
- }
- BoneWeight1[] boneWeights = new BoneWeight1[numVertices];
- if (hasWeights)
- {
- for (int i = 0; i < numVertices; i++)
- {
- boneWeights[i].weight = reader.ReadSingle();
- }
- }
- ushort numFaces = reader.ReadUInt16();
- //Debug.Log($"{fileName} {numVertices} vertices, {numFaces} faces");
- faces = new int[numFaces * 3];
- List<int> _faces = new List<int>();
- int v1, v2, v3;
- int counter = 0;
- for(int i = 0; i < numFaces; i++)
- {
- v1 = reader.ReadUInt16();
- v2 = reader.ReadUInt16();
- v3 = reader.ReadUInt16();
- if (v1 == v2 || v1 == v2 || v2 == v3) continue;
- _faces.Add(v1);
- _faces.Add(v2);
- _faces.Add(v3);
- counter++;
- }
- faces = _faces.ToArray();
- List<Line> bonelines = new List<Line>();
- Debug.Log($"{fileName} {counter} faces");
- if (hasWeights)
- {
- UInt16 numSkinJoints = reader.ReadUInt16();
- Debug.Log($"{fileName} {numVertices} vertices, {numSkinJoints} skinJoints");
- skinJoints = new string[numSkinJoints];
- char[] chars;// = new char[64];
- string skinJoint = string.Empty;
- int count = 0;
- Matrix4x4[] bindPoses = new Matrix4x4[numSkinJoints];
- for (int i = 0; i < numSkinJoints; i++)
- {
- chars = reader.ReadChars(64);
- skinJoint = chars[0].ToString();
- count = 1;
- while (chars[count]!='\0')
- {
- skinJoint += chars[count].ToString();
- count++;
- }
- skinJoints[i] = skinJoint;
- Debug.Log($"\"{skinJoints[i]}\"");
- bonelines.Add(new Line(skinJoint, skeleton.llmBones[skinJoint].position, skeleton.llmBones[skinJoint].position + skeleton.llmBones[skinJoint].end));
- bindPoses[i] = skeleton.llmBones[skinJoint].transform.worldToLocalMatrix * transform.worldToLocalMatrix;
- //These probably don't match up since there's more weights than skinJoints;
- //skeleton.Bones is a dictionary that converts names to bone indices
- //however the skeleton isn't completely ready for use either.
- //as as far as I know, I still need to actually go and add the transforms
- //for the bones to an array to for the mesh to know which indice is which bone
- //boneWeights[i].boneIndex = skeleton.boneIndices[skinJoints[i]];
- }
- mesh.bindposes = bindPoses;
- for (int i = 0; i < numVertices; i++)
- {
- if (bonelines == null) Debug.Log("bonelines null");
- string boneName = FindNearestLineName(bonelines, vertices[i]);
- if (boneName == null) Debug.Log("boneName null");
- boneWeights[i].boneIndex = skeleton.boneIndices[boneName];
- Vertices[i] = new Vertex(boneName, vertices[i]);
- }
- }
- Unity.Collections.NativeArray<BoneWeight1> _boneWeights = new Unity.Collections.NativeArray<BoneWeight1>(boneWeights, Unity.Collections.Allocator.Temp);
- Unity.Collections.NativeArray<byte> _bonesPerVertex = new Unity.Collections.NativeArray<byte>(bonesPerVertex, Unity.Collections.Allocator.Temp);
- // Create mesh
- mesh.vertices = vertices;
- mesh.normals = normals;
- mesh.uv = uvs;
- mesh.SetTriangles(faces,0);
- mesh.ReverseWind();
- mesh.RecalculateBounds();
- mesh.SetBoneWeights(_bonesPerVertex, _boneWeights); //no idea how to do this
- renderer.bones = skeleton.boneTransforms;
- //bw.
- // Set LOD group settings if applicable
- if (isLOD)
- {
- MeshFilter meshFilter = GetComponent<MeshFilter>();
- meshFilter.mesh = mesh;
- //SkinnedMeshRenderer meshRenderer = GetComponent<SkinnedMeshRenderer>();
- renderer.enabled = false;
- }
- else
- {
- //SkinnedMeshRenderer renderer = GetComponent<SkinnedMeshRenderer>();
- renderer.sharedMesh = mesh;
- renderer.ResetBounds();
- GetComponent<MeshFilter>().mesh = mesh;
- }
- reader.Close();
- stream.Close();
- }
- public class Line
- {
- public string lineName;
- public Vector3 lineStart;
- public Vector3 lineEnd;
- public Line(string lineName, Vector3 lineStart, Vector3 lineEnd)
- {
- this.lineName = lineName;
- this.lineStart = lineStart;
- this.lineEnd = lineEnd;
- }
- }
- class Vertex
- {
- public Color color;
- public Vector3 position;
- public Vertex(string name, Vector3 position)
- {
- color = SkeletonLoad.GetColorFromStringHash(name);
- this.position = position;
- }
- }
- Vertex[] Vertices;
- bool visualizeOriginalVertexPositions = true;
- private void Update()
- {
- float dotSize = 0.001f;
- //Vector3[] vertices = gameObject.GetComponent<SkinnedMeshRenderer>().sharedMesh.vertices;
- Vector3 vertex;
- //Vector3 skinnedVertexPosition;// = skinnedMeshRenderer.localToWorldMatrix.MultiplyPoint(skinnedMesh.vertices[vertexIndex])
- if (Input.GetKeyDown(KeyCode.Space))
- {
- visualizeOriginalVertexPositions = !visualizeOriginalVertexPositions;
- }
- else
- {
- if (visualizeOriginalVertexPositions)
- {
- //Debug.Log("original");
- for (int i = 0; i < Vertices.Length; i++)
- {
- vertex = transform.TransformPoint(Vertices[i].position);
- Debug.DrawLine(vertex - Vector3.up * dotSize, vertex + Vector3.up * dotSize, Vertices[i].color);
- Debug.DrawLine(vertex - Vector3.left * dotSize, vertex + Vector3.left * dotSize, Vertices[i].color);
- Debug.DrawLine(vertex - Vector3.forward * dotSize, vertex + Vector3.forward * dotSize, Vertices[i].color);
- }
- }
- else
- {
- //Debug.Log("not original");
- SkinnedMeshRenderer skinnedMeshRenderer = gameObject.GetComponent<SkinnedMeshRenderer>();
- Mesh bakedMesh = new Mesh();
- skinnedMeshRenderer.BakeMesh(bakedMesh);
- for (int i = 0; i < Vertices.Length; i++)
- {
- vertex = skinnedMeshRenderer.transform.TransformPoint(bakedMesh.vertices[i]);
- Debug.DrawLine(vertex - Vector3.up * dotSize, vertex + Vector3.up * dotSize, Vertices[i].color);
- Debug.DrawLine(vertex - Vector3.left * dotSize, vertex + Vector3.left * dotSize, Vertices[i].color);
- Debug.DrawLine(vertex - Vector3.forward * dotSize, vertex + Vector3.forward * dotSize, Vertices[i].color);
- }
- }
- }
- }
- List<Line> lines = new List<Line>();
- public string FindNearestLineName(List<Line> lines, Vector3 point)
- {
- float shortestDistance = float.MaxValue;
- string nearestLineName = "";
- foreach (Line line in lines)
- {
- Vector3 closestPoint = GetClosestPointOnFiniteLine(line.lineStart, line.lineEnd, point);
- float distance = Vector3.Distance(closestPoint, point);
- if (distance < shortestDistance)
- {
- shortestDistance = distance;
- nearestLineName = line.lineName;
- }
- }
- return nearestLineName;
- }
- Vector3 GetClosestPointOnFiniteLine(Vector3 lineStart, Vector3 lineEnd, Vector3 point)
- {
- Vector3 line_direction = lineEnd - lineStart;
- float line_length = line_direction.magnitude;
- line_direction.Normalize();
- float project_length = Mathf.Clamp(Vector3.Dot(point - lineStart, line_direction), 0f, line_length);
- return lineStart + line_direction * project_length;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment