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; } }
protected override bool buildCreateObjects(bool reload_asset, ref HoudiniProgressBar progress_bar) { bool needs_recook = false; for (int object_index = 0; object_index < prObjectCount; ++object_index) { progress_bar.incrementProgressBar(); try { if (!prObjects[object_index].isInstancer && (reload_asset || prObjects[object_index].hasTransformChanged || prObjects[object_index].haveGeosChanged)) { needs_recook |= createObject(object_index, reload_asset); } } catch (HoudiniError error) { // Per-object errors are not re-thrown so that the rest of the asset has a chance to load. Debug.LogWarning(error.ToString()); } } // Processing instancers. for (int object_index = 0; object_index < prObjectCount; ++object_index) { HAPI_ObjectInfo object_info = prObjects[object_index]; if (object_info.isInstancer) { try { if (object_info.objectToInstanceId >= 0) { int instanced_object_index = findObjectByNodeId(object_info.objectToInstanceId); if (instanced_object_index >= 0) { needs_recook |= createObject(instanced_object_index, reload_asset); } } if (reload_asset || object_info.haveGeosChanged) { instanceObjects(object_info.nodeId, object_index, progress_bar); } } catch (HoudiniError error) { // Per-object errors are not re-thrown so that the rest of the asset has a chance to load. Debug.LogWarning(error.ToString()); } } } if (prObjectCount <= 0) { bool needs_init = prObjectInfo.nodeId < 0 || reload_asset; if (prNodeInfo.type == HAPI_NodeType.HAPI_NODETYPE_OBJ) { prObjectInfo = HoudiniHost.getObjectInfo(prAssetId); } else if (prNodeInfo.type == HAPI_NodeType.HAPI_NODETYPE_SOP) { prObjectInfo = HoudiniHost.getObjectInfo(prNodeInfo.parentId); } else { Debug.LogError("Unsupported asset type!"); return(needs_recook); } if (needs_init) { init( prAssetId, prNodeId, prAsset, prObjectInfo.nodeId, prObjectInfo.name, prObjectInfo.isVisible); } needs_recook = refresh(reload_asset, prObjectInfo); } // Enumerate edit and paint geos. HoudiniGeoControl[] geo_controls = gameObject.GetComponentsInChildren <HoudiniGeoControl>(); prEditPaintGeos.Clear(); foreach (HoudiniGeoControl geo_control in geo_controls) { if (geo_control.prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE && geo_control.GetType() == typeof(HoudiniGeoControl)) { prEditPaintGeos.Add(geo_control); } } if (prEditPaintGeos.Count > 0 && prActiveAttributeManager == null) { prActiveAttributeManager = prEditPaintGeos[0].prGeoAttributeManager; } return(needs_recook); }
public void createObject(int object_id, int geo_id) { HAPI_ObjectInfo object_info = HoudiniHost.getObjectInfo(object_id); try { // Get position attributes (this is all we get for the curve's geometry). HAPI_AttributeInfo pos_attr_info = new HAPI_AttributeInfo(HoudiniConstants.HAPI_ATTRIB_POSITION); float[] pos_attr = new float[0]; HoudiniAssetUtility.getAttribute( geo_id, 0, HoudiniConstants.HAPI_ATTRIB_POSITION, ref pos_attr_info, ref pos_attr, HoudiniHost.getAttributeFloatData); if (!pos_attr_info.exists) { throw new HoudiniError("No position attribute found."); } int vertex_count = pos_attr_info.count; // Add vertices to the vertices array for guides. prVertices = new Vector3[vertex_count]; for (int i = 0; i < vertex_count; ++i) { for (int j = 0; j < 3; ++j) { prVertices[i][j] = pos_attr[i * 3 + j]; } prVertices[i].x = -prVertices[i].x; } // Set the Mesh Filter. if (gameObject.GetComponent <MeshFilter>() == null) { MeshFilter mesh_filter = gameObject.AddComponent <MeshFilter>(); mesh_filter.sharedMesh = new Mesh(); } // Set the Mesh Renderer. if (gameObject.GetComponent <MeshRenderer>() == null) { MeshRenderer mesh_renderer = gameObject.AddComponent <MeshRenderer>(); // This prevents curve from appearing in game (applies to entire game object). // Need this because the HAPI line shader doesn't work when building. mesh_renderer.tag = "EditorOnly"; // Set generic texture so it's not pink. Material line_material = new Material(Shader.Find("Houdini/Line")); mesh_renderer.material = line_material; } // Create guide and selection meshes. buildDummyMesh(); #if UNITY_EDITOR AssetDatabase.Refresh(); #endif // UNITY_EDITOR } catch (HoudiniError error) { error.addMessagePrefix("Obj(id: " + object_info.nodeId + ", name: " + object_info.name + ")"); error.addMessageDetail("Object Path: " + object_info.objectInstancePath); throw; } }