public override void AbcGetConfig(ref AbcAPI.aiConfig config) { if (m_normalsMode != AbcAPI.aiNormalsModeOverride.InheritStreamSetting) { config.normalsMode = (AbcAPI.aiNormalsMode)m_normalsMode; } if (m_tangentsMode != AbcAPI.aiTangentsModeOverride.InheritStreamSetting) { config.tangentsMode = (AbcAPI.aiTangentsMode)m_tangentsMode; } if (m_faceWinding != AbcAPI.aiFaceWindingOverride.InheritStreamSetting) { config.swapFaceWinding = (m_faceWinding == AbcAPI.aiFaceWindingOverride.Swap); } config.cacheTangentsSplits = m_cacheTangentsSplits; // if 'forceUpdate' is set true, even if alembic sample data do not change at all // AbcSampleUpdated will still be called (topologyChanged will be false) AlembicMaterial abcMaterials = m_trans.GetComponent <AlembicMaterial>(); config.forceUpdate = m_freshSetup || (abcMaterials != null ? abcMaterials.HasFacesetsChanged() : hasFacesets); }
public override void AbcSampleUpdated(AbcAPI.aiSample sample, bool topologyChanged) { AlembicMaterial abcMaterials = m_trans.GetComponent <AlembicMaterial>(); if (abcMaterials != null) { if (abcMaterials.HasFacesetsChanged()) { AbcVerboseLog("AlembicMesh.AbcSampleUpdated: Facesets updated, force topology update"); topologyChanged = true; } hasFacesets = (abcMaterials.GetFacesetsCount() > 0); } else if (hasFacesets) { AbcVerboseLog("AlembicMesh.AbcSampleUpdated: Facesets cleared, force topology update"); topologyChanged = true; hasFacesets = false; } if (m_freshSetup) { topologyChanged = true; m_freshSetup = false; } AbcAPI.aiPolyMeshGetSampleSummary(sample, ref m_sampleSummary, topologyChanged); AbcAPI.aiPolyMeshData vertexData = default(AbcAPI.aiPolyMeshData); UpdateSplits(m_sampleSummary.splitCount); for (int s = 0; s < m_sampleSummary.splitCount; ++s) { Split split = m_splits[s]; split.clear = topologyChanged; split.active = true; int vertexCount = AbcAPI.aiPolyMeshGetVertexBufferLength(sample, s); Array.Resize(ref split.positionCache, vertexCount); vertexData.positions = GetArrayPtr(split.positionCache); if (m_sampleSummary.hasNormals) { Array.Resize(ref split.normalCache, vertexCount); vertexData.normals = GetArrayPtr(split.normalCache); } else { Array.Resize(ref split.normalCache, 0); vertexData.normals = IntPtr.Zero; } if (m_sampleSummary.hasUVs) { Array.Resize(ref split.uvCache, vertexCount); vertexData.uvs = GetArrayPtr(split.uvCache); } else { Array.Resize(ref split.uvCache, 0); vertexData.uvs = IntPtr.Zero; } if (m_sampleSummary.hasTangents) { Array.Resize(ref split.tangentCache, vertexCount); vertexData.tangents = GetArrayPtr(split.tangentCache); } else { Array.Resize(ref split.tangentCache, 0); vertexData.tangents = IntPtr.Zero; } AbcAPI.aiPolyMeshFillVertexBuffer(sample, s, ref vertexData); split.center = vertexData.center; split.size = vertexData.size; } if (topologyChanged) { AbcAPI.aiFacesets facesets = default(AbcAPI.aiFacesets); AbcAPI.aiSubmeshSummary submeshSummary = default(AbcAPI.aiSubmeshSummary); AbcAPI.aiSubmeshData submeshData = default(AbcAPI.aiSubmeshData); if (abcMaterials != null) { abcMaterials.GetFacesets(ref facesets); } int numSubmeshes = AbcAPI.aiPolyMeshPrepareSubmeshes(sample, ref facesets); if (m_submeshes.Count > numSubmeshes) { m_submeshes.RemoveRange(numSubmeshes, m_submeshes.Count - numSubmeshes); } for (int s = 0; s < m_sampleSummary.splitCount; ++s) { m_splits[s].submeshCount = AbcAPI.aiPolyMeshGetSplitSubmeshCount(sample, s); } while (AbcAPI.aiPolyMeshGetNextSubmesh(sample, ref submeshSummary)) { if (submeshSummary.splitIndex >= m_splits.Count) { Debug.Log("Invalid split index"); continue; } Submesh submesh = null; if (submeshSummary.index < m_submeshes.Count) { submesh = m_submeshes[submeshSummary.index]; } else { submesh = new Submesh { indexCache = new int[0], facesetIndex = -1, splitIndex = -1, index = -1, update = true }; m_submeshes.Add(submesh); } submesh.facesetIndex = submeshSummary.facesetIndex; submesh.splitIndex = submeshSummary.splitIndex; submesh.index = submeshSummary.splitSubmeshIndex; submesh.update = true; Array.Resize(ref submesh.indexCache, 3 * submeshSummary.triangleCount); submeshData.indices = GetArrayPtr(submesh.indexCache); AbcAPI.aiPolyMeshFillSubmeshIndices(sample, ref submeshSummary, ref submeshData); } if (abcMaterials != null) { abcMaterials.AknowledgeFacesetsChanges(); } } else { for (int i = 0; i < m_submeshes.Count; ++i) { m_submeshes[i].update = false; } } AbcDirty(); }
public void OnGUI() { float hp = 5; float vp = 5; float hs = 5; float rh = 16; float lw; float fw; float bw; Rect r; // Material assignment file controls r = NewControlRect(true, rh, hp, vp); lw = r.width * 0.33f; EditorGUI.PrefixLabel(new Rect(r.x, r.y, lw, r.height), new GUIContent("Assignments File")); bw = 26; fw = r.width - lw - bw - 2 * hs; xmlPath = EditorGUI.TextField(new Rect(r.x + lw + hs, r.y, fw, r.height), xmlPath); if (GUI.Button(new Rect(r.x + lw + hs + fw + hs, r.y, bw, r.height), "...")) { string startFolder = (xmlPath.Length > 0 ? Path.GetDirectoryName(xmlPath) : Application.dataPath); xmlPath = MakeDataRelativePath(EditorUtility.OpenFilePanel("Select Material Assignment File", startFolder, "xml")); if (xmlPath.Length > 0) { materialFolder = Path.GetDirectoryName(xmlPath); } } // Material folder controls r = NewControlRect(true, rh, hp, vp); lw = r.width * 0.33f; EditorGUI.PrefixLabel(new Rect(r.x, r.y, lw, r.height), new GUIContent("Materials Folder")); bw = 26; fw = r.width - lw - bw - 2 * hs; materialFolder = EditorGUI.TextField(new Rect(r.x + lw + hs, r.y, fw, r.height), materialFolder); if (GUI.Button(new Rect(r.x + lw + hs + fw + hs, r.y, bw, r.height), "...")) { string startFolder = (materialFolder.Length > 0 ? materialFolder : Application.dataPath); materialFolder = MakeDataRelativePath(EditorUtility.OpenFolderPanel("Select Materials Folder", startFolder, "")); } // Target asset node controls r = NewControlRect(true, rh, hp, vp); lw = r.width * 0.33f; EditorGUI.PrefixLabel(new Rect(r.x, r.y, lw, r.height), new GUIContent("Asset Root")); fw = r.width - lw - hs; assetRoot = (GameObject)EditorGUI.ObjectField(new Rect(r.x + lw + hs, r.y, fw, r.height), assetRoot, typeof(GameObject), true); // Action buttons r = NewControlRect(false, rh, hp, vp); bw = 0.5f * (r.width - hs); if (GUI.Button(new Rect(r.x, r.y, bw, r.height), "Import")) { AlembicMaterial.Import(Application.dataPath + "/" + xmlPath, assetRoot, "Assets/" + materialFolder); //relMatFolder); } if (GUI.Button(new Rect(r.x + bw + hs, r.y, bw, r.height), "Export")) { AlembicMaterial.Export(Application.dataPath + "/" + xmlPath, assetRoot); } }
public static void Import(string xmlPath, GameObject root, string materialFolder) { XmlDocument doc = new XmlDocument(); doc.Load(xmlPath); XmlNode xmlRoot = doc.DocumentElement; XmlNodeList nodes = xmlRoot.SelectNodes("/assignments/node"); Dictionary <GameObject, List <AlembicMaterial.Assignment> > allAssignments = new Dictionary <GameObject, List <AlembicMaterial.Assignment> >(); foreach (XmlNode node in nodes) { string path = node.Attributes["path"].Value; XmlNodeList shaders = node.SelectNodes("shader"); foreach (XmlNode shader in shaders) { XmlAttribute name = shader.Attributes["name"]; XmlAttribute inst = shader.Attributes["instance"]; if (name == null) { continue; } int instNum = (inst == null ? 0 : Convert.ToInt32(inst.Value)); GameObject target = FindNode(root, path, instNum); if (target == null) { // Debug.Log("Could not find node: " + path); continue; } List <AlembicMaterial.Assignment> assignments; if (!allAssignments.ContainsKey(target)) { assignments = new List <AlembicMaterial.Assignment>(); allAssignments.Add(target, assignments); } else { assignments = allAssignments[target]; } Material material = GetMaterial(name.Value, materialFolder); if (material == null) { material = new Material(Shader.Find("Standard")); material.color = new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value); AssetDatabase.CreateAsset(material, materialFolder + "/" + name.Value + ".mat"); } // Get or create material assignment bool newlyAssigned = false; AlembicMaterial.Assignment a = null; if (a == null) { a = new AlembicMaterial.Assignment(); a.material = material; a.faces = new List <int>(); assignments.Add(a); newlyAssigned = true; } string faceset = shader.InnerText; faceset.Trim(); if (faceset.Length > 0 && (newlyAssigned || a.faces.Count > 0)) { string[] items = faceset.Split(FaceSep, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < items.Length; ++i) { string[] rng = items[i].Split(RangeSep, StringSplitOptions.RemoveEmptyEntries); if (rng.Length == 1) { a.faces.Add(Convert.ToInt32(rng[0])); } else if (rng.Length == 2) { int j0 = Convert.ToInt32(rng[0]); int j1 = Convert.ToInt32(rng[1]); for (int j = j0; j <= j1; ++j) { a.faces.Add(j); } } } if (!newlyAssigned) { a.faces = new List <int>(new HashSet <int>(a.faces)); } } else if (faceset.Length == 0 && a.faces.Count > 0) { // Shader assgined to whole object, remove any face level assignments a.faces.Clear(); } } } // Update AlembicMaterial components foreach (KeyValuePair <GameObject, List <AlembicMaterial.Assignment> > pair in allAssignments) { AlembicMaterial abcmaterial = pair.Key.GetComponent <AlembicMaterial>(); if (abcmaterial == null) { abcmaterial = pair.Key.AddComponent <AlembicMaterial>(); } abcmaterial.UpdateAssignments(pair.Value); } // Force refresh AlembicStream abcstream = root.GetComponent <AlembicStream>(); if (abcstream != null) { abcstream.m_forceRefresh = true; abcstream.SendMessage("AbcUpdate", abcstream.m_time, SendMessageOptions.DontRequireReceiver); } }