mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-08-12 00:09:02 +08:00
Accelerating split mesh.
This commit is contained in:
parent
53947ee6d3
commit
49233f4195
@ -41,7 +41,7 @@ public unsafe class DracoMeshLoader
|
|||||||
public Vector3[] vertices;
|
public Vector3[] vertices;
|
||||||
public Vector3[] normals;
|
public Vector3[] normals;
|
||||||
public Vector2[] uvs;
|
public Vector2[] uvs;
|
||||||
public Vector3[] colors;
|
public Color[] colors;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport ("dracodec_unity")] private static extern int DecodeMeshForUnity (
|
[DllImport ("dracodec_unity")] private static extern int DecodeMeshForUnity (
|
||||||
@ -53,81 +53,99 @@ public unsafe class DracoMeshLoader
|
|||||||
// to be splitted.
|
// to be splitted.
|
||||||
private void SplitMesh (DecodedMesh mesh, ref List<DecodedMesh> splittedMeshes)
|
private void SplitMesh (DecodedMesh mesh, ref List<DecodedMesh> splittedMeshes)
|
||||||
{
|
{
|
||||||
List<int> facesLeft = new List<int> ();
|
int[] IndexNew = new int[maxNumVerticesPerMesh];
|
||||||
for (int i = 0; i < mesh.faces.Length; ++i) {
|
int BaseIndex = 0;
|
||||||
facesLeft.Add (mesh.faces [i]);
|
int FaceCount = mesh.faces.Length;
|
||||||
}
|
int[] FaceIndex = new int[FaceCount];
|
||||||
int numSubMeshes = 0;
|
int[] NewFace = new int[FaceCount];
|
||||||
|
|
||||||
List<int> newCorners = new List<int> ();
|
|
||||||
Dictionary<int, int> indexToNewIndex = new Dictionary<int, int> ();
|
|
||||||
|
|
||||||
List<int> facesExtracted = new List<int> ();
|
for (int i = 0; i < FaceCount; i++)
|
||||||
List<Vector3> verticesExtracted = new List<Vector3> ();
|
{
|
||||||
List<Vector2> uvsExtracted = new List<Vector2> ();
|
FaceIndex[i] = -1;
|
||||||
List<Vector3> normalsExtracted = new List<Vector3> ();
|
}
|
||||||
List<Vector3> colorsExtracted = new List<Vector3> ();
|
|
||||||
|
|
||||||
while (facesLeft.Count > 0) {
|
while (BaseIndex < FaceCount)
|
||||||
numSubMeshes++;
|
{
|
||||||
List<int> tmpLeftFaces = new List<int> ();
|
int uniqueCornerId = 0;
|
||||||
facesExtracted.Clear ();
|
int UseIndex = 0;
|
||||||
verticesExtracted.Clear ();
|
int AddNew = 0;
|
||||||
uvsExtracted.Clear ();
|
int[] NewCorner = new int[3];
|
||||||
normalsExtracted.Clear ();
|
for (; BaseIndex + UseIndex < FaceCount;)
|
||||||
colorsExtracted.Clear ();
|
{
|
||||||
|
AddNew = 0;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (FaceIndex[mesh.faces[BaseIndex + UseIndex + i]] == -1)
|
||||||
|
{
|
||||||
|
NewCorner[AddNew] = mesh.faces[BaseIndex + UseIndex + i];
|
||||||
|
AddNew++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int uniqueCornerId = 0;
|
if (uniqueCornerId + AddNew > maxNumVerticesPerMesh)
|
||||||
indexToNewIndex.Clear ();
|
{
|
||||||
for (int face = 0; face < facesLeft.Count / 3; ++face) {
|
break;
|
||||||
newCorners.Clear ();
|
}
|
||||||
// If all indices has appeared or there's still space for more vertices.
|
|
||||||
for (int corner = 0; corner < 3; ++corner) {
|
|
||||||
if (!indexToNewIndex.ContainsKey (facesLeft [face * 3 + corner])) {
|
|
||||||
newCorners.Add (facesLeft [face * 3 + corner]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newCorners.Count + uniqueCornerId > maxNumVerticesPerMesh) {
|
|
||||||
// Save face for the next sub-mesh.
|
|
||||||
for (int corner = 0; corner < 3; ++corner) {
|
|
||||||
tmpLeftFaces.Add (facesLeft [face * 3 + corner]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Add new corners.
|
|
||||||
for (int i = 0; i < newCorners.Count; ++i) {
|
|
||||||
indexToNewIndex.Add (newCorners [i], uniqueCornerId);
|
|
||||||
verticesExtracted.Add (mesh.vertices [newCorners [i]]);
|
|
||||||
if (mesh.normals != null)
|
|
||||||
normalsExtracted.Add (mesh.normals [newCorners [i]]);
|
|
||||||
if (mesh.colors != null)
|
|
||||||
colorsExtracted.Add (mesh.colors [newCorners [i]]);
|
|
||||||
if (mesh.uvs != null)
|
|
||||||
uvsExtracted.Add (mesh.uvs [newCorners [i]]);
|
|
||||||
|
|
||||||
uniqueCornerId++;
|
for (int i = 0; i < AddNew; i++)
|
||||||
}
|
{
|
||||||
// Add face to this sub-mesh.
|
FaceIndex[NewCorner[i]] = uniqueCornerId;
|
||||||
for (int corner = 0; corner < 3; ++corner) {
|
IndexNew[uniqueCornerId] = NewCorner[i];
|
||||||
facesExtracted.Add (
|
uniqueCornerId++;
|
||||||
indexToNewIndex [facesLeft [face * 3 + corner]]);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DecodedMesh subMesh = new DecodedMesh ();
|
for (int i = 0; i < 3; i++)
|
||||||
subMesh.faces = facesExtracted.ToArray ();
|
{
|
||||||
subMesh.vertices = verticesExtracted.ToArray ();
|
NewFace[UseIndex] = FaceIndex[mesh.faces[BaseIndex + UseIndex]];
|
||||||
if (normalsExtracted.Count > 0) {
|
UseIndex++;
|
||||||
subMesh.normals = normalsExtracted.ToArray ();
|
}
|
||||||
}
|
}
|
||||||
if (uvsExtracted.Count > 0)
|
|
||||||
subMesh.uvs = uvsExtracted.ToArray ();
|
|
||||||
if (colorsExtracted.Count > 0)
|
|
||||||
subMesh.colors = colorsExtracted.ToArray ();
|
|
||||||
splittedMeshes.Add (subMesh);
|
|
||||||
|
|
||||||
facesLeft = tmpLeftFaces;
|
for (int i = 0; i < uniqueCornerId; i++)
|
||||||
}
|
{
|
||||||
|
FaceIndex[IndexNew[i]] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DecodedMesh subMesh = new DecodedMesh();
|
||||||
|
subMesh.faces = new int[UseIndex];
|
||||||
|
Array.Copy(NewFace, subMesh.faces, UseIndex);
|
||||||
|
subMesh.vertices = new Vector3[uniqueCornerId];
|
||||||
|
for (int i = 0; i < uniqueCornerId; i++)
|
||||||
|
{
|
||||||
|
subMesh.vertices[i] = mesh.vertices[IndexNew[i]];
|
||||||
|
}
|
||||||
|
if (mesh.normals != null)
|
||||||
|
{
|
||||||
|
subMesh.normals = new Vector3[uniqueCornerId];
|
||||||
|
for (int i = 0; i < uniqueCornerId; i++)
|
||||||
|
{
|
||||||
|
subMesh.normals[i] = mesh.normals[IndexNew[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh.colors != null)
|
||||||
|
{
|
||||||
|
subMesh.colors = new Color[uniqueCornerId];
|
||||||
|
for (int i = 0; i < uniqueCornerId; i++)
|
||||||
|
{
|
||||||
|
subMesh.colors[i] = mesh.colors[IndexNew[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh.uvs != null)
|
||||||
|
{
|
||||||
|
subMesh.uvs = new Vector2[uniqueCornerId];
|
||||||
|
for (int i = 0; i < uniqueCornerId; i++)
|
||||||
|
{
|
||||||
|
subMesh.uvs[i] = mesh.uvs[IndexNew[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
splittedMeshes.Add(subMesh);
|
||||||
|
|
||||||
|
BaseIndex += UseIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private float ReadFloatFromIntPtr (IntPtr data, int offset)
|
private float ReadFloatFromIntPtr (IntPtr data, int offset)
|
||||||
@ -176,11 +194,10 @@ public unsafe class DracoMeshLoader
|
|||||||
int numFaces = tmpMesh->numFaces;
|
int numFaces = tmpMesh->numFaces;
|
||||||
int[] newTriangles = new int[tmpMesh->numFaces * 3];
|
int[] newTriangles = new int[tmpMesh->numFaces * 3];
|
||||||
for (int i = 0; i < tmpMesh->numFaces; ++i) {
|
for (int i = 0; i < tmpMesh->numFaces; ++i) {
|
||||||
newTriangles [i * 3] = Marshal.ReadInt32 (tmpMesh->indices, i * 3 * 4);
|
byte* addr = (byte*)tmpMesh->indices + i * 3 * 4;
|
||||||
newTriangles [i * 3 + 1] =
|
newTriangles[i * 3] = *((int*)addr);
|
||||||
Marshal.ReadInt32 (tmpMesh->indices, i * 3 * 4 + 4);
|
newTriangles[i * 3 + 1] = *((int*)(addr + 4));
|
||||||
newTriangles [i * 3 + 2] =
|
newTriangles[i * 3 + 2] = *((int*)(addr + 8));
|
||||||
Marshal.ReadInt32 (tmpMesh->indices, i * 3 * 4 + 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For floating point numbers, there's no Marshal functions could directly
|
// For floating point numbers, there's no Marshal functions could directly
|
||||||
@ -193,9 +210,9 @@ public unsafe class DracoMeshLoader
|
|||||||
Vector3[] newNormals = new Vector3[0];
|
Vector3[] newNormals = new Vector3[0];
|
||||||
if (tmpMesh->hasNormal)
|
if (tmpMesh->hasNormal)
|
||||||
newNormals = new Vector3[tmpMesh->numVertices];
|
newNormals = new Vector3[tmpMesh->numVertices];
|
||||||
Vector3[] newColors = new Vector3[0];
|
Color[] newColors = new Color[0];
|
||||||
if (tmpMesh->hasColor)
|
if (tmpMesh->hasColor)
|
||||||
newColors = new Vector3[tmpMesh->numVertices];
|
newColors = new Color[tmpMesh->numVertices];
|
||||||
int byteStridePerValue = 4;
|
int byteStridePerValue = 4;
|
||||||
/*
|
/*
|
||||||
* TODO(zhafang): Change to:
|
* TODO(zhafang): Change to:
|
||||||
@ -207,35 +224,40 @@ public unsafe class DracoMeshLoader
|
|||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
byte* posaddr = (byte*)tmpMesh->position;
|
||||||
|
byte* normaladdr = (byte*)tmpMesh->normal;
|
||||||
|
byte* coloraddr = (byte*)tmpMesh->color;
|
||||||
|
byte* uvaddr = (byte*)tmpMesh->texcoord;
|
||||||
for (int i = 0; i < tmpMesh->numVertices; ++i) {
|
for (int i = 0; i < tmpMesh->numVertices; ++i) {
|
||||||
int numValuePerVertex = 3;
|
int numValuePerVertex = 3;
|
||||||
for (int j = 0; j < numValuePerVertex; ++j) {
|
|
||||||
int byteStridePerVertex = byteStridePerValue * numValuePerVertex;
|
for (int j = 0; j < numValuePerVertex; ++j)
|
||||||
newVertices [i] [j] =
|
{
|
||||||
ReadFloatFromIntPtr (
|
int byteStridePerVertex = byteStridePerValue * numValuePerVertex;
|
||||||
tmpMesh->position,
|
int OffSet = i * byteStridePerVertex + byteStridePerValue * j;
|
||||||
i * byteStridePerVertex + byteStridePerValue * j);
|
|
||||||
if (tmpMesh->hasNormal)
|
newVertices[i][j] = *((float*)(posaddr + OffSet));
|
||||||
newNormals [i] [j] =
|
if (tmpMesh->hasNormal)
|
||||||
ReadFloatFromIntPtr (
|
{
|
||||||
tmpMesh->normal,
|
newNormals[i][j] = *((float*)(normaladdr + OffSet));
|
||||||
i * byteStridePerVertex + byteStridePerValue * j);
|
}
|
||||||
if (tmpMesh->hasColor)
|
if (tmpMesh->hasColor)
|
||||||
newColors [i] [j] =
|
{
|
||||||
ReadFloatFromIntPtr (
|
newColors[i][j] = *((float*)(coloraddr + OffSet));
|
||||||
tmpMesh->color,
|
}
|
||||||
i * byteStridePerVertex + byteStridePerValue * j);
|
}
|
||||||
}
|
|
||||||
if (tmpMesh->hasTexcoord) {
|
|
||||||
numValuePerVertex = 2;
|
if (tmpMesh->hasTexcoord)
|
||||||
for (int j = 0; j < numValuePerVertex; ++j) {
|
{
|
||||||
int byteStridePerVertex = byteStridePerValue * numValuePerVertex;
|
numValuePerVertex = 2;
|
||||||
newUVs [i] [j] =
|
for (int j = 0; j < numValuePerVertex; ++j)
|
||||||
ReadFloatFromIntPtr (
|
{
|
||||||
tmpMesh->texcoord,
|
int byteStridePerVertex = byteStridePerValue * numValuePerVertex;
|
||||||
i * byteStridePerVertex + byteStridePerValue * j);
|
newUVs[i][j] = *((float*)(uvaddr + (i * byteStridePerVertex + byteStridePerValue * j)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Marshal.FreeCoTaskMem (tmpMesh->indices);
|
Marshal.FreeCoTaskMem (tmpMesh->indices);
|
||||||
@ -272,12 +294,8 @@ public unsafe class DracoMeshLoader
|
|||||||
mesh.uv = splittedMeshes [i].uvs;
|
mesh.uv = splittedMeshes [i].uvs;
|
||||||
|
|
||||||
if (splittedMeshes [i].colors != null) {
|
if (splittedMeshes [i].colors != null) {
|
||||||
mesh.colors = new Color[splittedMeshes [i].colors.Length];
|
mesh.colors = splittedMeshes[i].colors;
|
||||||
for (int j = 0; j < splittedMeshes [i].colors.Length; ++j) {
|
}
|
||||||
mesh.colors [j] = new Color (splittedMeshes [i].colors [j] [0],
|
|
||||||
splittedMeshes [i].colors [j] [1], splittedMeshes [i].colors [j] [2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splittedMeshes [i].normals != null) {
|
if (splittedMeshes [i].normals != null) {
|
||||||
mesh.normals = splittedMeshes [i].normals;
|
mesh.normals = splittedMeshes [i].normals;
|
||||||
@ -301,12 +319,8 @@ public unsafe class DracoMeshLoader
|
|||||||
Debug.Log ("Mesh doesn't have normals, recomputed.");
|
Debug.Log ("Mesh doesn't have normals, recomputed.");
|
||||||
}
|
}
|
||||||
if (newColors.Length != 0) {
|
if (newColors.Length != 0) {
|
||||||
mesh.colors = new Color[newColors.Length];
|
mesh.colors = newColors;
|
||||||
for (int i = 0; i < newColors.Length; ++i) {
|
}
|
||||||
mesh.colors [i] = new Color (newColors [i] [0],
|
|
||||||
newColors [i] [1], newColors [i] [2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh.RecalculateBounds ();
|
mesh.RecalculateBounds ();
|
||||||
meshes.Add (mesh);
|
meshes.Add (mesh);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user