public override void OnInspectorGUI()
        {
            if (!isHoudiniGeoFile && !fileCheckPerformed)
            {
                string assetPath = AssetDatabase.GetAssetPath(target);
                isHoudiniGeoFile   = (assetPath.EndsWith(".geo"));
                fileCheckPerformed = true;
            }
            else if (!isHoudiniGeoFile)
            {
                return;
            }

            if (houdiniGeo == null)
            {
                string assetPath = AssetDatabase.GetAssetPath(target);
                string outDir    = Path.GetDirectoryName(assetPath);
                string assetName = Path.GetFileNameWithoutExtension(assetPath);

                // Parse geo
                string geoOutputPath = string.Format("{0}/{1}.asset", outDir, assetName);
                houdiniGeo          = AssetDatabase.LoadAllAssetsAtPath(geoOutputPath).Where(a => a is HoudiniGeo).FirstOrDefault() as HoudiniGeo;
                houdiniGeoInspector = Editor.CreateEditor(houdiniGeo);
            }

            if (houdiniGeoInspector != null)
            {
                GUI.enabled = true;
                houdiniGeoInspector.DrawDefaultInspector();
            }
        }
예제 #2
0
        public static bool HasAttribute(this HoudiniGeo geo, string attrName, HoudiniGeoAttributeOwner owner)
        {
            if (owner == HoudiniGeoAttributeOwner.Any)
            {
                return(geo.attributes.Any(a => a.name == attrName));
            }

            return(geo.attributes.Any(a => a.owner == owner && a.name == attrName));
        }
        private static void ParseAttributes(HoudiniGeo geo, JToken attributesValueToken)
        {
            // "attributes",[
            //      "vertexattributes",[
            //			[(attribute obj)],
            //			[(attribute obj)],
            //			...
            //      ],
            //      "pointattributes",[
            //			[(attribute obj)],
            //			[(attribute obj)],
            //			...
            //      ],
            //		...
            // ],

            if (ATTRIBUTES_TO_PARSE == null)
            {
                ATTRIBUTES_TO_PARSE = new Dictionary <string, HoudiniGeoAttributeOwner>();
                ATTRIBUTES_TO_PARSE.Add("vertexattributes", HoudiniGeoAttributeOwner.Vertex);
                ATTRIBUTES_TO_PARSE.Add("pointattributes", HoudiniGeoAttributeOwner.Point);
                ATTRIBUTES_TO_PARSE.Add("primitiveattributes", HoudiniGeoAttributeOwner.Primitive);
                ATTRIBUTES_TO_PARSE.Add("globalattributes", HoudiniGeoAttributeOwner.Detail);
            }

            Dictionary <string, JToken> attributeTokensDict = ArrayKeyValueToDictionary(attributesValueToken.Children().ToArray());

            // Parse each attribute group
            var geoAttributes = new List <HoudiniGeoAttribute>();

            foreach (var attrKeyVal in ATTRIBUTES_TO_PARSE)
            {
                string attrGroupKey = attrKeyVal.Key;
                HoudiniGeoAttributeOwner attrOwner = attrKeyVal.Value;

                JToken groupValueToken;
                if (attributeTokensDict.TryGetValue(attrGroupKey, out groupValueToken))
                {
                    // Parse each attribute in group
                    foreach (var attributeToken in groupValueToken.Children())
                    {
                        var attribute = ParseSingleAttribute(attributeToken, attrOwner);
                        if (attribute != null)
                        {
                            geoAttributes.Add(attribute);
                        }
                    }
                }
            }

            geo.attributes = geoAttributes.ToArray();
        }
