Пример #1
0
        private static void GetValues(this HoudiniGeoAttribute attr, out string[] values)
        {
            if (!attr.ValidateForGetValues <string>(HoudiniGeoAttributeType.String, 1))
            {
                values = new string[0];
                return;
            }

            values = attr.stringValues;
        }
Пример #2
0
        private static void GetValues(this HoudiniGeoAttribute attr, out float[] values)
        {
            if (!attr.ValidateForGetValues <float>(HoudiniGeoAttributeType.Float, 1))
            {
                values = new float[0];
                return;
            }

            values = attr.floatValues;
        }
Пример #3
0
        private static void GetValues(this HoudiniGeoAttribute attr, out int[] values)
        {
            if (!attr.ValidateForGetValues <int>(HoudiniGeoAttributeType.Integer, 1))
            {
                values = new int[0];
                return;
            }

            values = attr.intValues;
        }
Пример #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 AddSingleAttributeToDictionary(List <object> attributes, HoudiniGeoAttribute attribute)
        {
            string typeString = HoudiniGeoFileParser.AttributeTypeEnumValueToCategoryString(attribute.type);

            // Each attribute has a list with two dictionaries: a header and a body.
            List <object> attributeDictionaries = new List <object>();

            attributes.Add(attributeDictionaries);

            // Header dictionary.
            Dictionary <string, object> header = new Dictionary <string, object>()
            {
                { "scope", "public" }, // TODO: Does this ever vary?
Пример #6
0
        private static void GetValues(this HoudiniGeoAttribute attr, out Vector2[] values)
        {
            if (!attr.ValidateForGetValues <Vector2>(HoudiniGeoAttributeType.Float, 2))
            {
                values = new Vector2[0];
                return;
            }

            // Convert to Vector2
            float[] rawValues = attr.floatValues;
            values = new Vector2[rawValues.Length / attr.tupleSize];
            for (int i = 0; i < values.Length; i++)
            {
                values[i].x = rawValues[i * attr.tupleSize];
                values[i].y = rawValues[i * attr.tupleSize + 1];
            }
        }
Пример #7
0
        private static bool ValidateForGetValues <T>(this HoudiniGeoAttribute attr, HoudiniGeoAttributeType expectedType,
                                                     int expectedMinTupleSize)
        {
            if (attr.type != expectedType)
            {
                Debug.LogError(string.Format("Cannot convert raw values of {0} attribute '{1}' to {2} (type: {3})",
                                             attr.owner, attr.name, typeof(T).Name, attr.type));
                return(false);
            }

            if (attr.tupleSize < expectedMinTupleSize)
            {
                Debug.LogError(string.Format("The tuple size of {0} attribute '{1}' too small for conversion to {2}",
                                             attr.owner, attr.name, typeof(T).Name));
                return(false);
            }

            return(true);
        }
Пример #8
0
        private static object GetAttributeValue(Type type, HoudiniGeoAttribute attribute, int index)
        {
            if (type == typeof(float))
            {
                return(attribute.floatValues[index]);
            }
            if (type == typeof(int))
            {
                return(attribute.intValues[index]);
            }
            if (type == typeof(string))
            {
                return(attribute.stringValues[index]);
            }
            if (type == typeof(Vector2))
            {
                return(new Vector2(attribute.floatValues[index * 2], attribute.floatValues[index * 2 + 1]));
            }
            if (type == typeof(Vector3))
            {
                return(new Vector3(attribute.floatValues[index * 3], attribute.floatValues[index * 3 + 1], attribute.floatValues[index * 3 + 2]));
            }
            if (type == typeof(Vector4))
            {
                return(new Vector4(attribute.floatValues[index * 4], attribute.floatValues[index * 4 + 1], attribute.floatValues[index * 4 + 2], attribute.floatValues[index * 4 + 3]));
            }
            if (type == typeof(Vector2Int))
            {
                return(new Vector2Int(attribute.intValues[index * 2], attribute.intValues[index * 2 + 1]));
            }
            if (type == typeof(Vector3Int))
            {
                return(new Vector3Int(attribute.intValues[index * 3], attribute.intValues[index * 3 + 1], attribute.intValues[index * 3 + 2]));
            }
            if (type == typeof(Color))
            {
                return(new Color(attribute.floatValues[index * 3], attribute.floatValues[index * 3 + 1], attribute.floatValues[index * 3 + 2]));
            }

            Debug.LogWarning($"Tried to get value of unrecognized type '{type.Name}'");
            return(null);
        }
Пример #9
0
        private static void GetValues(this HoudiniGeoAttribute attr, out Color[] values)
        {
            if (!attr.ValidateForGetValues <Color>(HoudiniGeoAttributeType.Float, 3))
            {
                values = new Color[0];
                return;
            }

            // Convert to Color
            float[] rawValues = attr.floatValues;
            values = new Color[rawValues.Length / attr.tupleSize];
            for (int i = 0; i < values.Length; i++)
            {
                values[i].r = rawValues[i * attr.tupleSize];
                values[i].g = rawValues[i * attr.tupleSize + 1];
                values[i].b = rawValues[i * attr.tupleSize + 2];
                values[i].a = 1;
                if (attr.tupleSize == 4)
                {
                    values[i].a = rawValues[i * attr.tupleSize + 3];
                }
            }
        }
Пример #10
0
        private static bool TryCreateAttribute(FieldInfo fieldInfo, out HoudiniGeoAttribute attribute)
        {
            attribute = null;

            Type type = fieldInfo.FieldType;

            if (type == typeof(float))
            {
                attribute = new HoudiniGeoAttribute {
                    type = HoudiniGeoAttributeType.Float, tupleSize = 1
                }
            }
            ;
            else if (type == typeof(int))
            {
                attribute = new HoudiniGeoAttribute {
                    type = HoudiniGeoAttributeType.Integer, tupleSize = 1
                }
            }
            ;
            else if (type == typeof(string))
            {
                attribute = new HoudiniGeoAttribute {
                    type = HoudiniGeoAttributeType.String, tupleSize = 1
                }
            }
            ;
            if (type == typeof(Vector2))
            {
                attribute = new HoudiniGeoAttribute {
                    type = HoudiniGeoAttributeType.Float, tupleSize = 2
                }
            }
            ;
            else if (type == typeof(Vector3))
            {
                attribute = new HoudiniGeoAttribute {
                    type = HoudiniGeoAttributeType.Float, tupleSize = 3
                }
            }
            ;
            else if (type == typeof(Vector4))
            {
                attribute = new HoudiniGeoAttribute {
                    type = HoudiniGeoAttributeType.Float, tupleSize = 4
                }
            }
            ;
            else if (type == typeof(Vector2Int))
            {
                attribute = new HoudiniGeoAttribute {
                    type = HoudiniGeoAttributeType.Integer, tupleSize = 2
                }
            }
            ;
            else if (type == typeof(Vector3Int))
            {
                attribute = new HoudiniGeoAttribute {
                    type = HoudiniGeoAttributeType.Integer, tupleSize = 3
                }
            }
            ;
            else if (type == typeof(Color))
            {
                attribute = new HoudiniGeoAttribute {
                    type = HoudiniGeoAttributeType.Float, tupleSize = 3
                }
            }
            ;

            if (attribute == null)
            {
                return(false);
            }

            attribute.name = fieldInfo.Name;
            return(true);
        }
Пример #11
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();
            }
        }
