/// <summary> /// Manage mesh memory /// Converts the marshaled unmanaged mesh memory to managed /// </summary> public static ManagedMeshData ManageMeshMemory(MeshData meshData) { ManagedMeshData managedMeshData = new ManagedMeshData(); managedMeshData.positions = MarshallPositions((int)meshData.positionsNum, meshData.positions); managedMeshData.normals = ((int)meshData.normalsNum > 0) ? MarshallNormals((int)meshData.normalsNum, meshData.normals) : null; managedMeshData.materials = new StringCollection(); managedMeshData.indices = new List <int[]>(); var facesetdataSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(FacesetData)); var currentReadPtr = meshData.facesets; for (var i = 0; i < (int)meshData.facesetsNum; ++i) { FacesetData fs = (FacesetData)System.Runtime.InteropServices.Marshal.PtrToStructure(currentReadPtr, typeof(FacesetData)); managedMeshData.materials.Add(fs.materialName); managedMeshData.indices.Add(MarshallTriangleIndices((int)fs.indicesNum, fs.indices)); currentReadPtr = MarshalData.AddToIntPtr(currentReadPtr, facesetdataSize); } managedMeshData.facesetNum = (int)meshData.facesetsNum; managedMeshData.uvs = new List <List <Vector2> >(); currentReadPtr = meshData.uvSets; var uvSetDataSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(UVData)); for (var i = 0; i < (int)meshData.uvSetNum; ++i) { UVData uvData = (UVData)System.Runtime.InteropServices.Marshal.PtrToStructure(currentReadPtr, typeof(UVData)); // Note: Not currently using triangle indices //managedMeshData.indices.Add(MarshallTriangleIndices((int)uvData.indicesNum, uvData.indices)); managedMeshData.uvs.Add(MarshallUVData((int)uvData.uvsNum, uvData.uvs)); currentReadPtr = MarshalData.AddToIntPtr(currentReadPtr, uvSetDataSize); } managedMeshData.uvNum = (int)meshData.uvSetNum; return(managedMeshData); }
public static void CreateAndSendMeshRequest(Mesh mesh, List <string> materialTokens, string token) { MeshData meshData = new MeshData(); meshData.entityToken = token; meshData.entityParentToken = ""; meshData.displayName = mesh.name; // Add positions, first convert from Unity to STP Vector3[] vertices = new Vector3[mesh.vertices.Length]; System.Array.Copy(mesh.vertices, vertices, mesh.vertices.Length); int vertCount = vertices.Length; for (int i = vertCount - 1; i >= 0; i--) { float tempY = vertices[i].y; vertices[i].y = -vertices[i].z; vertices[i].z = tempY; vertices[i].Scale(MarshalData.scaleFromUnitytoSTP); } System.Runtime.InteropServices.GCHandle pinnedVerticesArray = System.Runtime.InteropServices.GCHandle.Alloc(vertices, System.Runtime.InteropServices.GCHandleType.Pinned); meshData.positions = pinnedVerticesArray.AddrOfPinnedObject(); meshData.positionsNum = (System.UIntPtr)(vertices.Length * verticesDataStride); // Add normals Vector3[] normals = new Vector3[mesh.normals.Length]; System.Array.Copy(mesh.normals, normals, mesh.normals.Length); int normalCount = mesh.normals.Length; for (int i = normalCount - 1; i >= 0; i--) { float tempY = normals[i].y; normals[i].y = -normals[i].z; normals[i].z = tempY; } System.Runtime.InteropServices.GCHandle pinnedNormalsArray = System.Runtime.InteropServices.GCHandle.Alloc(normals, System.Runtime.InteropServices.GCHandleType.Pinned); meshData.normals = pinnedNormalsArray.AddrOfPinnedObject(); meshData.normalsNum = (System.UIntPtr)(normals.Length * normalsDataStride); // Add indices meshData.facesetsNum = (System.IntPtr)mesh.subMeshCount; System.Runtime.InteropServices.GCHandle[] pinnedIndicesArrays = new System.Runtime.InteropServices.GCHandle[(int)meshData.facesetsNum]; // Add facesets FacesetData[] faceSets = new FacesetData[(int)meshData.facesetsNum]; int structSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(FacesetData)); meshData.facesets = System.Runtime.InteropServices.Marshal.AllocHGlobal((int)meshData.facesetsNum * structSize); System.IntPtr facesetsPtr = meshData.facesets; // Change the winding order of indices int[][] indices = new int[(int)meshData.facesetsNum][]; var materialNum = materialTokens.Count; for (var i = 0; i < (int)meshData.facesetsNum; ++i) { int[] indicesList = mesh.GetTriangles(i); indices[i] = new int[indicesList.Length]; for (var indicePos = 0; indicePos < indicesList.Length; indicePos += indicesStride) { indices[i][indicePos + 0] = indicesList[indicePos + 0]; indices[i][indicePos + 1] = indicesList[indicePos + 2]; indices[i][indicePos + 2] = indicesList[indicePos + 1]; } pinnedIndicesArrays[i] = System.Runtime.InteropServices.GCHandle.Alloc( indices[i], System.Runtime.InteropServices.GCHandleType.Pinned ); faceSets[i].indices = pinnedIndicesArrays[i].AddrOfPinnedObject(); // Marshaling needs to use UIntPtr for size_t int indicesNum = indicesList.Length; //faceSets[i].indicesNum = (System.UIntPtr)indicesNum; faceSets[i].indicesNum = (ulong)indicesNum; // Marshal material tokens if (i < materialNum) { faceSets[i].materialName = materialTokens[i]; } else { faceSets[i].materialName = ""; } System.Runtime.InteropServices.Marshal.StructureToPtr(faceSets[i], facesetsPtr, false); facesetsPtr = (System.IntPtr)((long)facesetsPtr + structSize); } // Add UVs List <Vector2>[] meshUVs = new List <Vector2> [maxUV]; int uvCount = 0; for (int i = 0; i < maxUV; i++) { meshUVs[i] = new List <Vector2>(); mesh.GetUVs(i, meshUVs[i]); if (meshUVs[i].Count == 0) { break; } uvCount++; } UVData[] uvSets = new UVData[uvCount]; float[][] uvDataArr = new float[uvCount][]; structSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(UVData)); meshData.uvSetNum = (System.IntPtr)uvCount; meshData.uvSets = System.Runtime.InteropServices.Marshal.AllocHGlobal(uvCount * structSize); System.IntPtr uvSetsPtr = meshData.uvSets; System.Runtime.InteropServices.GCHandle[] pinnedUVArrays = new System.Runtime.InteropServices.GCHandle[uvCount]; for (int i = 0; i < uvCount; i++) { uvDataArr[i] = new float[meshUVs[i].Count * uvDataStride]; for (int uvInd = 0; uvInd < meshUVs[i].Count; uvInd++) { int uvDataInd = uvInd * uvDataStride; uvDataArr[i][uvDataInd] = meshUVs[i][uvInd].x; uvDataArr[i][uvDataInd + 1] = 1.0f - meshUVs[i][uvInd].y; // Convert UV from Unity to STP } // We are not using UV indices due to Unity not supporting them uvSets[i].indicesNum = 0; pinnedUVArrays[i] = System.Runtime.InteropServices.GCHandle.Alloc( uvDataArr[i], System.Runtime.InteropServices.GCHandleType.Pinned ); uvSets[i].uvs = pinnedUVArrays[i].AddrOfPinnedObject(); uvSets[i].uvsNum = (ulong)uvDataArr[i].Length; System.Runtime.InteropServices.Marshal.StructureToPtr(uvSets[i], uvSetsPtr, false); uvSetsPtr = (System.IntPtr)((long)uvSetsPtr + structSize); } System.IntPtr meshDataPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(meshData)); System.Runtime.InteropServices.Marshal.StructureToPtr(meshData, meshDataPtr, false); Debug.LogFormat("Mesh Push - Token:{0}, Parent:{1}, {2} positions, {3} facesets", meshData.entityToken, meshData.entityParentToken, (int)meshData.positionsNum, (int)meshData.facesetsNum); ImportMenu.stpUnitySendMeshData(meshDataPtr); // Free memory pinnedVerticesArray.Free(); pinnedNormalsArray.Free(); foreach (var pin in pinnedIndicesArrays) { pin.Free(); } System.Runtime.InteropServices.Marshal.FreeHGlobal(meshData.facesets); System.Runtime.InteropServices.Marshal.FreeHGlobal(meshDataPtr); }