예제 #4
0
 public static bool TryGetAttribute(this HoudiniGeo geo, string attrName, HoudiniGeoAttributeType type,
                                    HoudiniGeoAttributeOwner owner, out HoudiniGeoAttribute attr)
 {
     if (owner == HoudiniGeoAttributeOwner.Any)
     {
         attr = geo.attributes.FirstOrDefault(a => a.type == type && a.name == attrName);
     }
     else
     {
         attr = geo.attributes.FirstOrDefault(a => a.owner == owner && a.type == type && a.name == attrName);
     }
     return(attr != null);
 }
        private static void ParseTopology(HoudiniGeo geo, JToken topologyValueToken)
        {
            //"topology",[
            //   "pointref",[
            //      "indices",[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
            //   ]
            //],

            Dictionary <string, JToken> topologyDict = ArrayKeyValueToDictionary(topologyValueToken.Children().ToArray());
            Dictionary <string, JToken> pointRefDict = ArrayKeyValueToDictionary(topologyDict["pointref"].Children().ToArray());

            geo.pointRefs = pointRefDict["indices"].Values <int>().ToArray();
        }
        private static HoudiniGeo ParseInternal(string assetPath, HoudiniGeo existingGeo = null)
        {
            if (!File.Exists(assetPath))
            {
                throw new FileNotFoundException("File not found: " + assetPath);
            }

            // Parse the json
            JToken mainToken = null;

            try
            {
                mainToken = JToken.Parse(File.ReadAllText(assetPath));
            }
            catch (System.Exception e)
            {
                Debug.LogError(string.Format("HoudiniGeoParseError: JSON in file '{0}' could not be parsed", assetPath));
                throw e;
            }

            // The houdini geo format expects the main element to be an array
            if (mainToken.Type != JTokenType.Array)
            {
                throw new HoudiniGeoParseException("Unexpected type in geo json.");
            }

            // The main element is an array that actually functions as a dictionary!
            Dictionary <string, JToken> geoDataDict = ArrayKeyValueToDictionary(mainToken.Children().ToArray());

            HoudiniGeo houdiniGeo = existingGeo;

            if (houdiniGeo == null)
            {
                houdiniGeo = ScriptableObject.CreateInstance <HoudiniGeo>();
            }
            houdiniGeo.sourceAsset = AssetDatabase.LoadMainAssetAtPath(assetPath);

            houdiniGeo.fileVersion = geoDataDict["fileversion"].ValueSafe <string>();
            houdiniGeo.pointCount  = geoDataDict["pointcount"].ValueSafe <int>();
            houdiniGeo.vertexCount = geoDataDict["vertexcount"].ValueSafe <int>();
            houdiniGeo.primCount   = geoDataDict["primitivecount"].ValueSafe <int>();

            houdiniGeo.fileInfo = ParseFileInfo(geoDataDict["info"] as JObject);

            ParseTopology(houdiniGeo, geoDataDict["topology"]);
            ParseAttributes(houdiniGeo, geoDataDict["attributes"]);
            ParsePrimitives(houdiniGeo, geoDataDict["primitives"]);

            return(houdiniGeo);
        }
예제 #7
0
        internal static void ImportAllMeshes(this HoudiniGeo geo)
        {
            string geoAssetPath = AssetDatabase.GetAssetPath(geo);

            if (!File.Exists(geoAssetPath))
            {
                return;
            }

            // Convert to unity mesh and store mesh as sub asset
            if (geo.polyPrimitives.Length > 0)
            {
                var mesh = AssetDatabase.LoadAllAssetsAtPath(geoAssetPath).Where(a => a is Mesh).FirstOrDefault() as Mesh;
                if (mesh == null)
                {
                    mesh = new Mesh();
                    AssetDatabase.AddObjectToAsset(mesh, geoAssetPath);
                }

                geo.ToUnityMesh(mesh);
                EditorUtility.SetDirty(mesh);
            }
        }
