private bool createObject(int object_id, bool reload_asset) { bool needs_recook = false; HoudiniObjectControl object_control = null; HAPI_ObjectInfo object_info = prObjects[object_id]; // Create main underling. if (prGameObjects[object_id] == null) { prGameObjects[object_id] = new GameObject(object_info.name); prGameObjects[object_id].transform.parent = transform; prGameObjects[object_id].isStatic = gameObject.isStatic; object_control = prGameObjects[object_id].AddComponent <HoudiniObjectControl>(); object_control.init( prAssetId, object_info.nodeId, prAsset, object_info.nodeId, object_info.name, object_info.isVisible); } else { object_control = prGameObjects[object_id].GetComponent <HoudiniObjectControl>(); } GameObject main_child = prGameObjects[object_id]; try { needs_recook |= object_control.refresh(reload_asset, object_info); if (reload_asset || object_info.hasTransformChanged) { // Get transforms. HAPI_Transform trans = prObjectTransforms[object_id]; HoudiniAssetUtility.applyTransform(trans, main_child.transform); } } catch (HoudiniError error) { DestroyImmediate(main_child); prGameObjects[object_id] = null; error.addMessagePrefix("Obj(id: " + object_info.nodeId + ", name: " + object_info.name + ")"); error.addMessageDetail("Object Path: " + object_info.objectInstancePath); throw; } return(needs_recook); }
public override void reset() { base.reset(); // Please keep these in the same order and grouping as their declarations at the top. // Assets --------------------------------------------------------------------------------------------------- prAsset = this; prAssetInfo = new HAPI_AssetInfo(); prPreset = null; prAssetValidationId = -1; prAssetName = "ASSET_NAME"; prAssetOpName = "ASSET_OP_NAME"; prAssetHelp = "ASSET_HELP"; prAssetType = AssetType.TYPE_INVALID; prHAPIAssetType = HAPI_AssetType.HAPI_ASSETTYPE_INVALID; prAssetSubType = 0; // Parameters ----------------------------------------------------------------------------------------------- prPresetsMap = null; // Inputs --------------------------------------------------------------------------------------------------- prTransformInputCount = 0; prGeoInputCount = 0; prDownStreamTransformAssets = new List< HoudiniAsset >(); prUpStreamTransformAssets = new List< HoudiniAsset >(); prUpStreamTransformObjects = new List< GameObject >(); prDownStreamGeoAssets = new List< HoudiniAsset >(); prUpStreamGeoAssets = new List< HoudiniAsset >(); prUpStreamGeoObjects = new List< GameObject >(); prUpStreamGeoInputAssetIds = new List< int >(); myUpStreamGeoInputAssetValidationIds = new List< int >(); // Objects -------------------------------------------------------------------------------------------------- prObjectCount = 0; prHandleCount = 0; prObjects = new HAPI_ObjectInfo[ 0 ]; prGameObjects = new GameObject[ 0 ]; prObjectTransforms = new HAPI_Transform[ 0 ]; // Geos ----------------------------------------------------------------------------------------------------- prGeoAttributeManagerMap = null; // Baking --------------------------------------------------------------------------------------------------- prBakeStartTime = 0.0f; prBakeEndTime = 1.0f; prBakeSamplesPerSecond = 30; // GUI ------------------------------------------------------------------------------------------------------ prShowHoudiniControls = true; prShowCookLog = false; prShowHelp = false; prShowAssetSettings = true; prShowBakeOptions = false; prShowPaintTools = false; prShowInputControls = true; prAssetSettingsCategory = 0; prIsGeoVisible = true; prShowPinnedInstances = true; prAutoSelectAssetRootNode = HoudiniHost.myDefaultAutoSelectAssetRootNode; prShowOnlyVertexColours = false; prGenerateUVs = false; prGenerateLightmapUV2s = false; prGenerateTangents = true; prEnableCooking = HoudiniHost.myDefaultEnableCooking; prCookingTriggersDownCooks = HoudiniHost.myDefaultCookingTriggersDownCooks; prPlaymodePerFrameCooking = false; prPushUnityTransformToHoudini = HoudiniHost.myDefaultPushUnityTransformToHoudini; prTransformChangeTriggersCooks = HoudiniHost.myDefaultTransformChangeTriggersCooks; prImportTemplatedGeos = HoudiniHost.myDefaultImportTemplatedGeos; prSplitGeosByGroupOverride = false; prSplitGeosByGroup = HoudiniHost.myDefaultSplitGeosByGroup; prEnableLogging = false; prTransInputNames = new List< string >(); prGeoInputNames = new List< string >(); myProgressBarJustUsed = false; // Prefabs ------------------------------------------------------------------------------------------------------ prBackupAssetId = -1; prBackupAssetValidationId = -1; prReloadPrefabOnPlaymodeChange = false; prUpdatePrefabInstanceParmNames = new List< string >(); }
public void bakeAnimations( float start_time, float end_time, int samples_per_second, GameObject parent_object, HoudiniProgressBar progress_bar ) { #if UNITY_EDITOR try { //This build is needed in case the user changed a geometry input to the asset. //The geometry to be instanced needs to be re-brought in. buildClientSide(); int num_objects = prObjects.Length; for ( int ii = 0; ii < num_objects; ii++ ) { GameObject game_object = prGameObjects[ ii ]; HAPI_ObjectInfo obj_info = prObjects[ ii ]; if ( game_object != null ) { if ( !obj_info.isInstancer ) { HoudiniObjectControl obj_control = game_object.GetComponent< HoudiniObjectControl >(); obj_control.beginBakeAnimation(); } else { HoudiniInstancer instancer = game_object.GetComponent< HoudiniInstancer >(); instancer.beginBakeAnimation(); } } } int num_samples = Mathf.CeilToInt(samples_per_second*( end_time - start_time )); float total_sim_time = ( end_time - start_time ); float delta_time = total_sim_time / (float) num_samples; progress_bar.prTotal = num_samples; progress_bar.prCurrentValue = 0; for ( float curr_time = start_time; curr_time <= end_time; curr_time += delta_time ) { HoudiniHost.setTime( curr_time ); HoudiniHost.cookAsset( prAssetId, prSplitGeosByGroup, prImportTemplatedGeos ); HAPI_State state = HAPI_State.HAPI_STATE_STARTING_LOAD; while ( (int) state > (int) HAPI_State.HAPI_STATE_MAX_READY_STATE ) state = (HAPI_State) HoudiniHost.getStatus( HAPI_StatusType.HAPI_STATUS_COOK_STATE ); if ( state == HAPI_State.HAPI_STATE_READY_WITH_COOK_ERRORS ) { state = HAPI_State.HAPI_STATE_READY; Debug.LogWarning( "Cook Errors at time: " + curr_time + "\n" + HoudiniHost.getCookErrorMessage() ); } else if ( state == HAPI_State.HAPI_STATE_READY_WITH_FATAL_ERRORS ) { state = HAPI_State.HAPI_STATE_READY; HoudiniHost.throwCookError(); } HAPI_Transform[] object_transforms = new HAPI_Transform[ prObjectCount ]; HoudiniAssetUtility.getArray2Id( prAssetId, HAPI_RSTOrder.HAPI_SRT, HoudiniHost.getObjectTransforms, object_transforms, prObjectCount ); for ( int ii = 0; ii < num_objects; ii++ ) { GameObject game_object = prGameObjects[ ii ]; HAPI_ObjectInfo obj_info = prObjects[ ii ]; if ( game_object != null ) { if ( !obj_info.isInstancer ) { HoudiniObjectControl obj_control = game_object.GetComponent< HoudiniObjectControl >(); obj_control.bakeAnimation( curr_time, parent_object, object_transforms[ ii ] ); } else { HoudiniInstancer instancer = game_object.GetComponent< HoudiniInstancer >(); instancer.bakeAnimation( curr_time, parent_object ); } } } // Set progress bar information. progress_bar.prCurrentValue++; progress_bar.prMessage = "Baking: " + progress_bar.prCurrentValue + " of " + num_samples; progress_bar.displayProgressBar(); } bool found_anim = false; for ( int ii = 0; ii < num_objects; ii++ ) { GameObject game_object = prGameObjects[ ii ]; HAPI_ObjectInfo obj_info = prObjects[ ii ]; if ( game_object != null ) { if ( !obj_info.isInstancer ) { HoudiniObjectControl obj_control = game_object.GetComponent< HoudiniObjectControl >(); if ( obj_control.endBakeAnimation() ) found_anim = true; } else { HoudiniInstancer instancer = game_object.GetComponent< HoudiniInstancer >(); if ( instancer.endBakeAnimation( parent_object ) ) found_anim = true; } } } if ( !found_anim ) { EditorUtility.DisplayDialog( "Bake Error", "No animation was found to bake", "OK" ); } } catch ( HoudiniError error ) { Debug.LogWarning( error.ToString() ); } #endif // UNITY_EDITOR }
public static Matrix4x4 convertTransformQuatToMatrix( HAPI_Transform transform ) { #if ( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) float[] raw_matrix = new float[ 16 ]; HAPI_Result status_code = HAPI_ConvertTransformQuatToMatrix( ref mySession, ref transform, raw_matrix ); processStatusCode( status_code ); Matrix4x4 output = new Matrix4x4(); for ( int i = 0; i < 16; ++i ) output[ i ] = raw_matrix[ i ]; return output; #else throw new HoudiniErrorUnsupportedPlatform(); #endif }
public static HAPI_Transform convertMatrixToQuat( Matrix4x4 matrix, HAPI_RSTOrder rst_order ) { #if ( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) HAPI_Transform transform = new HAPI_Transform(); float[] raw_matrix = new float[ 16 ]; for ( int i = 0; i < 16; ++i ) raw_matrix[ i ] = matrix[ i ]; HAPI_Result status_code = HAPI_ConvertMatrixToQuat( ref mySession, raw_matrix, rst_order, ref transform ); processStatusCode( status_code ); return transform; #else throw new HoudiniErrorUnsupportedPlatform(); #endif }
public static HAPI_Transform[] getInstancerPartTransforms( HAPI_AssetId asset_id, HAPI_ObjectId object_id, HAPI_GeoId geo_id, HAPI_PartId part_id, HAPI_RSTOrder rst_order ) { #if ( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) HAPI_PartInfo part_info = new HAPI_PartInfo(); HAPI_Result status_code = HAPI_GetPartInfo( ref mySession, asset_id, object_id, geo_id, part_id, out part_info ); processStatusCode( status_code ); int count = part_info.instanceCount; HAPI_Transform[] transforms = new HAPI_Transform[ count ]; if ( count > 0 ) { status_code = HAPI_GetInstancerPartTransforms( ref mySession, asset_id, object_id, geo_id, part_id, rst_order, transforms, 0, count ); processStatusCode( status_code ); } return transforms; #else throw new HoudiniErrorUnsupportedPlatform(); #endif }
private static extern HAPI_Result HAPI_ConvertTransformQuatToMatrix( ref HAPI_Session session, ref HAPI_Transform transform, [Out] float[] matrix );
public void instanceObjects(HoudiniProgressBar progress_bar) { try { destroyChildren(); HAPI_ObjectInfo object_info = HoudiniHost.getObjectInfo(prObjectId); // Get Detail info. HAPI_GeoInfo geo_info = HoudiniHost.getDisplayGeoInfo(prObjectId); if (geo_info.partCount == 0) { return; } cacheNumInstances(); HAPI_Transform[] instance_transforms = new HAPI_Transform[myNumInstances]; Utility.getArray2Id( geo_info.nodeId, HAPI_RSTOrder.HAPI_SRT, HoudiniHost.getInstanceTransforms, instance_transforms, myNumInstances); // Get scale point attributes. HAPI_AttributeInfo scale_attr_info = new HAPI_AttributeInfo("scale"); float[] scale_attr = new float[0]; Utility.getAttribute( geo_info.nodeId, 0, "scale", ref scale_attr_info, ref scale_attr, HoudiniHost.getAttributeFloatData); if (scale_attr_info.exists && scale_attr_info.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT) { throw new HoudiniErrorIgnorable("I only understand scale as point attributes!"); } if (scale_attr_info.exists && scale_attr.Length != myNumInstances * 3) { throw new HoudiniError( "Unexpected scale array length found for asset: " + prAsset.prAssetId + "!\n" + "Expected length of: " + myNumInstances * 3 + " but given: " + scale_attr.Length); } HAPI_AttributeInfo script_attr_info = new HAPI_AttributeInfo("Unity_Script"); int[] script_attr = new int[0]; Utility.getAttribute( geo_info.nodeId, 0, "Unity_Script", ref script_attr_info, ref script_attr, HoudiniHost.getAttributeStringData); if (script_attr_info.exists && script_attr_info.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT) { throw new HoudiniErrorIgnorable("I only understand Unity_Script as point attributes!"); } if (script_attr_info.exists && script_attr.Length != myNumInstances) { throw new HoudiniError("Unexpected Unity_Script array length found for asset: " + prAsset.prAssetId + "!"); } int[] instance_attr = null; int[] name_attr = null; getInstanceAndNameAttrs(out instance_attr, out name_attr); progress_bar.prTotal = myNumInstances; List <int> exclusion_list = new List <int>(); instanceOverriddenObjects(myNumInstances, exclusion_list); List <string> unique_instantiated_names = new List <string>(); HoudiniInstancerPersistentData persistent_data = prPersistentData; if (persistent_data.variationChoice.Count != myNumInstances) { if (myNumInstances > persistent_data.variationChoice.Count) { int difference = myNumInstances - persistent_data.variationChoice.Count; for (int ii = 0; ii < difference; ii++) { persistent_data.variationChoice.Add(-1); } } else { int difference = persistent_data.variationChoice.Count - myNumInstances; persistent_data.variationChoice.RemoveRange( persistent_data.variationChoice.Count - difference, difference); } } bool liveTransformPropagationSetting = false; bool syncAssetTransformSetting = false; bool enableCooking = true; for (int i = 0; i < myNumInstances; ++i) { if (exclusion_list.Contains(i)) { continue; } GameObject obj_to_instance = null; if (instance_attr.Length > 0 || name_attr.Length > 0) { if (name_attr.Length > 0) { string obj_name = HoudiniHost.getString(name_attr[i]); int object_index = prAsset.findObjectByName(obj_name); if (object_index >= 0) { obj_to_instance = prAsset.prGameObjects[object_index]; } else { obj_to_instance = prAsset.findPartByName(obj_name, true); } if (obj_to_instance == null) { obj_to_instance = GameObject.Find(obj_name); } } else { string instanceObjectPath = HoudiniHost.getString(instance_attr[i]); string [] pathItems = instanceObjectPath.Split('/'); string instanceObjectName = pathItems[pathItems.Length - 1]; int objectIndex = prAsset.findObjectByName(instanceObjectName); if (objectIndex >= 0) { obj_to_instance = prAsset.prGameObjects[objectIndex]; } else { obj_to_instance = GameObject.Find(instanceObjectName); } } if (obj_to_instance != null) { HoudiniAsset hapi_asset = obj_to_instance.GetComponent <HoudiniAsset>(); if (hapi_asset != null) { liveTransformPropagationSetting = hapi_asset.prTransformChangeTriggersCooks; syncAssetTransformSetting = hapi_asset.prPushUnityTransformToHoudini; enableCooking = hapi_asset.prEnableCooking; hapi_asset.prTransformChangeTriggersCooks = false; hapi_asset.prPushUnityTransformToHoudini = false; hapi_asset.prEnableCooking = false; } } } else if (object_info.objectToInstanceId >= 0) { int object_to_instance_idx = prAsset.findObjectByNodeId(object_info.objectToInstanceId); if (object_to_instance_idx >= 0) { obj_to_instance = prAsset.prGameObjects[object_to_instance_idx]; } } if (obj_to_instance != null) { // Set progress bar information. progress_bar.prCurrentValue = i; progress_bar.prMessage = "Instancing: " + obj_to_instance.name + " (" + i + " of " + myNumInstances + ")"; progress_bar.displayProgressBar(); if (!unique_instantiated_names.Contains(obj_to_instance.name)) { unique_instantiated_names.Add(obj_to_instance.name); } Vector3 pos = new Vector3(); // Apply object transforms. // // Axis and Rotation conversions: // Note that Houdini's X axis points in the opposite direction that Unity's does. Also, Houdini's // rotation is right handed, whereas Unity is left handed. To account for this, we need to invert // the x coordinate of the translation, and do the same for the rotations (except for the x rotation, // which doesn't need to be flipped because the change in handedness AND direction of the left x axis // causes a double negative - yeah, I know). pos[0] = -instance_transforms[i].position[0]; pos[1] = instance_transforms[i].position[1]; pos[2] = instance_transforms[i].position[2]; Quaternion quat = new Quaternion(instance_transforms[i].rotationQuaternion[0], instance_transforms[i].rotationQuaternion[1], instance_transforms[i].rotationQuaternion[2], instance_transforms[i].rotationQuaternion[3]); Vector3 euler = quat.eulerAngles; euler.y = -euler.y; euler.z = -euler.z; Vector3 scale = new Vector3(instance_transforms[i].scale[0], instance_transforms[i].scale[1], instance_transforms[i].scale[2]); Matrix4x4 local_mat = new Matrix4x4(); local_mat.SetTRS(pos, Quaternion.Euler(euler), scale); // TODO: Now this *should* be the transform.localToWorldMatrix // but for some reason, after a scene load, we pick up compensating // factors in the local transform that cancel out the transform on the // asset. For now just use the asset's transform as the parent matrix. Matrix4x4 parent_mat = prAsset.transform.localToWorldMatrix; Matrix4x4 global_mat = parent_mat * local_mat; euler = HoudiniAssetUtility.getQuaternion(global_mat).eulerAngles; pos = HoudiniAssetUtility.getPosition(global_mat); scale = HoudiniAssetUtility.getScale(global_mat); //mat.SetTRS( pos, string script_to_attach = ""; if (script_attr_info.exists) { script_to_attach = HoudiniHost.getString(script_attr[i]); } instanceObject(obj_to_instance, pos, euler, i, scale_attr_info.exists, scale, script_attr_info.exists, script_to_attach); HoudiniAsset hapi_asset = obj_to_instance.GetComponent <HoudiniAsset>(); if (hapi_asset != null) { hapi_asset.prTransformChangeTriggersCooks = liveTransformPropagationSetting; hapi_asset.prPushUnityTransformToHoudini = syncAssetTransformSetting; hapi_asset.prEnableCooking = enableCooking; } } } updateUniqueInstantiatedNames(unique_instantiated_names); } catch (HoudiniError error) { Debug.LogWarning(error.ToString()); return; } }
public void bakeAnimation(float curr_time, GameObject parent_object, HAPI_Transform hapi_transform) { try { Matrix4x4 parent_xform_inverse = Matrix4x4.identity; if (parent_object != null) { parent_xform_inverse = parent_object.transform.localToWorldMatrix.inverse; } Vector3 pos = new Vector3(); // Apply object transforms. // // Axis and Rotation conversions: // Note that Houdini's X axis points in the opposite direction that Unity's does. Also, Houdini's // rotation is right handed, whereas Unity is left handed. To account for this, we need to invert // the x coordinate of the translation, and do the same for the rotations (except for the x rotation, // which doesn't need to be flipped because the change in handedness AND direction of the left x axis // causes a double negative - yeah, I know). pos[0] = -hapi_transform.position[0]; pos[1] = hapi_transform.position[1]; pos[2] = hapi_transform.position[2]; Quaternion quat = new Quaternion(hapi_transform.rotationQuaternion[0], hapi_transform.rotationQuaternion[1], hapi_transform.rotationQuaternion[2], hapi_transform.rotationQuaternion[3]); Vector3 euler = quat.eulerAngles; euler.y = -euler.y; euler.z = -euler.z; quat = Quaternion.Euler(euler); Vector3 scale = new Vector3(hapi_transform.scale[0], hapi_transform.scale[1], hapi_transform.scale[2]); if (parent_object != null) { Matrix4x4 world_mat = Matrix4x4.identity; world_mat.SetTRS(pos, quat, scale); Matrix4x4 local_mat = parent_xform_inverse * world_mat; quat = HoudiniAssetUtility.getQuaternion(local_mat); scale = HoudiniAssetUtility.getScale(local_mat); pos = HoudiniAssetUtility.getPosition(local_mat); } HoudiniCurvesCollection curves = myCurveCollection; addKeyToCurve(curr_time, pos[0], curves.tx); addKeyToCurve(curr_time, pos[1], curves.ty); addKeyToCurve(curr_time, pos[2], curves.tz); addKeyToCurve(curr_time, quat.x, curves.qx); addKeyToCurve(curr_time, quat.y, curves.qy); addKeyToCurve(curr_time, quat.z, curves.qz); addKeyToCurve(curr_time, quat.w, curves.qw); addKeyToCurve(curr_time, scale.x, curves.sx); addKeyToCurve(curr_time, scale.y, curves.sy); addKeyToCurve(curr_time, scale.z, curves.sz); } catch (HoudiniError error) { Debug.LogWarning(error.ToString()); return; } }
public void instanceObjects( HoudiniProgressBar progress_bar ) { try { destroyChildren(); HAPI_ObjectInfo object_info = prAsset.prObjects[ prObjectId ]; // Get Detail info. HAPI_GeoInfo geo_info = new HAPI_GeoInfo(); HoudiniHost.getGeoInfo( prAsset.prAssetId, prObjectId, 0, out geo_info ); if ( geo_info.partCount == 0 ) return; cacheNumInstances(); HAPI_Transform[] instance_transforms = new HAPI_Transform[ myNumInstances ]; Utility.getArray4Id( prAsset.prAssetId, prObjectId, 0, HAPI_RSTOrder.HAPI_SRT, HoudiniHost.getInstanceTransforms, instance_transforms, myNumInstances ); // Get scale point attributes. HAPI_AttributeInfo scale_attr_info = new HAPI_AttributeInfo( "scale" ); float[] scale_attr = new float[ 0 ]; Utility.getAttribute( prAsset.prAssetId, prObjectId, 0, 0, "scale", ref scale_attr_info, ref scale_attr, HoudiniHost.getAttributeFloatData ); if ( scale_attr_info.exists && scale_attr_info.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT ) throw new HoudiniErrorIgnorable( "I only understand scale as point attributes!" ); if ( scale_attr_info.exists && scale_attr.Length != myNumInstances * 3 ) throw new HoudiniError( "Unexpected scale array length found for asset: " + prAsset.prAssetId + "!\n" + "Expected length of: " + myNumInstances * 3 + " but given: " + scale_attr.Length ); HAPI_AttributeInfo script_attr_info = new HAPI_AttributeInfo( "Unity_Script" ); int[] script_attr = new int[ 0 ]; Utility.getAttribute( prAsset.prAssetId, prObjectId, 0, 0, "Unity_Script", ref script_attr_info, ref script_attr, HoudiniHost.getAttributeStringData ); if ( script_attr_info.exists && script_attr_info.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT ) throw new HoudiniErrorIgnorable( "I only understand Unity_Script as point attributes!" ); if ( script_attr_info.exists && script_attr.Length != myNumInstances ) throw new HoudiniError( "Unexpected Unity_Script array length found for asset: " + prAsset.prAssetId + "!" ); int[] instance_attr = null; int[] name_attr = null; getInstanceAndNameAttrs(out instance_attr,out name_attr ); progress_bar.prTotal = myNumInstances; List <int> exclusion_list = new List<int>(); instanceOverriddenObjects( myNumInstances, exclusion_list ); List < string > unique_instantiated_names = new List< string >(); HoudiniInstancerPersistentData persistent_data = prPersistentData; if( persistent_data.variationChoice.Count != myNumInstances ) { if( myNumInstances > persistent_data.variationChoice.Count ) { int difference = myNumInstances - persistent_data.variationChoice.Count; for( int ii = 0; ii < difference; ii++ ) { persistent_data.variationChoice.Add( -1 ); } } else { int difference = persistent_data.variationChoice.Count - myNumInstances; persistent_data.variationChoice.RemoveRange( persistent_data.variationChoice.Count - difference, difference ); } } bool liveTransformPropagationSetting = false; bool syncAssetTransformSetting = false; bool enableCooking = true; for ( int ii = 0; ii < myNumInstances; ++ii ) { if ( exclusion_list.Contains( ii ) ) continue; GameObject objToInstantiate = null; if ( instance_attr.Length > 0 || name_attr.Length > 0 ) { if( name_attr.Length > 0 ) { string obj_name = HoudiniHost.getString( name_attr[ ii ] ); int object_index = prAsset.findObjectByName( obj_name ); if ( object_index >= 0 ) { objToInstantiate = prAsset.prGameObjects[ object_index ]; } else { objToInstantiate = prAsset.findPartByName( obj_name, true ); } if( objToInstantiate == null ) { objToInstantiate = GameObject.Find( obj_name ); } } else { string instanceObjectPath = HoudiniHost.getString( instance_attr[ ii ] ); string[] pathItems = instanceObjectPath.Split('/'); string instanceObjectName = pathItems[ pathItems.Length - 1 ]; int objectIndex = prAsset.findObjectByName( instanceObjectName ); if ( objectIndex >= 0 ) objToInstantiate = prAsset.prGameObjects[ objectIndex ]; else objToInstantiate = GameObject.Find( instanceObjectName ); } if ( objToInstantiate != null ) { HoudiniAsset hapi_asset = objToInstantiate.GetComponent< HoudiniAsset >(); if ( hapi_asset != null ) { liveTransformPropagationSetting = hapi_asset.prTransformChangeTriggersCooks; syncAssetTransformSetting = hapi_asset.prPushUnityTransformToHoudini; enableCooking = hapi_asset.prEnableCooking; hapi_asset.prTransformChangeTriggersCooks = false; hapi_asset.prPushUnityTransformToHoudini = false; hapi_asset.prEnableCooking = false; } } } else if ( object_info.objectToInstanceId >= 0 ) objToInstantiate = prAsset.prGameObjects[ object_info.objectToInstanceId ]; if ( objToInstantiate != null ) { // Set progress bar information. progress_bar.prCurrentValue = ii; progress_bar.prMessage = "Instancing: " + objToInstantiate.name + " (" + ii + " of " + myNumInstances + ")"; progress_bar.displayProgressBar(); if ( !unique_instantiated_names.Contains( objToInstantiate.name ) ) { unique_instantiated_names.Add( objToInstantiate.name ); } Vector3 pos = new Vector3(); // Apply object transforms. // // Axis and Rotation conversions: // Note that Houdini's X axis points in the opposite direction that Unity's does. Also, Houdini's // rotation is right handed, whereas Unity is left handed. To account for this, we need to invert // the x coordinate of the translation, and do the same for the rotations (except for the x rotation, // which doesn't need to be flipped because the change in handedness AND direction of the left x axis // causes a double negative - yeah, I know). pos[ 0 ] = -instance_transforms[ ii ].position[ 0 ]; pos[ 1 ] = instance_transforms[ ii ].position[ 1 ]; pos[ 2 ] = instance_transforms[ ii ].position[ 2 ]; Quaternion quat = new Quaternion( instance_transforms[ ii ].rotationQuaternion[ 0 ], instance_transforms[ ii ].rotationQuaternion[ 1 ], instance_transforms[ ii ].rotationQuaternion[ 2 ], instance_transforms[ ii ].rotationQuaternion[ 3 ] ); Vector3 euler = quat.eulerAngles; euler.y = -euler.y; euler.z = -euler.z; Vector3 scale = new Vector3 ( instance_transforms[ ii ].scale[ 0 ], instance_transforms[ ii ].scale[ 1 ], instance_transforms[ ii ].scale[ 2 ] ); Matrix4x4 local_mat = new Matrix4x4(); local_mat.SetTRS( pos, Quaternion.Euler( euler ), scale ); // TODO: Now this *should* be the transform.localToWorldMatrix // but for some reason, after a scene load, we pick up compensating // factors in the local transform that cancel out the transform on the // asset. For now just use the asset's transform as the parent matrix. Matrix4x4 parent_mat = prAsset.transform.localToWorldMatrix; Matrix4x4 global_mat = parent_mat * local_mat; euler = HoudiniAssetUtility.getQuaternion( global_mat ).eulerAngles; pos = HoudiniAssetUtility.getPosition( global_mat ); scale = HoudiniAssetUtility.getScale( global_mat ); //mat.SetTRS( pos, string script_to_attach = ""; if( script_attr_info.exists ) script_to_attach = HoudiniHost.getString( script_attr[ ii ] ); instanceObject( objToInstantiate, pos, euler, ii, scale_attr_info.exists, scale, script_attr_info.exists, script_to_attach ); HoudiniAsset hapi_asset = objToInstantiate.GetComponent< HoudiniAsset >(); if ( hapi_asset != null ) { hapi_asset.prTransformChangeTriggersCooks = liveTransformPropagationSetting; hapi_asset.prPushUnityTransformToHoudini = syncAssetTransformSetting; hapi_asset.prEnableCooking = enableCooking; } } } updateUniqueInstantiatedNames( unique_instantiated_names ); } catch ( HoudiniError error ) { Debug.LogWarning( error.ToString() ); return; } }
public void bakeAnimation( float curr_time, GameObject parent_object ) { try { HAPI_Transform[] instance_transforms = new HAPI_Transform[ myNumInstances ]; Utility.getArray4Id( prAsset.prAssetId, prObjectId, 0, HAPI_RSTOrder.HAPI_SRT, HoudiniHost.getInstanceTransforms, instance_transforms, myNumInstances ); Matrix4x4 parent_xform_inverse = Matrix4x4.identity; if( parent_object != null ) parent_xform_inverse = parent_object.transform.localToWorldMatrix.inverse; for ( int ii = 0; ii < myNumInstances; ++ii ) { Vector3 pos = new Vector3(); // Apply object transforms. // // Axis and Rotation conversions: // Note that Houdini's X axis points in the opposite direction that Unity's does. Also, Houdini's // rotation is right handed, whereas Unity is left handed. To account for this, we need to invert // the x coordinate of the translation, and do the same for the rotations (except for the x rotation, // which doesn't need to be flipped because the change in handedness AND direction of the left x axis // causes a double negative - yeah, I know). pos[ 0 ] = -instance_transforms[ ii ].position[ 0 ]; pos[ 1 ] = instance_transforms[ ii ].position[ 1 ]; pos[ 2 ] = instance_transforms[ ii ].position[ 2 ]; Quaternion quat = new Quaternion( instance_transforms[ ii ].rotationQuaternion[ 0 ], instance_transforms[ ii ].rotationQuaternion[ 1 ], instance_transforms[ ii ].rotationQuaternion[ 2 ], instance_transforms[ ii ].rotationQuaternion[ 3 ] ); Vector3 euler = quat.eulerAngles; euler.y = -euler.y; euler.z = -euler.z; quat = Quaternion.Euler( euler ); Vector3 scale = new Vector3 ( instance_transforms[ ii ].scale[ 0 ], instance_transforms[ ii ].scale[ 1 ], instance_transforms[ ii ].scale[ 2 ] ); if( parent_object != null ) { Matrix4x4 world_mat = Matrix4x4.identity; world_mat.SetTRS( pos, quat, scale ); Matrix4x4 local_mat = parent_xform_inverse * world_mat; quat = HoudiniAssetUtility.getQuaternion( local_mat ); scale = HoudiniAssetUtility.getScale( local_mat ); pos = HoudiniAssetUtility.getPosition( local_mat ); } HoudiniCurvesCollection curves = myCurvesCollection[ ii ]; HoudiniAssetUtility.addKeyToCurve( curr_time, pos[0], curves.tx ); HoudiniAssetUtility.addKeyToCurve( curr_time, pos[1], curves.ty ); HoudiniAssetUtility.addKeyToCurve( curr_time, pos[2], curves.tz ); HoudiniAssetUtility.addKeyToCurve( curr_time, quat.x, curves.qx ); HoudiniAssetUtility.addKeyToCurve( curr_time, quat.y, curves.qy ); HoudiniAssetUtility.addKeyToCurve( curr_time, quat.z, curves.qz ); HoudiniAssetUtility.addKeyToCurve( curr_time, quat.w, curves.qw ); HoudiniAssetUtility.addKeyToCurve( curr_time, scale.x, curves.sx ); HoudiniAssetUtility.addKeyToCurve( curr_time, scale.y, curves.sy ); HoudiniAssetUtility.addKeyToCurve( curr_time, scale.z, curves.sz ); } } catch ( HoudiniError error ) { Debug.LogWarning( error.ToString() ); return; } }
HAPI_ConvertMatrixToQuat( float[] mat, HAPI_RSTOrder rst_order, ref HAPI_Transform transform_out);
HAPI_ConvertTransformQuatToMatrix( ref HAPI_Transform transform, [Out] float[] matrix);
HAPI_ConvertMatrixToQuat( ref HAPI_Session session, float[] matrix, HAPI_RSTOrder rst_order, ref HAPI_Transform transform_out);
public virtual bool build( bool reload_asset, bool unload_asset_first, bool serialization_recovery_only, bool force_reconnect, bool is_duplication, bool cook_downstream_assets, bool use_delay_for_progress_bar ) { // We can only build or do anything if we can link to our libraries. #if !( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) return false; #pragma warning disable 0162 #endif // !( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) if ( !HoudiniHost.isInstallationOk() ) return false; if ( !prEnableCooking ) return false; if ( isPrefabInstance() ) processParentPrefab(); // Run post-cook hook. foreach ( var asset_hook in prAssetHooks ) asset_hook.preCook( this ); HoudiniProgressBar progress_bar = new HoudiniProgressBar(); progress_bar.prUseDelay = use_delay_for_progress_bar; progress_bar.prAsset = this; try { progress_bar.prStartTime = System.DateTime.Now; bool is_first_time_build = false; // restore asset id and asset validation id from the backup whenever // reverting a prefab instance bool is_reverting_prefab_instance = isRevertingPrefabInstance(); if ( is_reverting_prefab_instance ) { prAssetId = prBackupAssetId; prAssetValidationId = prBackupAssetValidationId; } if ( reload_asset ) { if ( unload_asset_first ) { // There's no reason to abort the whole rebuild process because we can't unload // the asset first as that would leave the user with no options other than // to delete this HAPI asset and create a new one for this OTL. try { HoudiniHost.destroyAsset( prAssetId ); } catch ( HoudiniError ) {} // Once an asset is unloaded its id will is obviously no longer valid, so reset it here. prAssetId = -1; // Need to reset the parms as well. prParms.reset(); } try { int asset_id = 0; if ( prAssetId < 0 ) is_first_time_build = true; if ( unload_asset_first ) asset_id = buildCreateAsset( progress_bar ); else asset_id = prAssetId; // We need to update the prAssetId in case the cook is aborted/fails // and we need to clean up (unload the asset) in the catch. prAssetId = asset_id; prAssetInfo = HoudiniHost.getAssetInfo( asset_id ); HAPI_NodeInfo node_info = HoudiniHost.getNodeInfo( prAssetInfo.nodeId ); if ( reload_asset ) Debug.Log( "Houdini Engine: Asset Loaded - ID: " + prAssetInfo.id + "\n" + " Full Name: " + prAssetInfo.fullOpName + "\n" + " Version: " + prAssetInfo.version + "\n" + " Unique Node Id: " + node_info.uniqueHoudiniNodeId + "\n" + " Internal Node Path: " + node_info.internalNodePath + "\n" + " Asset Library File: " + prAssetInfo.filePath + "\n" ); } catch ( HoudiniError error ) { Debug.LogError( "Asset not loaded: " + error.ToString() ); // Nothing to build since the load failed. // Try to unload the asset so it doesn't dangle. if ( is_first_time_build ) { try { HoudiniHost.destroyAsset( prAssetId ); } catch ( HoudiniError ) {} } // Clean up. reset(); // If in play mode, disable live cooks. #if UNITY_EDITOR if ( EditorApplication.isPlaying ) #endif // UNITY_EDITOR { prPlaymodePerFrameCooking = false; } return false; // false for failed :( } } prAssetInfo = HoudiniHost.getAssetInfo( prAssetId ); // For convenience we copy some asset info properties locally (since they are constant anyway). // More imporantly, structs are not serialized and therefore putting them into their own // variables is required in order to maintain state between serialization cycles. prAssetId = prAssetInfo.id; prBackupAssetId = prAssetId; prAssetValidationId = prAssetInfo.validationId; prBackupAssetValidationId = prAssetValidationId; prNodeId = prAssetInfo.nodeId; prObjectNodeId = prAssetInfo.objectNodeId; prObjectCount = prAssetInfo.objectCount; prHandleCount = prAssetInfo.handleCount; prAssetName = prAssetInfo.name; prAssetOpName = prAssetInfo.fullOpName; prAssetHelp = prAssetInfo.helpText; prHAPIAssetType = prAssetInfo.type; prTransformInputCount = prAssetInfo.transformInputCount; prGeoInputCount = prAssetInfo.geoInputCount; #if UNITY_EDITOR if ( isPrefab() ) { string prefab_path = AssetDatabase.GetAssetPath( GetInstanceID() ); HoudiniHost.myCleanUpPrefabAssets[ prefab_path ] = prAssetId; } #endif // UNITY_EDITOR // Try to load presets. if ( ( reload_asset && ( unload_asset_first || is_reverting_prefab_instance ) ) #if UNITY_EDITOR // Only load presets during serialization recovery if we really need to. // The only such case is when we made changes DURING playmode and Unity // restores the parameter values from before going into playmode. // We only save presets while NOT in playmode which means to restore // the Houdini state to before playmode state we need to loadPreset() // with the last saved preset. In all other cases, like going INTO // playmode, we should avoid this step because loadPreset() WILL // cause a cook regardless if the parameters have changed or not which // is terrible for large assets. || ( serialization_recovery_only && !EditorApplication.isPlayingOrWillChangePlaymode && !prParms.prValuesEqualToHoudini ) #endif // UNITY_EDITOR ) { loadPreset(); progress_bar.statusCheckLoop(); // Transform may not have been saved as part of the presets so we have to rely // on the serialized value. if ( myLastLocalToWorld != Matrix4x4.zero && !isPrefab() ) { // If this is a prefab instance being reverted we don't want to use the // serialized value so don't change transform. if ( !is_reverting_prefab_instance ) { Matrix4x4 world_to_local = Matrix4x4.identity; if ( transform.parent ) world_to_local = transform.parent.worldToLocalMatrix; Matrix4x4 local = myLastLocalToWorld * world_to_local; transform.localPosition = HoudiniAssetUtility.getPosition( local ); transform.localRotation = HoudiniAssetUtility.getQuaternion( local ); Vector3 scale = HoudiniAssetUtility.getScale( local ); if ( !( Mathf.Approximately( 0.0f, scale.x ) && Mathf.Approximately( 0.0f, scale.y ) && Mathf.Approximately( 0.0f, scale.z ) ) ) { transform.localScale = HoudiniAssetUtility.getScale( local ); } } if ( prPushUnityTransformToHoudini ) { pushAssetTransformToHoudini(); } } } if ( reload_asset ) { progress_bar.prCurrentValue = 0; progress_bar.prTotal = prObjectCount + prHandleCount; progress_bar.displayProgressBar(); myProgressBarJustUsed = true; // Add input fields. if ( is_first_time_build || !force_reconnect ) initAssetConnections(); // Clean up. destroyChildren( transform ); prGameObjects = new GameObject[ prObjectCount ]; } if ( reload_asset || serialization_recovery_only ) { // Need to re-acquire all the params for all the child controls that have parms exposed. prParms.getParameterValues(); foreach ( HoudiniParms parms in GetComponentsInChildren< HoudiniParms >() ) parms.getParameterValues(); // Custom work during a full build (custom to each subclass). buildFullBuildCustomWork( ref progress_bar, is_duplication ); } if ( !reload_asset && !serialization_recovery_only ) { progress_bar.displayProgressBar(); updateParameters( progress_bar ); } // Create local object info caches (transforms need to be stored in a parallel array). if ( prObjects == null || prObjects.Length != prObjectCount ) prObjects = new HAPI_ObjectInfo[ prObjectCount ]; if ( prObjectTransforms == null || prObjectTransforms.Length != prObjectCount ) prObjectTransforms = new HAPI_Transform[ prObjectCount ]; // Refresh object info arrays as they are lost after serialization. HoudiniAssetUtility.getArray1Id( prAssetId, HoudiniHost.getObjects, prObjects, prObjectCount ); HoudiniAssetUtility.getArray2Id( prAssetId, HAPI_RSTOrder.HAPI_SRT, HoudiniHost.getObjectTransforms, prObjectTransforms, prObjectCount ); bool objects_need_recook = false; if ( !serialization_recovery_only ) { // Set asset's transform. if ( prPushUnityTransformToHoudini ) HoudiniAssetUtility.getHoudiniTransformAndApply( prAssetId, prAssetName, transform ); progress_bar.prMessage = "Loading and composing objects..."; // Destroy/copy non-copiable but still serialized member data. if ( is_duplication ) { myAssetOTLUndoInfo = null; if ( myGeoAttributeManagerMap != null ) { myGeoAttributeManagerMap = myGeoAttributeManagerMap.copy(); myGeoAttributeManagerMap.name = prAssetName + "_GeoAttributeManagerMap"; } if ( myPresetsMap != null ) { myPresetsMap = myPresetsMap.clone(); myPresetsMap.name = prAssetName + "_PresetMap"; } } // Custom way to load objects (custom to each subclass). objects_need_recook = buildCreateObjects( reload_asset, ref progress_bar ); // Process dependent assets. if ( cook_downstream_assets ) processDependentAssets( serialization_recovery_only, force_reconnect, is_duplication, use_delay_for_progress_bar ); } // This tells Unity that values have been overridden for this prefab instance // (eg. asset id, validation id, node id, etc). #if UNITY_EDITOR if ( isPrefabInstance() ) PrefabUtility.RecordPrefabInstancePropertyModifications( this ); #endif // UNITY_EDITOR // A bit of a hack (but not terrible). If we have presets for other child controls // they set their presets by now so we need to rebuild with the new presets. if ( objects_need_recook ) { build( false, // reload_asset false, // unload_asset_first false, // serializatin_recovery_only false, // force_reconnect false, // is_duplication false, // cook_downstream_assets true // use_delay_for_progress_bar ); } } catch ( HoudiniErrorIgnorable ) {} catch ( HoudiniErrorProgressCancelled error ) { // If in play mode, disable live cooks. #if UNITY_EDITOR if ( EditorApplication.isPlaying ) #endif // UNITY_EDITOR { prPlaymodePerFrameCooking = false; } Debug.LogError( error.ToString() + "\nSource: " + error.Source ); } catch ( HoudiniError error ) { Debug.LogError( error.ToString() + "\nSource: " + error.Source ); } catch ( System.Exception error ) { Debug.LogError( error.ToString() + "\nSource: " + error.Source ); } finally { progress_bar.clearProgressBar(); myProgressBarJustUsed = false; // Run post-cook hook. foreach ( var asset_hook in prAssetHooks ) asset_hook.postCook( this ); } // We can only build or do anything if we can link to our libraries. #if !( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) #pragma warning restore 0162 #endif // !( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) return true; }
public void bakeAnimation(float curr_time, GameObject parent_object) { try { HAPI_GeoInfo geo_info = HoudiniHost.getDisplayGeoInfo(prObjectId); HAPI_Transform[] instance_transforms = new HAPI_Transform[myNumInstances]; Utility.getArray2Id( geo_info.nodeId, HAPI_RSTOrder.HAPI_SRT, HoudiniHost.getInstanceTransforms, instance_transforms, myNumInstances); Matrix4x4 parent_xform_inverse = Matrix4x4.identity; if (parent_object != null) { parent_xform_inverse = parent_object.transform.localToWorldMatrix.inverse; } for (int ii = 0; ii < myNumInstances; ++ii) { Vector3 pos = new Vector3(); // Apply object transforms. // // Axis and Rotation conversions: // Note that Houdini's X axis points in the opposite direction that Unity's does. Also, Houdini's // rotation is right handed, whereas Unity is left handed. To account for this, we need to invert // the x coordinate of the translation, and do the same for the rotations (except for the x rotation, // which doesn't need to be flipped because the change in handedness AND direction of the left x axis // causes a double negative - yeah, I know). pos[0] = -instance_transforms[ii].position[0]; pos[1] = instance_transforms[ii].position[1]; pos[2] = instance_transforms[ii].position[2]; Quaternion quat = new Quaternion(instance_transforms[ii].rotationQuaternion[0], instance_transforms[ii].rotationQuaternion[1], instance_transforms[ii].rotationQuaternion[2], instance_transforms[ii].rotationQuaternion[3]); Vector3 euler = quat.eulerAngles; euler.y = -euler.y; euler.z = -euler.z; quat = Quaternion.Euler(euler); Vector3 scale = new Vector3(instance_transforms[ii].scale[0], instance_transforms[ii].scale[1], instance_transforms[ii].scale[2]); if (parent_object != null) { Matrix4x4 world_mat = Matrix4x4.identity; world_mat.SetTRS(pos, quat, scale); Matrix4x4 local_mat = parent_xform_inverse * world_mat; quat = HoudiniAssetUtility.getQuaternion(local_mat); scale = HoudiniAssetUtility.getScale(local_mat); pos = HoudiniAssetUtility.getPosition(local_mat); } HoudiniCurvesCollection curves = myCurvesCollection[ii]; HoudiniAssetUtility.addKeyToCurve(curr_time, pos[0], curves.tx); HoudiniAssetUtility.addKeyToCurve(curr_time, pos[1], curves.ty); HoudiniAssetUtility.addKeyToCurve(curr_time, pos[2], curves.tz); HoudiniAssetUtility.addKeyToCurve(curr_time, quat.x, curves.qx); HoudiniAssetUtility.addKeyToCurve(curr_time, quat.y, curves.qy); HoudiniAssetUtility.addKeyToCurve(curr_time, quat.z, curves.qz); HoudiniAssetUtility.addKeyToCurve(curr_time, quat.w, curves.qw); HoudiniAssetUtility.addKeyToCurve(curr_time, scale.x, curves.sx); HoudiniAssetUtility.addKeyToCurve(curr_time, scale.y, curves.sy); HoudiniAssetUtility.addKeyToCurve(curr_time, scale.z, curves.sz); } } catch (HoudiniError error) { Debug.LogWarning(error.ToString()); return; } }
HAPI_ConvertMatrixToQuat( ref HAPI_Session session, float[] matrix, HAPI_RSTOrder rst_order, ref HAPI_Transform transform_out );
HAPI_ConvertTransformQuatToMatrix( ref HAPI_Session session, ref HAPI_Transform transform, [Out] float[] matrix );
private static extern HAPI_Result HAPI_ConvertMatrixToQuat( ref HAPI_Session session, float[] matrix, HAPI_RSTOrder rst_order, ref HAPI_Transform transform_out );