Experimenting with texture-coordinate conversion
This commit is contained in:
@@ -4,13 +4,13 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Objects.Other;
|
||||
using Objects.Primitive;
|
||||
using Speckle.ConnectorUnity;
|
||||
using Speckle.Core.Models;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
using Mesh = Objects.Geometry.Mesh;
|
||||
using Object = UnityEngine.Object;
|
||||
using SColor = System.Drawing.Color;
|
||||
|
||||
namespace Objects.Converter.Unity
|
||||
{
|
||||
@@ -57,14 +57,14 @@ namespace Objects.Converter.Unity
|
||||
/// </summary>
|
||||
/// <param name="arr"></param>
|
||||
/// <returns></returns>
|
||||
public Vector3[] ArrayToPoints(IEnumerable<double> arr, string units)
|
||||
public Vector3[] ArrayToPoints(IList<double> arr, string units)
|
||||
{
|
||||
if (arr.Count() % 3 != 0) throw new Exception("Array malformed: length%3 != 0.");
|
||||
if (arr.Count % 3 != 0) throw new Exception("Array malformed: length%3 != 0.");
|
||||
|
||||
Vector3[] points = new Vector3[arr.Count() / 3];
|
||||
var asArray = arr.ToArray();
|
||||
for (int i = 2, k = 0; i < arr.Count(); i += 3)
|
||||
points[k++] = VectorByCoordinates(asArray[i - 2], asArray[i - 1], asArray[i], units);
|
||||
Vector3[] points = new Vector3[arr.Count / 3];
|
||||
|
||||
for (int i = 2, k = 0; i < arr.Count; i += 3)
|
||||
points[k++] = VectorByCoordinates(arr[i - 2], arr[i - 1], arr[i], units);
|
||||
|
||||
|
||||
return points;
|
||||
@@ -109,53 +109,62 @@ namespace Objects.Converter.Unity
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Speckle mesh to a GameObject with a mesh renderer
|
||||
/// Converts the <see cref="MeshFilter"/> component on <paramref name="go"/> into a Speckle <see cref="Mesh"/>
|
||||
/// </summary>
|
||||
/// <param name="speckleMesh"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="go">The Unity <see cref="GameObject"/> to convert</param>
|
||||
/// <returns>The converted <see cref="Mesh"/>, <see langword="null"/> if no <see cref="MeshFilter"/> on <paramref name="go"/> exists</returns>
|
||||
public Mesh MeshToSpeckle(GameObject go)
|
||||
{
|
||||
//TODO: support multiple filters?
|
||||
var filter = go.GetComponent<MeshFilter>();
|
||||
if (filter == null)
|
||||
if (filter == null) return null;
|
||||
|
||||
var nativeMesh = filter.mesh;
|
||||
|
||||
var nTriangles = nativeMesh.triangles;
|
||||
List<int> sFaces = new List<int>(nTriangles.Length * 4);
|
||||
for (int i = 2; i < nTriangles.Length; i += 3)
|
||||
{
|
||||
return null;
|
||||
sFaces.Add(0); //Triangle cardinality indicator
|
||||
|
||||
sFaces.Add(nTriangles[i]);
|
||||
sFaces.Add(nTriangles[i - 1]);
|
||||
sFaces.Add(nTriangles[i - 2]);
|
||||
}
|
||||
|
||||
//convert triangle array into speckleMesh faces
|
||||
List<int> faces = new List<int>();
|
||||
int i = 0;
|
||||
//store them here, makes it like 1000000x faster?
|
||||
var triangles = filter.mesh.triangles;
|
||||
while (i < triangles.Length)
|
||||
var nVertices = nativeMesh.vertices;
|
||||
List<double> sVertices = new List<double>(nVertices.Length * 3);
|
||||
foreach (var vertex in nVertices)
|
||||
{
|
||||
faces.Add(0);
|
||||
var p = go.transform.TransformPoint(vertex);
|
||||
sVertices.Add(p.x);
|
||||
sVertices.Add(p.y);
|
||||
sVertices.Add(p.z);
|
||||
}
|
||||
|
||||
var nColors = nativeMesh.colors;
|
||||
List<int> sColors = new List<int>(nColors.Length);
|
||||
sColors.AddRange(nColors.Select(c => c.ToIntColor()));
|
||||
|
||||
faces.Add(triangles[i + 0]);
|
||||
faces.Add(triangles[i + 2]);
|
||||
faces.Add(triangles[i + 1]);
|
||||
i += 3;
|
||||
var nTexCoords = nativeMesh.uv;
|
||||
List<double> sTexCoords = new List<double>(nTexCoords.Length * 2);
|
||||
foreach (var uv in nTexCoords)
|
||||
{
|
||||
sTexCoords.Add(uv.x);
|
||||
sTexCoords.Add(uv.y);
|
||||
}
|
||||
|
||||
var mesh = new Mesh();
|
||||
// get the speckle data from the go here
|
||||
// so that if the go comes from speckle, typed props will get overridden below
|
||||
AttachUnityProperties(mesh, go);
|
||||
|
||||
|
||||
mesh.vertices = sVertices;
|
||||
mesh.faces = sFaces;
|
||||
mesh.colors = sColors;
|
||||
mesh.textureCoordinates = sTexCoords;
|
||||
mesh.units = ModelUnits;
|
||||
|
||||
var vertices = filter.mesh.vertices;
|
||||
foreach (var vertex in vertices)
|
||||
{
|
||||
var p = go.transform.TransformPoint(vertex);
|
||||
var sp = PointToSpeckle(p);
|
||||
mesh.vertices.Add(sp.x);
|
||||
mesh.vertices.Add(sp.y);
|
||||
mesh.vertices.Add(sp.z);
|
||||
}
|
||||
|
||||
mesh.faces = faces;
|
||||
|
||||
return mesh;
|
||||
}
|
||||
#endregion
|
||||
@@ -181,7 +190,7 @@ namespace Objects.Converter.Unity
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Speckle point to a GameObject with a line renderer
|
||||
/// Converts a Speckle <paramref name="point"/> to a <see cref="GameObject"/> with a <see cref="LineRenderer"/>
|
||||
/// </summary>
|
||||
/// <param name="point"></param>
|
||||
/// <returns></returns>
|
||||
@@ -189,13 +198,13 @@ namespace Objects.Converter.Unity
|
||||
{
|
||||
Vector3 newPt = VectorByCoordinates(point.x, point.y, point.z, point.units);
|
||||
|
||||
var go = NewPointBasedGameObject(new Vector3[2] { newPt, newPt }, point.speckle_type);
|
||||
var go = NewPointBasedGameObject(new Vector3[] { newPt, newPt }, point.speckle_type);
|
||||
return go;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Speckle line to a GameObject with a line renderer
|
||||
/// Converts a Speckle <paramref name="line"/> to a <see cref="GameObject"/> with a <see cref="LineRenderer"/>
|
||||
/// </summary>
|
||||
/// <param name="line"></param>
|
||||
/// <returns></returns>
|
||||
@@ -208,31 +217,31 @@ namespace Objects.Converter.Unity
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Speckle polyline to a GameObject with a line renderer
|
||||
/// Converts a Speckle <paramref name="polyline"/> to a <see cref="GameObject"/> with a <see cref="LineRenderer"/>
|
||||
/// </summary>
|
||||
/// <param name="polyline"></param>
|
||||
/// <returns></returns>
|
||||
public GameObject PolylineToNative(Polyline polyline)
|
||||
{
|
||||
var points = polyline.points.Select(x => VectorFromPoint(x));
|
||||
var points = polyline.GetPoints().Select(VectorFromPoint);
|
||||
|
||||
var go = NewPointBasedGameObject(points.ToArray(), polyline.speckle_type);
|
||||
return go;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Speckle curve to a GameObject with a line renderer
|
||||
/// Converts a Speckle <paramref name="curve"/> to a <see cref="GameObject"/> with a <see cref="LineRenderer"/>
|
||||
/// </summary>
|
||||
/// <param name="curve"></param>
|
||||
/// <returns></returns>
|
||||
public GameObject CurveToNative(Curve curve)
|
||||
{
|
||||
var points = ArrayToPoints(curve.points, curve.units);
|
||||
var go = NewPointBasedGameObject(points.ToArray(), curve.speckle_type);
|
||||
var go = NewPointBasedGameObject(points, curve.speckle_type);
|
||||
return go;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public GameObject MeshToNative(Base speckleMeshObject)
|
||||
{
|
||||
if (!(speckleMeshObject["displayMesh"] is Mesh))
|
||||
@@ -242,11 +251,11 @@ namespace Objects.Converter.Unity
|
||||
speckleMeshObject["renderMaterial"] as RenderMaterial, speckleMeshObject.GetMembers());
|
||||
}
|
||||
/// <summary>
|
||||
/// Converts a Speckle mesh to a GameObject with a mesh renderer
|
||||
/// Converts <paramref name="speckleMesh"/> to a <see cref="GameObject"/> with a <see cref="MeshRenderer"/>
|
||||
/// </summary>
|
||||
/// <param name="speckleMesh">Mesh to convert</param>
|
||||
/// <param name="renderMaterial">If provided will override the renderMaterial on the mesh itself</param>
|
||||
/// <param name="properties">If provided will override the properties on the mesh itself</param>
|
||||
/// <param name="renderMaterial">If provided, will override the renderMaterial on the mesh itself</param>
|
||||
/// <param name="properties">If provided, will override the properties on the mesh itself</param>
|
||||
/// <returns></returns>
|
||||
public GameObject MeshToNative(
|
||||
Mesh speckleMesh, RenderMaterial renderMaterial = null,
|
||||
@@ -257,10 +266,10 @@ namespace Objects.Converter.Unity
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
var recenterMeshTransforms = true; //TODO: figure out how best to change this?
|
||||
|
||||
|
||||
speckleMesh.AlignVerticesWithTexCoordsByIndex();
|
||||
var verts = ArrayToPoints(speckleMesh.vertices, speckleMesh.units);
|
||||
|
||||
|
||||
@@ -270,15 +279,17 @@ namespace Objects.Converter.Unity
|
||||
// TODO: Check if this is causing issues with normals for mesh
|
||||
while (i < speckleMesh.faces.Count)
|
||||
{
|
||||
if (speckleMesh.faces[i] == 0)
|
||||
int n = speckleMesh.faces[i];
|
||||
if (n < 3) n += 3; // 0 -> 3, 1 - > 4
|
||||
|
||||
if (n == 3)
|
||||
{
|
||||
//Triangles
|
||||
tris.Add(speckleMesh.faces[i + 1]);
|
||||
tris.Add(speckleMesh.faces[i + 3]);
|
||||
tris.Add(speckleMesh.faces[i + 2]);
|
||||
i += 4;
|
||||
}
|
||||
else
|
||||
else if (n == 4)
|
||||
{
|
||||
//Quads to triangles
|
||||
tris.Add(speckleMesh.faces[i + 1]);
|
||||
@@ -288,12 +299,16 @@ namespace Objects.Converter.Unity
|
||||
tris.Add(speckleMesh.faces[i + 1]);
|
||||
tris.Add(speckleMesh.faces[i + 4]);
|
||||
tris.Add(speckleMesh.faces[i + 3]);
|
||||
|
||||
i += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO n-gon triangulation, for now n-gon faces will be ignored
|
||||
|
||||
}
|
||||
|
||||
i += n + 1;
|
||||
}
|
||||
|
||||
|
||||
var go = new GameObject { name = speckleMesh.speckle_type };
|
||||
var mesh = new UnityEngine.Mesh { name = speckleMesh.speckle_type };
|
||||
|
||||
@@ -322,18 +337,37 @@ namespace Objects.Converter.Unity
|
||||
verts[l] -= meshBounds.center;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
mesh.SetVertices(verts);
|
||||
mesh.SetTriangles(tris, 0);
|
||||
|
||||
if (speckleMesh.bbox != null)
|
||||
//Set texture coordinates
|
||||
bool hasValidUVs = speckleMesh.TextureCoordinatesCount == speckleMesh.VerticesCount;
|
||||
if(speckleMesh.textureCoordinates.Count > 0 && !hasValidUVs) Debug.LogWarning($"Expected number of UV coordinates to equal vertices. Got {speckleMesh.TextureCoordinatesCount} expected {speckleMesh.VerticesCount}. \nID = {speckleMesh.id}", mesh);
|
||||
|
||||
if (hasValidUVs)
|
||||
{
|
||||
var uv = new List<Vector2>(speckleMesh.TextureCoordinatesCount);
|
||||
for (int j = 0; j < speckleMesh.TextureCoordinatesCount; j++)
|
||||
{
|
||||
var (u, v) = speckleMesh.GetTextureCoordinate(j);
|
||||
uv.Add(new Vector2((float)u,(float)v));
|
||||
}
|
||||
mesh.SetUVs(0, uv);
|
||||
}
|
||||
else if (speckleMesh.bbox != null)
|
||||
{
|
||||
//Attempt to generate some crude UV coordinates using bbox
|
||||
var uv = GenerateUV(verts, (float)speckleMesh.bbox.xSize.Length, (float)speckleMesh.bbox.ySize.Length).ToList();
|
||||
mesh.SetUVs(0, uv);
|
||||
}
|
||||
|
||||
//Set vertex colors
|
||||
if (speckleMesh.colors.Count == speckleMesh.VerticesCount)
|
||||
{
|
||||
static Color ToUnityColor(SColor color) => new Color(color.R, color.G, color.B, color.A);
|
||||
var colors = speckleMesh.colors.Select(c => ToUnityColor(SColor.FromArgb(c))).ToList();
|
||||
mesh.SetColors(colors);
|
||||
}
|
||||
|
||||
// BUG: causing some funky issues with meshes
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user