예제 #8
0
        public static void ToUnityMesh(this HoudiniGeo geo, Mesh mesh)
        {
            if (geo.polyPrimitives.Length == 0)
            {
                Debug.LogError("Cannot convert HoudiniGeo to Mesh because geo has no PolyPrimitives");
                return;
            }

            mesh.name = geo.name;
            int[] indices     = geo.polyPrimitives.SelectMany(p => p.indices).ToArray();
            int   vertexCount = indices.Length;

            if (vertexCount > 65000)
            {
                throw new Exception(string.Format("Vertex count ({0}) exceeds limit of {1}!", geo.vertexCount, 65000));
            }

            // Check if position attribute P exists
            HoudiniGeoAttribute posAttr = null;

            if (!geo.TryGetAttribute(HoudiniGeo.POS_ATTR_NAME, HoudiniGeoAttributeType.Float, out posAttr))
            {
                Debug.LogWarning("HoudiniGEO has no Position attribute on points or vertices");
            }

            // Get Vertex/Point positions
            Vector3[] posAttrValues = null;
            posAttr.GetValues(out posAttrValues);

            // Get uv attribute values
            HoudiniGeoAttribute uvAttr = null;

            Vector2[] uvAttrValues = null;
            if (geo.TryGetAttribute(HoudiniGeo.UV_ATTR_NAME, HoudiniGeoAttributeType.Float, out uvAttr))
            {
                uvAttr.GetValues(out uvAttrValues);
            }

            // Get uv2 attribute values
            HoudiniGeoAttribute uv2Attr = null;

            Vector2[] uv2AttrValues = null;
            if (geo.TryGetAttribute(HoudiniGeo.UV2_ATTR_NAME, HoudiniGeoAttributeType.Float, out uv2Attr))
            {
                uv2Attr.GetValues(out uv2AttrValues);
            }

            // Get normal attribute values
            HoudiniGeoAttribute normalAttr = null;

            Vector3[] normalAttrValues = null;
            if (geo.TryGetAttribute(HoudiniGeo.NORMAL_ATTR_NAME, HoudiniGeoAttributeType.Float, out normalAttr))
            {
                normalAttr.GetValues(out normalAttrValues);
            }

            // Get color attribute values
            HoudiniGeoAttribute colorAttr = null;

            Color[] colorAttrValues = null;
            if (geo.TryGetAttribute(HoudiniGeo.COLOR_ATTR_NAME, HoudiniGeoAttributeType.Float, out colorAttr))
            {
                colorAttr.GetValues(out colorAttrValues);

                // Get alpha color values
                HoudiniGeoAttribute alphaAttr       = null;
                float[]             alphaAttrValues = null;
                if (geo.TryGetAttribute(HoudiniGeo.ALPHA_ATTR_NAME, HoudiniGeoAttributeType.Float, colorAttr.owner, out alphaAttr))
                {
                    alphaAttr.GetValues(out alphaAttrValues);

                    if (colorAttrValues.Length == alphaAttrValues.Length)
                    {
                        for (int i = 0; i < colorAttrValues.Length; i++)
                        {
                            colorAttrValues[i].a = alphaAttrValues[i];
                        }
                    }
                }
            }

            // Get tangent attribute values
            HoudiniGeoAttribute tangentAttr = null;

            Vector3[] tangentAttrValues = null;
            if (geo.TryGetAttribute(HoudiniGeo.TANGENT_ATTR_NAME, HoudiniGeoAttributeType.Float, out tangentAttr))
            {
                tangentAttr.GetValues(out tangentAttrValues);
            }

            // Get material primitive attribute (Multiple materials result in multiple submeshes)
            HoudiniGeoAttribute materialAttr = null;

            string[] materialAttributeValues = null;
            if (geo.TryGetAttribute(HoudiniGeo.MATERIAL_ATTR_NAME, HoudiniGeoAttributeType.String, HoudiniGeoAttributeOwner.Primitive, out materialAttr))
            {
                materialAttr.GetValues(out materialAttributeValues);
            }

            // Create our mesh attribute buffers
            var submeshInfo = new Dictionary <string, List <int> >();
            var positions   = new Vector3[vertexCount];
            var uvs         = new Vector2[vertexCount]; // unity doesn't like it when meshes have no uvs
            var uvs2        = (uv2Attr != null) ? new Vector2[vertexCount] : null;
            var normals     = (normalAttr != null) ? new Vector3[vertexCount] : null;
            var colors      = (colorAttr != null) ? new Color[vertexCount] : null;
            var tangents    = (tangentAttr != null) ? new Vector4[vertexCount] : null;

            // Fill the mesh buffers
            int[] vertToPoint = geo.pointRefs;
            Dictionary <int, int> vertIndexGlobalToLocal = new Dictionary <int, int>();

            for (int i = 0; i < vertexCount; ++i)
            {
                int vertIndex  = indices[i];
                int pointIndex = vertToPoint[vertIndex];
                vertIndexGlobalToLocal.Add(vertIndex, i);

                // Position
                switch (posAttr.owner)
                {
                case HoudiniGeoAttributeOwner.Vertex:
                    positions[i] = posAttrValues[vertIndex];
                    break;

                case HoudiniGeoAttributeOwner.Point:
                    positions[i] = posAttrValues[pointIndex];
                    break;
                }

                // UV1
                if (uvAttr != null)
                {
                    switch (uvAttr.owner)
                    {
                    case HoudiniGeoAttributeOwner.Vertex:
                        uvs[i] = uvAttrValues[vertIndex];
                        break;

                    case HoudiniGeoAttributeOwner.Point:
                        uvs[i] = uvAttrValues[pointIndex];
                        break;
                    }
                }
                else
                {
                    // Unity likes to complain when a mesh doesn't have any UVs so we'll just add a default
                    uvs[i] = Vector2.zero;
                }

                // UV2
                if (uv2Attr != null)
                {
                    switch (uv2Attr.owner)
                    {
                    case HoudiniGeoAttributeOwner.Vertex:
                        uvs2[i] = uv2AttrValues[vertIndex];
                        break;

                    case HoudiniGeoAttributeOwner.Point:
                        uvs2[i] = uv2AttrValues[pointIndex];
                        break;
                    }
                }

                // Normals
                if (normalAttr != null)
                {
                    switch (normalAttr.owner)
                    {
                    case HoudiniGeoAttributeOwner.Vertex:
                        normals[i] = normalAttrValues[vertIndex];
                        break;

                    case HoudiniGeoAttributeOwner.Point:
                        normals[i] = normalAttrValues[pointIndex];
                        break;
                    }
                }

                // Colors
                if (colorAttr != null)
                {
                    switch (colorAttr.owner)
                    {
                    case HoudiniGeoAttributeOwner.Vertex:
                        colors[i] = colorAttrValues[vertIndex];
                        break;

                    case HoudiniGeoAttributeOwner.Point:
                        colors[i] = colorAttrValues[pointIndex];
                        break;
                    }
                }

                // Fill tangents info
                if (tangentAttr != null)
                {
                    switch (tangentAttr.owner)
                    {
                    case HoudiniGeoAttributeOwner.Vertex:
                        tangents[i] = tangentAttrValues[vertIndex];
                        break;

                    case HoudiniGeoAttributeOwner.Point:
                        tangents[i] = tangentAttrValues[pointIndex];
                        break;
                    }
                }
            }

            // Get primitive attribute values and created submeshes
            foreach (var polyPrim in geo.polyPrimitives)
            {
                // Normals
                if (normalAttr != null && normalAttr.owner == HoudiniGeoAttributeOwner.Primitive)
                {
                    foreach (var vertIndex in polyPrim.indices)
                    {
                        int localVertIndex = vertIndexGlobalToLocal[vertIndex];
                        normals[localVertIndex] = normalAttrValues[polyPrim.id];
                    }
                }

                // Colors
                if (colorAttr != null && colorAttr.owner == HoudiniGeoAttributeOwner.Primitive)
                {
                    foreach (var vertIndex in polyPrim.indices)
                    {
                        int localVertIndex = vertIndexGlobalToLocal[vertIndex];
                        colors[localVertIndex] = colorAttrValues[polyPrim.id];
                    }
                }

                // Add face to submesh based on material attribute
                var materialName = (materialAttr == null) ? HoudiniGeo.DEFAULT_MATERIAL_NAME : materialAttributeValues[polyPrim.id];
                if (!submeshInfo.ContainsKey(materialName))
                {
                    submeshInfo.Add(materialName, new List <int>());
                }
                submeshInfo[materialName].AddRange(polyPrim.triangles);
            }

            // Assign buffers to mesh
            mesh.vertices     = positions;
            mesh.subMeshCount = submeshInfo.Count;
            mesh.uv           = uvs;
            mesh.uv2          = uvs2;
            mesh.normals      = normals;
            mesh.colors       = colors;
            mesh.tangents     = tangents;

            // Set submesh indexbuffers
            int submeshIndex = 0;

            foreach (var item in submeshInfo)
            {
                // Skip empty submeshes
                if (item.Value.Count == 0)
                {
                    continue;
                }

                // Set the indices for the submesh (Reversed by default because axis coordinates Z flipped)
                IEnumerable <int> submeshIndices = item.Value;
                if (!geo.importSettings.reverseWinding)
                {
                    submeshIndices = submeshIndices.Reverse();
                }
                mesh.SetIndices(submeshIndices.ToArray(), MeshTopology.Triangles, submeshIndex);

                submeshIndex++;
            }

            // Calculate any missing buffers
            mesh.ConvertToUnityCoordinates();
            mesh.RecalculateBounds();
            if (normalAttr == null)
            {
                mesh.RecalculateNormals();
            }
        }
