using System; using UnityEngine; using UnityEngine.XR.iOS; using System.Text; namespace Utils { /// /// Since unity doesn't flag the Vector4 as serializable, we /// need to create our own version. This one will automatically convert /// between Vector4 and SerializableVector4 /// [Serializable] public class SerializableVector4 { /// /// x component /// public float x; /// /// y component /// public float y; /// /// z component /// public float z; /// /// w component /// public float w; /// /// Constructor /// /// /// /// /// public SerializableVector4(float rX, float rY, float rZ, float rW) { x = rX; y = rY; z = rZ; w = rW; } /// /// Returns a string representation of the object /// /// public override string ToString() { return String.Format("[{0}, {1}, {2}, {3}]", x, y, z, w); } /// /// Automatic conversion from SerializableVector4 to Vector4 /// /// /// public static implicit operator Vector4(SerializableVector4 rValue) { return new Vector4(rValue.x, rValue.y, rValue.z, rValue.w); } /// /// Automatic conversion from Vector4 to SerializableVector4 /// /// /// public static implicit operator SerializableVector4(Vector4 rValue) { return new SerializableVector4(rValue.x, rValue.y, rValue.z, rValue.w); } } [Serializable] public class serializableUnityARMatrix4x4 { public SerializableVector4 column0; public SerializableVector4 column1; public SerializableVector4 column2; public SerializableVector4 column3; public serializableUnityARMatrix4x4(SerializableVector4 v0, SerializableVector4 v1, SerializableVector4 v2, SerializableVector4 v3) { column0 = v0; column1 = v1; column2 = v2; column3 = v3; } /// /// Automatic conversion from UnityARMatrix4x4 to serializableUnityARMatrix4x4 /// /// /// public static implicit operator serializableUnityARMatrix4x4(UnityARMatrix4x4 rValue) { return new serializableUnityARMatrix4x4(rValue.column0, rValue.column1, rValue.column2, rValue.column3); } /// /// Automatic conversion from serializableUnityARMatrix4x4 to UnityARMatrix4x4 /// /// /// public static implicit operator UnityARMatrix4x4(serializableUnityARMatrix4x4 rValue) { return new UnityARMatrix4x4(rValue.column0, rValue.column1, rValue.column2, rValue.column3); } public static implicit operator serializableUnityARMatrix4x4(Matrix4x4 rValue) { return new serializableUnityARMatrix4x4(rValue.GetColumn(0), rValue.GetColumn(1), rValue.GetColumn(2), rValue.GetColumn(3)); } public static implicit operator Matrix4x4(serializableUnityARMatrix4x4 rValue) { #if UNITY_2017_1_OR_NEWER return new Matrix4x4(rValue.column0, rValue.column1, rValue.column2, rValue.column3); #else Matrix4x4 mRet = new Matrix4x4 (); mRet.SetColumn (0, rValue.column0); mRet.SetColumn (1, rValue.column1); mRet.SetColumn (2, rValue.column2); mRet.SetColumn (3, rValue.column3); return mRet; #endif } }; [Serializable] public class serializableSHC { public byte [] shcData; public serializableSHC(byte [] inputSHCData) { shcData = inputSHCData; } public static implicit operator serializableSHC(float [] floatsSHC) { if (floatsSHC != null) { byte [] createBuf = new byte[floatsSHC.Length * sizeof(float)]; for(int i = 0; i < floatsSHC.Length; i++) { Buffer.BlockCopy( BitConverter.GetBytes( floatsSHC[i] ), 0, createBuf, (i)*sizeof(float), sizeof(float) ); } return new serializableSHC (createBuf); } else { return new serializableSHC(null); } } public static implicit operator float [] (serializableSHC spc) { if (spc.shcData != null) { int numFloats = spc.shcData.Length / (sizeof(float)); float [] shcFloats = new float[numFloats]; for (int i = 0; i < numFloats; i++) { shcFloats [i] = BitConverter.ToSingle (spc.shcData, i * sizeof(float)); } return shcFloats; } else { return null; } } }; [Serializable] public class serializableUnityARLightData { public LightDataType whichLight; public serializableSHC lightSHC; public SerializableVector4 primaryLightDirAndIntensity; public float ambientIntensity; public float ambientColorTemperature; serializableUnityARLightData(UnityARLightData lightData) { whichLight = lightData.arLightingType; if (whichLight == LightDataType.DirectionalLightEstimate) { lightSHC = lightData.arDirectonalLightEstimate.sphericalHarmonicsCoefficients; Vector3 lightDir = lightData.arDirectonalLightEstimate.primaryLightDirection; float lightIntensity = lightData.arDirectonalLightEstimate.primaryLightIntensity; primaryLightDirAndIntensity = new SerializableVector4 (lightDir.x, lightDir.y, lightDir.z, lightIntensity); } else { ambientIntensity = lightData.arLightEstimate.ambientIntensity; ambientColorTemperature = lightData.arLightEstimate.ambientColorTemperature; } } public static implicit operator serializableUnityARLightData(UnityARLightData rValue) { return new serializableUnityARLightData(rValue); } public static implicit operator UnityARLightData(serializableUnityARLightData rValue) { UnityARDirectionalLightEstimate udle = null; UnityARLightEstimate ule = new UnityARLightEstimate (rValue.ambientIntensity, rValue.ambientColorTemperature); if (rValue.whichLight == LightDataType.DirectionalLightEstimate) { Vector3 lightDir = new Vector3 (rValue.primaryLightDirAndIntensity.x, rValue.primaryLightDirAndIntensity.y, rValue.primaryLightDirAndIntensity.z); udle = new UnityARDirectionalLightEstimate (rValue.lightSHC, lightDir, rValue.primaryLightDirAndIntensity.w); } return new UnityARLightData(rValue.whichLight, ule, udle); } } [Serializable] public class serializableUnityARCamera { public serializableUnityARMatrix4x4 worldTransform; public serializableUnityARMatrix4x4 projectionMatrix; public ARTrackingState trackingState; public ARTrackingStateReason trackingReason; public UnityVideoParams videoParams; public serializableUnityARLightData lightData; public serializablePointCloud pointCloud; public serializableUnityARMatrix4x4 displayTransform; public serializableUnityARCamera( serializableUnityARMatrix4x4 wt, serializableUnityARMatrix4x4 pm, ARTrackingState ats, ARTrackingStateReason atsr, UnityVideoParams uvp, UnityARLightData lightDat, serializableUnityARMatrix4x4 dt, serializablePointCloud spc) { worldTransform = wt; projectionMatrix = pm; trackingState = ats; trackingReason = atsr; videoParams = uvp; lightData = lightDat; displayTransform = dt; pointCloud = spc; } public static implicit operator serializableUnityARCamera(UnityARCamera rValue) { return new serializableUnityARCamera(rValue.worldTransform, rValue.projectionMatrix, rValue.trackingState, rValue.trackingReason, rValue.videoParams, rValue.lightData, rValue.displayTransform, rValue.pointCloudData); } public static implicit operator UnityARCamera(serializableUnityARCamera rValue) { return new UnityARCamera (rValue.worldTransform, rValue.projectionMatrix, rValue.trackingState, rValue.trackingReason, rValue.videoParams, rValue.lightData, rValue.displayTransform, rValue.pointCloud); } }; [Serializable] public class serializableUnityARPlaneAnchor { public serializableUnityARMatrix4x4 worldTransform; public SerializableVector4 center; public SerializableVector4 extent; public ARPlaneAnchorAlignment planeAlignment; public byte[] identifierStr; public serializableUnityARPlaneAnchor( serializableUnityARMatrix4x4 wt, SerializableVector4 ctr, SerializableVector4 ext, ARPlaneAnchorAlignment apaa, byte [] idstr) { worldTransform = wt; center = ctr; extent = ext; planeAlignment = apaa; identifierStr = idstr; } public static implicit operator serializableUnityARPlaneAnchor(ARPlaneAnchor rValue) { serializableUnityARMatrix4x4 wt = rValue.transform; SerializableVector4 ctr = new SerializableVector4 (rValue.center.x, rValue.center.y, rValue.center.z, 1.0f); SerializableVector4 ext = new SerializableVector4 (rValue.extent.x, rValue.extent.y, rValue.extent.z, 1.0f); byte[] idstr = Encoding.UTF8.GetBytes (rValue.identifier); return new serializableUnityARPlaneAnchor(wt, ctr, ext, rValue.alignment, idstr); } public static implicit operator ARPlaneAnchor(serializableUnityARPlaneAnchor rValue) { ARPlaneAnchor retValue; retValue.identifier = Encoding.UTF8.GetString (rValue.identifierStr); retValue.center = new Vector3 (rValue.center.x, rValue.center.y, rValue.center.z); retValue.extent = new Vector3 (rValue.extent.x, rValue.extent.y, rValue.extent.z); retValue.alignment = rValue.planeAlignment; retValue.transform = rValue.worldTransform; return retValue; } }; [Serializable] public class serializablePointCloud { public byte [] pointCloudData; public serializablePointCloud(byte [] inputPoints) { pointCloudData = inputPoints; } public static implicit operator serializablePointCloud(Vector3 [] vecPointCloud) { if (vecPointCloud != null) { byte [] createBuf = new byte[vecPointCloud.Length * sizeof(float) * 3]; for(int i = 0; i < vecPointCloud.Length; i++) { int bufferStart = i * 3; Buffer.BlockCopy( BitConverter.GetBytes( vecPointCloud[i].x ), 0, createBuf, (bufferStart)*sizeof(float), sizeof(float) ); Buffer.BlockCopy( BitConverter.GetBytes( vecPointCloud[i].y ), 0, createBuf, (bufferStart+1)*sizeof(float), sizeof(float) ); Buffer.BlockCopy( BitConverter.GetBytes( vecPointCloud[i].z ), 0, createBuf, (bufferStart+2)*sizeof(float), sizeof(float) ); } return new serializablePointCloud (createBuf); } else { return new serializablePointCloud(null); } } public static implicit operator Vector3 [] (serializablePointCloud spc) { if (spc.pointCloudData != null) { int numVectors = spc.pointCloudData.Length / (3 * sizeof(float)); Vector3 [] pointCloudVec = new Vector3[numVectors]; for (int i = 0; i < numVectors; i++) { int bufferStart = i * 3; pointCloudVec [i].x = BitConverter.ToSingle (spc.pointCloudData, (bufferStart) * sizeof(float)); pointCloudVec [i].y = BitConverter.ToSingle (spc.pointCloudData, (bufferStart+1) * sizeof(float)); pointCloudVec [i].z = BitConverter.ToSingle (spc.pointCloudData, (bufferStart+2) * sizeof(float)); } return pointCloudVec; } else { return null; } } }; [Serializable] public class serializableARSessionConfiguration { public UnityARAlignment alignment; public UnityARPlaneDetection planeDetection; public bool getPointCloudData; public bool enableLightEstimation; public serializableARSessionConfiguration(UnityARAlignment align, UnityARPlaneDetection planeDet, bool getPtCloud, bool enableLightEst) { alignment = align; planeDetection = planeDet; getPointCloudData = getPtCloud; enableLightEstimation = enableLightEst; } public static implicit operator serializableARSessionConfiguration(ARKitWorldTrackingSessionConfiguration awtsc) { return new serializableARSessionConfiguration (awtsc.alignment, awtsc.planeDetection, awtsc.getPointCloudData, awtsc.enableLightEstimation); } public static implicit operator ARKitWorldTrackingSessionConfiguration (serializableARSessionConfiguration sasc) { return new ARKitWorldTrackingSessionConfiguration (sasc.alignment, sasc.planeDetection, sasc.getPointCloudData, sasc.enableLightEstimation); } }; [Serializable] public class serializableARKitInit { public serializableARSessionConfiguration config; public UnityARSessionRunOption runOption; public serializableARKitInit(serializableARSessionConfiguration cfg, UnityARSessionRunOption option) { config = cfg; runOption = option; } }; [Serializable] public class serializableFromEditorMessage { public Guid subMessageId; public serializableARKitInit arkitConfigMsg; }; }