/// <summary> /// Generates heightfield/terrain data from the given object relevant for uploading to Houdini. /// </summary> /// <param name="inputObject"></param> /// <returns>Valid input object or null if given object is not supported</returns> public HEU_InputDataTerrain GenerateTerrainDataFromGameObject(GameObject inputObject) { HEU_InputDataTerrain inputData = null; Terrain terrain = inputObject.GetComponent<Terrain>(); if (terrain != null) { TerrainData terrainData = terrain.terrainData; Vector3 terrainSize = terrainData.size; if (terrainSize.x != terrainSize.z) { Debug.LogError("Only square sized terrains are supported for input! Change to square size and try again."); return null; } inputData = new HEU_InputDataTerrain(); inputData._inputObject = inputObject; inputData._terrain = terrain; inputData._terrainData = terrainData; // Height values in Unity are normalized between 0 and 1, so this height scale // will multiply them before uploading to Houdini. inputData._heightScale = terrainSize.y; // Terrain heightMapResolution is the pixel resolution, which we set to the number of voxels // by dividing the terrain size with it. In Houdini, this is the Grid Spacing. inputData._voxelSize = terrainSize.x / inputData._terrainData.heightmapResolution; // This is the number of heightfield voxels on each dimension. inputData._numPointsX = Mathf.RoundToInt(inputData._terrainData.heightmapResolution * inputData._voxelSize); inputData._numPointsY = Mathf.RoundToInt(inputData._terrainData.heightmapResolution * inputData._voxelSize); Matrix4x4 transformMatrix = inputObject.transform.localToWorldMatrix; HAPI_TransformEuler transformEuler = HEU_HAPIUtility.GetHAPITransformFromMatrix(ref transformMatrix); // Volume transform used for all heightfield layers inputData._transform = new HAPI_Transform(false); // Unity terrain pivots are at bottom left, but Houdini uses centered heightfields so // apply local position offset by half sizes and account for coordinate change inputData._transform.position[0] = terrainSize.z * 0.5f; inputData._transform.position[1] = -terrainSize.x * 0.5f; inputData._transform.position[2] = 0; // Volume scale controls final size, but requires to be divided by 2 inputData._transform.scale[0] = terrainSize.x * 0.5f; inputData._transform.scale[1] = terrainSize.z * 0.5f; inputData._transform.scale[2] = 0.5f; inputData._transform.rotationQuaternion[0] = 0f; inputData._transform.rotationQuaternion[1] = 0f; inputData._transform.rotationQuaternion[2] = 0f; inputData._transform.rotationQuaternion[3] = 1f; } return inputData; }
/// <summary> /// Set the input node's transform. /// </summary> /// <param name="session">Session that the input node exists in</param> /// <param name="inputObject">The input object info containing data about the input</param> /// <param name="inputNodeID">The input node ID</param> /// <param name="bKeepWorldTransform">Whether to use world transform or not</param> /// <returns></returns> internal static bool UploadInputObjectTransform(HEU_SessionBase session, HEU_InputObjectInfo inputObject, HAPI_NodeId inputNodeID, bool bKeepWorldTransform) { Matrix4x4 inputTransform = Matrix4x4.identity; if (inputObject._useTransformOffset) { if (bKeepWorldTransform) { // Add offset tranform to world transform Transform inputObjTransform = inputObject._gameObject.transform; Vector3 position = inputObjTransform.position + inputObject._translateOffset; Quaternion rotation = inputObjTransform.rotation * Quaternion.Euler(inputObject._rotateOffset); Vector3 scale = Vector3.Scale(inputObjTransform.localScale, inputObject._scaleOffset); Vector3 rotVector = rotation.eulerAngles; inputTransform = HEU_HAPIUtility.GetMatrix4x4(ref position, ref rotVector, ref scale); } else { // Offset from origin. inputTransform = HEU_HAPIUtility.GetMatrix4x4(ref inputObject._translateOffset, ref inputObject._rotateOffset, ref inputObject._scaleOffset); } } else { inputTransform = inputObject._gameObject.transform.localToWorldMatrix; } HAPI_TransformEuler transformEuler = HEU_HAPIUtility.GetHAPITransformFromMatrix(ref inputTransform); HAPI_NodeInfo inputNodeInfo = new HAPI_NodeInfo(); if (!session.GetNodeInfo(inputNodeID, ref inputNodeInfo)) { return false; } if (session.SetObjectTransform(inputNodeInfo.parentId, ref transformEuler)) { inputObject._syncdTransform = inputTransform; inputObject._syncdChildTransforms.Clear(); GetChildrenTransforms(inputObject._gameObject.transform, ref inputObject._syncdChildTransforms); } return true; }