Пример #12
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);
 }
Пример #13
0
        private static HoudiniGeoAttribute ParseSingleAttribute(JToken attrToken, HoudiniGeoAttributeOwner owner)
        {
            // NUMERIC
            // [
            //      [
            //          "scope","public",
            //          "type","numeric",
            //          "name","P",														<- Extract This
            //          "options",{
            //              "type":{
            //                  "type":"string",
            //                  "value":"hpoint"
            //              }
            //          }
            //      ],
            //      [
            //          "size",4,														<- Extract This
            //          "storage","fpreal32",											<- Extract This
            //          "defaults",[
            //              "size",4,
            //              "storage","fpreal64",
            //              "values",[0,0,0,1]
            //          ],
            //          "values",[
            //              "size",4,
            //              "storage","fpreal32",
            //              "tuples",[[-0.5,-0.5,-0.5,1],[0.5,-0.5,-0.5,1],...]			<- Extract This
            //          ]
            //      ]
            // ]

            // STRING
            // [
            //      [
            //          "scope","public",
            //          "type","string",
            //          "name","varmap",
            //          "options",{
            //          }
            //      ],
            //      [
            //          "size",1,
            //          "storage","int32",
            //          "strings",["SHIT_INT -> SHIT_INT"],
            //          "indices",[
            //              "size",1,
            //              "storage","int32",
            //              "arrays",[[0]]
            //          ]
            //      ]
            // ]

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

            var geoAttribute = new HoudiniGeoAttribute();

            geoAttribute.owner = owner;

            // Parse header block
            Dictionary <string, JToken> headerBlockDict = ArrayKeyValueToDictionary(headerToken.Children().ToArray());

            geoAttribute.name = headerBlockDict["name"].Value <string>();
            string valueType = headerBlockDict["type"].Value <string>();

            // Parse body block
            Dictionary <string, JToken> valuesBlockDict = ArrayKeyValueToDictionary(bodyToken.Children().ToArray());

            geoAttribute.tupleSize = valuesBlockDict["size"].Value <int>();

            // Parse Numeric types
            if (valueType == "numeric")
            {
                // Get storage type (float, int)
                string storageType = valuesBlockDict["storage"].Value <string>();
                geoAttribute.type = AttributeTypeStrToEnumValue(storageType);
                if (geoAttribute.type == HoudiniGeoAttributeType.Invalid)
                {
                    Debug.LogWarning("HoudiniGeoFileParser: unsuppored numeric storage type " + valueType);
                    return(null);
                }

                // Get all values
                Dictionary <string, JToken> valuesDict = ArrayKeyValueToDictionary(valuesBlockDict["values"].Children().ToArray());
                if (geoAttribute.type == HoudiniGeoAttributeType.Float)
                {
                    int    tupleSize = valuesDict["size"].Value <int>();
                    string valuesKey = (tupleSize == 1) ? "arrays" : "tuples";
                    geoAttribute.floatValues = valuesDict[valuesKey].Children().SelectMany(t => t.Values <float>()).ToArray();
                }
                else if (geoAttribute.type == HoudiniGeoAttributeType.Integer)
                {
                    geoAttribute.intValues = valuesDict["arrays"].Children().SelectMany(t => t.Values <int>()).ToArray();
                }
            }
            // Parse String types
            else if (valueType == "string")
            {
                geoAttribute.type = HoudiniGeoAttributeType.String;

                Dictionary <string, JToken> indicesDict = ArrayKeyValueToDictionary(valuesBlockDict["indices"].Children().ToArray());
                string[] stringValues = valuesBlockDict["strings"].Values <string>().ToArray();
                int[]    indices      = indicesDict["arrays"].Children().SelectMany(t => t.Values <int>()).ToArray();

                geoAttribute.stringValues = indices.Select(i => (i >= 0 && i < stringValues.Length) ? stringValues[i] : "").ToArray();
            }
            // Unexpected type?
            else
            {
                Debug.LogWarning("HoudiniGeoFileParser: unsuppored attribute valueType " + valueType);
                return(null);
            }

            return(geoAttribute);
        }