/// <summary> /// Iterates through all Child nodes and adds the data to the /// commandDescriptor. /// </summary> /// <param name="transform"> /// Transform, which is searched for possible meshes. /// </param> /// <param name="useAllChildNodes"> /// If true: Also process child nodes, which are administered by another /// VLModelTrackableBehaviour /// </param> /// <param name="addDataDescriptor"> /// Fills the ModelDataDescriptors with a DataDescriptor, a description of the /// data structure of the model data. /// </param> /// <param name="commandDescriptor"> /// Reference to the command structure of the json command, which will be /// filled by this function. /// </param> private void IterateThroughChildNodes( Transform transform, bool useAllChildNodes, bool addDataDescriptor, ref AddModelDataCommandDescription commandDescriptor) { MeshFilter mesh = transform.GetComponent <MeshFilter>(); // If child node has a mesh, add this to the list if (mesh && !this.AddModelDescription( transform, useAllChildNodes, addDataDescriptor, ref commandDescriptor)) { // If node is inactive or should not be added to commandDescriptor // do not iterate through the child nodes. return; } // Add child nodes foreach (Transform child in transform) { this.IterateThroughChildNodes( child, useAllChildNodes, addDataDescriptor, ref commandDescriptor); } }
/// <summary> /// Add all (sub)meshes to the tracking system. If a sub mesh has its own /// VLModelTrackableBehaviour, it will not be added, but this behaviour should /// manage the relevant submeshes. /// </summary> public void UpdateModel(bool success = true) { if (success && this.modelTrackerBehaviour.workerBehaviour) { VLWorker worker = this.modelTrackerBehaviour.workerBehaviour.GetWorker(); if (worker == null) { Debug.Log("[vlUnitySDK] VLModelTrackableBehaviour.UpdateModel: Worker is not correctly initialized\n"); return; } AddModelDataCommandDescription command = this.GenerateModelDataDescriptor(true); byte[] binaryData = this.GenerateBinaryData( this.modelData, this.binaryOffset); GCHandle binaryDataHandle = GCHandle.Alloc(binaryData, GCHandleType.Pinned); IntPtr data = binaryDataHandle.AddrOfPinnedObject(); UInt32 dataLength = Convert.ToUInt32(binaryData.Length); gcHandleQueue.Enqueue(binaryDataHandle); worker.PushJsonAndBinaryCommand( VLJsonUtility.ToJson(command), data, dataLength, dispatchAddModelCallbackDelegate, GCHandle.ToIntPtr(this.gcHandle)); } }
/// <summary> /// Generates an AddModelDataCommandDescription from all meshes, which /// will be administered by this behaviour. /// </summary> /// <param name="addDataDescriptor"></param> /// Fills the ModelDataDescriptors with a DataDescriptor, a description of the /// data structure of the model data. This will create more trafic and /// completely delete and remove the model from memory. If you only have /// minor changes (transformation, model (de)activation, etc.) set this to /// false. /// <param name="useAllChildNodes"> /// If true: Also process child nodes, which are administered by another /// VLModelTrackableBehaviour. /// </param> /// <returns></returns> private AddModelDataCommandDescription GenerateModelDataDescriptor( bool addDataDescriptor, bool useAllChildNodes = false) { // Reset global data this.binaryOffset = 0; this.modelData.Clear(); this.globalUpdateCount++; AddModelDataCommandDescription commandDescriptor = new AddModelDataCommandDescription(); IterateThroughChildNodes( this.transform, useAllChildNodes, addDataDescriptor, ref commandDescriptor); return(commandDescriptor); }
/// <summary> /// Updates the transformation of all (sub)meshes in the tracking system. /// It has to be called after each update in a transform which is relevant /// for the location of a related mesh. /// </summary> /// <param name="useAllChildNodes"> /// If useAllChildNodes is true, this will update all locations of /// submeshes, even if they have their own VLModelTrackableBehaviour. It does /// not update the modelDescriptions of this behaviour. /// </param> public void UpdateTransformation(bool useAllChildNodes) { if (this.modelTrackerBehaviour.HasWorkerReference()) { VLWorker worker = this.modelTrackerBehaviour.workerBehaviour.GetWorker(); if (worker == null) { Debug.Log("[vlUnitySDK] VLModelTrackableBehaviour: Worker is not correctly initialized\n"); return; } AddModelDataCommandDescription command = this.GenerateModelDataDescriptor(false, useAllChildNodes); worker.PushJsonAndBinaryCommand( VLJsonUtility.ToJson(command), IntPtr.Zero, 0, null, IntPtr.Zero); } }
/// <summary> /// Add a ModelDataDescriptors of the mesh inside the transform to the /// commandDescriptor /// </summary> /// <param name="transform"> /// Transform, which is searched for possible meshes. /// </param> /// <param name="useAllChildNodes"> /// If true: Also process child nodes, which are administered by another /// VLModelTrackableBehaviour /// </param> /// <param name="addDataDescriptor"> /// Fills the ModelDataDescriptor with a DataDescriptor, a description of the /// data structure of the model data. /// </param> /// <param name="commandDescriptor"> /// Reference to the command structure of the json command, which will be /// filled by this function. /// </param> /// <returns><c>True</c> if the model could be serialized into the visionlib.</c>False</c> if the data could not be gathered.</returns> private bool AddModelDescription( Transform transform, bool useAllChildNodes, bool addDataDescription, ref AddModelDataCommandDescription commandDescriptor) { // If transform is not active, do not add the model if (!transform.gameObject.activeInHierarchy) { return(false); } // See if another VLModelTrackableBehaviour is active in this transform. If // this is the case, break execution of this node and its children. VLModelTrackableBehaviour trackable = transform.GetComponent <VLModelTrackableBehaviour>(); if (!useAllChildNodes && trackable && trackable != this && trackable.enabled) { return(false); } if (trackable == null) { trackable = this; } Quaternion rotation = transform.rotation; Vector3 globalScale = GetGlobalScale(transform); Vector3 position = transform.position; // On HoloLens, the content node is added to the camera and thus the // transformation of the mesh will be changed. This change has to be // removed when streaming the data into the vlSDK Transform contentTransform = getContentTransform(); if (contentTransform != null) { Vector3 contentGlobalScale = GetGlobalScale(contentTransform); rotation = Quaternion.Inverse(contentTransform.rotation) * rotation; globalScale = new Vector3( globalScale.x / contentGlobalScale.x, globalScale.y / contentGlobalScale.y, globalScale.z / contentGlobalScale.z); position = Quaternion.Inverse(contentTransform.rotation) * (position - contentTransform.position); } VLUnityCameraHelper.ToVLInPlace(ref position, ref rotation, modelTrackerBehaviour.workerBehaviour.flipCoordinateSystemHandedness); MeshFilter mesh = transform.GetComponent <MeshFilter>(); string uniqueUnityModelID = mesh.GetInstanceID().ToString(); ModelTransform modelTransform = new ModelTransform(); modelTransform.t = new float[] { position.x, position.y, position.z }; modelTransform.s = new float[] { globalScale.x, globalScale.y, globalScale.z }; modelTransform.q = new float[] { rotation.x, rotation.y, rotation.z, rotation.w }; ModelDataDescriptor descriptor = new ModelDataDescriptor(); descriptor.name = uniqueUnityModelID; descriptor.type = "model"; descriptor.enabled = trackable.useForTracking; descriptor.occluder = trackable.occluder; descriptor.transform = modelTransform; if (addDataDescription) { descriptor.subModels = new BinaryDataDescriptor[] { CreateDataDescriptor(mesh) }; } commandDescriptor.models.Add(descriptor); return(true); }