예제 #9
0
 public static bool TryGetAttribute(this HoudiniGeo geo, string attrName, HoudiniGeoAttributeType type, out HoudiniGeoAttribute attr)
 {
     attr = geo.attributes.FirstOrDefault(a => a.type == type && a.name == attrName);
     return(attr != null);
 }
 public static void ParseInto(string assetPath, HoudiniGeo existingGeo)
 {
     ParseInternal(assetPath, existingGeo);
 }
        private static void ParsePrimitives(HoudiniGeo geo, JToken primitivesValueToken)
        {
            // Polygon Mesh
            // Only type: "run", runtiype: "Poly" supported for now.
            //
            // "primitives",[
            //      [
            //          [Header],
            //          [Body]
            //      ],
            //      [
            //          [Header],
            //          [Body]
            //      ],
            //		...
            // ],

            int primIdCounter = 0;

            var polyPrimitives        = new List <PolyPrimitive>();
            var bezierCurvePrimitives = new List <BezierCurvePrimitive>();
            var nurbCurvePrimitives   = new List <NURBCurvePrimitive>();

            foreach (var primitiveToken in primitivesValueToken.Children())
            {
                // Primitive [[Header], [Body]]
                //[
                //	[
                //		"type","run",
                //		"runtype","Poly",
                //		"varyingfields",["vertex"],
                //		"uniformfields",{
                //		"closed":true
                //		}
                //	],
                //	[
                //		[[0,1,2,3]],
                //		[[4,5,6,7]],
                //		[[8,9,10,11]],
                //		[[12,13,14,15]],
                //		...
                //	]
                //]

                JToken[] childBlockTokens = primitiveToken.Children().ToArray();
                JToken   headerToken      = childBlockTokens[0];
                JToken   bodyToken        = childBlockTokens[1];

                // Parse header
                Dictionary <string, JToken> headerDict = ArrayKeyValueToDictionary(headerToken.Children().ToArray());
                string type = headerDict["type"].Value <string>();

                // Parse RunType primitives
                if (type == "run")
                {
                    string runType = headerDict["runtype"].Value <string>();
                    switch (runType)
                    {
                    case "Poly":
                        polyPrimitives.AddRange(ParsePolyPrimitiveGroup(headerDict, bodyToken, primIdCounter));
                        break;

                    case "BezierCurve":
                        //bezierCurvePrimitives.AddRange(primitives);
                        break;

                    case "NURBCurve":
                        //nurbCurvePrimitives.AddRange(primitives);
                        break;
                    }
                }
            }

            geo.polyPrimitives        = polyPrimitives.ToArray();
            geo.bezierCurvePrimitives = bezierCurvePrimitives.ToArray();
            geo.nurbCurvePrimitives   = nurbCurvePrimitives.ToArray();
        }